diff --git a/moonlight-common/src/com/limelight/nvstream/control/ControlStream.java b/moonlight-common/src/com/limelight/nvstream/control/ControlStream.java index ed5020f9..6fe33c4d 100644 --- a/moonlight-common/src/com/limelight/nvstream/control/ControlStream.java +++ b/moonlight-common/src/com/limelight/nvstream/control/ControlStream.java @@ -186,6 +186,7 @@ public class ControlStream implements ConnectionStatusListener, InputPacketSende // Prevent multiple clients from writing to the stream at the same time synchronized (this) { if (context.serverGeneration >= ConnectionContext.SERVER_GENERATION_5) { + enetConnection.pumpSocket(); packet.write(enetConnection); } else { @@ -200,7 +201,7 @@ public class ControlStream implements ConnectionStatusListener, InputPacketSende synchronized (this) { sendPacket(packet); if (context.serverGeneration >= ConnectionContext.SERVER_GENERATION_5) { - enetConnection.readPacket(128, CONTROL_TIMEOUT); + enetConnection.readPacket(0, CONTROL_TIMEOUT); } else { new NvCtlResponse(in); @@ -574,8 +575,10 @@ public class ControlStream implements ConnectionStatusListener, InputPacketSende // Use the class's serialization buffer to construct the wireform to send synchronized (serializationBuffer) { serializationBuffer.rewind(); + serializationBuffer.limit(serializationBuffer.capacity()); serializationBuffer.putShort(type); serializationBuffer.put(payload); + serializationBuffer.limit(serializationBuffer.position()); conn.writePacket(serializationBuffer); } diff --git a/moonlight-common/src/com/limelight/nvstream/enet/EnetConnection.java b/moonlight-common/src/com/limelight/nvstream/enet/EnetConnection.java index b49368d6..0cf4f63f 100644 --- a/moonlight-common/src/com/limelight/nvstream/enet/EnetConnection.java +++ b/moonlight-common/src/com/limelight/nvstream/enet/EnetConnection.java @@ -37,21 +37,54 @@ public class EnetConnection implements Closeable { return conn; } + public void pumpSocket() throws IOException { + int ret; + while ((ret = readPacket(enetClient, null, 0, 0)) > 0); + if (ret < 0) { + throw new IOException("ENet connection failed"); + } + } + public ByteBuffer readPacket(int maxSize, int timeout) throws IOException { - ByteBuffer buffer = ByteBuffer.allocate(maxSize); + ByteBuffer buffer; + byte[] array; + int length; - int readLength = readPacket(enetClient, buffer.array(), buffer.limit(), timeout); - if (readLength <= 0) { - throw new IOException("Failed to receive ENet packet"); + if (maxSize != 0) { + buffer = ByteBuffer.allocate(maxSize); + array = buffer.array(); + length = buffer.limit(); + } + else { + // The caller doesn't want the packet back + buffer = null; + array = null; + length = 0; } - buffer.limit(readLength); - - return buffer; + int readLength = readPacket(enetClient, array, length, timeout); + if (readLength > length && length != 0) { + // This is a packet that was unexpectedly large compared to + // what the caller was expected. + throw new IOException("Received ENet packet too large: "+readLength); + } + else if (readLength <= 0) { + // We either got nothing or a socket error + throw new IOException("Failed to receive ENet packet"); + } + else if (length == 0) { + // We received a packet but the caller didn't want it back + return null; + } + else { + // A packet was received which matched the caller's expectations + buffer.limit(readLength); + return buffer; + } } public void writePacket(ByteBuffer buffer) throws IOException { - if (!writePacket(enetClient, enetPeer, buffer.array(), buffer.position(), ENET_PACKET_FLAG_RELIABLE)) { + if (!writePacket(enetClient, enetPeer, buffer.array(), buffer.limit(), ENET_PACKET_FLAG_RELIABLE)) { throw new IOException("Failed to send ENet packet"); } }