예제 #1
0
파일: Client.cs 프로젝트: DomGrieco/server
        private static void EndReceive(IAsyncResult ar)
        {
            var client = (Client)ar.AsyncState;
            var socket = client.Socket;

            try
            {
                int count = socket.EndReceive(ar);

                for (int i = 0; i < count; ++i)
                {
                    client.fullRecvBuffer.Add(client.recvBuffer[i]);
                }

                if (count == 0 || client.fullRecvBuffer[0] != 0xAA)
                {
                    Logger.DebugFormat("cid {0}: client is disconnected or corrupt packets received", client.ConnectionId);
                    client.Connected = false;
                    return;
                }

                while (client.fullRecvBuffer.Count > 3)
                {
                    Logger.Debug("in fullRecvBuffer loop");
                    int length = client.fullRecvBuffer[1]*256 + client.fullRecvBuffer[2] + 3;

                    if (length > client.fullRecvBuffer.Count)
                        break;

                    var range = client.fullRecvBuffer.GetRange(0, length);
                    var buffer = range.ToArray();

                    client.fullRecvBuffer.RemoveRange(0, length);

                    var packet = new ClientPacket(buffer);

                    if (packet.ShouldEncrypt)
                        packet.Decrypt(client);

                    if (packet.Opcode == 0x39 || packet.Opcode == 0x3A)
                        packet.DecryptDialog();

                    if (client.Connected)
                    {
                        if (Constants.PACKET_THROTTLES.ContainsKey(packet.Opcode))
                        {
                            ThrottleInfo tinfo;

                            if (client.Throttle.TryGetValue(packet.Opcode, out tinfo))
                            {
                                tinfo.Received();
                                if (tinfo.IsThrottled)
                                {
                                    Logger.InfoFormat("cid {0}: opcode 0x{0:X2} throttled", client.ConnectionId,
                                        packet.Opcode);
                                    if (tinfo.TotalThrottled > tinfo.Throttle.DisconnectAfter)
                                    {
                                        Logger.InfoFormat("cid {0}: opcode 0x{0:X2} throttle limit reached: disconnected",
                                            client.ConnectionId, packet.Opcode);
                                        client.Connected = false;
                                        break;
                                    }
                                    client.recving = false;
                                    continue;
                                }
                            }
                            else
                            {
                                // We've never seen this packet before on this client. And obviously, as a result,
                                // we can be neither squelched nor throttled.
                                Logger.DebugFormat("cid {0}: creating throttle for opcode 0x{0:X2}", client.ConnectionId,
                                    packet.Opcode);
                                client.Throttle[packet.Opcode] = new ThrottleInfo(packet.Opcode);
                            }
                        }
                        Logger.Debug("Proceeding to packet processing");
                        // For Lobby and Login, we simply process the packet as we can do so in a 
                        // thread safe manner.
                        // For World, which involves game logic, we queue the packet for processing by
                        // the world consumer thread.

                        try
                        {
                            if (client.Server is Lobby)
                            {
                                Logger.DebugFormat("Lobby: 0x{0:X2}", packet.Opcode);
                                var handler = (client.Server as Lobby).PacketHandlers[packet.Opcode];
                                handler.Invoke(client, packet);
                                client.UpdateLastReceived();
                            }
                            else if (client.Server is Login)
                            {
                                var handler = (client.Server as Login).PacketHandlers[packet.Opcode];
                                handler.Invoke(client, packet);
                                Logger.DebugFormat("Login: 0x{0:X2}", packet.Opcode);
                                client.UpdateLastReceived();
                            }
                            else
                            {
                                if (packet.Opcode != 0x45 && packet.Opcode != 0x75)
                                {
                                    // Heartbeats don't effect our idle calcuations
                                    client.UpdateLastReceived((packet.Opcode != 0x45 && packet.Opcode != 0x75));
                                }
                                Logger.DebugFormat("Queuing: 0x{0:X2}", packet.Opcode);
                                World.MessageQueue.Add(new HybrasylClientMessage(packet, client.ConnectionId));

                            }
                        }
                        catch (Exception e)
                        {
                            Logger.ErrorFormat("EXCEPTION IN HANDLING: {0}: {1}", packet.Opcode, e);
                        }
                        client.recving = false;
                    }
                }
            }
            catch (Exception e)
            {
                client.Connected = false;
                Logger.ErrorFormat(e.ToString());
            }
        }
예제 #2
0
파일: Client.cs 프로젝트: saroque/server
        private static void EndReceive(IAsyncResult ar)
        {
            var client = (Client)ar.AsyncState;
            var socket = client.Socket;

            try
            {
                int count = socket.EndReceive(ar);

                for (int i = 0; i < count; ++i)
                {
                    client.fullRecvBuffer.Add(client.recvBuffer[i]);
                }

                if (count == 0 || client.fullRecvBuffer[0] != 0xAA)
                {
                    Logger.DebugFormat("cid {0}: client is disconnected or corrupt packets received", client.ConnectionId);
                    client.Connected = false;
                    return;
                }

                while (client.fullRecvBuffer.Count > 3)
                {
                    Logger.Debug("in fullRecvBuffer loop");
                    int length = client.fullRecvBuffer[1] * 256 + client.fullRecvBuffer[2] + 3;

                    if (length > client.fullRecvBuffer.Count)
                    {
                        break;
                    }

                    var range  = client.fullRecvBuffer.GetRange(0, length);
                    var buffer = range.ToArray();

                    client.fullRecvBuffer.RemoveRange(0, length);

                    var packet = new ClientPacket(buffer);

                    if (packet.ShouldEncrypt)
                    {
                        packet.Decrypt(client);
                    }

                    if (packet.Opcode == 0x39 || packet.Opcode == 0x3A)
                    {
                        packet.DecryptDialog();
                    }

                    if (client.Connected)
                    {
                        if (Constants.PACKET_THROTTLES.ContainsKey(packet.Opcode))
                        {
                            ThrottleInfo tinfo;

                            if (client.Throttle.TryGetValue(packet.Opcode, out tinfo))
                            {
                                tinfo.Received();
                                if (tinfo.IsThrottled)
                                {
                                    Logger.InfoFormat("cid {0}: opcode 0x{0:X2} throttled", client.ConnectionId,
                                                      packet.Opcode);
                                    if (tinfo.TotalThrottled > tinfo.Throttle.DisconnectAfter)
                                    {
                                        Logger.InfoFormat("cid {0}: opcode 0x{0:X2} throttle limit reached: disconnected",
                                                          client.ConnectionId, packet.Opcode);
                                        client.Connected = false;
                                        break;
                                    }
                                    client.recving = false;
                                    continue;
                                }
                            }
                            else
                            {
                                // We've never seen this packet before on this client. And obviously, as a result,
                                // we can be neither squelched nor throttled.
                                Logger.DebugFormat("cid {0}: creating throttle for opcode 0x{0:X2}", client.ConnectionId,
                                                   packet.Opcode);
                                client.Throttle[packet.Opcode] = new ThrottleInfo(packet.Opcode);
                            }
                        }
                        Logger.Debug("Proceeding to packet processing");
                        // For Lobby and Login, we simply process the packet as we can do so in a
                        // thread safe manner.
                        // For World, which involves game logic, we queue the packet for processing by
                        // the world consumer thread.

                        try
                        {
                            if (client.Server is Lobby)
                            {
                                Logger.DebugFormat("Lobby: 0x{0:X2}", packet.Opcode);
                                var handler = (client.Server as Lobby).PacketHandlers[packet.Opcode];
                                handler.Invoke(client, packet);
                                client.UpdateLastReceived();
                            }
                            else if (client.Server is Login)
                            {
                                var handler = (client.Server as Login).PacketHandlers[packet.Opcode];
                                handler.Invoke(client, packet);
                                Logger.DebugFormat("Login: 0x{0:X2}", packet.Opcode);
                                client.UpdateLastReceived();
                            }
                            else
                            {
                                if (packet.Opcode != 0x45 && packet.Opcode != 0x75)
                                {
                                    // Heartbeats don't effect our idle calcuations
                                    client.UpdateLastReceived((packet.Opcode != 0x45 && packet.Opcode != 0x75));
                                }
                                Logger.DebugFormat("Queuing: 0x{0:X2}", packet.Opcode);
                                World.MessageQueue.Add(new HybrasylClientMessage(packet, client.ConnectionId));
                            }
                        }
                        catch (Exception e)
                        {
                            Logger.ErrorFormat("EXCEPTION IN HANDLING: {0}: {1}", packet.Opcode, e);
                        }
                        client.recving = false;
                    }
                }
            }
            catch (Exception e)
            {
                client.Connected = false;
                Logger.ErrorFormat(e.ToString());
            }
        }
예제 #3
0
        public void ReadCallback(IAsyncResult ar)
        {
            ClientState state = (ClientState)ar.AsyncState;
            Client      client;
            SocketError errorCode;
            int         bytesRead = 0;

            if (this is Login)
            {
                Logger.InfoFormat("This is a login ReadCallback");
            }
            try
            {
                bytesRead = state.WorkSocket.EndReceive(ar, out errorCode);
                if (errorCode != SocketError.Success)
                {
                    bytesRead = 0;
                }
            }
            catch (SocketException)
            {
                state.WorkSocket.Close();
            }
            catch (ObjectDisposedException)
            {
                state.WorkSocket.Close();
            }

            if (!GlobalConnectionManifest.ConnectedClients.TryGetValue(state.Id, out client))
            {
                // Is this a redirect?
                Redirect redirect;
                if (!GlobalConnectionManifest.TryGetRedirect(state.Id, out redirect))
                {
                    Logger.ErrorFormat("Receive: data from unknown client (id {0}, closing connection", state.Id);
                    state.WorkSocket.Close();
                    state.WorkSocket.Dispose();
                    return;
                }
                client             = redirect.Client;
                client.ClientState = state;
                GlobalConnectionManifest.RegisterClient(client);
            }

            if (bytesRead > 0)
            {
                if (this is Login)
                {
                    Logger.InfoFormat("Dafuq bro");
                }
                var inboundBytes = state.ReceiveBufferTake(bytesRead).ToArray();
                if (inboundBytes[0] != 0xAA)
                {
                    Logger.DebugFormat("cid {0}: client is wat",
                                       client.ConnectionId);
                    state.ResetReceive();
                }
                else
                {
                    while (inboundBytes.Length > 3)
                    {
                        Logger.InfoFormat("Inside while loop");
                        var packetLength = ((int)inboundBytes[1] << 8) + (int)inboundBytes[2] + 3;
                        if (packetLength > inboundBytes.Length)
                        {
                            // We haven't received the entire packet yet; read more bytes
                            break;
                        }
                        else
                        {
                            // We've received an intact packet, pop it off
                            ClientPacket receivedPacket =
                                new ClientPacket(state.ReceiveBufferPop(packetLength).ToArray());
                            // Also remove it from our local buffer...this seems kinda gross to me
                            inboundBytes =
                                new List <byte>(inboundBytes).GetRange(packetLength,
                                                                       inboundBytes.Length - packetLength)
                                .ToArray();

                            if (receivedPacket.ShouldEncrypt)
                            {
                                receivedPacket.Decrypt(client);
                            }
                            if (receivedPacket.Opcode == 0x39 || receivedPacket.Opcode == 0x3A)
                            {
                                receivedPacket.DecryptDialog();
                            }
                            try
                            {
                                if (this is Lobby)
                                {
                                    Logger.InfoFormat("Lobby: 0x{0:X2}", receivedPacket.Opcode);
                                    var handler = (this as Lobby).PacketHandlers[receivedPacket.Opcode];
                                    handler.Invoke(client, receivedPacket);
                                    Logger.InfoFormat("Lobby packet done");
                                    client.UpdateLastReceived();
                                }
                                else if (this is Login)
                                {
                                    Logger.InfoFormat("Login: 0x{0:X2}", receivedPacket.Opcode);
                                    var handler = (this as Login).PacketHandlers[receivedPacket.Opcode];
                                    handler.Invoke(client, receivedPacket);
                                    Logger.InfoFormat("Login packet done");
                                    client.UpdateLastReceived();
                                }
                                else
                                {
                                    client.UpdateLastReceived(receivedPacket.Opcode != 0x45 &&
                                                              receivedPacket.Opcode != 0x75);
                                    Logger.InfoFormat("Queuing: 0x{0:X2}", receivedPacket.Opcode);
                                    World.MessageQueue.Add(new HybrasylClientMessage(receivedPacket,
                                                                                     client.ConnectionId));
                                    Logger.InfoFormat("World packet done");
                                }
                            }
                            catch (Exception e)
                            {
                                Logger.ErrorFormat("EXCEPTION IN HANDLING: 0x{0:X2}: {1}", receivedPacket.Opcode, e);
                            }
                        }
                    }
                }
            }
            else
            {
                Logger.DebugFormat("cid {0}: client is disconnected or corrupt packets received",
                                   client.ConnectionId);
                client.Disconnect();
                return;
            }

            // Continue getting dem bytes
            try
            {
                state.WorkSocket.BeginReceive(state.Buffer, 0, state.Buffer.Length, 0,
                                              new AsyncCallback(this.ReadCallback), state);
                Logger.InfoFormat("Triggering receive callback");
            }
            catch (ObjectDisposedException)
            {
                //client.Disconnect();
                state.WorkSocket.Close();
            }
            catch (SocketException)
            {
                client.Disconnect();
            }
        }