/// <summary> /// Event called whenever raw data is received on the TCP socket. /// </summary> private void TCPPacketReceived(object sender, SocketAsyncEventArgs e) { // Parse out the actual RCON packet RCONPacket packet = RCONPacket.FromBytes(e.Buffer); if (packet.Type == PacketType.AuthResponse) { // Failed auth responses return with an ID of -1 if (packet.Id == -1) { throw new AuthenticationException($"Authentication failed for {_tcp.RemoteEndPoint}."); } // Tell Connect that authentication succeeded _authenticationTask.SetResult(true); } // Forward to handler RCONPacketReceived(packet); // Continue listening if (!_connected) { return; } _tcp.ReceiveAsync(e); }
/// <summary> /// Event called whenever raw data is received on the TCP socket. /// </summary> private void TCPPacketReceived(object sender, SocketAsyncEventArgs e) { // Parse out the actual RCON packet RCONPacket packet = null; try { packet = RCONPacket.FromBytes(e.Buffer); } catch (Exception exception) { Console.WriteLine("Unable to read packet, this has been observed when trying to communicate" + " with a server that is currently booting.\n" + exception.Message); Dispose(); return; } if (packet.Type == PacketType.AuthResponse) { // Failed auth responses return with an ID of -1 if (packet.Id == -1) { Console.WriteLine($"Authentication failed for {_tcp.RemoteEndPoint}."); Dispose(); return; } // Tell Connect that authentication succeeded try { _authenticationTask.SetResult(true); } catch { Console.WriteLine("Failure setting authentication task - disposing"); Dispose(); return; } } // Forward to handler RCONPacketReceived(packet); // Continue listening if (!_connected) { return; } _tcp.ReceiveAsync(e); }
/// <summary> /// Event called whenever raw data is received on the TCP socket. /// </summary> private void TCPPacketReceived(object sender, SocketAsyncEventArgs e) { int size = BitConverter.ToInt32(e.Buffer, 0) + 4; if (size > e.Buffer.Length) { throw new OverflowException($"RCON message {size} bytes is larger than TCP buffer {e.Buffer.Length} bytes"); } if (e.BytesTransferred + e.Offset < size) { // need more data, put e back for another go... e.SetBuffer(e.Offset + e.BytesTransferred, size - (e.Offset + e.BytesTransferred)); if (!_connected) { return; } _tcp.ReceiveAsync(e); } else { // Parse out the actual RCON packet RCONPacket packet = RCONPacket.FromBytes(e.Buffer); if (packet.Type == PacketType.AuthResponse) { // Failed auth responses return with an ID of -1 if (packet.Id == -1) { throw new AuthenticationException($"Authentication failed for {_tcp.RemoteEndPoint}."); } // Tell Connect that authentication succeeded _authenticationTask.SetResult(true); } // Forward to handler RCONPacketReceived(packet); // Continue listening if (!_connected) { return; } e.SetBuffer(0, 4); _tcp.ReceiveAsync(e); } }
/// <summary> /// Read data from pipeline when available, constructing new RCON packets /// </summary> /// <param name="reader"></param> /// <returns>Consumer Task</returns> async Task ReadPipeAsync(PipeReader reader) { byte[] byteArr = new byte[Constants.MAX_PACKET_SIZE]; while (true) { ReadResult result = await reader.ReadAsync(); ReadOnlySequence <byte> buffer = result.Buffer; SequencePosition packetStart = buffer.Start; if (buffer.Length < 4) { if (result.IsCompleted) { break; } reader.AdvanceTo(packetStart, buffer.End); continue; // Complete header not yet received } int size = BitConverter.ToInt32(buffer.Slice(packetStart, 4).ToArray(), 0); if (buffer.Length >= size + 4) { // Get packet end positions SequencePosition packetEnd = buffer.GetPosition(size + 4, packetStart); byteArr = buffer.Slice(packetStart, packetEnd).ToArray(); RCONPacket packet = RCONPacket.FromBytes(byteArr); if (packet.Type == PacketType.AuthResponse) { // Failed auth responses return with an ID of -1 if (packet.Id == -1) { _authenticationTask.SetException( new AuthenticationException($"Authentication failed for {_tcp.RemoteEndPoint}.") ); } // Tell Connect that authentication succeeded _authenticationTask.SetResult(true); } // Forward rcon packet to handler RCONPacketReceived(packet); reader.AdvanceTo(packetEnd); } else { reader.AdvanceTo(packetStart, buffer.End); } // Tell the PipeReader how much of the buffer we have consumed // Stop reading if there's no more data coming if (buffer.IsEmpty && result.IsCompleted) { break; // exit loop } } // If authentication did not complete _authenticationTask.TrySetException( new AuthenticationException($"Server did not respond to auth {_tcp.RemoteEndPoint}.") ); // Mark the PipeReader as complete await reader.CompleteAsync(); }