예제 #1
0
        protected void Ping()
        {
            while (Running && Pinging)
            {
                Thread.Sleep(PingSleep);

                lock (ClientsList) {
                    lock (ClientsDict) {
                        for (int e = ClientsList.Count - 1; e >= 0; e--)
                        {
                            TCPServerClient client = ClientsList[e];

                            try {
                                using (IOStream stream = new IOStream()) {
                                    stream.WriteDouble(client.RTT);
                                    stream.WriteString(DateTime.UtcNow.ToString("O"));

                                    byte[] arr = stream.ToArray();

                                    client.Send(new TCPMessage()
                                    {
                                        Code    = TCPMessageCode.Ping,
                                        Content = arr
                                    });
                                }
                            } catch (Exception er) {
                                RemoveClient(client, TCPDisconnectType.Timeout);
                            }
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Stop the server
        /// </summary>
        public void Stop()
        {
            if (Logging)
            {
                Logger.Write("REGION", "Method [Stop]");
            }

            if (Logging)
            {
                Logger.Write("INFO", "Stopping server");
            }

            Running = false;

            lock (ClientsList)
                lock (ClientsDict) {
                    for (int e = ClientsList.Count - 1; e >= 0; e--)
                    {
                        TCPServerClient client = ClientsList[e];

                        RemoveClient(client, TCPDisconnectType.Disconnect, e);
                    }
                }

            try {
                Socket.Shutdown(SocketShutdown.Both);
                Socket.Close();
            } catch (Exception er) {
            }

            ManagementThread.Join();
            ListenThread.Join();

            ListenThread     = new Thread(() => Listen());
            ManagementThread = new Thread(Management);

            Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
            Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
            Socket.Bind(new IPEndPoint(Address, Port));

            if (Logging)
            {
                Logger.Write("INFO", "Stopped server");
            }
        }
예제 #3
0
        /// <summary>
        /// Read tcp message off the stream
        /// </summary>
        /// <param name="client"></param>
        /// <returns></returns>
        public TCPMessage Read(TCPServerClient client)
        {
            byte first;

            try {
                first = (byte)Stream.ReadByte();
            } catch (Exception e) {
                return(null);
            }

            if (!IsClientConnected(client))
            {
                return(null);
            }

            byte second = (byte)Stream.ReadByte();
            uint len    = ReadLength(second);

            if (len != 0)
            {
                // solve encoded bytes xor

                byte[] key     = TCPReaderWriter.Read(Stream, 4);
                byte[] encoded = TCPReaderWriter.Read(Stream, len);
                byte[] decoded = new byte[len];

                for (int e = 0; e < encoded.Length; e++)
                {
                    decoded[e] = (byte)(encoded[e] ^ key[e % 4]);
                }

                return(new TCPMessage()
                {
                    Client = client,
                    Code = (TCPMessageCode)first,
                    Content = decoded,
                    Sent = DateTime.Now
                });
            }

            return(null);
        }
예제 #4
0
        /// <summary>
        /// Get appropiate stream of socket
        /// </summary>
        /// <param name="client"></param>
        /// <returns></returns>
        protected Stream GetStream(TCPServerClient client)
        {
            Stream stream = new NetworkStream(client.Socket);

            if (SSL == null)
            {
                return(stream);
            }

            try {
                SslStream sslStream = new SslStream(stream, false);
                var       task      = sslStream.AuthenticateAsServerAsync(SSL, false, SSLProtocol, true);
                task.Start();
                task.Wait();

                return(sslStream);
            } catch (Exception e) {
                return(null);
            }
        }
예제 #5
0
        /// <summary>
        /// Listen for new connections
        /// </summary>
        protected void Listen()
        {
            if (Logging)
            {
                Logger.Write("REGION", "Method [Listen]");
            }

            Socket.Listen(Backlog);

            if (Logging)
            {
                Logger.Write("INFO", "Start listening for clients");
            }

            while (Running)
            {
                Socket socket = Socket.Accept();

                if (Logging)
                {
                    Logger.Write("INFO", "New socket connected");
                }

                TCPServerClient client = new TCPServerClient(
                    socket, RandomGen.GenRandomUID(ClientsDict, UIDLength));

                client.Joined = DateTime.Now;

                Thread clientThread = new Thread(() => ListenClient(client));
                client.Thread = clientThread;

                clientThread.Start();

                if (Logging)
                {
                    Logger.Write("INFO", "Created client and started thread");
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Management to handle automated kicks etc
        /// </summary>
        protected void Management()
        {
            while (Running)
            {
                Thread.Sleep(ManagementSleep);

                lock (ClientsList) {
                    lock (ClientsDict) {
                        for (int e = ClientsList.Count - 1; e >= 0; e--)
                        {
                            TCPServerClient c = ClientsList[e];

                            if ((DateTime.Now - c.Joined) > HandshakeTimeout &&
                                RequireHandshake && !c.DoneHandshake)
                            {
                                RemoveClient(c, TCPDisconnectType.NoHandshake);
                            }
                        }
                    }
                }
            }
        }
예제 #7
0
 /// <summary>
 /// Check if client is still connected
 /// </summary>
 /// <param name="client"></param>
 /// <returns></returns>
 public static bool IsClientConnected(TCPServerClient client)
 {
     return(IsClientConnected(client.Socket));
 }
예제 #8
0
        /// <summary>
        /// Listen for new messages of individual clients
        /// </summary>
        /// <param name="client"></param>
        protected void ListenClient(TCPServerClient client)
        {
            if (Logging)
            {
                Logger.Write("REGION", "Method [ListenClient]");
            }

            using (Stream ns = GetStream(client)) {
                client.Stream = ns;

                client.Writer = new TCPWriter(ns);
                client.Reader = new TCPReader(ns);

                if (Logging)
                {
                    Logger.Write("INFO", "Created stream, writer and reader for client: " + client.UID);
                }

                lock (ClientsList) ClientsList.Add(client);
                lock (ClientsDict) ClientsDict.Add(client.UID, client);
                OnConnected?.Invoke(client);

                if (RequireHandshake)
                {
                    TCPMessage message = client.Reader.Read(client);

                    if (message.Code != TCPMessageCode.Init ||
                        message.Content.Length > 10)
                    {
                        RemoveClient(client, TCPDisconnectType.NoHandshake);
                        return;
                    }

                    if (Logging)
                    {
                        Logger.Write("SUCCESS", "Handshake: " + client.UID);
                    }

                    client.DoneHandshake = true;

                    client.Send(new TCPMessage()
                    {
                        Code    = TCPMessageCode.Init,
                        Content = new byte[] { 0, 1, 0 }
                    });
                }

                while (Running && ClientsDict.ContainsKey(client.UID))
                {
                    TCPMessage message = client.Reader.Read(client);

                    if (message == null)
                    {
                        RemoveClient(client, TCPDisconnectType.Timeout);
                        return;
                    }

                    if (Logging)
                    {
                        Logger.Write("INFO", "New message " + Enum.GetName(typeof(TCPMessageCode), message.Code) + " from user: " + client.UID);
                    }

                    if (message.Code == TCPMessageCode.Message)
                    {
                        OnMessage?.Invoke(client, message);
                    }
                }
            }
        }
예제 #9
0
        /// <summary>
        /// Removes a client from the server
        /// </summary>
        /// <param name="client"></param>
        /// <param name="type"></param>
        public void RemoveClient(TCPServerClient client, TCPDisconnectType type = TCPDisconnectType.Disconnect)
        {
            if (Logging)
            {
                Logger.Write("REGION", "Method [RemoveClient]");
            }

            if (type == TCPDisconnectType.NoHandshake)
            {
                if (Logging)
                {
                    Logger.Write("INFO", "Client no handshake: " + client.UID);
                }
                OnNoHandshake?.Invoke(client);
            }
            else if (type == TCPDisconnectType.Disconnect)
            {
                if (Logging)
                {
                    Logger.Write("INFO", "Client disconnect: " + client.UID);
                }
                OnDisconnected?.Invoke(client);
            }
            else if (type == TCPDisconnectType.Timeout)
            {
                if (Logging)
                {
                    Logger.Write("INFO", "Client timeout: " + client.UID);
                }
                OnTimeout?.Invoke(client);
            }
            else if (type == TCPDisconnectType.Kick)
            {
                if (Logging)
                {
                    Logger.Write("INFO", "Client kick: " + client.UID);
                }
                OnKick?.Invoke(client);
            }

            lock (ClientsDict) ClientsDict.Remove(client.UID);
            lock (ClientsList) {
                for (int e = ClientsList.Count - 1; e >= 0; e--)
                {
                    if (ClientsList[e].UID == client.UID)
                    {
                        if (Logging)
                        {
                            Logger.Write("INFO", "Client found in ClientsList: " + client.UID);
                        }
                        ClientsList.RemoveAt(e);
                        break;
                    }
                }
            }

            try {
                client.Socket.Shutdown(SocketShutdown.Both);
                client.Socket.Close();
            } catch (Exception e) {
                if (Logging)
                {
                    Logger.Write("FAILED", "Socket shutdown/close", e);
                }
            }
        }
예제 #10
0
 /// <summary>
 /// Kicks user
 /// </summary>
 /// <param name="client"></param>
 public void Kick(TCPServerClient client)
 {
     RemoveClient(client, TCPDisconnectType.Kick);
 }