Пример #1
0
        private void ListenToReader()
        {
            int port = (spec.Side == NetworkSide.SERVER ? PortClient : PortServer);
            int UdpReceiveTimeout = 1000;

            UdpClient  Listener = null;
            IPEndPoint groupEP  = new IPEndPoint((IP == "127.0.0.1" ? IPAddress.Loopback : IPAddress.Any), port);

            try
            {
                Running = true;
                ConsoleEx.WriteLine($"UDP Server listening on Port {port}");

                while (Running)
                {
                    try
                    {
                        if (Listener == null)
                        {
                            Listener = new UdpClient(port);
                            Listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, UdpReceiveTimeout);
                        }
                    }
                    catch (SocketException ex)
                    {
                        if (ex.SocketErrorCode == SocketError.AddressAlreadyInUse)
                        {
                            ConsoleEx.WriteLine("UDP Socket Port Collision");
                        }
                        else
                        {
                            ConsoleEx.WriteLine(ex.ToString());
                        }

                        return;
                    }
                    catch (Exception ex)
                    {
                        ConsoleEx.WriteLine(ex.ToString());
                        return;
                    }

                    byte[] bytes = null;

                    try
                    {
                        bytes = Listener.Receive(ref groupEP);
                    }
                    catch (SocketException ex)
                    {
                        if (ex.SocketErrorCode == SocketError.TimedOut)
                        {
                            Listener?.Client?.Close();
                            Listener?.Close();
                            Listener = null;
                            continue;
                        }
                        else
                        {
                            throw ex;
                        }
                    }

                    spec.Connector.hub.QueueMessage(new NetCoreSimpleMessage(Encoding.ASCII.GetString(bytes, 0, bytes.Length)));
                }
            }
            catch (ThreadAbortException)
            {
                ConsoleEx.WriteLine("Ongoing UDPLink Thread Killed");
            }
            catch (Exception e)
            {
                ConsoleEx.WriteLine(e.ToString());
            }
            finally
            {
                Listener?.Client?.Close();
                Listener?.Close();
            }
        }
Пример #2
0
        private bool StartClient()
        {
            client = new TcpClient();
            TcpClient clientRef = client;

            try
            {
                IAsyncResult result  = null;
                bool         success = false;

                try
                {
                    result  = client.BeginConnect(IP, Port, null, null);
                    success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(200)); //This will block the thread for 200ms
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }

                if (!success || result == null || client == null)
                {
                    throw new Exception("Failed to connect");
                }

                client.EndConnect(result);
                clientStream = client.GetStream();

                if (streamReadingThread != null)
                {
                    streamReadingThread.Abort();
                    while (streamReadingThread != null && streamReadingThread.IsAlive)
                    {
                        System.Windows.Forms.Application.DoEvents();
                        Thread.Sleep(10);
                    } //Lets wait for the thread to die
                }

                streamReadingThread              = new Thread(() => StoreMessages(clientStream));
                streamReadingThread.Name         = "TCP CLIENT";
                streamReadingThread.IsBackground = true;
                streamReadingThread.Start();
                ConsoleEx.WriteLine($"Started new TCPLink Thread for CLIENT");
            }
            catch (Exception ex)
            {
                if (ex.Message != "Failed to connect")
                {
                    DiscardException(ex);
                }

                try
                {
                    clientStream?.Close();
                    clientStream = null;
                } catch { }

                try
                {
                    if (Object.ReferenceEquals(clientRef, client))
                    {
                        client?.Close();
                        client = null;
                    }
                }
                catch { }

                status = NetworkStatus.DISCONNECTED;
                ConsoleEx.WriteLine($"Connecting Failed");
                spec.Connector.hub.QueueMessage(new NetCoreAdvancedMessage("{EVENT_CLIENTCONNECTINGFAILED}"));
                //spec.OnClientConnectingFailed(null);

                return(false);
            }

            return(true);
        }
Пример #3
0
        internal bool ProcessAdvancedMessage(NetCoreMessage _message)
        {
            NetCoreAdvancedMessage message;

            if (_message is NetCoreAdvancedMessage)
            {
                message = (_message as NetCoreAdvancedMessage);
            }
            else
            {
                message = new NetCoreAdvancedMessage(_message.Type); // promote message to Advanced if simple ({BOOP} command goes through UDP Link)
            }
            if (!message.Type.StartsWith("{EVENT_") || ConsoleEx.ShowDebug)
            {
                ConsoleEx.WriteLine(spec.Side.ToString() + ":Process advanced message -> " + message.Type.ToString());
            }

            switch (message.Type)
            {
            // NetCore Internal Commands
            // Some of these commands go through the UDP Link but are upgraded to an Advanced Message
            // As they are parsed by the Message Hub

            case "{HI}":     //Greetings to confirm that communication is established

                expectingSomeone = true;
                status           = NetworkStatus.CONNECTED;

                if (spec.Side == NetworkSide.SERVER)
                {
                    //Server receives {HI} after client has established connection
                    ConsoleEx.WriteLine($"TCP Server Connected");
                    //spec.OnServerConnected(null);
                    spec.Connector.hub.QueueMessage(new NetCoreAdvancedMessage("{EVENT_SERVERCONNECTED}"));

                    SendMessage(new NetCoreAdvancedMessage("{HI}"));
                }
                else     //(side == NetworkSide.CLIENT)
                {
                    //Client always sends the first {HI} but will wait for the Server to reply with one
                    ConsoleEx.WriteLine($"TCP Client Connected to {IP}:{Port}");
                    //spec.OnClientConnected(null);
                    spec.Connector.hub.QueueMessage(new NetCoreAdvancedMessage("{EVENT_CLIENTCONNECTED}"));
                }



                break;

            case "{BYE}":     // End of disconnect
                Kill();
                break;

            case "{BOOP}":      // Ping system to confirm is TCP link is still in order
                                // Boops are redirected through the UDP pipe so if the TCP Link is busy transfering a lot of data
                                // or is jammed waiting for a return, these will still go through
                BoopMonitoringCounter = DefaultBoopMonitoringCounter;
                break;


            //THREADSAFE EVENT FIRING
            case "{EVENT_CLIENTCONNECTING}":
                spec.OnClientConnecting(null);
                break;

            case "{EVENT_CLIENTCONNECTINGFAILED}":
                spec.OnClientConnectingFailed(null);
                break;

            case "{EVENT_CLIENTCONNECTED}":
                spec.OnClientConnected(null);
                break;

            case "{EVENT_CLIENTDISCONNECTED}":
                spec.OnClientDisconnected(null);
                break;

            case "{EVENT_CLIENTCONNECTIONLOST}":
                spec.OnClientConnectionLost(null);
                break;

            case "{EVENT_SERVERLISTENING}":
                spec.OnServerListening(null);
                break;

            case "{EVENT_SERVERCONNECTED}":
                spec.OnServerConnected(null);
                break;

            case "{EVENT_SERVERDISCONNECTED}":
                spec.OnServerDisconnected(null);
                break;

            case "{EVENT_SERVERCONNECTIONLOST}":
                spec.OnServerConnectionLost(null);
                break;

            case "{EVENT_SYNCEDMESSAGESTART}":
                spec.OnSyncedMessageStart(null);
                break;

            case "{EVENT_SYNCEDMESSAGEEND}":
                spec.OnSyncedMessageEnd(null);
                break;


            default:
                //If message wasn't procesed, just return false
                //Message may be handled on an upper level
                return(false);
            }


            return(true);
        }
Пример #4
0
        internal void StopNetworking(bool stopGracefully = true, bool stayConnected = false)
        {
            TcpClient clientRef = client;

            if (stopGracefully)
            {   //If this is a graceful stop, try to say {BYE} before leaving
                lock (PeerMessageQueueLock)
                {
                    PeerMessageQueue.Clear();
                    spec.Connector.hub.SendMessage(new NetCoreAdvancedMessage("{BYE}"));
                    //When the {BYE} command gets sent, a {SAYBYE} command will be queued in own side's Message Hub.
                    //Both sides will then call StopNetworking with the stopGracefully flag set to false.
                }

                return;
            }

            BoopMonitoringTimer?.Stop();
            BoopMonitoringTimer = null;

            supposedToBeConnected = false;

            if (!stayConnected)
            {
                expectingSomeone = false;
            }

            if (spec.Side == NetworkSide.CLIENT)
            {
                if (stayConnected)
                {
                    ConsoleEx.WriteLine($"TCP Client Connection Lost");
                    //spec.OnClientConnectionLost(null);
                    spec.Connector.hub.QueueMessage(new NetCoreAdvancedMessage("{EVENT_CLIENTCONNECTIONLOST}"));
                }
                else
                {
                    ConsoleEx.WriteLine($"TCP Client Disconnected");
                    //spec.OnClientDisconnected(null);
                    spec.Connector.hub.QueueMessage(new NetCoreAdvancedMessage("{EVENT_CLIENTDISCONNECTED}"));
                }
            }
            else if (spec.Side == NetworkSide.SERVER)
            {
                if (stayConnected)
                {
                    ConsoleEx.WriteLine($"TCP Server Connection Lost");
                    //spec.OnServerConnectionLost(null);
                    spec.Connector.hub.QueueMessage(new NetCoreAdvancedMessage("{EVENT_SERVERCONNECTIONLOST}"));
                }
                else
                {
                    ConsoleEx.WriteLine($"TCP Server Disconnected");
                    //spec.OnServerDisconnected(null);
                    spec.Connector.hub.QueueMessage(new NetCoreAdvancedMessage("{EVENT_SERVERDISCONNECTED}"));
                }
            }

            status = (stayConnected ? NetworkStatus.CONNECTIONLOST : NetworkStatus.DISCONNECTED);

            lock (PeerMessageQueueLock)
                PeerMessageQueue.Clear();


            KillConnections(clientRef);

            spec.Connector.watch.Kill(); //Kills the ReturnWatch if waiting for a value
        }
Пример #5
0
 private void DiscardException(Exception ex)
 {
     //Discarded exception but write it in console
     ConsoleEx.WriteLine($"{spec.Side}:{status} -> {ex} \n Supposed to be connected -> {supposedToBeConnected} \n expectingsomeone -> {expectingSomeone} \n status -> {status} \n {ex.StackTrace}");
 }
Пример #6
0
        private void StoreMessages(NetworkStream providedStream)
        {
            var config = new SerializerConfig();

            config.Advanced.PersistTypeCache = true;
            config.OnResolveFormatter.Add((c, t) =>
            {
                if (t == typeof(HashSet <byte[]>))
                {
                    return(new NetCore.NetCore_Extensions.HashSetFormatterThatKeepsItsComparer());
                }
                return(null);                // continue searching
            });
            var serializer = new CerasSerializer(config);

            TcpListener   server        = null;
            Socket        socket        = null;
            NetworkStream networkStream = null;

            if (providedStream != null)
            {
                networkStream = providedStream;
            }

            try
            {
                if (networkStream == null)
                {
                    server = new TcpListener((IP == "127.0.0.1" ? IPAddress.Loopback : IPAddress.Any), Port);
                    server.Start();
                    socket        = KillableAcceptSocket(server);
                    networkStream = new NetworkStream(socket);

                    server.Stop();
                }

                networkStream.ReadTimeout  = 20;
                networkStream.WriteTimeout = int.MaxValue;  //Using {BOOP} commands routed through UDP/TCP

                if (spec.Side == NetworkSide.CLIENT)
                {
                    SendMessage(new NetCoreAdvancedMessage("{HI}"));    //The exchange of {HI} command confirms that link is established on Receiving
                }
                while (true)
                {
                    if (networkStream != null && networkStream.DataAvailable)
                    {
                        if (spec.Side == NetworkSide.SERVER && (!socket?.Connected ?? true))
                        {
                            return;
                        }

                        NetCoreAdvancedMessage message = null;

                        try
                        {
                            using (MemoryStream ms = new MemoryStream())
                            {
                                Stopwatch sw = new Stopwatch();
                                sw.Start();

                                //Read the size
                                int    lengthToReceive  = 0;
                                byte[] _lengthToReceive = new byte[4];
                                networkStream.Read(_lengthToReceive, 0, _lengthToReceive.Length);
                                lengthToReceive = BitConverter.ToInt32(_lengthToReceive, 0);

                                //Console.WriteLine("I want this many bytes: " + lengthToReceive);
                                //Now read until we have that many bytes
                                long bytesRead = CopyBytes(lengthToReceive, networkStream, ms);
                                //Console.WriteLine("I got this many bytes: " + bytesRead);

                                //Deserialize it
                                ms.Position = 0;

                                //cmd = (RTC_Command)binaryFormatter.Deserialize(ms);
                                var temp = ms.ToArray();
                                message = serializer.Deserialize <NetCoreAdvancedMessage>(temp);

                                sw.Stop();
                                if (message.Type != "{BOOP}" && sw.ElapsedMilliseconds > 50)
                                {
                                    Console.WriteLine("It took " + sw.ElapsedMilliseconds + " ms to deserialize cmd " + message.Type + " of " + temp.Length + " bytes");
                                }
                            }
                        }
                        catch { throw; }

                        if (message != null)
                        {
                            if (message.Type == "{RETURNVALUE}")
                            {
                                spec.Connector.watch.AddReturn(message);
                            }
                            else
                            {
                                spec.Connector.hub.QueueMessage(message);
                            }
                        }
                    }

                    while (PeerMessageQueue.Count > 0)
                    {
                        NetCoreMessage pendingMessage;

                        lock (PeerMessageQueueLock)
                        {
                            pendingMessage = PeerMessageQueue.First.Value;
                            PeerMessageQueue.RemoveFirst();
                        }

                        try
                        {
                            Stopwatch sw = new Stopwatch();
                            sw.Start();
                            //Write the length of the command to the first four bytes
                            byte[] buf = serializer.Serialize(pendingMessage);

                            //Write the length of the incoming object to the NetworkStream
                            byte[] length = BitConverter.GetBytes(buf.Length);
                            networkStream.Write(length, 0, length.Length);

                            networkStream.Write(buf, 0, buf.Length);
                            sw.Stop();
                            if (pendingMessage.Type != "{BOOP}" && sw.ElapsedMilliseconds > 50)
                            {
                                Console.WriteLine("It took " + sw.ElapsedMilliseconds + " ms to serialize backCmd " + pendingMessage.Type + " of " + buf.Length + " bytes");
                            }
                        }
                        catch
                        {
                            throw;
                        }

                        if (pendingMessage.Type == "{BYE}")
                        {
                            lock (PeerMessageQueueLock) //Since we're shutting down, let's clear the message queue
                                PeerMessageQueue?.Clear();
                        }

                        if (status == NetworkStatus.DISCONNECTED || status == NetworkStatus.CONNECTIONLOST)
                        {
                            //If the link's status changed from an outside factor, we want to stop the thread.

                            lock (PeerMessageQueueLock)
                                PeerMessageQueue?.Clear();

                            return;
                        }
                    }

                    Thread.Sleep(spec.messageReadTimerDelay);
                }
            }
            catch (Exception ex)
            {
                if (ex is ThreadAbortException)
                {
                    ConsoleEx.WriteLine("Ongoing TCPLink Thread Killed");
                }
                else if (ex.InnerException != null && ex.InnerException is SocketException)
                {
                    ConsoleEx.WriteLine("Ongoing TCPLink Socket Closed during use");
                }
                else if (ex is SerializationException)
                {
                    ConsoleEx.WriteLine("Ongoing TCPLink Closed during Serialization operation");
                }
                else if (ex is ObjectDisposedException)
                {
                    ConsoleEx.WriteLine("Ongoing TCPLink Closed during Socket acceptance");
                }
                else
                {
                    DiscardException(ex);
                }
            }
            finally
            {
                //Let's force close everything JUST IN CASE

                try
                {
                    networkStream?.Close();
                    networkStream?.Dispose();
                }
                catch { } //nobody cares why this failed


                try
                {
                    socket?.Shutdown(SocketShutdown.Both);
                    socket?.Dispose();
                }
                catch { } //nobody cares why this failed


                try
                {
                    server?.Stop();
                }
                catch (Exception ex)
                {
                    DiscardException(ex);
                }

                if (status == NetworkStatus.CONNECTED)
                {
                    status = (expectingSomeone ? NetworkStatus.CONNECTIONLOST : NetworkStatus.DISCONNECTED);
                }
                else if (status != NetworkStatus.CONNECTIONLOST)
                {
                    status = NetworkStatus.DISCONNECTED;
                }

                //Kill synced query if happenning
                spec.Connector.watch.Kill();
            }
        }
Пример #7
0
 private void DiscardException(Exception ex)
 {
     //Discarded exception but write it in console
     ConsoleEx.WriteLine($"{spec.Side}:{status} -> {ex}");
 }
Пример #8
0
        private void StoreMessages(NetworkStream providedStream)
        {
            var binaryFormatter = new BinaryFormatter();

            TcpListener   server        = null;
            Socket        socket        = null;
            NetworkStream networkStream = null;

            if (providedStream != null)
            {
                networkStream = providedStream;
            }

            try
            {
                if (networkStream == null)
                {
                    server = new TcpListener((IP == "127.0.0.1" ? IPAddress.Loopback : IPAddress.Any), Port);
                    server.Start();
                    socket        = KillableAcceptSocket(server);
                    networkStream = new NetworkStream(socket);

                    server.Stop();
                }

                networkStream.ReadTimeout  = int.MaxValue;  //We don't put a timeout because we can detect broken links
                networkStream.WriteTimeout = int.MaxValue;  //Using {BOOP} commands routed through UDP/TCP

                if (spec.Side == NetworkSide.CLIENT)
                {
                    SendMessage(new NetCoreAdvancedMessage("{HI}"));    //The exchange of {HI} command confirms that link is established on Receiving
                }
                while (true)
                {
                    if (networkStream != null && networkStream.DataAvailable)
                    {
                        NetCoreAdvancedMessage message;
                        try
                        {
                            message = (NetCoreAdvancedMessage)binaryFormatter.Deserialize(networkStream);   //This is blocking
                        }
                        catch { throw; }

                        if (message != null)
                        {
                            if (message.Type == "{RETURNVALUE}")
                            {
                                spec.Connector.watch.AddReturn(message);
                            }
                            else
                            {
                                spec.Connector.hub.QueueMessage(message);
                            }
                        }
                    }

                    while (PeerMessageQueue.Count > 0)
                    {
                        NetCoreMessage pendingMessage;

                        lock (PeerMessageQueueLock)
                        {
                            pendingMessage = PeerMessageQueue.First.Value;
                            PeerMessageQueue.RemoveFirst();
                        }

                        try
                        {
                            binaryFormatter.Serialize(networkStream, pendingMessage);
                        }
                        catch
                        {
                            throw;
                        }

                        if (pendingMessage.Type == "{BYE}")
                        {
                            lock (PeerMessageQueueLock) //Since we're shutting down, let's clear the message queue
                                PeerMessageQueue.Clear();
                        }

                        if (status == NetworkStatus.DISCONNECTED || status == NetworkStatus.CONNECTIONLOST)
                        {
                            //If the link's status changed from an outside factor, we want to stop the thread.

                            lock (PeerMessageQueueLock)
                                PeerMessageQueue.Clear();

                            return;
                        }
                    }

                    Thread.Sleep(spec.messageReadTimerDelay);
                }
            }
            catch (Exception ex)
            {
                if (ex is ThreadAbortException)
                {
                    ConsoleEx.WriteLine("Ongoing TCPLink Thread Killed");
                }
                else if (ex.InnerException != null && ex.InnerException is SocketException)
                {
                    ConsoleEx.WriteLine("Ongoing TCPLink Socket Closed during use");
                }
                else if (ex is SerializationException)
                {
                    ConsoleEx.WriteLine("Ongoing TCPLink Closed during Serialization operation");
                }
                else if (ex is ObjectDisposedException)
                {
                    ConsoleEx.WriteLine("Ongoing TCPLink Closed during Socket acceptance");
                }
                else
                {
                    DiscardException(ex);
                }
            }
            finally
            {
                //Let's force close everything JUST IN CASE

                try
                {
                    networkStream.Close();
                    networkStream.Dispose();
                }
                catch { } //nobody cares why this failed


                try
                {
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Dispose();
                }
                catch { } //nobody cares why this failed


                try
                {
                    server.Stop();
                }
                catch { } //nobody cares why this failed

                if (status == NetworkStatus.CONNECTED)
                {
                    status = (expectingSomeone ? NetworkStatus.CONNECTIONLOST : NetworkStatus.DISCONNECTED);
                }
                else if (status != NetworkStatus.CONNECTIONLOST)
                {
                    status = NetworkStatus.DISCONNECTED;
                }

                //Kill synced query if happenning
                spec.Connector.watch.Kill();
            }
        }