/// <summary> /// Begins the process of receiving a message from the client. /// This method must manually be called to Begin receiving data /// </summary> public void BeginReceive() { try { if (Connection != null) { // Reset Buffer offset back to the original allocated offset BufferDataToken token = ReadEventArgs.UserToken as BufferDataToken; ReadEventArgs.SetBuffer(token.BufferOffset, token.BufferBlockSize); // Begin Receiving if (!Connection.ReceiveAsync(ReadEventArgs)) { ProcessReceive(); } } } catch (ObjectDisposedException) { if (!DisconnectEventCalled) { // Disconnect user DisconnectEventCalled = true; OnDisconnected?.Invoke(); } } catch (SocketException e) { HandleSocketError(e.SocketErrorCode); } }
/// <summary> /// Once data has been recived from the client, this method is called /// to process the data. Once a message has been completed, the OnDataReceived /// event will be called /// </summary> private void ProcessReceive() { // If we do not get a success code here, we have a bad socket if (ReadEventArgs.SocketError != SocketError.Success) { HandleSocketError(ReadEventArgs.SocketError); return; } // Force disconnect (Specifically for Gpsp, whom will spam empty connections) if (ReadEventArgs.BytesTransferred == 0) { Dispose(false); return; } else { // Fetch our message as a string from the Buffer BufferDataToken token = ReadEventArgs.UserToken as BufferDataToken; RecvMessage.Append( Encoding.UTF8.GetString( ReadEventArgs.Buffer, token.BufferOffset, ReadEventArgs.BytesTransferred ) ); // Process Message string received = RecvMessage.ToString(); if (DataAttempt < 5) { if (IsMessageFinished.Invoke(received)) { if (LogWriter.Log.DebugSockets) { LogWriter.Log.Write(LogLevel.Debug, "{0} [Recv] TCP data: {1}", SocketManager.ServerName, received); } DataAttempt = 0; // tell our parent that we recieved a message RecvMessage.Clear(); // Clear old junk OnDataReceived.Invoke(received); } DataAttempt++; } else { // Looks like the client is sending a lot of data that is not valid LogWriter.Log.Write(LogLevel.Info, "TCP stream {0} is sending a lot of data! Connection closed.", RemoteEndPoint); Dispose(false); } } // Begin receiving again BeginReceive(); }
public GamespyUdpPacket(SocketAsyncEventArgs e) { // Get our recived bytes BytesRecieved = new byte[e.BytesTransferred]; BufferDataToken token = e.UserToken as BufferDataToken; Array.Copy(e.Buffer, token.BufferOffset, BytesRecieved, 0, e.BytesTransferred); // Set our internal variables AsyncEventArgs = e; }
/// <summary> /// Sets the contents of the SocketAsyncEventArgs buffer, /// so a reply can be sent to the remote host connection /// </summary> /// <param name="contents">The new contents to set the buffer to</param> /// <returns>The length of bytes written to the buffer</returns> public int SetBufferContents(byte[] contents) { BufferDataToken token = AsyncEventArgs.UserToken as BufferDataToken; if (contents.Length > token.BufferBlockSize) { throw new ArgumentOutOfRangeException("contents", "Contents are larger then the allocated buffer block size."); } // Copy contents to buffer, then set buffer position Array.Copy(contents, 0, AsyncEventArgs.Buffer, token.BufferOffset, contents.Length); AsyncEventArgs.SetBuffer(token.BufferOffset, contents.Length); return(contents.Length); }
/// <summary> /// Begins accepting a new Connection asynchronously /// </summary> protected async void StartAcceptAsync() { // If we are shutting down, dont receive again if (!IsRunning) { return; } try { // Enforce max connections. If we are capped on connections, the new connection will stop here, // and retrun once a connection is opened up from the Release() method await MaxConnectionsEnforcer..WaitAsync(); // Fetch ourselves an available AcceptEventArg for the next connection SocketAsyncEventArgs AcceptEventArg = SocketReadWritePool.Pop(); AcceptEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, Port); // Reset the Async's Buffer position for the next read BufferDataToken token = AcceptEventArg.UserToken as BufferDataToken; AcceptEventArg.SetBuffer(token.BufferOffset, token.BufferBlockSize); // Begin accpetion connections bool willRaiseEvent = Listener.ReceiveFromAsync(AcceptEventArg); // If we wont raise event, that means a connection has already been accepted syncronously // and the Accept_Completed event will NOT be fired. So we manually call ProcessAccept if (!willRaiseEvent) { IOComplete(this, AcceptEventArg); } } catch (ObjectDisposedException) { // Happens when the server is shutdown } catch (Exception e) { L.LogError( "ERROR: [GamespyUdpSocket.StartAccept] An Exception was thrown while attempting to recieve" + " a conenction. Generating Exception Log" ); ExceptionHandler.GenerateExceptionLog(e); } }
/// <summary> /// Once data has been recived from the client, this method is called /// to process the data. Once a message has been completed, the OnDataReceived /// event will be called /// </summary> private void ProcessReceive() { // If we do not get a success code here, we have a bad socket if (ReadEventArgs.SocketError != SocketError.Success) { HandleSocketError(ReadEventArgs.SocketError); return; } // Force disconnect (Specifically for Gpsp, whom will spam empty connections) if (ReadEventArgs.BytesTransferred == 0) { Close(); return; } else { // Fetch our message as a string from the Buffer BufferDataToken token = ReadEventArgs.UserToken as BufferDataToken; RecvMessage.Append( Encoding.UTF8.GetString( ReadEventArgs.Buffer, token.BufferOffset, ReadEventArgs.BytesTransferred ) ); // Process Message string received = RecvMessage.ToString(); if (received.EndsWith("final\\") || received.EndsWith("\x00\x00\x00\x00")) { // tell our parent that we recieved a message RecvMessage.Clear(); // Clear old junk DataReceived(received); } } // Begin receiving again BeginReceive(); }
/// <summary> /// Begins the process of receiving a message from the client. /// This method must manually be called to Begin receiving data /// </summary> public void BeginReceive() { try { if (Connection != null) { // Reset Buffer offset back to the original allocated offset BufferDataToken token = ReadEventArgs.UserToken as BufferDataToken; ReadEventArgs.SetBuffer(token.BufferOffset, token.BufferBlockSize); // Begin Receiving if (!Connection.ReceiveAsync(ReadEventArgs)) { ProcessReceive(); } } } catch (ObjectDisposedException e) { if (!DisconnectEventCalled) { // Uh-Oh. idk how we got here L.LogError("WARNING: [GamespyStream.BeginReceive] ObjectDisposedException was thrown: " + e.Message); // Disconnect user DisconnectEventCalled = true; if (OnDisconnect != null) { OnDisconnect(); } } } catch (SocketException e) { HandleSocketError(e.SocketErrorCode); } }
/// <summary> /// Sends a message Asynchronously to the client connection /// </summary> private void ProcessSend() { // Return if we are closing the socket if (SocketClosed) { return; } // Bool holder bool willRaiseEvent = true; // Prevent an connection loss exception try { // Prevent race conditions by locking here. // ** Make sure to set WaitingOnAsync Inside the LOCK! ** lock (_lockObj) { // If we are waiting on the IO operation to complete, we exit here if (WaitingOnAsync) { return; } // Get the number of bytes remaining to be sent int NumBytesToSend = SendMessage.Count - SendBytesOffset; // If there are no more bytes to send, then reset if (NumBytesToSend <= 0) { SendMessage.Clear(); SendBytesOffset = 0; WaitingOnAsync = false; return; } // Make sure we arent sending more data then what we have space for BufferDataToken Token = WriteEventArgs.UserToken as BufferDataToken; if (NumBytesToSend > Token.BufferBlockSize) { NumBytesToSend = Token.BufferBlockSize; } // Copy our message to the Write Buffer SendMessage.CopyTo(SendBytesOffset, WriteEventArgs.Buffer, Token.BufferOffset, NumBytesToSend); WriteEventArgs.SetBuffer(Token.BufferOffset, NumBytesToSend); // We have to exit the lock() before we can handle the event manually WaitingOnAsync = true; willRaiseEvent = Connection.SendAsync(WriteEventArgs); } } catch (ObjectDisposedException) { WaitingOnAsync = false; Dispose(false); } // If we wont raise the IO event, that means a connection sent the messsage syncronously if (!willRaiseEvent) { // Remember, if we are here, data was sent Synchronously... IOComplete event is not called! // First, Check for a closed conenction if (WriteEventArgs.BytesTransferred == 0 || WriteEventArgs.SocketError != SocketError.Success) { Dispose(false); return; } // Append to the offset SendBytesOffset += WriteEventArgs.BytesTransferred; WaitingOnAsync = false; ProcessSend(); } }