private void DisconnectSession(AsyncSocketSession session) { // Socket already gone, someone else already cleaned it up Task removedSocket; if (!sessions.TryRemove(session, out removedSocket)) { return; } try { session.Socket.Shutdown(SocketShutdown.Both); } catch (Exception) { } session.Socket.Close(); if (session.Player != null) { session.Player.HasTwoFactorAuthenticated = null; logger.Info("Player disconnect {0}(1) IP: {2}", session.Player.Name, session.Player.PlayerId, session.RemoteIP); } else { logger.Debug("Socket disconnect without logged in player IP[{0}]", session.RemoteIP); } ThreadPool.UnsafeQueueUserWorkItem(obj => session.ProcessEvent(new Packet(Command.OnDisconnect)), null); }
private void Add(AsyncSocketSession session) { session.OnClose += OnClose; var readTask = ReadLoop(session); sessions.TryAdd(session, readTask); readTask.CatchUnhandledException("ReadTask for " + session.RemoteIP); }
private async Task ReadLoop(AsyncSocketSession session) { session.ProcessEvent(new Packet(Command.OnConnect)); var hasCheckedForPolicyFile = false; var socketAwaitable = socketAwaitablePool.Take(); var buffer = bufferManager.GetBuffer(); socketAwaitable.Buffer = buffer; try { do { // Check if it's a policy file request if (!hasCheckedForPolicyFile && session.PacketMaker.Length > 22) { hasCheckedForPolicyFile = true; if (Encoding.UTF8.GetString(session.PacketMaker.GetBytes(), 0, 22) == "<policy-file-request/>") { logger.Debug("Serving policy file through game server to {0}", session.RemoteIP); try { await session.SendAsyncImmediatelly(policyFile); session.Socket.Shutdown(SocketShutdown.Both); session.Socket.Close(1); } catch (Exception e) { if (logger.IsDebugEnabled) { logger.Debug(e, "Handled exception while serving policy file on main game port"); } } Task removedSocket; sessions.TryRemove(session, out removedSocket); return; } } // Keep processing as many packets as we can do { Packet packet = session.PacketMaker.GetNextPacket(); if (packet == null) { // Remove the player if after processing packets we still have over 1MB of data remaining. // This probably means the player is spamming the server with an invalid client if (session.PacketMaker.Length > 1048576) { DisconnectSession(session); return; } break; } session.Process(packet); }while (true); // Read more data var result = await session.Socket.ReceiveAsync(socketAwaitable); if (result != SocketError.Success || socketAwaitable.Transferred.Count == 0) { break; } session.PacketMaker.Append(socketAwaitable.Transferred); }while (true); DisconnectSession(session); } catch (SocketException e) { logger.Info(e, "Handled socket exception while receiving socket data IP[{0}]", session.RemoteIP); DisconnectSession(session); } catch (ObjectDisposedException) { } catch (Exception e) { logger.ErrorException("Unhandled exception in readloop", e); throw; } finally { socketAwaitable.Clear(); socketAwaitablePool.Add(socketAwaitable); bufferManager.ReleaseBuffer(buffer); } }