예제 #1
0
        /// <summary> Processes incoming UDP packet, then starts the listener again. </summary>
        private static void HandleUDPData(IAsyncResult Result)
        {
            UdpClient  Listener;
            IPEndPoint ReceivedEndpoint;

            byte[] Data;
            string ClientName;

            try
            {
                Listener         = (UdpClient)Result.AsyncState;
                ReceivedEndpoint = new IPEndPoint(IPAddress.Any, 0);
                Data             = Listener.EndReceive(Result, ref ReceivedEndpoint);
                ClientName       = FindClient(ReceivedEndpoint, true);
            }
            catch (Exception Exc)
            {
                Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Failed to receive UDP data.");
                Log.Exception(Log.Source.NETWORK, Exc);
                return;
            }
            if (Data.Length == 0) // TODO: Can this happen?
            {
                Log.Output(Log.Severity.INFO, Log.Source.NETWORK, "Client has disconnected.");
                if (ClientName != null)
                {
                    lock (Clients[ClientName]) { Clients[ClientName].Connected = false; }
                }
            }
            else
            {
                if (ClientName == null) // New client
                {
                    try { ClientName = UtilData.ToString(Data); } catch { }
                    if (ClientName != null && ClientName.Length > 0)
                    {
                        Log.Output(Log.Severity.INFO, Log.Source.NETWORK, "UDP Client connected with name \"" + ClientName + "\".");
                        lock (Clients)
                        {
                            if (Clients.ContainsKey(ClientName))
                            {
                                Clients[ClientName].EndpointUDP = ReceivedEndpoint;
                                Clients[ClientName].Connected   = true;
                            }
                            else
                            {
                                ScarletClient NewClient = new ScarletClient()
                                {
                                    EndpointUDP = ReceivedEndpoint,
                                    Name        = ClientName,
                                    Connected   = true
                                };
                                Clients.Add(ClientName, NewClient);
                            }
                        }

                        // Create buffer for the client
                        CreateBufferIfClientIsNew(ClientName);
                    }
                    else
                    {
                        Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "UDP Client sent invalid name upon connecting.");
                    }
                }
                else // Existing client
                {
                    Packet ReceivedPack = new Packet(new Message(Data), false, ClientName);
                    ReceiveQueue.Enqueue(ReceivedPack);

                    if (StorePackets)
                    {
                        PacketsReceived.Add(ReceivedPack);
                    }
                }
            }
            Listener.BeginReceive(HandleUDPData, Listener);
        }
예제 #2
0
        /// <summary>
        /// Waits for, and receives data from a connected TCP client.
        /// This must be started on a thread, as it will block until CommHandler.Stopping is true, or the client disconnects.
        /// </summary>
        /// <param name="ClientObj"> The client to receive data from. Must be TcpClient. </param>
        private static void HandleTCPClient(object ClientObj)
        {
            TcpClient     Client  = (TcpClient)ClientObj;
            NetworkStream Receive = Client.GetStream();

            if (!Receive.CanRead)
            {
                Log.Output(Log.Severity.ERROR, Log.Source.NETWORK, "Client connection does not permit reading.");
                throw new Exception("NetworkStream does not support reading");
            }
            // Receive client name.
            String ClientName;

            byte[] DataBuffer = new byte[Math.Max(ReceiveBufferSize, 64)];
            try
            {
                int DataSize = Receive.Read(DataBuffer, 0, DataBuffer.Length);
                if (DataSize == 0)
                {
                    Receive?.Close();
                    if (!Stopping)
                    {
                        Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Client disconnected before sending name.");
                    }
                    return;
                }
                else
                {
                    ClientName = null;
                    try { ClientName = UtilData.ToString(DataBuffer.Take(DataSize).ToArray()); } catch { }
                    if (ClientName != null && ClientName.Length > 0)
                    {
                        Log.Output(Log.Severity.INFO, Log.Source.NETWORK, "TCP Client connected with name \"" + ClientName + "\".");
                        lock (Clients)
                        {
                            if (Clients.ContainsKey(ClientName))
                            {
                                Clients[ClientName].TCP       = Client;
                                Clients[ClientName].Connected = true;
                            }
                            else
                            {
                                ScarletClient NewClient = new ScarletClient()
                                {
                                    TCP       = Client,
                                    Name      = ClientName,
                                    Connected = true
                                };
                                Clients.Add(ClientName, NewClient);
                            }
                        }

                        // Create buffer for the client
                        CreateBufferIfClientIsNew(ClientName);
                    }
                    else
                    {
                        Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Invalid TCP client name received. Dropping connection.");
                    }
                }
            }
            catch (Exception Exc)
            {
                Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Failed to read name from incoming client. Dropping connection.");
                Log.Exception(Log.Source.NETWORK, Exc);
                Receive?.Close();
                return;
            }
            ClientConnChange(new EventArgs());
            WatchdogManager.AddWatchdog(ClientName);

            // Receive data from client.
            DataBuffer = new byte[ReceiveBufferSize];
            while (!Stopping && Clients[ClientName].Connected)
            {
                try
                {
                    int DataSize = Receive.Read(DataBuffer, 0, DataBuffer.Length);
                    Log.Output(Log.Severity.DEBUG, Log.Source.NETWORK, "Received data from client (TCP).");
                    if (DataSize == 0)
                    {
                        Log.Output(Log.Severity.INFO, Log.Source.NETWORK, "Client has disconnected.");
                        lock (Clients[ClientName]) { Clients[ClientName].Connected = false; }
                        break;
                    }
                    if (DataSize >= 5)
                    {
                        byte[]     Data           = DataBuffer.Take(DataSize).ToArray();
                        IPEndPoint ClientEndpoint = (IPEndPoint)Client.Client.RemoteEndPoint;
                        Packet     ReceivedPack   = new Packet(new Message(Data), false, ClientName);
                        ReceiveQueue.Enqueue(ReceivedPack);

                        if (StorePackets)
                        {
                            PacketsReceived.Add(ReceivedPack);
                        }
                    }
                    else
                    {
                        Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Data received from client was too short. Discarding.");
                    }
                }
                catch (IOException IOExc)
                {
                    if (IOExc.InnerException is SocketException)
                    {
                        int Error = ((SocketException)IOExc.InnerException).ErrorCode;
                        Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Failed to read data from connected client with SocketExcpetion code " + Error);
                        Log.Exception(Log.Source.NETWORK, IOExc);
                        if (Error == 10054)
                        {
                            Clients[ClientName].Connected = false;
                        }
                    }
                    else
                    {
                        Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Failed to read data from connected client because of IO exception.");
                        Log.Exception(Log.Source.NETWORK, IOExc);
                    }
                }
                catch (Exception OtherExc)
                {
                    Log.Output(Log.Severity.WARNING, Log.Source.NETWORK, "Failed to read data from connected client.");
                    Log.Exception(Log.Source.NETWORK, OtherExc);
                }
                Thread.Sleep(OperationPeriod);
            }
            lock (Clients) { Clients.Remove(ClientName); }
            Client.Client.Disconnect(true);
            Receive.Close();
            Client.Close();
            ClientConnChange(new EventArgs());
        }