made most client relay handshake code
This commit is contained in:
parent
5eef920554
commit
caad879284
8 changed files with 369 additions and 21 deletions
|
@ -82,7 +82,7 @@ public class EaglerSPRelay extends WebSocketServer {
|
|||
Iterator<EaglerSPClient> itr = clientConnections.values().iterator();
|
||||
while(itr.hasNext()) {
|
||||
EaglerSPClient cl = itr.next();
|
||||
if(millis - cl.createdOn > 5000l) {
|
||||
if(millis - cl.createdOn > 6900l) {
|
||||
cl.disconnect(IPacketFEDisconnectClient.TYPE_TIMEOUT, "Took too long to connect!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket;
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket00Handshake;
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket01ICEServers;
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket03ICECandidate;
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket04Description;
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFFErrorCode;
|
||||
import net.minecraft.src.INetworkManager;
|
||||
import net.minecraft.src.LoadingScreenRenderer;
|
||||
import net.minecraft.src.NetHandler;
|
||||
import net.minecraft.src.Packet;
|
||||
|
||||
public class LANClientNetworkManager implements INetworkManager {
|
||||
|
||||
private static final int PRE = 0, INIT = 1, SENT_ICE_CANDIDATE = 2, SENT_DESCRIPTION = 3;
|
||||
|
||||
private static final String[] initStateNames = new String[] { "PRE", "INIT", "SENT_ICE_CANDIDATE", "SENT_DESCRIPTION" };
|
||||
|
||||
public final String displayCode;
|
||||
public final String displayRelay;
|
||||
|
||||
private LANClientNetworkManager(String displayCode, String displayRelay) {
|
||||
this.displayCode = displayCode;
|
||||
this.displayRelay = displayRelay;
|
||||
}
|
||||
|
||||
public static LANClientNetworkManager connectToWorld(RelayServerSocket sock, LoadingScreenRenderer loadingScreen,
|
||||
String displayCode, String displayRelay) {
|
||||
EaglerAdapter.clearLANClientState();
|
||||
loadingScreen.displayProgressMessage("Connecting to '" + displayCode + "' via " + displayRelay + "...");
|
||||
int connectState = -1;
|
||||
IPacket pkt;
|
||||
mainLoop: while(!sock.isClosed()) {
|
||||
if((pkt = sock.readPacket()) != null) {
|
||||
if(pkt instanceof IPacket00Handshake) {
|
||||
if(connectState == PRE) {
|
||||
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved handshake, "
|
||||
+ "client id: " + ((IPacket00Handshake)pkt).connectionCode);
|
||||
connectState = INIT;
|
||||
}else {
|
||||
sock.close();
|
||||
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: "
|
||||
+ "IPacket00Handshake in state " + initStateNames[connectState]);
|
||||
return null;
|
||||
}
|
||||
}else if(pkt instanceof IPacket01ICEServers) {
|
||||
if(connectState == INIT) {
|
||||
IPacket01ICEServers ipkt = (IPacket01ICEServers) pkt;
|
||||
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] provided ICE servers:");
|
||||
List<String> servers = new ArrayList();
|
||||
for(net.lax1dude.eaglercraft.sp.relay.pkt.ICEServerSet.RelayServer srv : ipkt.servers) {
|
||||
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] " + srv.type.name()
|
||||
+ ": " + srv.address);
|
||||
servers.add(srv.getICEString());
|
||||
}
|
||||
EaglerAdapter.clientLANSetICEServersAndConnect(servers.toArray(new String[servers.size()]));
|
||||
long lm = System.currentTimeMillis();
|
||||
do {
|
||||
String c = EaglerAdapter.clientLANAwaitICECandidate();
|
||||
if(c != null) {
|
||||
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] client sent ICE candidate");
|
||||
sock.writePacket(new IPacket03ICECandidate("", c));
|
||||
connectState = SENT_ICE_CANDIDATE;
|
||||
continue mainLoop;
|
||||
}
|
||||
}while(System.currentTimeMillis() - lm > 3000l);
|
||||
sock.close();
|
||||
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] client provide ICE candidate timeout");
|
||||
return null;
|
||||
}else {
|
||||
sock.close();
|
||||
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: "
|
||||
+ "IPacket01ICEServers in state " + initStateNames[connectState]);
|
||||
return null;
|
||||
}
|
||||
}else if(pkt instanceof IPacket03ICECandidate) {
|
||||
if(connectState == SENT_ICE_CANDIDATE) {
|
||||
IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt;
|
||||
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved server ICE candidate");
|
||||
EaglerAdapter.clientLANSetICECandidate(ipkt.candidate);
|
||||
long lm = System.currentTimeMillis();
|
||||
do {
|
||||
String c = EaglerAdapter.clientLANAwaitDescription();
|
||||
if(c != null) {
|
||||
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] client sent description");
|
||||
sock.writePacket(new IPacket04Description("", c));
|
||||
connectState = SENT_DESCRIPTION;
|
||||
continue mainLoop;
|
||||
}
|
||||
}while(System.currentTimeMillis() - lm > 3000l);
|
||||
sock.close();
|
||||
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] client provide description timeout");
|
||||
return null;
|
||||
}else {
|
||||
sock.close();
|
||||
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: "
|
||||
+ "IPacket03ICECandidate in state " + initStateNames[connectState]);
|
||||
return null;
|
||||
}
|
||||
}else if(pkt instanceof IPacket04Description) {
|
||||
if(connectState == SENT_DESCRIPTION) {
|
||||
IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt;
|
||||
System.out.println("Relay [" + displayRelay + "|" + displayCode + "] recieved server description");
|
||||
EaglerAdapter.clientLANSetDescription(ipkt.candidate);
|
||||
|
||||
// TODO: handle description, return packet 05 or 06
|
||||
|
||||
}else {
|
||||
sock.close();
|
||||
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] unexpected packet: "
|
||||
+ "IPacket04Description in state " + initStateNames[connectState]);
|
||||
return null;
|
||||
}
|
||||
}else if(pkt instanceof IPacketFFErrorCode) {
|
||||
IPacketFFErrorCode ipkt = (IPacketFFErrorCode) pkt;
|
||||
System.err.println("Relay [" + displayRelay + "|" + displayCode + "] connection failed: " +
|
||||
IPacketFFErrorCode.code2string(ipkt.code) + "(" + ipkt.code + "): " + ipkt.desc);
|
||||
Throwable t;
|
||||
while((t = sock.getException()) != null) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
sock.close();
|
||||
return null;
|
||||
}else {
|
||||
System.err.println("Relay [" + displayRelay + "] unexpected packet: " + pkt.getClass().getSimpleName());
|
||||
sock.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(20l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNetHandler(NetHandler var1) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addToSendQueue(Packet var1) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wakeThreads() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processReadPackets() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serverShutdown() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int packetSize() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void networkShutdown(String var1, Object... var2) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeConnections() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerURI() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,13 @@
|
|||
package net.lax1dude.eaglercraft;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket;
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacket00Handshake;
|
||||
import net.lax1dude.eaglercraft.sp.relay.pkt.IPacketFFErrorCode;
|
||||
import net.minecraft.src.NBTBase;
|
||||
import net.minecraft.src.NBTTagCompound;
|
||||
import net.minecraft.src.NBTTagList;
|
||||
|
@ -180,44 +184,100 @@ public class RelayManager {
|
|||
}
|
||||
}
|
||||
|
||||
public RelayServer getWorkingRelay(Consumer<String> progressCallback) {
|
||||
private RelayServerSocket connectHandshake(RelayServer relay, int type, String code) {
|
||||
RelayServerSocket sock = relay.openSocket();
|
||||
while(!sock.isClosed()) {
|
||||
if(sock.isOpen()) {
|
||||
sock.writePacket(new IPacket00Handshake(type, IntegratedServer.preferredRelayVersion, code));
|
||||
while(!sock.isClosed()) {
|
||||
IPacket pkt = sock.nextPacket();
|
||||
if(pkt != null) {
|
||||
if(pkt instanceof IPacket00Handshake) {
|
||||
return sock;
|
||||
}else if(pkt instanceof IPacketFFErrorCode) {
|
||||
IPacketFFErrorCode ipkt = (IPacketFFErrorCode) pkt;
|
||||
System.err.println("Relay [" + relay.address + "] failed: " + IPacketFFErrorCode.code2string(ipkt.code) +
|
||||
"(" + ipkt.code + "): " + ipkt.desc);
|
||||
Throwable t;
|
||||
while((t = sock.getException()) != null) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
sock.close();
|
||||
return null;
|
||||
}else {
|
||||
System.err.println("Relay [" + relay.address + "] unexpected packet: " + pkt.getClass().getSimpleName());
|
||||
sock.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(20l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(20l);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
System.err.println("Relay [" + relay.address + "] connection failed!");
|
||||
Throwable t;
|
||||
while((t = sock.getException()) != null) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final List<RelayServer> brokenServers = new LinkedList();
|
||||
|
||||
public RelayServerSocket getWorkingRelay(Consumer<String> progressCallback, int type, String code) {
|
||||
brokenServers.clear();
|
||||
if(relays.size() > 0) {
|
||||
long millis = System.currentTimeMillis();
|
||||
if(millis - lastPingThrough > 10000l) {
|
||||
if(millis - lastPingThrough < 10000l) {
|
||||
RelayServer relay = getPrimary();
|
||||
if(relay.getPing() > 0l && relay.getPingCompatible().isCompatible()) {
|
||||
return relay;
|
||||
progressCallback.accept(relay.address);
|
||||
RelayServerSocket sock = connectHandshake(relay, type, code);
|
||||
if(sock != null) {
|
||||
return sock;
|
||||
}else {
|
||||
brokenServers.add(relay);
|
||||
}
|
||||
}
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
RelayServer relayEtr = relays.get(i);
|
||||
if(relayEtr != relay) {
|
||||
if(relayEtr.getPing() > 0l && relayEtr.getPingCompatible().isCompatible()) {
|
||||
return relayEtr;
|
||||
progressCallback.accept(relayEtr.address);
|
||||
RelayServerSocket sock = connectHandshake(relayEtr, type, code);
|
||||
if(sock != null) {
|
||||
return sock;
|
||||
}else {
|
||||
brokenServers.add(relayEtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return getWorkingRelayActive(progressCallback);
|
||||
return getWorkingCodeRelayActive(progressCallback, type, code);
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private RelayServer getWorkingRelayActive(Consumer<String> progressCallback) {
|
||||
private RelayServerSocket getWorkingCodeRelayActive(Consumer<String> progressCallback, int type, String code) {
|
||||
if(relays.size() > 0) {
|
||||
RelayServer relay = getPrimary();
|
||||
progressCallback.accept(relay.address);
|
||||
relay.pingBlocking();
|
||||
if(relay.getPing() > 0l && relay.getPingCompatible().isCompatible()) {
|
||||
return relay;
|
||||
}
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
RelayServer relayEtr = relays.get(i);
|
||||
if(relayEtr != relay) {
|
||||
progressCallback.accept(relayEtr.address);
|
||||
relayEtr.pingBlocking();
|
||||
if(relayEtr.getPing() > 0l && relayEtr.getPingCompatible().isCompatible()) {
|
||||
return relayEtr;
|
||||
RelayServer srv = relays.get(i);
|
||||
if(!brokenServers.contains(srv)) {
|
||||
progressCallback.accept(srv.address);
|
||||
RelayServerSocket sock = connectHandshake(srv, type, code);
|
||||
if(sock != null) {
|
||||
return sock;
|
||||
}else {
|
||||
brokenServers.add(srv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ public class RelayServer {
|
|||
private VersionMismatch queriedCompatible;
|
||||
private long ping = 0l;
|
||||
private long workingPing = 0l;
|
||||
public long lastPing = 0l;
|
||||
|
||||
public RelayServer(String address, String comment, boolean primary) {
|
||||
this.address = address;
|
||||
|
@ -95,6 +96,7 @@ public class RelayServer {
|
|||
queriedCompatible = query.getCompatible();
|
||||
workingPing = ping;
|
||||
}
|
||||
lastPing = System.currentTimeMillis();
|
||||
query = null;
|
||||
}
|
||||
}
|
||||
|
@ -111,4 +113,8 @@ public class RelayServer {
|
|||
}
|
||||
}
|
||||
|
||||
public RelayServerSocket openSocket() {
|
||||
return EaglerAdapter.openRelayConnection(address);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ public interface RelayServerSocket {
|
|||
void writePacket(IPacket pkt);
|
||||
|
||||
IPacket readPacket();
|
||||
IPacket nextPacket();
|
||||
|
||||
RateLimit getRatelimitHistory();
|
||||
|
||||
|
|
|
@ -26,6 +26,16 @@ public class ICEServerSet {
|
|||
this.username = null;
|
||||
this.password = null;
|
||||
}
|
||||
|
||||
public String getICEString() {
|
||||
if(type == RelayType.STUN) {
|
||||
return address;
|
||||
}else if(type == RelayType.TURN) {
|
||||
return address + ";" + username + ";" + password;
|
||||
}else {
|
||||
throw new IllegalStateException("Unknown relay type: " + (type == null ? "null" : type.name()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,27 @@ public class IPacketFFErrorCode extends IPacket {
|
|||
public static final int TYPE_SERVER_DISCONNECTED = 0x06;
|
||||
public static final int TYPE_UNKNOWN_CLIENT = 0x07;
|
||||
|
||||
public static final String[] packetTypes = new String[0x08];
|
||||
|
||||
static {
|
||||
packetTypes[TYPE_INTERNAL_ERROR] = "TYPE_INTERNAL_ERROR";
|
||||
packetTypes[TYPE_PROTOCOL_VERSION] = "TYPE_PROTOCOL_VERSION";
|
||||
packetTypes[TYPE_INVALID_PACKET] = "TYPE_INVALID_PACKET";
|
||||
packetTypes[TYPE_ILLEGAL_OPERATION] = "TYPE_ILLEGAL_OPERATION";
|
||||
packetTypes[TYPE_CODE_LENGTH] = "TYPE_CODE_LENGTH";
|
||||
packetTypes[TYPE_INCORRECT_CODE] = "TYPE_INCORRECT_CODE";
|
||||
packetTypes[TYPE_SERVER_DISCONNECTED] = "TYPE_SERVER_DISCONNECTED";
|
||||
packetTypes[TYPE_UNKNOWN_CLIENT] = "TYPE_UNKNOWN_CLIENT";
|
||||
}
|
||||
|
||||
public static String code2string(int i) {
|
||||
if(i >= 0 || i < packetTypes.length) {
|
||||
return packetTypes[i];
|
||||
}else {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
public int code;
|
||||
public String desc;
|
||||
|
||||
|
|
|
@ -3578,6 +3578,15 @@ public class EaglerAdapterImpl2 {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket nextPacket() {
|
||||
if(packets.size() > 0) {
|
||||
return packets.get(0);
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RateLimit getRatelimitHistory() {
|
||||
|
@ -3632,6 +3641,11 @@ public class EaglerAdapterImpl2 {
|
|||
public IPacket readPacket() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPacket nextPacket() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RateLimit getRatelimitHistory() {
|
||||
|
@ -3670,6 +3684,9 @@ public class EaglerAdapterImpl2 {
|
|||
public static final int LAN_CLIENT_CONNECTING = 1;
|
||||
public static final int LAN_CLIENT_CONNECTED = 2;
|
||||
|
||||
private static String clientICECandidate = null;
|
||||
private static String clientDescription = null;
|
||||
|
||||
public static final boolean clientLANSupported() {
|
||||
return rtcLANClient.LANClientSupported();
|
||||
}
|
||||
|
@ -3680,13 +3697,13 @@ public class EaglerAdapterImpl2 {
|
|||
rtcLANClient.setDescriptionHandler(new EaglercraftLANClient.DescriptionHandler() {
|
||||
@Override
|
||||
public void call(String description) {
|
||||
|
||||
clientDescription = description;
|
||||
}
|
||||
});
|
||||
rtcLANClient.setICECandidateHandler(new EaglercraftLANClient.ICECandidateHandler() {
|
||||
@Override
|
||||
public void call(String candidate) {
|
||||
|
||||
clientICECandidate = candidate;
|
||||
}
|
||||
});
|
||||
rtcLANClient.setRemoteDataChannelHandler(new EaglercraftLANClient.ClientSignalHandler() {
|
||||
|
@ -3734,6 +3751,43 @@ public class EaglerAdapterImpl2 {
|
|||
return clientLANPacketBuffer.size() > 0 ? clientLANPacketBuffer.remove(0) : null;
|
||||
}
|
||||
|
||||
public static final void clientLANSetICEServersAndConnect(String[] servers) {
|
||||
rtcLANClient.setICEServers(servers);
|
||||
}
|
||||
|
||||
public static final void clearLANClientState() {
|
||||
clientICECandidate = null;
|
||||
clientDescription = null;
|
||||
}
|
||||
|
||||
public static final String clientLANAwaitICECandidate() {
|
||||
if(clientICECandidate != null) {
|
||||
String ret = clientICECandidate;
|
||||
clientICECandidate = null;
|
||||
return ret;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String clientLANAwaitDescription() {
|
||||
if(clientDescription != null) {
|
||||
String ret = clientDescription;
|
||||
clientDescription = null;
|
||||
return ret;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final void clientLANSetICECandidate(String candidate) {
|
||||
rtcLANClient.signalRemoteICECandidate(candidate);
|
||||
}
|
||||
|
||||
public static final void clientLANSetDescription(String description) {
|
||||
rtcLANClient.signalRemoteDescription(description);
|
||||
}
|
||||
|
||||
private static EaglercraftLANServer rtcLANServer = null;
|
||||
|
||||
@JSBody(params = { }, script = "return window.startLANServer();")
|
||||
|
|
Loading…
Reference in a new issue