Пример #1
0
        internal object SendSyncedMessage(NetCoreAdvancedMessage message, bool priority = false)
        {
            //A synced will block the sender's thread until a response is received

            if (!IsSendingAdvancedMessageAuthorized(message))
            {
                return(null);
            }

            message.requestGuid = Guid.NewGuid();

            lock (PeerMessageQueueLock)
            {
                if (priority)
                {
                    PeerMessageQueue.AddFirst(message);
                }
                else
                {
                    PeerMessageQueue.AddLast(message);
                }
            }

            ConsoleEx.WriteLine($"{spec.Side.ToString()}:Sent synced advanced message \"{message.Type.ToString()}\", priority:{priority.ToString()}");

            return(spec.Connector.watch.GetValue((Guid)message.requestGuid, message.Type)); //This will lock here until value is returned from peer
        }
Пример #2
0
        public void AddReturn(NetCoreAdvancedMessage message)
        {
            if (!message.requestGuid.HasValue)
            {
                return;
            }

            SyncReturns.TryAdd(message.requestGuid.Value, message.objectValue);
        }
Пример #3
0
        public void setReturnValue(object _objectValue)
        {
            var message = new NetCoreAdvancedMessage("{RETURNVALUE}")
            {
                objectValue = _objectValue
            };

            if (returnMessage != null)
            {
                RTCV.Common.Logging.GlobalLogger.Warn($"NetCoreEventArgs: ReturnValue was already set but was overriden with another value");
            }

            _returnMessage = message;
        }
Пример #4
0
        internal bool IsSendingAdvancedMessageAuthorized(NetCoreAdvancedMessage message)
        {
            if (message.Type == "{HI}") // {HI} is the only command that can go blindly through the pipe before the link is established
            {
                return(true);
            }
            else if (status != NetworkStatus.CONNECTED)
            {
                ConsoleEx.WriteLine($"{spec.Side.ToString()} -> Can't send message \"{message.Type.ToString()}\", link is not established");
                return(false);
            }

            return(true);
        }
Пример #5
0
        public void setReturnValue(object _objectValue)
        {
            var message = new NetCoreAdvancedMessage("{RETURNVALUE}")
            {
                objectValue = _objectValue
            };

            if (returnMessage != null)
            {
                ConsoleEx.WriteLine($"ReturnValue was already set but was overriden with another value");
            }

            _returnMessage = message;
        }
Пример #6
0
        internal void SendMessage(NetCoreAdvancedMessage message, bool priority = false)
        {
            if (!IsSendingAdvancedMessageAuthorized(message))
            {
                return;
            }

            lock (PeerMessageQueueLock)
            {
                if (priority) //If there is a stream of data occuring, priority ensures that a message will skip the line and gets sent ASAP
                {
                    PeerMessageQueue.AddFirst(message);
                }
                else
                {
                    PeerMessageQueue.AddLast(message);
                }
            }

            ConsoleEx.WriteLine($"{spec.Side.ToString()} -> Sent advanced message \"{message.Type.ToString()}\", priority:{priority.ToString()}");
        }
Пример #7
0
 public NetCoreEventArgs(string type, object objectValue)
 {
     message = new NetCoreAdvancedMessage(type, objectValue);
 }
Пример #8
0
 public void AddReturn(NetCoreAdvancedMessage message)
 {
     SyncReturns.Add((Guid)message.requestGuid, message.objectValue);
 }
Пример #9
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);
        }
Пример #10
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();
            }
        }