Пример #1
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);
        }
Пример #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 { }

                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
 private void DiscardException(Exception ex)
 {
     //Discarded exception but write it in console
     ConsoleEx.WriteLine($"{spec.Side}:{status} -> {ex}");
 }
Пример #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 && (status == NetworkStatus.CONNECTED || status == NetworkStatus.CONNECTING))
            {
                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 && (status == NetworkStatus.CONNECTED || status == NetworkStatus.LISTENING))
            {
                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 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();
            }
        }