Update #42 - Fixed several WebRTC bugs and other issues

This commit is contained in:
lax1dude
2024-11-16 21:47:35 -08:00
parent 4d66ca140a
commit 64ac208565
95 changed files with 1084 additions and 501 deletions

View File

@ -53,18 +53,23 @@ public class PlatformAudio {
@Override
public void pause(boolean setPaused) {
if(setPaused) {
if(sndSystem.playing(sourceName)) {
if(!paused) {
sndSystem.pause(sourceName);
paused = true;
}
paused = true;
}else {
if(!sndSystem.playing(sourceName)) {
if(paused) {
sndSystem.play(sourceName);
paused = false;
}
paused = false;
}
}
@Override
public void repeat(boolean en) {
sndSystem.setLooping(sourceName, en);
}
@Override
public void restart() {
this.stall = PlatformRuntime.steadyTimeMillis();
@ -172,7 +177,7 @@ public class PlatformAudio {
private static int sourceCounter = 0;
public static IAudioHandle beginPlayback(IAudioResource track, float x, float y, float z,
float volume, float pitch) {
float volume, float pitch, boolean repeat) {
if(sndSystem == null) {
return null;
}
@ -188,12 +193,13 @@ public class PlatformAudio {
sndSystem.setTemporary(srcName, true);
sndSystem.setPitch(srcName, pitch);
sndSystem.setVolume(srcName, volume);
sndSystem.setLooping(srcName, repeat);
sndSystem.play(srcName);
return new PaulscodeAudioHandle(srcName);
}
public static IAudioHandle beginPlaybackStatic(IAudioResource track, float volume, float pitch) {
public static IAudioHandle beginPlaybackStatic(IAudioResource track, float volume, float pitch, boolean repeat) {
if(sndSystem == null) {
return null;
}
@ -204,6 +210,7 @@ public class PlatformAudio {
sndSystem.setTemporary(srcName, true);
sndSystem.setPitch(srcName, pitch);
sndSystem.setVolume(srcName, volume);
sndSystem.setLooping(srcName, repeat);
sndSystem.play(srcName);
return new PaulscodeAudioHandle(srcName);

View File

@ -567,7 +567,11 @@ public class PlatformRuntime {
public static InputStream newGZIPInputStream(InputStream is) throws IOException {
return new GZIPInputStream(is);
}
public static void downloadRemoteURIByteArray(String assetPackageURI, boolean forceCache, final Consumer<byte[]> cb) {
downloadRemoteURIByteArray(assetPackageURI, cb);
}
public static void downloadRemoteURIByteArray(String assetPackageURI, final Consumer<byte[]> cb) {
logger.info("Downloading: {}");
try(InputStream is = (new URL(assetPackageURI)).openStream()) {

View File

@ -1,7 +1,6 @@
package net.lax1dude.eaglercraft.v1_8.internal;
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelPeerState;
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelReadyState;
/**
@ -89,28 +88,8 @@ public class PlatformVoiceClient {
}
public static EnumVoiceChannelPeerState getPeerState() {
return EnumVoiceChannelPeerState.LOADING;
}
public static EnumVoiceChannelReadyState getReadyState() {
return EnumVoiceChannelReadyState.NONE;
}
public static EnumVoiceChannelPeerState getPeerStateConnect() {
return EnumVoiceChannelPeerState.LOADING;
}
public static EnumVoiceChannelPeerState getPeerStateInitial() {
return EnumVoiceChannelPeerState.LOADING;
}
public static EnumVoiceChannelPeerState getPeerStateDesc() {
return EnumVoiceChannelPeerState.LOADING;
}
public static EnumVoiceChannelPeerState getPeerStateIce() {
return EnumVoiceChannelPeerState.LOADING;
}
}

View File

@ -5,18 +5,8 @@ import dev.onvoid.webrtc.internal.NativeLoader;
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer;
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANPeerEvent;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayLoggerImpl;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQuery;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQueryImpl;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQueryRateLimitDummy;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerRateLimitTracker;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocketImpl;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocketRateLimitDummy;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQuery;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQueryImpl;
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQueryRateLimitDummy;
import org.apache.commons.lang3.SystemUtils;
import org.json.JSONArray;
@ -50,11 +40,8 @@ public class PlatformWebRTC {
private static final Logger logger = LogManager.getLogger("PlatformWebRTC");
private static final RelayLoggerImpl loggerImpl = new RelayLoggerImpl(LogManager.getLogger("RelayPacket"));
private static final Object lock1 = new Object();
private static final Object lock2 = new Object();
private static final Object lock3 = new Object();
private static final List<ScheduledRunnable> scheduledRunnables = new LinkedList<>();
@ -93,8 +80,6 @@ public class PlatformWebRTC {
return supported;
}
private static final Map<String, RTCDataChannel> fuckTeaVM = new HashMap<>();
private static final Comparator<ScheduledRunnable> sortTasks = (r1, r2) -> {
return (int)(r1.runAt - r2.runAt);
};
@ -177,9 +162,17 @@ public class PlatformWebRTC {
synchronized (lock1) {
if (iceCandidate.sdp != null && !iceCandidate.sdp.isEmpty()) {
if (iceCandidates.isEmpty()) {
scheduleTask(3000l, () -> {
final int[] candidateState = new int[2];
final Runnable[] runnable = new Runnable[1];
scheduleTask(2000l, runnable[0] = () -> {
synchronized (lock1) {
if (peerConnection != null && peerConnection.getConnectionState() != RTCPeerConnectionState.DISCONNECTED) {
int trial = ++candidateState[1];
if(candidateState[0] != iceCandidates.size() && trial < 3) {
candidateState[0] = iceCandidates.size();
scheduleTask(2000l, runnable[0]);
return;
}
clientICECandidate = JSONWriter.valueToString(iceCandidates);
iceCandidates.clear();
}
@ -382,6 +375,8 @@ public class PlatformWebRTC {
public LANServer client;
public String peerId;
public RTCPeerConnection peerConnection;
public RTCDataChannel dataChannel;
public String ipcChannel;
public LANPeer(LANServer client, String peerId, RTCPeerConnection peerConnection) {
this.client = client;
@ -390,10 +385,9 @@ public class PlatformWebRTC {
}
public void disconnect() {
synchronized (fuckTeaVM) {
if (fuckTeaVM.get(peerId) != null) {
fuckTeaVM.remove(peerId).close();
}
if(dataChannel != null) {
dataChannel.close();
dataChannel = null;
}
peerConnection.close();
peerConnection = null;
@ -472,16 +466,36 @@ public class PlatformWebRTC {
client.signalRemoteDisconnect(peerId);
}
}
public void mapIPC(String ipcChannel) {
if(this.ipcChannel == null) {
if(ipcChannel != null) {
this.ipcChannel = ipcChannel;
synchronized(this.client.ipcMapList) {
this.client.ipcMapList.put(ipcChannel, this);
}
}
}else {
if(ipcChannel == null) {
synchronized(this.client.ipcMapList) {
this.client.ipcMapList.remove(this.ipcChannel);
}
this.ipcChannel = null;
}
}
}
}
public static class LANServer {
public Set<Map<String, String>> iceServers = new HashSet<>();
public Map<String, LANPeer> peerList = new HashMap<>();
public Map<String, LANPeer> ipcMapList = new HashMap<>();
public byte peerState = PEERSTATE_LOADING;
public byte peerStateConnect = PEERSTATE_LOADING;
public byte peerStateInitial = PEERSTATE_LOADING;
public byte peerStateDesc = PEERSTATE_LOADING;
public byte peerStateIce = PEERSTATE_LOADING;
private final Object lock3 = new Object();
public void setIceServers(String[] urls) {
iceServers.clear();
@ -502,23 +516,28 @@ public class PlatformWebRTC {
}
public void sendPacketToRemoteClient(String peerId, RTCDataChannelBuffer buffer) {
LANPeer thePeer = this.peerList.get(peerId);
LANPeer thePeer;
synchronized(peerList) {
thePeer = peerList.get(peerId);
}
if (thePeer != null) {
boolean b = false;
synchronized (fuckTeaVM) {
if (fuckTeaVM.get(thePeer.peerId) != null && fuckTeaVM.get(thePeer.peerId).getState() == RTCDataChannelState.OPEN) {
try {
fuckTeaVM.get(thePeer.peerId).send(buffer);
} catch (Throwable e) {
b = true;
}
} else {
b = true;
}
}
if (b) {
signalRemoteDisconnect(peerId);
sendPacketToRemoteClient(thePeer, buffer);
}
}
public void sendPacketToRemoteClient(LANPeer thePeer, RTCDataChannelBuffer buffer) {
boolean b = false;
if(thePeer.dataChannel != null && thePeer.dataChannel.getState() == RTCDataChannelState.OPEN) {
try {
thePeer.dataChannel.send(buffer);
} catch (Exception e) {
b = true;
}
} else {
b = true;
}
if (b) {
signalRemoteDisconnect(thePeer.peerId);
}
}
@ -537,16 +556,25 @@ public class PlatformWebRTC {
iceServer.password = server.getOrDefault("credential", null);
rtcConfig.iceServers.add(iceServer);
}
RTCPeerConnection[] peerConnection = new RTCPeerConnection[1];
final RTCPeerConnection[] peerConnection = new RTCPeerConnection[1];
final LANPeer[] peerInstance = new LANPeer[1];
peerConnection[0] = pcFactory.createPeerConnection(rtcConfig, new PeerConnectionObserver() {
@Override
public void onIceCandidate(RTCIceCandidate iceCandidate) {
synchronized (lock3) {
if (iceCandidate.sdp != null && !iceCandidate.sdp.isEmpty()) {
if (iceCandidates.isEmpty()) {
scheduleTask(3000l, () -> {
final int[] candidateState = new int[2];
final Runnable[] runnable = new Runnable[1];
scheduleTask(2000l, runnable[0] = () -> {
synchronized (lock3) {
if (peerConnection[0] != null && peerConnection[0].getConnectionState() != RTCPeerConnectionState.DISCONNECTED) {
int trial = ++candidateState[1];
if(candidateState[0] != iceCandidates.size() && trial < 3) {
candidateState[0] = iceCandidates.size();
scheduleTask(2000l, runnable[0]);
return;
}
LANPeerEvent.LANPeerICECandidateEvent e = new LANPeerEvent.LANPeerICECandidateEvent(peerId, JSONWriter.valueToString(iceCandidates));
synchronized (serverLANEventBuffer) {
serverLANEventBuffer.put(peerId, e);
@ -582,9 +610,11 @@ public class PlatformWebRTC {
return;
}
if (dataChannel == null) return;
synchronized (fuckTeaVM) {
fuckTeaVM.put(peerId, dataChannel);
if(peerInstance[0].dataChannel != null) {
dataChannel.close();
return;
}
peerInstance[0].dataChannel = dataChannel;
synchronized (serverLANEventBuffer) {
serverLANEventBuffer.put(peerId, new LANPeerEvent.LANPeerDataChannelEvent(peerId));
}
@ -604,9 +634,14 @@ public class PlatformWebRTC {
if (!buffer.binary) return;
byte[] data = new byte[buffer.data.remaining()];
buffer.data.get(data);
LANPeerEvent.LANPeerPacketEvent e = new LANPeerEvent.LANPeerPacketEvent(peerId, data);
synchronized (serverLANEventBuffer) {
serverLANEventBuffer.put(peerId, e);
LANPeer peer = peerInstance[0];
if(peer.ipcChannel != null) {
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(peer.ipcChannel, data));
}else {
LANPeerEvent.LANPeerPacketEvent e = new LANPeerEvent.LANPeerPacketEvent(peerId, data);
synchronized (serverLANEventBuffer) {
serverLANEventBuffer.put(peerId, e);
}
}
}
});
@ -627,8 +662,10 @@ public class PlatformWebRTC {
}
}
});
LANPeer peerInstance = new LANPeer(this, peerId, peerConnection[0]);
peerList.put(peerId, peerInstance);
peerInstance[0] = new LANPeer(this, peerId, peerConnection[0]);
synchronized(peerList) {
peerList.put(peerId, peerInstance[0]);
}
if (peerStateConnect != PEERSTATE_SUCCESS) peerStateConnect = PEERSTATE_SUCCESS;
} catch (Throwable e) {
if (peerStateConnect == PEERSTATE_LOADING) peerStateConnect = PEERSTATE_FAILED;
@ -636,14 +673,20 @@ public class PlatformWebRTC {
}
public void signalRemoteDescription(String peerId, String descJSON) {
LANPeer thePeer = peerList.get(peerId);
LANPeer thePeer;
synchronized(peerList) {
thePeer = peerList.get(peerId);
}
if (thePeer != null) {
thePeer.setRemoteDescription(descJSON);
}
}
public void signalRemoteICECandidate(String peerId, String candidate) {
LANPeer thePeer = peerList.get(peerId);
LANPeer thePeer;
synchronized(peerList) {
thePeer = peerList.get(peerId);
}
if (thePeer != null) {
thePeer.addICECandidate(candidate);
}
@ -651,7 +694,12 @@ public class PlatformWebRTC {
public void signalRemoteDisconnect(String peerId) {
if (peerId == null || peerId.isEmpty()) {
for (LANPeer thePeer : peerList.values()) {
List<LANPeer> cpy;
synchronized(peerList) {
cpy = new ArrayList<>(peerList.values());
peerList.clear();
}
for (LANPeer thePeer : cpy) {
if (thePeer != null) {
try {
thePeer.disconnect();
@ -662,55 +710,44 @@ public class PlatformWebRTC {
}
}
}
peerList.clear();
synchronized (fuckTeaVM) {
fuckTeaVM.clear();
}
return;
}
LANPeer thePeer = peerList.get(peerId);
LANPeer thePeer;
synchronized(peerList) {
thePeer = peerList.remove(peerId);
}
if (thePeer != null) {
peerList.remove(peerId);
if(thePeer.ipcChannel != null) {
synchronized(ipcMapList) {
ipcMapList.remove(thePeer.ipcChannel);
}
}
try {
thePeer.disconnect();
} catch (Throwable ignored) {
}
synchronized (fuckTeaVM) {
fuckTeaVM.remove(peerId);
}
synchronized (serverLANEventBuffer) {
serverLANEventBuffer.put(thePeer.peerId, new LANPeerEvent.LANPeerDisconnectEvent(peerId));
}
}
}
public void serverPeerMapIPC(String peer, String ipcChannel) {
LANPeer peerr;
synchronized(peerList) {
peerr = peerList.get(peer);
}
if(peerr != null) {
peerr.mapIPC(ipcChannel);
}
}
public int countPeers() {
return peerList.size();
synchronized(peerList) {
return peerList.size();
}
}
}
public static RelayQuery openRelayQuery(String addr) {
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
return new RelayQueryRateLimitDummy(limit);
}
return new RelayQueryImpl(addr);
}
public static RelayWorldsQuery openRelayWorldsQuery(String addr) {
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
return new RelayWorldsQueryRateLimitDummy(limit);
}
return new RelayWorldsQueryImpl(addr);
}
public static RelayServerSocket openRelayConnection(String addr, int timeout) {
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
return new RelayServerSocketRateLimitDummy(limit);
}
return new RelayServerSocketImpl(addr, timeout);
}
private static LANClient rtcLANClient = null;
@ -883,6 +920,27 @@ public class PlatformWebRTC {
rtcLANServer.signalRemoteDescription(peer, description);
}
public static void serverLANPeerMapIPC(String peer, String ipcChannel) {
rtcLANServer.serverPeerMapIPC(peer, ipcChannel);
}
public static boolean serverLANPeerPassIPC(IPCPacketData ipcPacket) {
if(rtcLANServer != null) {
LANPeer peer;
synchronized(rtcLANServer.ipcMapList) {
peer = rtcLANServer.ipcMapList.get(ipcPacket.channel);
}
if(peer != null) {
rtcLANServer.sendPacketToRemoteClient(peer, new RTCDataChannelBuffer(ByteBuffer.wrap(ipcPacket.contents), true));
return true;
}else {
return false;
}
}else {
return false;
}
}
public static void serverLANDisconnectPeer(String peer) {
rtcLANServer.signalRemoteDisconnect(peer);
}
@ -893,4 +951,5 @@ public class PlatformWebRTC {
}
return rtcLANServer.countPeers();
}
}

View File

@ -141,7 +141,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
int l = src.remaining();
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
for(int i = 0; i < l; ++i) {
UnsafeUtils.setMemByte(address + position + l, src.get());
UnsafeUtils.setMemByte(address + position + i, src.get());
}
position += l;
}

View File

@ -150,7 +150,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
int l = src.remaining();
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
for(int i = 0; i < l; ++i) {
UnsafeUtils.setMemFloat(address + ((position + l) << SHIFT), src.get());
UnsafeUtils.setMemFloat(address + ((position + i) << SHIFT), src.get());
}
position += l;
}

View File

@ -150,7 +150,7 @@ public class EaglerLWJGLIntBuffer implements IntBuffer {
int l = src.remaining();
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
for(int i = 0; i < l; ++i) {
UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get());
UnsafeUtils.setMemInt(address + ((position + i) << SHIFT), src.get());
}
position += l;
}

View File

@ -150,7 +150,7 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer {
int l = src.remaining();
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
for(int i = 0; i < l; ++i) {
UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get());
UnsafeUtils.setMemInt(address + ((position + i) << SHIFT), src.get());
}
position += l;
}

View File

@ -8,6 +8,7 @@ import net.lax1dude.eaglercraft.v1_8.Filesystem;
import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter;
import net.lax1dude.eaglercraft.v1_8.internal.IEaglerFilesystem;
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.DesktopClientConfigAdapter;
import net.lax1dude.eaglercraft.v1_8.sp.server.internal.lwjgl.MemoryConnection;
@ -45,6 +46,9 @@ public class ServerPlatformSingleplayer {
}
public static void sendPacket(IPCPacketData packet) {
if(PlatformWebRTC.serverLANPeerPassIPC(packet)) {
return;
}
synchronized(MemoryConnection.serverToClientQueue) {
MemoryConnection.serverToClientQueue.add(packet);
}