diff --git a/javascript/eagswebrtc.js b/javascript/eagswebrtc.js index 8703e7e..8c05e0b 100644 --- a/javascript/eagswebrtc.js +++ b/javascript/eagswebrtc.js @@ -19,10 +19,6 @@ window.initializeVoiceClient = (() => { const READYSTATE_ABORTED = -1; const READYSTATE_DEVICE_INITIALIZED = 1; - const PEERSTATE_FAILED = 0; - const PEERSTATE_SUCCESS = 1; - const PEERSTATE_LOADING = 2; - class EaglercraftVoicePeer { constructor(client, peerId, peerConnection, offer) { @@ -31,52 +27,43 @@ window.initializeVoiceClient = (() => { this.peerConnection = peerConnection; this.stream = null; - const self = this; this.peerConnection.addEventListener("icecandidate", (evt) => { if(evt.candidate) { - self.client.iceCandidateHandler(self.peerId, JSON.stringify({ sdpMLineIndex: evt.candidate.sdpMLineIndex, candidate: evt.candidate.candidate })); + this.client.iceCandidateHandler(this.peerId, JSON.stringify({ sdpMLineIndex: evt.candidate.sdpMLineIndex, candidate: evt.candidate.candidate })); } }); this.peerConnection.addEventListener("track", (evt) => { - self.rawStream = evt.streams[0]; + this.rawStream = evt.streams[0]; const aud = new Audio(); aud.autoplay = true; aud.muted = true; aud.onended = function() { aud.remove(); }; - aud.srcObject = self.rawStream; - self.client.peerTrackHandler(self.peerId, self.rawStream); + aud.srcObject = this.rawStream; + this.client.peerTrackHandler(this.peerId, this.rawStream); }); this.peerConnection.addStream(this.client.localMediaStream.stream); if (offer) { this.peerConnection.createOffer((desc) => { const selfDesc = desc; - self.peerConnection.setLocalDescription(selfDesc, () => { - self.client.descriptionHandler(self.peerId, JSON.stringify(selfDesc)); - if (self.client.peerStateInitial != PEERSTATE_SUCCESS) self.client.peerStateInitial = PEERSTATE_SUCCESS; + this.peerConnection.setLocalDescription(selfDesc, () => { + this.client.descriptionHandler(this.peerId, JSON.stringify(selfDesc)); }, (err) => { - console.error("Failed to set local description for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateInitial == PEERSTATE_LOADING) self.client.peerStateInitial = PEERSTATE_FAILED; - self.client.signalDisconnect(self.peerId); + console.error("Failed to set local description for \"" + this.peerId + "\"! " + err); + this.client.signalDisconnect(this.peerId); }); }, (err) => { - console.error("Failed to set create offer for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateInitial == PEERSTATE_LOADING) self.client.peerStateInitial = PEERSTATE_FAILED; - self.client.signalDisconnect(self.peerId); + console.error("Failed to set create offer for \"" + this.peerId + "\"! " + err); + this.client.signalDisconnect(this.peerId); }); } this.peerConnection.addEventListener("connectionstatechange", (evt) => { - if(self.peerConnection.connectionState === 'disconnected') { - self.client.signalDisconnect(self.peerId); - } else if (self.peerConnection.connectionState === 'connected') { - if (self.client.peerState != PEERSTATE_SUCCESS) self.client.peerState = PEERSTATE_SUCCESS; - } else if (self.peerConnection.connectionState === 'failed') { - if (self.client.peerState == PEERSTATE_LOADING) self.client.peerState = PEERSTATE_FAILED; - self.client.signalDisconnect(self.peerId); + if(this.peerConnection.connectionState === 'disconnected' || this.peerConnection.connectionState === 'failed') { + this.client.signalDisconnect(this.peerId); } }); @@ -91,46 +78,38 @@ window.initializeVoiceClient = (() => { } setRemoteDescription(descJSON) { - const self = this; try { const remoteDesc = JSON.parse(descJSON); this.peerConnection.setRemoteDescription(remoteDesc, () => { - if(remoteDesc.type == 'offer') { - self.peerConnection.createAnswer((desc) => { + if(remoteDesc.type === 'offer') { + this.peerConnection.createAnswer((desc) => { const selfDesc = desc; - self.peerConnection.setLocalDescription(selfDesc, () => { - self.client.descriptionHandler(self.peerId, JSON.stringify(selfDesc)); - if (self.client.peerStateDesc != PEERSTATE_SUCCESS) self.client.peerStateDesc = PEERSTATE_SUCCESS; + this.peerConnection.setLocalDescription(selfDesc, () => { + this.client.descriptionHandler(this.peerId, JSON.stringify(selfDesc)); }, (err) => { - console.error("Failed to set local description for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED; - self.client.signalDisconnect(self.peerId); + console.error("Failed to set local description for \"" + this.peerId + "\"! " + err); + this.client.signalDisconnect(this.peerId); }); }, (err) => { - console.error("Failed to create answer for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED; - self.client.signalDisconnect(self.peerId); + console.error("Failed to create answer for \"" + this.peerId + "\"! " + err); + this.client.signalDisconnect(this.peerId); }); } }, (err) => { - console.error("Failed to set remote description for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED; - self.client.signalDisconnect(self.peerId); + console.error("Failed to set remote description for \"" + this.peerId + "\"! " + err); + this.client.signalDisconnect(this.peerId); }); } catch (err) { - console.error("Failed to parse remote description for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED; - self.client.signalDisconnect(self.peerId); + console.error("Failed to parse remote description for \"" + this.peerId + "\"! " + err); + this.client.signalDisconnect(this.peerId); } } addICECandidate(candidate) { try { this.peerConnection.addIceCandidate(new RTCIceCandidate(JSON.parse(candidate))); - if (this.client.peerStateIce != PEERSTATE_SUCCESS) this.client.peerStateIce = PEERSTATE_SUCCESS; } catch (err) { console.error("Failed to parse ice candidate for \"" + this.peerId + "\"! " + err); - if (this.client.peerStateIce == PEERSTATE_LOADING) this.client.peerStateIce = PEERSTATE_FAILED; this.client.signalDisconnect(this.peerId); } } @@ -144,11 +123,6 @@ window.initializeVoiceClient = (() => { this.hasInit = false; this.peerList = new Map(); this.readyState = READYSTATE_NONE; - this.peerState = PEERSTATE_LOADING; - this.peerStateConnect = PEERSTATE_LOADING; - this.peerStateInitial = PEERSTATE_LOADING; - this.peerStateDesc = PEERSTATE_LOADING; - this.peerStateIce = PEERSTATE_LOADING; this.iceCandidateHandler = null; this.descriptionHandler = null; this.peerTrackHandler = null; @@ -165,9 +139,9 @@ window.initializeVoiceClient = (() => { this.ICEServers.length = 0; for(var i = 0; i < urls.length; ++i) { var etr = urls[i].split(";"); - if(etr.length == 1) { + if(etr.length === 1) { this.ICEServers.push({ urls: etr[0] }); - }else if(etr.length == 3) { + }else if(etr.length === 3) { this.ICEServers.push({ urls: etr[0], username: etr[1], credential: etr[2] }); } } @@ -195,21 +169,20 @@ window.initializeVoiceClient = (() => { initializeDevices() { if(!this.hasInit) { - const self = this; navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then((stream) => { - self.microphoneVolumeAudioContext = new AudioContext(); - self.localRawMediaStream = stream; - self.localRawMediaStream.getAudioTracks()[0].enabled = false; - self.localMediaStream = self.microphoneVolumeAudioContext.createMediaStreamDestination(); - self.localMediaStreamGain = self.microphoneVolumeAudioContext.createGain(); - var localStreamIn = self.microphoneVolumeAudioContext.createMediaStreamSource(stream); - localStreamIn.connect(self.localMediaStreamGain); - self.localMediaStreamGain.connect(self.localMediaStream); - self.localMediaStreamGain.gain.value = 1.0; - self.readyState = READYSTATE_DEVICE_INITIALIZED; + this.microphoneVolumeAudioContext = new AudioContext(); + this.localRawMediaStream = stream; + this.localRawMediaStream.getAudioTracks()[0].enabled = false; + this.localMediaStream = this.microphoneVolumeAudioContext.createMediaStreamDestination(); + this.localMediaStreamGain = this.microphoneVolumeAudioContext.createGain(); + var localStreamIn = this.microphoneVolumeAudioContext.createMediaStreamSource(stream); + localStreamIn.connect(this.localMediaStreamGain); + this.localMediaStreamGain.connect(this.localMediaStream); + this.localMediaStreamGain.gain.value = 1.0; + this.readyState = READYSTATE_DEVICE_INITIALIZED; this.hasInit = true; }).catch((err) => { - self.readyState = READYSTATE_ABORTED; + this.readyState = READYSTATE_ABORTED; }); }else { this.readyState = READYSTATE_DEVICE_INITIALIZED; @@ -224,44 +197,17 @@ window.initializeVoiceClient = (() => { this.localMediaStreamGain.gain.value = val * 2.0; } } - - resetPeerStates() { - this.peerState = this.peerStateConnect = this.peerStateInitial = this.peerStateDesc = this.peerStateIce = PEERSTATE_LOADING; - } - - getPeerState() { - return this.peerState; - } - - getPeerStateConnect() { - return this.peerStateConnect; - } - - getPeerStateInitial() { - return this.peerStateInitial; - } - - getPeerStateDesc() { - return this.peerStateDesc; - } - - getPeerStateIce() { - return this.peerStateIce; - } getReadyState() { return this.readyState; } signalConnect(peerId, offer) { - if (!this.hasInit) this.initializeDevices(); try { - const peerConnection = new RTCPeerConnection({ iceServers: this.ICEServers, optional: [ { DtlsSrtpKeyAgreement: true } ] }); - const peerInstance = new EaglercraftVoicePeer(this, peerId, peerConnection, offer); - this.peerList.set(peerId, peerInstance); - if (this.peerStateConnect != PEERSTATE_SUCCESS) this.peerStateConnect = PEERSTATE_SUCCESS; + const peerConnection = new RTCPeerConnection({ iceServers: this.ICEServers, optional: [ { DtlsSrtpKeyAgreement: true } ] }); + const peerInstance = new EaglercraftVoicePeer(this, peerId, peerConnection, offer); + this.peerList.set(peerId, peerInstance); } catch (e) { - if (this.peerStateConnect == PEERSTATE_LOADING) this.peerStateConnect = PEERSTATE_FAILED; } } @@ -341,11 +287,11 @@ window.initializeLANClient = (() => { initializeClient() { try { - if(this.dataChannel != null) { + if(this.dataChannel !== null) { this.dataChannel.close(); this.dataChannel = null; } - if(this.peerConnection != null) { + if(this.peerConnection !== null) { this.peerConnection.close(); } this.peerConnection = new RTCPeerConnection({ iceServers: this.ICEServers, optional: [ { DtlsSrtpKeyAgreement: true } ] }); @@ -359,9 +305,9 @@ window.initializeLANClient = (() => { this.ICEServers.length = 0; for(var i = 0; i < urls.length; ++i) { var etr = urls[i].split(";"); - if(etr.length == 1) { + if(etr.length === 1) { this.ICEServers.push({ urls: etr[0] }); - }else if(etr.length == 3) { + }else if(etr.length === 3) { this.ICEServers.push({ urls: etr[0], username: etr[1], credential: etr[2] }); } } @@ -392,7 +338,7 @@ window.initializeLANClient = (() => { } sendPacketToServer(buffer) { - if(this.dataChannel != null && this.dataChannel.readyState == "open") { + if(this.dataChannel !== null && this.dataChannel.readyState === "open") { this.dataChannel.send(buffer); }else { this.signalRemoteDisconnect(false); @@ -400,15 +346,14 @@ window.initializeLANClient = (() => { } signalRemoteConnect() { - const self = this; const iceCandidates = []; this.peerConnection.addEventListener("icecandidate", (evt) => { if(evt.candidate) { - if(iceCandidates.length == 0) setTimeout(() => { - if(self.peerConnection != null && self.peerConnection.connectionState != "disconnected") { - self.iceCandidateHandler(JSON.stringify(iceCandidates)); + if(iceCandidates.length === 0) setTimeout(() => { + if(this.peerConnection !== null && this.peerConnection.connectionState !== "disconnected") { + this.iceCandidateHandler(JSON.stringify(iceCandidates)); iceCandidates.length = 0; } }, 3000); @@ -423,36 +368,36 @@ window.initializeLANClient = (() => { while(iceCandidates.length > 0) { await new Promise(resolve => setTimeout(resolve, 0)); } - self.remoteDataChannelHandler(self.dataChannel); + this.remoteDataChannelHandler(this.dataChannel); }); this.dataChannel.addEventListener("message", (evt) => { - self.remotePacketHandler(evt.data); + this.remotePacketHandler(evt.data); }, false); this.peerConnection.createOffer((desc) => { const selfDesc = desc; - self.peerConnection.setLocalDescription(selfDesc, () => { - self.descriptionHandler(JSON.stringify(selfDesc)); + this.peerConnection.setLocalDescription(selfDesc, () => { + this.descriptionHandler(JSON.stringify(selfDesc)); }, (err) => { console.error("Failed to set local description! " + err); - self.readyState = READYSTATE_FAILED; - self.signalRemoteDisconnect(false); + this.readyState = READYSTATE_FAILED; + this.signalRemoteDisconnect(false); }); }, (err) => { console.error("Failed to set create offer! " + err); - self.readyState = READYSTATE_FAILED; - self.signalRemoteDisconnect(false); + this.readyState = READYSTATE_FAILED; + this.signalRemoteDisconnect(false); }); this.peerConnection.addEventListener("connectionstatechange", (evt) => { - if(self.peerConnection.connectionState === 'disconnected') { - self.signalRemoteDisconnect(false); - } else if (self.peerConnection.connectionState === 'connected') { - self.readyState = READYSTATE_CONNECTED; - } else if (self.peerConnection.connectionState === 'failed') { - self.readyState = READYSTATE_FAILED; - self.signalRemoteDisconnect(false); + if(this.peerConnection.connectionState === 'disconnected') { + this.signalRemoteDisconnect(false); + } else if (this.peerConnection.connectionState === 'connected') { + this.readyState = READYSTATE_CONNECTED; + } else if (this.peerConnection.connectionState === 'failed') { + this.readyState = READYSTATE_FAILED; + this.signalRemoteDisconnect(false); } }); } @@ -481,11 +426,11 @@ window.initializeLANClient = (() => { } signalRemoteDisconnect(quiet) { - if(this.dataChannel != null) { + if(this.dataChannel !== null) { this.dataChannel.close(); this.dataChannel = null; } - if(this.peerConnection != null) { + if(this.peerConnection !== null) { this.peerConnection.close(); } if(!quiet) this.remoteDisconnectHandler(); @@ -510,10 +455,6 @@ window.startLANClient = () => { window.initializeLANServer = (() => { - const PEERSTATE_FAILED = 0; - const PEERSTATE_SUCCESS = 1; - const PEERSTATE_LOADING = 2; - class EaglercraftLANPeer { constructor(client, peerId, peerConnection) { @@ -522,15 +463,13 @@ window.initializeLANServer = (() => { this.peerConnection = peerConnection; this.dataChannel = null; - const self = this; - const iceCandidates = []; this.peerConnection.addEventListener("icecandidate", (evt) => { if(evt.candidate) { - if(iceCandidates.length == 0) setTimeout(() => { - if(self.peerConnection != null && self.peerConnection.connectionState != "disconnected") { - self.client.iceCandidateHandler(self.peerId, JSON.stringify(iceCandidates)); + if(iceCandidates.length === 0) setTimeout(() => { + if(this.peerConnection !== null && this.peerConnection.connectionState !== "disconnected") { + this.client.iceCandidateHandler(this.peerId, JSON.stringify(iceCandidates)); iceCandidates.length = 0; } }, 3000); @@ -542,28 +481,23 @@ window.initializeLANServer = (() => { while(iceCandidates.length > 0) { await new Promise(resolve => setTimeout(resolve, 0)); } - self.dataChannel = evt.channel; - self.client.remoteClientDataChannelHandler(self.peerId, self.dataChannel); - self.dataChannel.addEventListener("message", (evt) => { - self.client.remoteClientPacketHandler(self.peerId, evt.data); + this.dataChannel = evt.channel; + this.client.remoteClientDataChannelHandler(this.peerId, this.dataChannel); + this.dataChannel.addEventListener("message", (evt) => { + this.client.remoteClientPacketHandler(this.peerId, evt.data); }, false); }, false); this.peerConnection.addEventListener("connectionstatechange", (evt) => { - if(self.peerConnection.connectionState === 'disconnected') { - self.client.signalRemoteDisconnect(self.peerId); - } else if (self.peerConnection.connectionState === 'connected') { - if (self.client.peerState != PEERSTATE_SUCCESS) self.client.peerState = PEERSTATE_SUCCESS; - } else if (self.peerConnection.connectionState === 'failed') { - if (self.client.peerState == PEERSTATE_LOADING) self.client.peerState = PEERSTATE_FAILED; - self.client.signalRemoteDisconnect(self.peerId); + if(this.peerConnection.connectionState === 'disconnected' || this.peerConnection.connectionState === 'failed') { + this.client.signalRemoteDisconnect(this.peerId); } }); } disconnect() { - if(this.dataChannel != null) { + if(this.dataChannel !== null) { this.dataChannel.close(); this.dataChannel = null; } @@ -571,36 +505,30 @@ window.initializeLANServer = (() => { } setRemoteDescription(descJSON) { - const self = this; try { const remoteDesc = JSON.parse(descJSON); this.peerConnection.setRemoteDescription(remoteDesc, () => { - if(remoteDesc.type == 'offer') { - self.peerConnection.createAnswer((desc) => { + if(remoteDesc.type === 'offer') { + this.peerConnection.createAnswer((desc) => { const selfDesc = desc; - self.peerConnection.setLocalDescription(selfDesc, () => { - self.client.descriptionHandler(self.peerId, JSON.stringify(selfDesc)); - if (self.client.peerStateDesc != PEERSTATE_SUCCESS) self.client.peerStateDesc = PEERSTATE_SUCCESS; + this.peerConnection.setLocalDescription(selfDesc, () => { + this.client.descriptionHandler(this.peerId, JSON.stringify(selfDesc)); }, (err) => { - console.error("Failed to set local description for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED; - self.client.signalRemoteDisconnect(self.peerId); + console.error("Failed to set local description for \"" + this.peerId + "\"! " + err); + this.client.signalRemoteDisconnect(this.peerId); }); }, (err) => { - console.error("Failed to create answer for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED; - self.client.signalRemoteDisconnect(self.peerId); + console.error("Failed to create answer for \"" + this.peerId + "\"! " + err); + this.client.signalRemoteDisconnect(this.peerId); }); } }, (err) => { - console.error("Failed to set remote description for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED; - self.client.signalRemoteDisconnect(self.peerId); + console.error("Failed to set remote description for \"" + this.peerId + "\"! " + err); + this.client.signalRemoteDisconnect(this.peerId); }); } catch (err) { - console.error("Failed to parse remote description for \"" + self.peerId + "\"! " + err); - if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED; - self.client.signalRemoteDisconnect(self.peerId); + console.error("Failed to parse remote description for \"" + this.peerId + "\"! " + err); + this.client.signalRemoteDisconnect(this.peerId); } } @@ -610,10 +538,8 @@ window.initializeLANServer = (() => { for (let candidate of candidateList) { this.peerConnection.addIceCandidate(new RTCIceCandidate(candidate)); } - if (this.client.peerStateIce != PEERSTATE_SUCCESS) this.client.peerStateIce = PEERSTATE_SUCCESS; } catch (err) { console.error("Failed to parse ice candidate for \"" + this.peerId + "\"! " + err); - if (this.client.peerStateIce == PEERSTATE_LOADING) this.client.peerStateIce = PEERSTATE_FAILED; this.client.signalRemoteDisconnect(this.peerId); } } @@ -626,11 +552,6 @@ window.initializeLANServer = (() => { this.ICEServers = []; this.hasInit = false; this.peerList = new Map(); - this.peerState = PEERSTATE_LOADING; - this.peerStateConnect = PEERSTATE_LOADING; - this.peerStateInitial = PEERSTATE_LOADING; - this.peerStateDesc = PEERSTATE_LOADING; - this.peerStateIce = PEERSTATE_LOADING; this.iceCandidateHandler = null; this.descriptionHandler = null; this.remoteClientDataChannelHandler = null; @@ -650,9 +571,9 @@ window.initializeLANServer = (() => { this.ICEServers.length = 0; for(var i = 0; i < urls.length; ++i) { var etr = urls[i].split(";"); - if(etr.length == 1) { + if(etr.length === 1) { this.ICEServers.push({ urls: etr[0] }); - }else if(etr.length == 3) { + }else if(etr.length === 3) { this.ICEServers.push({ urls: etr[0], username: etr[1], credential: etr[2] }); } } @@ -681,7 +602,7 @@ window.initializeLANServer = (() => { sendPacketToRemoteClient(peerId, buffer) { var thePeer = this.peerList.get(peerId); if((typeof thePeer !== "undefined") && thePeer !== null) { - if(thePeer.dataChannel != null && thePeer.dataChannel.readyState == "open") { + if(thePeer.dataChannel != null && thePeer.dataChannel.readyState === "open") { thePeer.dataChannel.send(buffer); }else { this.signalRemoteDisconnect(peerId); @@ -689,38 +610,12 @@ window.initializeLANServer = (() => { } } - resetPeerStates() { - this.peerState = this.peerStateConnect = this.peerStateInitial = this.peerStateDesc = this.peerStateIce = PEERSTATE_LOADING; - } - - getPeerState() { - return this.peerState; - } - - getPeerStateConnect() { - return this.peerStateConnect; - } - - getPeerStateInitial() { - return this.peerStateInitial; - } - - getPeerStateDesc() { - return this.peerStateDesc; - } - - getPeerStateIce() { - return this.peerStateIce; - } - signalRemoteConnect(peerId) { try { const peerConnection = new RTCPeerConnection({ iceServers: this.ICEServers, optional: [ { DtlsSrtpKeyAgreement: true } ] }); const peerInstance = new EaglercraftLANPeer(this, peerId, peerConnection); this.peerList.set(peerId, peerInstance); - if (this.peerStateConnect != PEERSTATE_SUCCESS) this.peerStateConnect = PEERSTATE_SUCCESS; } catch (e) { - if (this.peerStateConnect == PEERSTATE_LOADING) this.peerStateConnect = PEERSTATE_FAILED; } } @@ -739,7 +634,7 @@ window.initializeLANServer = (() => { } signalRemoteDisconnect(peerId) { - if(peerId.length == 0) { + if(peerId.length === 0) { for(const thePeer of this.peerList.values()) { if((typeof thePeer !== "undefined") && thePeer !== null) { this.peerList.delete(peerId); diff --git a/src/main/java/net/lax1dude/eaglercraft/IntegratedServerLAN.java b/src/main/java/net/lax1dude/eaglercraft/IntegratedServerLAN.java index 625d92d..62d4a2c 100644 --- a/src/main/java/net/lax1dude/eaglercraft/IntegratedServerLAN.java +++ b/src/main/java/net/lax1dude/eaglercraft/IntegratedServerLAN.java @@ -176,42 +176,33 @@ public class IntegratedServerLAN { } private static final class LANClient { - - private static final int PRE = 0, SENT_ICE_CANDIDATE = 2, SENT_DESCRIPTION = 3, CONNECTED = 4, CLOSED = 5; + + private static final int PRE = 0, RECEIVED_ICE_CANDIDATE = 1, SENT_ICE_CANDIDATE = 2, RECEIVED_DESCRIPTION = 3, + SENT_DESCRIPTION = 4, RECEIVED_SUCCESS = 5, CONNECTED = 6, CLOSED = 7; protected final String clientId; protected int state = PRE; protected boolean dead = false; + protected String localICECandidate = null; + protected final long startTime; protected LANClient(String clientId) { this.clientId = clientId; + this.startTime = EaglerAdapter.steadyTimeMillis(); EaglerAdapter.serverLANCreatePeer(clientId); } protected void handleICECandidates(String candidates) { if(state == SENT_DESCRIPTION) { EaglerAdapter.serverLANPeerICECandidates(clientId, candidates); - long millis = EaglerAdapter.steadyTimeMillis(); - do { - LANPeerEvent evt; - if((evt = EaglerAdapter.serverLANGetEvent(clientId)) != null) { - if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) { - lanRelaySocket.writePacket(new IPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates)); - state = SENT_ICE_CANDIDATE; - return; - }else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) { - System.err.println("LAN client '" + clientId + "' disconnected while waiting for server ICE candidates"); - }else { - System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName()); - } - disconnect(); - return; - } - EaglerAdapter.sleep(20); - }while(EaglerAdapter.steadyTimeMillis() - millis < 5000l); - System.err.println("Getting server ICE candidates for '" + clientId + "' timed out!"); - disconnect(); + if(localICECandidate != null) { + lanRelaySocket.writePacket(new IPacket03ICECandidate(clientId, localICECandidate)); + localICECandidate = null; + state = SENT_ICE_CANDIDATE; + }else { + state = RECEIVED_ICE_CANDIDATE; + } }else { System.err.println("Relay [" + lanRelaySocket.getURI() + "] unexpected IPacket03ICECandidate for '" + clientId + "'"); } @@ -220,26 +211,7 @@ public class IntegratedServerLAN { protected void handleDescription(String description) { if(state == PRE) { EaglerAdapter.serverLANPeerDescription(clientId, description); - long millis = EaglerAdapter.steadyTimeMillis(); - do { - LANPeerEvent evt; - if((evt = EaglerAdapter.serverLANGetEvent(clientId)) != null) { - if(evt instanceof LANPeerEvent.LANPeerDescriptionEvent) { - lanRelaySocket.writePacket(new IPacket04Description(clientId, ((LANPeerEvent.LANPeerDescriptionEvent)evt).description)); - state = SENT_DESCRIPTION; - return; - }else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) { - System.err.println("LAN client '" + clientId + "' disconnected while waiting for server description"); - }else { - System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName()); - } - disconnect(); - return; - } - EaglerAdapter.sleep(20); - }while(EaglerAdapter.steadyTimeMillis() - millis < 5000l); - System.err.println("Getting server description for '" + clientId + "' timed out!"); - disconnect(); + state = RECEIVED_DESCRIPTION; }else { System.err.println("Relay [" + lanRelaySocket.getURI() + "] unexpected IPacket04Description for '" + clientId + "'"); } @@ -247,30 +219,7 @@ public class IntegratedServerLAN { protected void handleSuccess() { if(state == SENT_ICE_CANDIDATE) { - long millis = EaglerAdapter.steadyTimeMillis(); - do { - LANPeerEvent evt; - while((evt = EaglerAdapter.serverLANGetEvent(clientId)) != null && evt instanceof LANPeerEvent.LANPeerICECandidateEvent) { - // skip ice candidates - } - if(evt != null) { - if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) { - EaglerAdapter.enableChannel("NET|" + clientId); - IntegratedServer.sendIPCPacket(new IPCPacket0CPlayerChannel(clientId, true)); - state = CONNECTED; - return; - }else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) { - System.err.println("LAN client '" + clientId + "' disconnected while waiting for connection"); - }else { - System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName()); - } - disconnect(); - return; - } - EaglerAdapter.sleep(20); - }while(EaglerAdapter.steadyTimeMillis() - millis < 5000l); - System.err.println("Getting server description for '" + clientId + "' timed out!"); - disconnect(); + state = RECEIVED_SUCCESS; }else { System.err.println("Relay [" + lanRelaySocket.getURI() + "] unexpected IPacket05ClientSuccess for '" + clientId + "'"); } @@ -286,23 +235,70 @@ public class IntegratedServerLAN { } protected void update() { - if(state == CONNECTED) { - PKT pk; - while(state == CONNECTED && (pk = EaglerAdapter.recieveFromIntegratedServer("NET|" + clientId)) != null) { - EaglerAdapter.serverLANWritePacket(clientId, pk.data); + if(state != CLOSED) { + if(state != CONNECTED && EaglerAdapter.steadyTimeMillis() - startTime > 13000l) { + System.out.println("LAN client '" + clientId + "' handshake timed out"); + disconnect(); + return; } - LANPeerEvent evt; - while(state == CONNECTED && (evt = EaglerAdapter.serverLANGetEvent(clientId)) != null) { - if(evt instanceof LANPeerEvent.LANPeerPacketEvent) { - EaglerAdapter.sendToIntegratedServer("NET|" + clientId, ((LANPeerEvent.LANPeerPacketEvent)evt).payload); - }else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) { + List l = EaglerAdapter.serverLANGetAllEvent(clientId); + if(l == null) { + return; + } + read_loop: for(int i = 0, s = l.size(); i < s; ++i) { + LANPeerEvent evt = l.get(i); + if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) { System.out.println("LAN client '" + clientId + "' disconnected"); disconnect(); }else { - System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName()); + switch(state) { + case SENT_DESCRIPTION:{ + if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) { + localICECandidate = ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates; + continue read_loop; + } + } + case RECEIVED_ICE_CANDIDATE: { + if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) { + lanRelaySocket.writePacket(new IPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates)); + state = SENT_ICE_CANDIDATE; + continue read_loop; + } + } + case RECEIVED_DESCRIPTION: { + if(evt instanceof LANPeerEvent.LANPeerDescriptionEvent) { + lanRelaySocket.writePacket(new IPacket04Description(clientId, ((LANPeerEvent.LANPeerDescriptionEvent)evt).description)); + state = SENT_DESCRIPTION; + continue read_loop; + } + } + case SENT_ICE_CANDIDATE: + case RECEIVED_SUCCESS: { + if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) { + EaglerAdapter.enableChannel("NET|" + clientId); + state = CONNECTED; + continue read_loop; + } + } + case CONNECTED: { + if(evt instanceof LANPeerEvent.LANPeerPacketEvent) { + EaglerAdapter.sendToIntegratedServer("NET|" + clientId, ((LANPeerEvent.LANPeerPacketEvent)evt).payload); + continue read_loop; + } + } + default: { + break; + } + } + if(state != CLOSED) { + System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName()); + } disconnect(); + return; } } + }else { + disconnect(); } } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java index a6b8e77..3c3a2b0 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/EaglerAdapterImpl2.java @@ -58,7 +58,6 @@ import org.teavm.jso.dom.html.HTMLVideoElement; import org.teavm.jso.media.MediaError; import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.DataView; -import org.teavm.jso.typedarrays.Float32Array; import org.teavm.jso.typedarrays.Int32Array; import org.teavm.jso.typedarrays.Uint8Array; import org.teavm.jso.typedarrays.Uint8ClampedArray; @@ -2632,7 +2631,6 @@ public class EaglerAdapterImpl2 { public static final void enableVoice(Voice.VoiceChannel enable) { if (enabledChannel == enable) return; - voiceClient.resetPeerStates(); if (enabledChannel == Voice.VoiceChannel.PROXIMITY) { for (String username : nearbyPlayers) voiceClient.signalDisconnect(username, false); for (String username : recentlyNearbyPlayers) voiceClient.signalDisconnect(username, false); @@ -2752,13 +2750,10 @@ public class EaglerAdapterImpl2 { public static final Voice.VoiceChannel getVoiceChannel() { return enabledChannel; } - public static final boolean voicePeerErrored() { - return voiceClient.getPeerState() == EaglercraftVoiceClient.PEERSTATE_FAILED || voiceClient.getPeerStateConnect() == EaglercraftVoiceClient.PEERSTATE_FAILED || voiceClient.getPeerStateInitial() == EaglercraftVoiceClient.PEERSTATE_FAILED || voiceClient.getPeerStateDesc() == EaglercraftVoiceClient.PEERSTATE_FAILED || voiceClient.getPeerStateIce() == EaglercraftVoiceClient.PEERSTATE_FAILED; - } public static final Voice.VoiceStatus getVoiceStatus() { return (!voiceAvailable() || !voiceAllowed()) ? Voice.VoiceStatus.UNAVAILABLE : (voiceClient.getReadyState() != EaglercraftVoiceClient.READYSTATE_DEVICE_INITIALIZED ? - Voice.VoiceStatus.CONNECTING : (voicePeerErrored() ? Voice.VoiceStatus.UNAVAILABLE : Voice.VoiceStatus.CONNECTED)); + Voice.VoiceStatus.CONNECTING : Voice.VoiceStatus.CONNECTED); } private static boolean talkStatus = false; @@ -4258,6 +4253,26 @@ public class EaglerAdapterImpl2 { return null; } } + + public static final List serverLANGetAllEvent(String clientId) { + if(serverLANEventBuffer.size() > 0) { + List lst = null; + Iterator i = serverLANEventBuffer.iterator(); + while(i.hasNext()) { + LANPeerEvent evt = i.next(); + if(evt.getPeerId().equals(clientId)) { + i.remove(); + if(lst == null) { + lst = new ArrayList<>(); + } + lst.add(evt); + } + } + return lst; + }else { + return null; + } + } private static final int fragmentSize = 65536; diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/EaglercraftLANServer.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/EaglercraftLANServer.java index a006ab9..06ca4fe 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/EaglercraftLANServer.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/EaglercraftLANServer.java @@ -6,10 +6,6 @@ import org.teavm.jso.typedarrays.ArrayBuffer; public interface EaglercraftLANServer extends JSObject { - final int PEERSTATE_FAILED = 0; - final int PEERSTATE_SUCCESS = 1; - final int PEERSTATE_LOADING = 2; - boolean LANServerSupported(); void initializeServer(); @@ -28,18 +24,6 @@ public interface EaglercraftLANServer extends JSObject { void sendPacketToRemoteClient(String peerId, ArrayBuffer buffer); - void resetPeerStates(); - - int getPeerState(); - - int getPeerStateConnect(); - - int getPeerStateInitial(); - - int getPeerStateDesc(); - - int getPeerStateIce(); - void signalRemoteConnect(String peerId); void signalRemoteDescription(String peerId, String descJSON); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/EaglercraftVoiceClient.java b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/EaglercraftVoiceClient.java index 17e6d83..cb2ba41 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/EaglercraftVoiceClient.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/adapter/teavm/EaglercraftVoiceClient.java @@ -10,10 +10,6 @@ public interface EaglercraftVoiceClient extends JSObject { int READYSTATE_ABORTED = -1; int READYSTATE_DEVICE_INITIALIZED = 1; - int PEERSTATE_FAILED = 0; - int PEERSTATE_SUCCESS = 1; - int PEERSTATE_LOADING = 2; - boolean voiceClientSupported(); void initializeDevices(); @@ -34,18 +30,6 @@ public interface EaglercraftVoiceClient extends JSObject { void mutePeer(String peerId, boolean muted); - void resetPeerStates(); - - int getPeerState(); - - int getPeerStateConnect(); - - int getPeerStateInitial(); - - int getPeerStateDesc(); - - int getPeerStateIce(); - int getReadyState(); int signalConnect(String peerId, boolean offer);