void ReceiveCallback(IAsyncResult ar) { PacketState state = null; try { int bytesreceived = rconSocket.EndReceive(ar); state = (PacketState)ar.AsyncState; state.BytesSoFar += bytesreceived; #if DEBUG Console.WriteLine("Receive Callback. Packet: {0} First packet: {1}, Bytes so far: {2}", state.PacketCount, state.IsPacketLength, state.BytesSoFar); #endif // Spin the processing of this data off into another thread. ThreadPool.QueueUserWorkItem((object pool_state) => { ProcessIncomingData(state); }); } catch (SocketException se) { OnError(MessageCode.ConnectionClosed, se.Message); Disconnect(); } catch (ObjectDisposedException ode) { OnError(MessageCode.AlreadyDisposed, ode.Message); } }
void GetNewPacketFromServer() { // Prepare the state information for a new packet. PacketState state = new PacketState(); state.IsPacketLength = true; state.Data = new byte[4]; state.PacketCount = PacketCount; PacketCount++; // If we're debugging, log the packetstate. // Can use this to trace the packets later. #if DEBUG TempPackets.Add(state); #endif try { rconSocket.BeginReceive(state.Data, 0, 4, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); } catch (SocketException se) { OnError(MessageCode.ConnectionFailed, se.Message); Disconnect(); } }
void StartToReceive(PacketState state) { try { rconSocket.BeginReceive(state.Data, state.BytesSoFar, state.PacketLength - state.BytesSoFar, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); } catch (SocketException se) { OnError(MessageCode.ConnectionClosed, se.Message); Disconnect(); } }
void ProcessIncomingData(PacketState state) { if (state.IsPacketLength) { // First 4 bytes of a new packet. state.PacketLength = BitConverter.ToInt32(state.Data, 0); state.IsPacketLength = false; state.BytesSoFar = 0; state.Data = new byte[state.PacketLength]; if (state.PacketLength > 0) { StartToReceive(state); } else { OnError(MessageCode.EmptyPacket, null); // Treat as a fatal error? Disconnect(); } } else { // This is a fragment of a complete packet. if (state.BytesSoFar < state.PacketLength) { // We don't have all the data, ask the network for the rest. StartToReceive(state); } else { // This is the whole packet, so we can go ahead and pack it up into a structure and then punt it upstairs. #if DEBUG Console.WriteLine("Complete packet."); #endif RCONPacket ReturnedPacket = new RCONPacket(); ReturnedPacket.ParseFromBytes(state.Data, this); ThreadPool.QueueUserWorkItem((object pool_state) => { ProcessResponse(ReturnedPacket); }); // Wait for new packet. GetNewPacketFromServer(); } } }