예제 #1
0
        private void ReadCallback(IAsyncResult ar)
        {
            Client client = ar.AsyncState as Client;
            try
            {
                if (client != null)
                {
                    NetworkStream networkStream = client.NetworkStream;
                    int bytesRead = networkStream.EndRead(ar);

                    // Keep track of the total number of bytes read in the client
                    client.BytesRead += bytesRead;

                    if (bytesRead == 0)
                    {
                        Console.WriteLine("Got 0 bytes from {0}, marking as OFFLINE.", client.User.Username);
                        RemoveClient(client);
                    }

                    // Allocate a new byte array the size of the data that needs to be read from client.Buffer
                    byte[] data = new byte[bytesRead];
                    Buffer.BlockCopy(
                        client.Buffer,
                        0,
                        data,
                        0,
                        bytesRead);

                    if (client.DataBuffer == null)
                        client.DataBuffer = new MemoryStream();

                    // Do we need to get the packet length header?
                    if (client.PacketLength == null)
                    {
                        if (client.DataBuffer.Length > 0)
                        {
                            byte[] packetLengthBytes = new byte[4];
                            Buffer.BlockCopy(
                                client.DataBuffer.ToArray(),
                                0,
                                packetLengthBytes,
                                0,
                                packetLengthBytes.Length);
                            client.PacketLength = BitConverter.ToInt32(packetLengthBytes, 0);

                            Console.WriteLine("Found {0} bytes leftover from previous packet to parse, expecting {1} bytes.",
                                client.DataBuffer.Length,
                                client.PacketLength);
                        }
                        else
                        {
                            // Read the first Int32 to get the packet length and then use the byte[4] to get the packetLength
                            byte[] packetLengthBytes = new byte[4];
                            Buffer.BlockCopy(
                                data,
                                0,
                                packetLengthBytes,
                                0,
                                packetLengthBytes.Length);

                            client.PacketLength = BitConverter.ToInt32(packetLengthBytes, 0);
                        }
                        Console.WriteLine("Reading in new packet, size of {0} bytes.", client.PacketLength);
                    }

                    client.DataBuffer.Write(data, 4, (int) client.PacketLength);

                    int actual = (data.Length - 4);
                    Console.WriteLine("> Expecting {0} bytes. Actually recieved {1} bytes.", client.PacketLength, actual);

                    if (actual < client.PacketLength) // is it less than or greater?
                    {
                        // Copy the remaining data do the client.dataBuffer
                        Console.WriteLine(" [!!!] Received less data than the we wanted. Appending rest to the dataBuffer and waiting for more");

                        byte[] toAppend = new byte[actual];
                        Buffer.BlockCopy(
                            data,
                            4,
                            toAppend,
                            0,
                            actual);

                        client.DataBuffer.Write(toAppend, (int)client.DataBuffer.Length, actual);

                        // Continue listening for more
                        networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client);
                    }
                    else
                    {
                        Console.WriteLine(" > Parsing packet size of {0} bytes and removing that length from the buffer.", client.PacketLength);

                        // Allocate memory for the packet we want to parse based on the packet length we acquired
                        byte[] packetToParse = new byte[(int) client.PacketLength];
                        // Copy the data
                        Buffer.BlockCopy(
                            client.DataBuffer.ToArray(),
                            0,
                            packetToParse,
                            0,
                            (int) client.PacketLength
                            );

                        // Clear the old data out and leave the remaining
                        int newArray = (int) (client.DataBuffer.Length - client.PacketLength);

                        if (newArray > 0) // Is it greater?
                        {
                            Console.WriteLine(" [!!!] Received more data than we wanted.");

                            byte[] toPutBackInBuffer = new byte[newArray];

                            Buffer.BlockCopy(
                                client.DataBuffer.ToArray(),
                                (int) client.PacketLength,
                                toPutBackInBuffer,
                                0,
                                newArray);

                            // Clear
                            client.DataBuffer.Position = 0;
                            client.DataBuffer.SetLength(0);

                            Console.WriteLine(" [!!] Checking extra data sent, size of {0} bytes.", toPutBackInBuffer.Length);
                            client.DataBuffer.Write(toPutBackInBuffer, 0, toPutBackInBuffer.Length);
                        }
                        else
                        {
                            // Tell client to get the length again from a new packet header
                            client.PacketLength = null;

                            // Parse the databuffer
                            CollabPacket.Packet packet = CollabPacket.ClassSerializer.DeserializeByteArray(packetToParse);

                            // Clear the data buffer
                            client.DataBuffer.Position = 0;
                            client.DataBuffer.SetLength(0);

                            if (packet.Message != null)
                            {
                                string[] parts = packet.Message.Split('|');

                                switch (parts[0])
                                {
                                    case "LOGIN":
                                        if (parts.Length > 2)
                                        {
                                            string username = parts[1];
                                            string password = parts[2];

                                            CollabPacket.Packet loginReply = new CollabPacket.Packet();

                                            if (Program.DbConnection.AuthenticateUser(username, password))
                                            {

                                                loginReply.Message = "LOGIN_SUCCESS";
                                                loginReply.User = Program.DbConnection.GetUserByUsername(username);

                                                client.User = loginReply.User;

                                                AddClient(client);
                                            }
                                            else
                                            {
                                                loginReply.Message = "LOGIN_FAILED";
                                            }

                                            Write(client.TcpClient,
                                                  CollabPacket.ClassSerializer.SerializeClass(loginReply));
                                        }
                                        break;

                                    case "REQUEST_FRIENDS":
                                        if (packet.User != null)
                                        {
                                            // Query out every friend in the databse for the p.User.UserID into a List<User>
                                            // Foreach User u in List<User> create a packet with the message LIST_FRIEND and the User object of that individual from
                                            List<CollabPacket.User> friends =
                                                Program.DbConnection.ReturnFriends(packet.User.UserID);

                                            foreach (CollabPacket.User u in friends)
                                            {
                                                CollabPacket.Packet listFriend = new CollabPacket.Packet {User = u};

                                                // Send the friend as ONLINE if they exist in the connectedClients list, otherwise send them as OFFLINE
                                                listFriend.Message = IsFriendOnline(u.UserID)
                                                                         ? "LIST_FRIEND|ONLINE"
                                                                         : "LIST_FRIEND|OFFLINE";

                                                Console.WriteLine("Sending FriendID: {0} to UserID: {1} ({2}).",
                                                                  u.UserID,
                                                                  packet.User.UserID, listFriend.Message.Split('|')[1]);

                                                Write(client.TcpClient,
                                                      CollabPacket.ClassSerializer.SerializeClass(listFriend));
                                            }
                                        }
                                        break;

                                    case "SHARE_REQUEST":
                                        if (parts.Length > 3)
                                        {
                                            int targetUserID = Convert.ToInt32(parts[1]);
                                            string windowTitle = parts[2];
                                            IntPtr hWnd = (IntPtr) Convert.ToInt32(parts[3]);

                                            CollabPacket.User targetUser =
                                                Program.DbConnection.GetUserByUserID(targetUserID);

                                            Console.WriteLine(
                                                "Got request from {0} to share screen with {1}. Sending request to {1}.",
                                                packet.User.Username,
                                                targetUser.Username
                                                );

                                            CollabPacket.Packet shareRequest = new CollabPacket.Packet
                                                {
                                                    User = packet.User,
                                                    WindowTitle = windowTitle,
                                                    ShareID = packet.User.UserID,
                                                    Message = "SHARE_PROMPT"
                                                };

                                            SendToUserID(targetUserID,
                                                         CollabPacket.ClassSerializer.SerializeClass(shareRequest));
                                        }
                                        break;
                                    case "MOUSE_MOVE":
                                        //Console.WriteLine("Got mouse data from user: {0}x{1}", packet.MousePacket.X, packet.MousePacket.Y);
                                        SendToAllExceptSender(packet, client);
                                        break;

                                    case "I":
                                        SendToAllExceptSender(packet, client);
                                        break;
                                }

                                // Continue listening for more
                                networkStream.BeginRead(client.Buffer, 0, client.Buffer.Length, ReadCallback, client);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);

                // Remove the client from the list.
                // TODO: Fix
                // RemoveClient(client);
            }
        }
예제 #2
0
        private void RemoveClient(Client c)
        {
            // Push out online notification
            if (_connectedClients.Contains(c))
            {
                if (c.User != null)
                {
                    Console.WriteLine("User logged OFF: {0}.", c.User.Username);
                }

                CollabPacket.Packet onlineNotification = new CollabPacket.Packet
                    {
                        Message = "FRIEND_OFFLINE",
                        User = c.User
                    };

                SendToAllExceptSender(onlineNotification, c);

                lock (_connectedClients)
                {
                    _connectedClients.Remove(c);
                }
            }
        }
예제 #3
0
        private void ParsePacket(byte[] dataToParse, Client client, NetworkStream networkStream)
        {
            CollabPacket.Packet packet = CollabPacket.ClassSerializer.DeserializeByteArray(dataToParse);

            if (packet.Message != null)
            {
                string[] parts = packet.Message.Split('|');

                switch (parts[0])
                {
                    case "LOGIN":
                        if (parts.Length > 2)
                        {
                            string username = parts[1];
                            string password = parts[2];

                            CollabPacket.Packet loginReply = new CollabPacket.Packet();

                            if (Program.DbConnection.AuthenticateUser(username, password))
                            {

                                loginReply.Message = "LOGIN_SUCCESS";
                                loginReply.User = Program.DbConnection.GetUserByUsername(username);

                                client.User = loginReply.User;

                                AddClient(client);
                            }
                            else
                            {
                                loginReply.Message = "LOGIN_FAILED";
                            }

                            Write(client.TcpClient,
                                  CollabPacket.ClassSerializer.SerializeClass(loginReply));
                        }
                        break;

                    case "REQUEST_FRIENDS":
                        if (packet.User != null)
                        {
                            // Query out every friend in the databse for the p.User.UserID into a List<User>
                            // Foreach User u in List<User> create a packet with the message LIST_FRIEND and the User object of that individual from
                            List<CollabPacket.User> friends =
                                Program.DbConnection.ReturnFriends(packet.User.UserID);

                            foreach (CollabPacket.User u in friends)
                            {
                                CollabPacket.Packet listFriend = new CollabPacket.Packet { User = u };

                                // Send the friend as ONLINE if they exist in the connectedClients list, otherwise send them as OFFLINE
                                listFriend.Message = IsFriendOnline(u.UserID)
                                                         ? "LIST_FRIEND|ONLINE"
                                                         : "LIST_FRIEND|OFFLINE";

                                Console.WriteLine("Sending FriendID: {0} to UserID: {1} ({2}).",
                                                  u.UserID,
                                                  packet.User.UserID, listFriend.Message.Split('|')[1]);

                                Write(client.TcpClient,
                                      CollabPacket.ClassSerializer.SerializeClass(listFriend));
                            }
                        }
                        break;

                    case "SHARE_REQUEST":
                        if (parts.Length > 3)
                        {
                            int targetUserID = Convert.ToInt32(parts[1]);
                            string windowTitle = parts[2];
                            IntPtr hWnd = (IntPtr)Convert.ToInt32(parts[3]);

                            CollabPacket.User targetUser =
                                Program.DbConnection.GetUserByUserID(targetUserID);

                            Console.WriteLine(
                                "Got request from {0} to share screen with {1}. Sending request to {1}.",
                                packet.User.Username,
                                targetUser.Username
                                );

                            CollabPacket.Packet shareRequest = new CollabPacket.Packet
                            {
                                User = packet.User,
                                WindowTitle = windowTitle,
                                ShareID = packet.User.UserID,
                                Message = "SHARE_PROMPT"
                            };

                            SendToUserID(targetUserID,
                                         CollabPacket.ClassSerializer.SerializeClass(shareRequest));
                        }
                        break;

                    case "JOIN_SHARE":
                        Console.WriteLine("{0} joined share id {1}", packet.User.Username, packet.ShareID);

                        CollabPacket.Packet pShareJoin = new CollabPacket.Packet
                        {
                            Message = "JOIN_SHARE",
                            ShareID = packet.ShareID,
                            User = packet.User
                        };

                        SendToAllExceptSender(pShareJoin, client);
                        break;

                    case "MOUSE_MOVE":
                        //Console.WriteLine("Got mouse data from user: {0}x{1}", packet.MousePacket.X, packet.MousePacket.Y);
                        SendToAllExceptSender(packet, client);
                        break;

                    case "MOUSE_CLICK":
                        //Console.WriteLine("Got mouse data from user: {0}x{1}", packet.MousePacket.X, packet.MousePacket.Y);
                        SendToAllExceptSender(packet, client);
                        break;

                    case "KB":
                        //Console.WriteLine("Got mouse data from user: {0}x{1}", packet.MousePacket.X, packet.MousePacket.Y);
                        SendToAllExceptSender(packet, client);
                        break;

                    case "I":
                        SendToAllExceptSender(packet, client);
                        break;
                }
            }
        }