added a "LANClientNetworkManager"

This commit is contained in:
LAX1DUDE 2022-08-16 23:05:42 -07:00
parent caad879284
commit b70eb6bdc6
3 changed files with 153 additions and 26 deletions

View File

@ -398,6 +398,9 @@ window.initializeLANClient = (() => {
signalRemoteConnect() { signalRemoteConnect() {
const self = this; const self = this;
if(self.readyState === READYSTATE_CONNECTED || self.readyState === READYSTATE_CONNECTING) {
signalRemoteDisconnect();
}
this.peerConnection.addEventListener("icecandidate", (evt) => { this.peerConnection.addEventListener("icecandidate", (evt) => {
if(evt.candidate) { if(evt.candidate) {
self.iceCandidateHandler(JSON.stringify({ sdpMLineIndex: evt.candidate.sdpMLineIndex, candidate: evt.candidate.candidate })); self.iceCandidateHandler(JSON.stringify({ sdpMLineIndex: evt.candidate.sdpMLineIndex, candidate: evt.candidate.candidate }));

View File

@ -1,5 +1,10 @@
package net.lax1dude.eaglercraft; package net.lax1dude.eaglercraft;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -8,9 +13,10 @@ import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket00Handshake;
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket01ICEServers; import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket01ICEServers;
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket03ICECandidate; import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket03ICECandidate;
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket04Description; import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket04Description;
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket05ClientSuccess;
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket06ClientFailure;
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFFErrorCode; import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFFErrorCode;
import net.minecraft.src.INetworkManager; import net.minecraft.src.INetworkManager;
import net.minecraft.src.LoadingScreenRenderer;
import net.minecraft.src.NetHandler; import net.minecraft.src.NetHandler;
import net.minecraft.src.Packet; import net.minecraft.src.Packet;
@ -23,24 +29,29 @@ public class LANClientNetworkManager implements INetworkManager {
public final String displayCode; public final String displayCode;
public final String displayRelay; public final String displayRelay;
private NetHandler theNetHandler;
private LANClientNetworkManager(String displayCode, String displayRelay) { private LANClientNetworkManager(String displayCode, String displayRelay) {
this.displayCode = displayCode; this.displayCode = displayCode;
this.displayRelay = displayRelay; this.displayRelay = displayRelay;
this.theNetHandler = null;
} }
public static LANClientNetworkManager connectToWorld(RelayServerSocket sock, LoadingScreenRenderer loadingScreen, public static LANClientNetworkManager connectToWorld(RelayServerSocket sock, String displayCode, String displayRelay) {
String displayCode, String displayRelay) {
EaglerAdapter.clearLANClientState(); EaglerAdapter.clearLANClientState();
loadingScreen.displayProgressMessage("Connecting to '" + displayCode + "' via " + displayRelay + "...");
int connectState = -1; int connectState = -1;
IPacket pkt; IPacket pkt;
mainLoop: while(!sock.isClosed()) { mainLoop: while(!sock.isClosed()) {
if((pkt = sock.readPacket()) != null) { if((pkt = sock.readPacket()) != null) {
if(pkt instanceof IPacket00Handshake) { if(pkt instanceof IPacket00Handshake) {
if(connectState == PRE) { if(connectState == PRE) {
// %%%%%% Process IPacket00Handshake %%%%%%
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved handshake, " System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved handshake, "
+ "client id: " + ((IPacket00Handshake)pkt).connectionCode); + "client id: " + ((IPacket00Handshake)pkt).connectionCode);
connectState = INIT; connectState = INIT;
}else { }else {
sock.close(); sock.close();
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: " System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: "
@ -49,7 +60,12 @@ public class LANClientNetworkManager implements INetworkManager {
} }
}else if(pkt instanceof IPacket01ICEServers) { }else if(pkt instanceof IPacket01ICEServers) {
if(connectState == INIT) { if(connectState == INIT) {
// %%%%%% Process IPacket01ICEServers %%%%%%
IPacket01ICEServers ipkt = (IPacket01ICEServers) pkt; IPacket01ICEServers ipkt = (IPacket01ICEServers) pkt;
// print servers
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] provided ICE servers:"); System.out.println("Relay [" + displayRelay + "|" + displayCode + "] provided ICE servers:");
List<String> servers = new ArrayList(); List<String> servers = new ArrayList();
for(net.lax1dude.eaglercraft.sp.relay.pkt.ICEServerSet.RelayServer srv : ipkt.servers) { for(net.lax1dude.eaglercraft.sp.relay.pkt.ICEServerSet.RelayServer srv : ipkt.servers) {
@ -57,20 +73,30 @@ public class LANClientNetworkManager implements INetworkManager {
+ ": " + srv.address); + ": " + srv.address);
servers.add(srv.getICEString()); servers.add(srv.getICEString());
} }
// process
EaglerAdapter.clientLANSetICEServersAndConnect(servers.toArray(new String[servers.size()])); EaglerAdapter.clientLANSetICEServersAndConnect(servers.toArray(new String[servers.size()]));
// await result
long lm = System.currentTimeMillis(); long lm = System.currentTimeMillis();
do { do {
String c = EaglerAdapter.clientLANAwaitICECandidate(); String c = EaglerAdapter.clientLANAwaitICECandidate();
if(c != null) { if(c != null) {
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] client sent ICE candidate"); System.out.println("Relay [" + displayRelay + "|" + displayCode + "] client sent ICE candidate");
// 'this.iceCandidateHandler' was called, send result:
sock.writePacket(new IPacket03ICECandidate("", c)); sock.writePacket(new IPacket03ICECandidate("", c));
connectState = SENT_ICE_CANDIDATE; connectState = SENT_ICE_CANDIDATE;
continue mainLoop; continue mainLoop;
} }
}while(System.currentTimeMillis() - lm > 3000l); }while(System.currentTimeMillis() - lm > 3000l);
// no ice candidates were sent
sock.close(); sock.close();
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] client provide ICE candidate timeout"); System.err.println("Relay [" + displayRelay + "|" + displayCode + "] client provide ICE candidate timeout");
return null; return null;
}else { }else {
sock.close(); sock.close();
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: " System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: "
@ -79,22 +105,35 @@ public class LANClientNetworkManager implements INetworkManager {
} }
}else if(pkt instanceof IPacket03ICECandidate) { }else if(pkt instanceof IPacket03ICECandidate) {
if(connectState == SENT_ICE_CANDIDATE) { if(connectState == SENT_ICE_CANDIDATE) {
// %%%%%% Process IPacket03ICECandidate %%%%%%
IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt; IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt;
// process
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved server ICE candidate"); System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved server ICE candidate");
EaglerAdapter.clientLANSetICECandidate(ipkt.candidate); EaglerAdapter.clientLANSetICECandidate(ipkt.candidate);
// await result
long lm = System.currentTimeMillis(); long lm = System.currentTimeMillis();
do { do {
String c = EaglerAdapter.clientLANAwaitDescription(); String c = EaglerAdapter.clientLANAwaitDescription();
if(c != null) { if(c != null) {
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] client sent description"); System.out.println("Relay [" + displayRelay + "|" + displayCode + "] client sent description");
// 'this.descriptionHandler' was called, send result:
sock.writePacket(new IPacket04Description("", c)); sock.writePacket(new IPacket04Description("", c));
connectState = SENT_DESCRIPTION; connectState = SENT_DESCRIPTION;
continue mainLoop; continue mainLoop;
} }
}while(System.currentTimeMillis() - lm > 3000l); }while(System.currentTimeMillis() - lm > 3000l);
// no description was sent
sock.close(); sock.close();
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] client provide description timeout"); System.err.println("Relay [" + displayRelay + "|" + displayCode + "] client provide description timeout");
return null; return null;
}else { }else {
sock.close(); sock.close();
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: " System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: "
@ -103,11 +142,35 @@ public class LANClientNetworkManager implements INetworkManager {
} }
}else if(pkt instanceof IPacket04Description) { }else if(pkt instanceof IPacket04Description) {
if(connectState == SENT_DESCRIPTION) { if(connectState == SENT_DESCRIPTION) {
// %%%%%% Process IPacket04Description %%%%%%
IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt; IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt;
// process
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved server description"); System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved server description");
EaglerAdapter.clientLANSetDescription(ipkt.candidate); EaglerAdapter.clientLANSetDescription(ipkt.candidate);
// await result
long lm = System.currentTimeMillis();
do {
if(EaglerAdapter.clientLANAwaitChannel()) {
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] client opened data channel");
// 'this.remoteDataChannelHandler' was called, success
sock.writePacket(new IPacket05ClientSuccess());
sock.close();
return new LANClientNetworkManager(displayCode, displayRelay);
}
}while(System.currentTimeMillis() - lm > 3000l);
// TODO: handle description, return packet 05 or 06 // no channel was opened
sock.writePacket(new IPacket06ClientFailure());
sock.close();
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] client open data channel timeout");
return null;
}else { }else {
sock.close(); sock.close();
@ -116,6 +179,9 @@ public class LANClientNetworkManager implements INetworkManager {
return null; return null;
} }
}else if(pkt instanceof IPacketFFErrorCode) { }else if(pkt instanceof IPacketFFErrorCode) {
// %%%%%% Process IPacketFFErrorCode %%%%%%
IPacketFFErrorCode ipkt = (IPacketFFErrorCode) pkt; IPacketFFErrorCode ipkt = (IPacketFFErrorCode) pkt;
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] connection failed: " + System.err.println("Relay [" + displayRelay + "|" + displayCode + "] connection failed: " +
IPacketFFErrorCode.code2string(ipkt.code) + "(" + ipkt.code + "): " + ipkt.desc); IPacketFFErrorCode.code2string(ipkt.code) + "(" + ipkt.code + "): " + ipkt.desc);
@ -125,7 +191,11 @@ public class LANClientNetworkManager implements INetworkManager {
} }
sock.close(); sock.close();
return null; return null;
}else { }else {
// %%%%%% Unexpected Packet %%%%%%
System.err.println("Relay [" + displayRelay + "] unexpected packet: " + pkt.getClass().getSimpleName()); System.err.println("Relay [" + displayRelay + "] unexpected packet: " + pkt.getClass().getSimpleName());
sock.close(); sock.close();
return null; return null;
@ -141,56 +211,92 @@ public class LANClientNetworkManager implements INetworkManager {
@Override @Override
public void setNetHandler(NetHandler var1) { public void setNetHandler(NetHandler var1) {
// TODO Auto-generated method stub theNetHandler = var1;
} }
@Override @Override
public void addToSendQueue(Packet var1) { public void addToSendQueue(Packet var1) {
// TODO Auto-generated method stub try {
ByteArrayOutputStream bao = new ByteArrayOutputStream(var1.getPacketSize() + 1);
Packet.writePacket(var1, new DataOutputStream(bao));
EaglerAdapter.clientLANSendPacket(bao.toByteArray());
}catch(IOException e) {
System.err.println("Failed to serialize minecraft packet '" + var1.getClass().getSimpleName() + "' to remote LAN world");
e.printStackTrace();
}
} }
@Override @Override
public void wakeThreads() { public void wakeThreads() {
// TODO Auto-generated method stub // no
} }
@Override @Override
public void processReadPackets() { public void processReadPackets() {
// TODO Auto-generated method stub if(this.theNetHandler != null) {
byte[] data;
while((data = EaglerAdapter.clientLANReadPacket()) != null) {
try {
ByteArrayInputStream bai = new ByteArrayInputStream(data);
int pktId = bai.read();
if(pktId == -1) {
System.err.println("Recieved invalid '-1' packet");
continue;
}
Packet pkt = Packet.getNewPacket(pktId);
if(pkt == null) {
System.err.println("Recieved invalid '" + pktId + "' packet");
continue;
}
pkt.readPacketData(new DataInputStream(bai));
try {
pkt.processPacket(theNetHandler);
}catch(Throwable t) {
System.err.println("Could not process minecraft packet 0x" + Integer.toHexString(pkt.getPacketId()) + " class '" + pkt.getClass().getSimpleName() + "' from remote LAN world");
t.printStackTrace();
}
}catch(IOException ex) {
System.err.println("Could not deserialize a " + data.length + " byte long minecraft packet of type '" + (data.length <= 0 ? -1 : (int)(data[0] & 0xFF)) + "' from remote LAN world");
}
}
}
} }
@Override @Override
public void serverShutdown() { public void serverShutdown() {
// TODO Auto-generated method stub if(!EaglerAdapter.clientLANClosed()) {
EaglerAdapter.clientLANCloseConnection();
}
} }
@Override @Override
public int packetSize() { public int packetSize() {
// TODO Auto-generated method stub
return 0; return 0;
} }
@Override @Override
public void networkShutdown(String var1, Object... var2) { public void networkShutdown(String var1, Object... var2) {
// TODO Auto-generated method stub if(!EaglerAdapter.clientLANClosed()) {
EaglerAdapter.clientLANCloseConnection();
}
} }
@Override @Override
public void closeConnections() { public void closeConnections() {
// TODO Auto-generated method stub if(!EaglerAdapter.clientLANClosed()) {
EaglerAdapter.clientLANCloseConnection();
}
} }
@Override @Override
public String getServerURI() { public String getServerURI() {
// TODO Auto-generated method stub return "[lan:" + displayRelay + ":" + displayCode + "]";
return null;
} }
} }

View File

@ -3686,6 +3686,8 @@ public class EaglerAdapterImpl2 {
private static String clientICECandidate = null; private static String clientICECandidate = null;
private static String clientDescription = null; private static String clientDescription = null;
private static boolean clientDataChannelOpen = false;
private static boolean clientDataChannelClosed = false;
public static final boolean clientLANSupported() { public static final boolean clientLANSupported() {
return rtcLANClient.LANClientSupported(); return rtcLANClient.LANClientSupported();
@ -3709,7 +3711,7 @@ public class EaglerAdapterImpl2 {
rtcLANClient.setRemoteDataChannelHandler(new EaglercraftLANClient.ClientSignalHandler() { rtcLANClient.setRemoteDataChannelHandler(new EaglercraftLANClient.ClientSignalHandler() {
@Override @Override
public void call() { public void call() {
// basically useless, ignore for now. clientDataChannelOpen = true;
} }
}); });
rtcLANClient.setRemotePacketHandler(new EaglercraftLANClient.RemotePacketHandler() { rtcLANClient.setRemotePacketHandler(new EaglercraftLANClient.RemotePacketHandler() {
@ -3726,7 +3728,7 @@ public class EaglerAdapterImpl2 {
rtcLANClient.setRemoteDisconnectHandler(new EaglercraftLANClient.ClientSignalHandler() { rtcLANClient.setRemoteDisconnectHandler(new EaglercraftLANClient.ClientSignalHandler() {
@Override @Override
public void call() { public void call() {
// disconnected clientDataChannelClosed = true;
} }
}); });
} }
@ -3753,11 +3755,14 @@ public class EaglerAdapterImpl2 {
public static final void clientLANSetICEServersAndConnect(String[] servers) { public static final void clientLANSetICEServersAndConnect(String[] servers) {
rtcLANClient.setICEServers(servers); rtcLANClient.setICEServers(servers);
rtcLANClient.signalRemoteConnect();
} }
public static final void clearLANClientState() { public static final void clearLANClientState() {
clientICECandidate = null; clientICECandidate = null;
clientDescription = null; clientDescription = null;
clientDataChannelOpen = false;
clientDataChannelClosed = false;
} }
public static final String clientLANAwaitICECandidate() { public static final String clientLANAwaitICECandidate() {
@ -3780,6 +3785,19 @@ public class EaglerAdapterImpl2 {
} }
} }
public static final boolean clientLANAwaitChannel() {
if(clientDataChannelOpen) {
clientDataChannelOpen = false;
return true;
}else {
return false;
}
}
public static final boolean clientLANClosed() {
return clientDataChannelClosed;
}
public static final void clientLANSetICECandidate(String candidate) { public static final void clientLANSetICECandidate(String candidate) {
rtcLANClient.signalRemoteICECandidate(candidate); rtcLANClient.signalRemoteICECandidate(candidate);
} }
@ -3842,7 +3860,7 @@ public class EaglerAdapterImpl2 {
rtcLANServer.setRemoteClientDisconnectHandler(new EaglercraftLANServer.ClientSignalHandler() { rtcLANServer.setRemoteClientDisconnectHandler(new EaglercraftLANServer.ClientSignalHandler() {
@Override @Override
public void call() { public void call() {
// disconnected clientDataChannelClosed = true;
} }
}); });
} }