public void DisconnectClient(SOEClient client, ushort reason, bool clientBased = false)
        {
            // Disconnect
            Log("Disconnecting client on {0} (ID: {1}) for reason: {2}", client.GetClientAddress(), client.GetClientID(), (SOEDisconnectReasons)reason);

            // Are they a connected client?
            if (Clients.Contains(client))
            {
                // We don't care about them anymore
                // Open their ID as a space
                Host2ClientID.Remove(client.Client);
                SessionID2ClientID.Remove(client.GetSessionID());
                Clients[client.GetClientID()] = null;
            }

            // Was this a disconnect request from the client itself?
            if (!clientBased)
            {
                // Tell them we're disconnecting them
                SOEWriter packetWriter = new SOEWriter((ushort)SOEOPCodes.DISCONNECT);

                // Arguments
                packetWriter.AddUInt32(client.GetSessionID());
                packetWriter.AddUInt16(reason);

                // Send!
                SOEPacket packet = packetWriter.GetFinalSOEPacket(client, true, false);
                client.SendPacket(packet);
            }
        }
Exemple #2
0
        private void DoReceiveFrom(IAsyncResult iar)
        {
            //Get the received message.
            Socket   recvSock = (Socket)iar.AsyncState;
            EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);

            int msgLen = recvSock.EndReceiveFrom(iar, ref clientEP);

            byte[] localMsg = new byte[msgLen];
            Array.Copy(buffer, localMsg, msgLen);

            //Start listening for a new message.
            EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);

            udpSock.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref newClientEP, DoReceiveFrom, udpSock);

            // Found our client
            if (origin == null || (origin.Port != ((IPEndPoint)clientEP).Port) && ((IPEndPoint)clientEP).Address.Equals(origin.Address))
            {
                if (origin != null)
                {
                    Console.WriteLine("[Info] Found new client, did the old one get disconnected?");
                }
                else
                {
                    Console.WriteLine("[Info] Found new client");
                }
                origin = (IPEndPoint)clientEP;
            }

            // Message is C -> S
            if (((IPEndPoint)clientEP).Address.Equals(origin.Address))
            {
                udpSock.SendTo(localMsg, destination);
            }
            // Message is S -> C
            else
            {
                switch (localMsg[1])
                {
                case 2:                         // SOE_SESSION_REPLY
                    byte[] crcSeed = new byte[4];
                    Array.Copy(localMsg, 6, crcSeed, 0, 4);
                    Program.session = new Session(crcSeed);
                    break;

                case 9:                         // SOE_CHL_DATA_A
                    SOEPacket packet = new SOEPacket(localMsg);
                    Console.WriteLine("[Debug] Packet " + (localMsg.SequenceEqual(packet.ToArray()) ? "succesfully" : "unsuccessfully") + " rebuilt");
                    localMsg = packet.ToArray();
                    break;

                default:
                    Console.WriteLine("[Debug] Unknown SOE opcode: {0}", localMsg[1]);
                    break;
                }
                udpSock.SendTo(localMsg, origin);
            }
        }
Exemple #3
0
        public void SendPacket(SOEPacket packet)
        {
            // Send the packet
            Server.SendPacket(this, packet);

            // This client is still alive
            Interact();
        }
Exemple #4
0
        public void HandlePing(SOEClient sender)
        {
            // Setup a writer
            SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.PING);
            SOEPacket pong   = writer.GetFinalSOEPacket(sender, false, false);

            // Send a pong!
            sender.SendPacket(pong);
        }
Exemple #5
0
        private void ReceivedSequenceOutOfOrder(ushort sequenceNumber)
        {
            // Setup a writer
            SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.OUT_OF_ORDER_RELIABLE_DATA);

            // Where abouts did the sending mess up?
            writer.AddUInt16(sequenceNumber);

            // Send the packet
            SOEPacket packet = writer.GetFinalSOEPacket(Client, true, true);

            Client.SendPacket(packet);
        }
Exemple #6
0
        public void HandleSessionRequest(SOEClient sender, SOEPacket packet)
        {
            // Setup a reader
            SOEReader reader = new SOEReader(packet);

            // Get the data from the packet
            uint   crcLength     = reader.ReadUInt32();
            uint   sessionID     = reader.ReadUInt32();
            uint   udpBufferSize = reader.ReadUInt32();
            string protocol      = reader.ReadNullTerminatedString();

            // Is the client using the correct protocol?
            if (ProtocolString == protocol)
            {
                // Can we encrypt/compress?
                bool encryptable  = false;
                bool compressable = true;

                // Start the session and manage the client
                sender.StartSession(crcLength, sessionID, udpBufferSize);
                sender.SetCompressable(compressable);
                sender.SetEncryptable(encryptable);

                Server.ConnectionManager.AddNewClient(sender);

                // Setup a writer
                SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.SESSION_RESPONSE);

                // Write a response
                writer.AddUInt32(sessionID);
                writer.AddUInt32(sender.GetCRCSeed());
                writer.AddByte((byte)crcLength);
                writer.AddBoolean(compressable);
                writer.AddBoolean(encryptable);
                writer.AddUInt32(udpBufferSize);
                writer.AddUInt32(3);

                // Get the response
                SOEPacket response = writer.GetFinalSOEPacket(sender, false, false);

                // Send the response!
                sender.SendPacket(response);
            }
            else
            {
                // They aren't using the right protocol...
                Log("Got connection request from client with incorrect protocol. Client: {0}, Server: {1}", protocol, ProtocolString);
            }
        }
Exemple #7
0
        public void HandlePacket(SOEClient sender, SOEPacket packet)
        {
            // Operation
            ushort opCode = packet.GetOpCode();

            // Security Measure
            if (!sender.HasSession())
            {
                if (opCode != (ushort)SOEOPCodes.SESSION_REQUEST)
                {
                    // We really don't care about this client.
                    // They can try send stuff as much as possible.
                    // TODO: Handle this (cuz attacks)
                    return;
                }
            }

            // Handle!
            switch ((SOEOPCodes)opCode)
            {
            case SOEOPCodes.SESSION_REQUEST:
                HandleSessionRequest(sender, packet);
                break;

            case SOEOPCodes.MULTI:
                Console.WriteLine("MULTI!");
                // TODO
                break;

            case SOEOPCodes.DISCONNECT:
                HandleDisconnect(sender, packet);
                break;

            case SOEOPCodes.PING:
                HandlePing(sender);
                break;

            case SOEOPCodes.RELIABLE_DATA:
            case SOEOPCodes.FRAGMENTED_RELIABLE_DATA:
            case SOEOPCodes.ACK_RELIABLE_DATA:
                sender.DataChannel.Receive(packet);
                break;

            default:
                Log("Received Unknown SOEPacket 0x{0:X2}!", packet.GetOpCode());
                break;
            }
        }
Exemple #8
0
        private void Acknowledge(ushort sequenceNumber)
        {
            // Setup a writer
            SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.ACK_RELIABLE_DATA);

            // Compressed? (Always false)
            writer.AddBoolean(false);

            // Add the sequence number
            writer.AddUInt16(sequenceNumber);

            // Send the packet
            SOEPacket packet = writer.GetFinalSOEPacket(Client, true, true);

            Client.SendPacket(packet);
        }
Exemple #9
0
        public void HandleDisconnect(SOEClient sender, SOEPacket packet)
        {
            // Setup a reader
            SOEReader reader = new SOEReader(packet);

            // Get the data from the packet
            uint   sessionID = reader.ReadUInt32();
            ushort reason    = reader.ReadUInt16();

            // Handle
            if (sessionID == sender.GetSessionID())
            {
                Console.WriteLine("Disconnecting");
                Server.ConnectionManager.DisconnectClient(sender, reason, true);
            }
        }
Exemple #10
0
        private void SendMessage(SOEMessage message)
        {
            // Setup a writer
            SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.RELIABLE_DATA);

            // Sequence number
            ushort sequenceNumber = GetNextSequenceNumber();

            writer.AddUInt16(sequenceNumber);

            // Add the message
            writer.AddMessage(message);

            // Get the final packet and send it!
            SOEPacket packet = writer.GetFinalSOEPacket(Client, true, true);

            Client.SendPacket(packet);

            // TODO repeat-till-acknowledged
        }
Exemple #11
0
        public void Receive(SOEPacket packet)
        {
            ushort opCode = packet.GetOpCode();

            if (opCode == (ushort)SOEOPCodes.FRAGMENTED_RELIABLE_DATA)
            {
                ReceiveFragment(packet);
            }
            else if (opCode == (ushort)SOEOPCodes.RELIABLE_DATA)
            {
                ReceiveMessage(packet);
            }
            else if (opCode == (ushort)SOEOPCodes.ACK_RELIABLE_DATA)
            {
                // TODO: Handle repeat-until-acknowledged and all that comes with it.
                Log("Data Ack");
            }
            else
            {
                // Shrug ¯\_(ツ)_/¯
                Log("Received a packet that was not data or acknowledge. Discarding..");
            }
        }
Exemple #12
0
        private void ReceiveMessage(SOEPacket packet)
        {
            SOEReader reader = new SOEReader(packet);

            // Have we received in order?
            ushort sequenceNumber = reader.ReadUInt16();

            if ((sequenceNumber != LastReceivedSequenceNumber + 1) && (sequenceNumber != 0))
            {
                ReceivedSequenceOutOfOrder(sequenceNumber);
                return;
            }

            // Acknowledge
            Acknowledge(sequenceNumber);
            LastReceivedSequenceNumber = sequenceNumber;

            // Get the SOEMessage
            byte[] data = reader.ReadToEnd();

            // Handle!
            Client.ReceiveMessage(data);
        }
Exemple #13
0
 public void SendPacket(SOEClient client, SOEPacket packet)
 {
     // Send the message
     UdpClient.Send(packet.GetRaw(), packet.GetLength(), client.Client);
 }
Exemple #14
0
        private void ReceiveFragment(SOEPacket packet)
        {
            // Setup a reader
            SOEReader reader = new SOEReader(packet);

            reader.ReadUInt16();

            // Have we already started a fragmented packet?
            if (StartedFragmentedPacket)
            {
                // One less fragment till we need to acknowledge!
                FragmentsTillAck--;

                // Get our sequence number
                uint previousFragmentSequenceNumber = FragmentSequenceNumber;
                FragmentSequenceNumber = reader.ReadUInt16();

                // Did we get a correct sequence number?
                if (FragmentSequenceNumber != previousFragmentSequenceNumber + 1)
                {
                    // Out of order!
                    ReceivedSequenceOutOfOrder(FragmentSequenceNumber);
                    return;
                }

                // Append the rest of the packet to the fragmented data
                for (int i = 4; i < FragmentedData.Length; i++)
                {
                    FragmentedData[ReceivedFragmentsSize] = reader.ReadByte();
                    ReceivedFragmentsSize++;
                }
            }
            else
            {
                // We're expecting the starting packet
                FragmentSequenceNumber = reader.ReadUInt16();
                uint totalSize = reader.ReadUInt32();

                // Is this a valid sequence number?
                if ((FragmentSequenceNumber != LastReceivedSequenceNumber + 1) && (FragmentSequenceNumber != 0))
                {
                    // Out of order!
                    ReceivedSequenceOutOfOrder(FragmentSequenceNumber);
                    return;
                }

                // Get the total size
                FragmentedData = new byte[totalSize];

                // How many fragments till we need to acknowledge
                FragmentsTillAck = 4;

                // Append the rest of the packet to the fragmented data
                for (int i = 8; i < FragmentedData.Length; i++)
                {
                    FragmentedData[ReceivedFragmentsSize] = reader.ReadByte();
                    ReceivedFragmentsSize++;
                }

                // Started a fragmented packet
                StartedFragmentedPacket = true;
            }

            // Are we finished with the fragmented data?
            if (ReceivedFragmentsSize >= FragmentedData.Length)
            {
                // Finish fragmented packet
                StartedFragmentedPacket = false;
                FragmentsTillAck        = 0;

                // Handle the fragmented packet as a RELIABLE_DATA packet
                SOEWriter writer = new SOEWriter((ushort)SOEOPCodes.RELIABLE_DATA);
                writer.AddBytes(FragmentedData);

                SOEPacket wholePacket = writer.GetFinalSOEPacket(Client, false, false);

                // Receive this packet!
                Receive(wholePacket);
                return;
            }

            // Do we need to acknowledge?
            if (FragmentsTillAck == 0)
            {
                Acknowledge(FragmentSequenceNumber);
                FragmentsTillAck = 5;
            }
        }