static void RecvCallback(object sender, SocketAsyncEventArgs e) { TcpSocket s = (TcpSocket)e.UserToken; if (s.Disconnected) { return; } try { // If received 0, means socket was closed int recvLen = e.BytesTransferred; if (recvLen == 0) { s.Disconnect(); return; } s.HandleReceived(s.recvBuffer, recvLen); if (!s.Disconnected) { s.ReceiveNextAsync(); } } catch (SocketException) { s.Disconnect(); } catch (ObjectDisposedException) { // Socket was closed by another thread, mark as disconnected } catch (Exception ex) { Logger.LogError(ex); s.Disconnect(); } }
static void SendCallback(object sender, SocketAsyncEventArgs e) { TcpSocket s = (TcpSocket)e.UserToken; try { // TODO: Need to check if all data was sent or not? int sent = e.BytesTransferred; lock (s.sendLock) { s.sendInProgress = false; while (s.sendQueue.Count > 0) { // DoSendAsync returns false if SendAsync completed sync // If that happens, SendCallback isn't called so we need to send data here instead s.sendInProgress = s.TrySendAsync(s.sendQueue.Dequeue()); if (s.sendInProgress) { return; } if (s.Disconnected) { s.sendQueue.Clear(); } } } } catch (SocketException) { s.Disconnect(); } catch (ObjectDisposedException) { // Socket was already closed by another thread } catch (Exception ex) { Logger.LogError(ex); } }
static void SendCallback(object sender, SocketAsyncEventArgs e) { TcpSocket s = (TcpSocket)e.UserToken; try { lock (s.sendLock) { // check if last packet was only partially sent for (;;) { int sent = e.BytesTransferred; int count = e.Count; if (sent >= count || sent <= 0) { break; } // last packet was only partially sent - resend rest of packet s.sendArgs.SetBuffer(e.Offset + sent, e.Count - sent); s.sendInProgress = s.socket.SendAsync(s.sendArgs); if (s.sendInProgress) { return; } } s.sendInProgress = false; while (s.sendQueue.Count > 0) { // DoSendAsync returns false if SendAsync completed sync // If that happens, SendCallback isn't called so we need to send data here instead s.sendInProgress = s.TrySendAsync(s.sendQueue.Dequeue()); if (s.sendInProgress) { return; } if (s.Disconnected) { s.sendQueue.Clear(); } } } } catch (SocketException) { s.Disconnect(); } catch (ObjectDisposedException) { // Socket was already closed by another thread } catch (Exception ex) { Logger.LogError(ex); } }
static void AcceptCallback(IAsyncResult result) { if (Server.shuttingDown) { return; } TcpListen listen = (TcpListen)result.AsyncState; TcpSocket s = null; try { Socket raw = listen.socket.EndAccept(result); bool cancel = false; OnConnectionReceivedEvent.Call(raw, ref cancel); if (cancel) { // intentionally non-clean connection close try { raw.Close(); } catch { } } else { s = new TcpSocket(raw); Logger.Log(LogType.UserActivity, s.IP + " connected to the server."); s.Init(); } } catch (Exception ex) { if (!(ex is SocketException)) { Logger.LogError(ex); } if (s != null) { s.Close(); } } listen.AcceptNextAsync(); }
static void RecvCallback(object sender, SocketAsyncEventArgs e) { Player p = null; try { TcpSocket s = (TcpSocket)e.UserToken; p = s.player; if (p.disconnected) { return; } int recvLen = e.BytesTransferred; if (recvLen == 0) { p.Disconnect(); return; } // Packets may not always be fully received in a Receive call // As such, we may need to retain a little bit of partial packet data Buffer.BlockCopy(s.recvBuffer, 0, s.unprocessed, s.unprocessedLen, recvLen); s.unprocessedLen += recvLen; int processedLen = p.ProcessReceived(s.unprocessed, s.unprocessedLen); // Disconnect invalid clients if (p.nonPlayerClient && processedLen == -1) { s.Close(); p.disconnected = true; } if (processedLen == -1) { return; } // move remaining partial packet data back to start of unprocessed buffer for (int i = processedLen; i < s.unprocessedLen; i++) { s.unprocessed[i - processedLen] = s.unprocessed[i]; } s.unprocessedLen -= processedLen; if (!p.disconnected) { s.ReceiveNextAsync(); } } catch (SocketException) { if (p != null) { p.Disconnect(); } } catch (ObjectDisposedException) { // Socket was closed by another thread, mark as disconnected if (p == null) { return; } Player.connections.Remove(p); p.RemoveFromPending(); p.disconnected = true; } catch (Exception ex) { Logger.LogError(ex); if (p != null) { p.Leave("Error!"); } } }