/// <summary>
        /// Disconnects the network system. You should kill threads ONLY from main thread
        /// </summary>
        /// <param name="reason">Reason</param>
        public static void Disconnect(string reason = "unknown")
        {
            lock (DisconnectLock)
            {
                if (MainSystem.NetworkState > ClientState.Disconnected)
                {
                    LunaLog.Log($"[LMP]: Disconnected, reason: {reason}");
                    if (!HighLogic.LoadedSceneIsEditor && !HighLogic.LoadedSceneIsFlight)
                    {
                        SystemsContainer.Get <MainSystem>().ForceQuit = true;
                    }
                    else
                    {
                        //User is in flight so just display a message but don't force him to main menu...
                        NetworkSystem.DisplayDisconnectMessage = true;
                    }

                    SystemsContainer.Get <MainSystem>().Status = $"Disconnected: {reason}";

                    //DO NOT set networkstate as disconnected as we are in another thread!
                    MainSystem.NetworkState = ClientState.DisconnectRequested;

                    NetworkMain.ClientConnection.Disconnect(reason);
                    NetworkMain.ClientConnection.Shutdown(reason);
                    NetworkMain.ResetConnectionStaticsAndQueues();
                }
            }
        }
        /// <summary>
        /// Disconnects the network system. You should kill threads ONLY from main thread
        /// </summary>
        /// <param name="reason">Reason</param>
        public static void Disconnect(string reason = "unknown")
        {
            lock (DisconnectLock)
            {
                if (MainSystem.Singleton.NetworkState != ClientState.DISCONNECTED)
                {
                    Debug.Log("[LMP]: Disconnected, reason: " + reason);
                    if (!HighLogic.LoadedSceneIsEditor && !HighLogic.LoadedSceneIsFlight)
                    {
                        MainSystem.Singleton.ForceQuit = true;
                    }
                    else
                    {
                        //User is in flight so just display a message but don't force him to main menu...
                        MainSystem.Singleton.DisplayDisconnectMessage = true;
                    }

                    MainSystem.Singleton.GameRunning  = false;
                    MainSystem.Singleton.Status       = "Disconnected: " + reason;
                    MainSystem.Singleton.NetworkState = ClientState.DISCONNECTED;
                    NetworkMain.ClientConnection.Disconnect(reason);
                    NetworkMain.ClientConnection.Shutdown(reason);
                    NetworkMain.ResetConnectionStaticsAndQueues();
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Sends the network message. It will skip client messages to send when we are not connected
        /// </summary>
        /// <param name="message"></param>
        private static void SendNetworkMessage(IMessageBase message)
        {
            if (NetworkMain.ClientConnection.Status == NetPeerStatus.NotRunning)
            {
                NetworkMain.ClientConnection.Start();
            }

            var clientMessage    = message as IClientMessageBase;
            var masterSrvMessage = message as IMasterServerMessageBase;

            if (clientMessage?.MessageType == ClientMessageType.SyncTime)
            {
                SystemsContainer.Get <TimeSyncerSystem>().RewriteMessage(message.Data);
            }

            message.Data.SentTime = DateTime.UtcNow.Ticks;
            var bytes = message.Serialize(SettingsSystem.CurrentSettings.CompressionEnabled);

            if (bytes != null)
            {
                try
                {
                    NetworkStatistics.LastSendTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

                    if (masterSrvMessage != null && clientMessage == null)
                    {
                        foreach (var masterServer in NetworkServerList.MasterServers)
                        {
                            //Create a new message for every main server otherwise lidgren complains when you reuse the msg
                            var lidgrenMsg = NetworkMain.ClientConnection.CreateMessage(bytes.Length);
                            lidgrenMsg.Write(message.Serialize(SettingsSystem.CurrentSettings.CompressionEnabled));

                            NetworkMain.ClientConnection.SendUnconnectedMessage(lidgrenMsg, masterServer);
                            NetworkMain.ClientConnection.FlushSendQueue();
                        }
                    }
                    else
                    {
                        if (SystemsContainer.Get <MainSystem>().NetworkState >= ClientState.Connected)
                        {
                            var lidgrenMsg = NetworkMain.ClientConnection.CreateMessage(bytes.Length);
                            lidgrenMsg.Write(message.Serialize(SettingsSystem.CurrentSettings.CompressionEnabled));
                            NetworkMain.ClientConnection.SendMessage(lidgrenMsg, message.NetDeliveryMethod, message.Channel);
                        }
                    }

                    NetworkMain.ClientConnection.FlushSendQueue();
                }
                catch (Exception e)
                {
                    NetworkMain.HandleDisconnectException(e);
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Sends the network message. It will skip client messages to send when we are not connected
        /// </summary>
        /// <param name="message"></param>
        private static void SendNetworkMessage(IMessageBase message)
        {
            if (NetworkMain.ClientConnection.Status == NetPeerStatus.NotRunning)
            {
                NetworkMain.ClientConnection.Start();
            }

            message.Data.SentTime = LunaNetworkTime.UtcNow.Ticks;
            try
            {
                NetworkStatistics.LastSendTime = LunaNetworkTime.UtcNow;

                if (message is IMasterServerMessageBase)
                {
                    foreach (var masterServer in NetworkServerList.MasterServers)
                    {
                        //Don't reuse lidgren messages, he does that on it's own
                        var lidgrenMsg = NetworkMain.ClientConnection.CreateMessage(message.GetMessageSize());

                        message.Serialize(lidgrenMsg);
                        NetworkMain.ClientConnection.SendUnconnectedMessage(lidgrenMsg, masterServer);

                        //Force send of packets
                        NetworkMain.ClientConnection.FlushSendQueue();
                    }
                }
                else
                {
                    if (MainSystem.NetworkState >= ClientState.Connected)
                    {
                        var lidgrenMsg = NetworkMain.ClientConnection.CreateMessage(message.GetMessageSize());

                        message.Serialize(lidgrenMsg);
                        NetworkMain.ClientConnection.SendMessage(lidgrenMsg, message.NetDeliveryMethod, message.Channel);
                    }
                }

                //Force send of packets
                NetworkMain.ClientConnection.FlushSendQueue();
                message.Recycle();
            }
            catch (Exception e)
            {
                NetworkMain.HandleDisconnectException(e);
            }
        }
        private static void ConnectToServerAddress(IPEndPoint destination)
        {
            try
            {
                var outmsg = NetworkMain.ClientConnection.CreateMessage(1);
                outmsg.Write((byte)NetIncomingMessageType.ConnectionApproval);

                NetworkMain.ClientConnection.Start();
                NetworkMain.ClientConnection.Connect(destination);
                NetworkMain.ClientConnection.FlushSendQueue();

                var connectionTrials = 0;
                while (MainSystem.NetworkState == ClientState.Connecting &&
                       NetworkMain.ClientConnection.ConnectionStatus == NetConnectionStatus.Disconnected &&
                       connectionTrials <= SettingsSystem.CurrentSettings.ConnectionTries)
                {
                    connectionTrials++;
                    Thread.Sleep(SettingsSystem.CurrentSettings.MsBetweenConnectionTries);
                }

                if (NetworkMain.ClientConnection.ConnectionStatus != NetConnectionStatus.Disconnected)
                {
                    LunaLog.Log($"[LMP]: Connected to {destination.Address} port {destination.Port}");
                    SystemsContainer.Get <MainSystem>().Status = "Connected";
                    MainSystem.NetworkState = ClientState.Connected;
                    NetworkSender.OutgoingMessages.Enqueue(NetworkMain.CliMsgFactory.CreateNew <HandshakeCliMsg>(new HandshakeRequestMsgData()));
                }
                else if (MainSystem.NetworkState == ClientState.Connecting)
                {
                    LunaLog.LogError("[LMP]: Failed to connect within the timeout!");
                    Disconnect("Initial connection timeout");
                }
            }
            catch (Exception e)
            {
                NetworkMain.HandleDisconnectException(e);
            }
        }
Exemple #6
0
        /// <summary>
        /// Main receiveing thread
        /// </summary>
        public static void ReceiveMain()
        {
            try
            {
                while (!NetworkConnection.ResetRequested)
                {
                    if (NetworkMain.ClientConnection.ReadMessage(out var msg))
                    {
                        NetworkStatistics.LastReceiveTime = LunaNetworkTime.UtcNow;
                        switch (msg.MessageType)
                        {
                        case NetIncomingMessageType.DebugMessage:
                            LunaLog.Log("[Lidgen DEBUG] " + msg.ReadString());
                            break;

                        case NetIncomingMessageType.VerboseDebugMessage:
                            LunaLog.Log("[Lidgen VERBOSE] " + msg.ReadString());
                            break;

                        case NetIncomingMessageType.NatIntroductionSuccess:
                            NetworkServerList.HandleNatIntroduction(msg);
                            break;

                        case NetIncomingMessageType.ConnectionLatencyUpdated:
                            NetworkStatistics.PingMs = (float)TimeSpan.FromSeconds(msg.ReadFloat()).TotalMilliseconds;
                            break;

                        case NetIncomingMessageType.UnconnectedData:
                            NetworkServerList.HandleServersList(msg);
                            break;

                        case NetIncomingMessageType.Data:
                            try
                            {
                                var deserializedMsg = NetworkMain.SrvMsgFactory.Deserialize(msg, LunaNetworkTime.UtcNow.Ticks);
                                if (deserializedMsg != null)
                                {
                                    EnqueueMessageToSystem(deserializedMsg as IServerMessageBase);
                                }
                            }
                            catch (Exception e)
                            {
                                LunaLog.LogError($"[LMP]: Error deserializing message! {e}");
                            }
                            break;

                        case NetIncomingMessageType.StatusChanged:
                            switch ((NetConnectionStatus)msg.ReadByte())
                            {
                            case NetConnectionStatus.Disconnected:
                                var reason = msg.ReadString();
                                NetworkConnection.Disconnect(reason);
                                break;
                            }
                            break;

                        default:
                            LunaLog.Log($"[LMP]: LIDGREN: {msg.MessageType} -- {msg.PeekString()}");
                            break;
                        }
                        NetworkMain.ClientConnection.Recycle(msg);
                    }
                    else
                    {
                        Thread.Sleep(SettingsSystem.CurrentSettings.SendReceiveMsInterval);
                    }
                }
            }
            catch (Exception e)
            {
                LunaLog.LogError($"[LMP]: Receive message thread error: {e}");
                NetworkMain.HandleDisconnectException(e);
            }
        }
        /// <summary>
        /// Main receiveing thread
        /// </summary>
        public static void ReceiveMain()
        {
            try
            {
                while (!MainSystem.Singleton.Quit)
                {
                    NetIncomingMessage msg;
                    while (NetworkMain.ClientConnection.ReadMessage(out msg))
                    {
                        NetworkStatistics.LastReceiveTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                        switch (msg.MessageType)
                        {
                        case NetIncomingMessageType.NatIntroductionSuccess:
                            NetworkServerList.HandleNatIntroduction(msg);
                            break;

                        case NetIncomingMessageType.ConnectionLatencyUpdated:
                            NetworkStatistics.PingMs = (float)TimeSpan.FromSeconds(msg.ReadFloat()).TotalMilliseconds;
                            break;

                        case NetIncomingMessageType.UnconnectedData:
                            NetworkServerList.HandleServersList(msg);
                            break;

                        case NetIncomingMessageType.Data:
                            try
                            {
                                var deserializedMsg = NetworkMain.SrvMsgFactory.Deserialize(msg.ReadBytes(msg.LengthBytes), DateTime.UtcNow.Ticks);
                                EnqueueMessageToSystem(deserializedMsg as IServerMessageBase);
                            }
                            catch (Exception e)
                            {
                                Debug.LogError("[LMP]: Error deserializing message!");
                                NetworkMain.HandleDisconnectException(e);
                            }
                            break;

                        case NetIncomingMessageType.StatusChanged:
                            switch ((NetConnectionStatus)msg.ReadByte())
                            {
                            case NetConnectionStatus.Disconnected:
                                var reason = msg.ReadString();
                                NetworkConnection.Disconnect(reason);
                                break;
                            }
                            break;

                        default:
                            Debug.Log("[LMP]: LIDGREN: " + msg.MessageType + "-- " + msg.PeekString());
                            break;
                        }
                    }

                    Thread.Sleep(SettingsSystem.CurrentSettings.SendReceiveMsInterval);
                }
            }
            catch (Exception e)
            {
                Debug.LogError("[LMP]: Receive message thread error: " + e);
                NetworkMain.HandleDisconnectException(e);
            }
        }
        private static void ConnectToServer(string endpointString, string serverPassword)
        {
            if (NetworkMain.ClientConnection.Status == NetPeerStatus.NotRunning)
            {
                NetworkMain.ClientConnection.Start();
            }

            if (MainSystem.NetworkState <= ClientState.Disconnected)
            {
                var endpoint = CreateEndpoint(endpointString);
                if (endpoint == null)
                {
                    return;
                }

                MainSystem.Singleton.Status = $"Connecting to {endpoint.Address}:{endpoint.Port}";
                LunaLog.Log($"[LMP]: Connecting to {endpoint.Address} port {endpoint.Port}");

                MainSystem.NetworkState = ClientState.Connecting;
                try
                {
                    var outmsg = NetworkMain.ClientConnection.CreateMessage(serverPassword.GetByteCount());
                    outmsg.Write(serverPassword);

                    NetworkMain.ClientConnection.Connect(endpoint, outmsg);
                    NetworkMain.ClientConnection.FlushSendQueue();

                    var connectionTrials = 0;
                    while (MainSystem.NetworkState >= ClientState.Connecting &&
                           NetworkMain.ClientConnection.ConnectionStatus != NetConnectionStatus.Connected &&
                           connectionTrials < SettingsSystem.CurrentSettings.ConnectionTries)
                    {
                        connectionTrials++;
                        Thread.Sleep(SettingsSystem.CurrentSettings.MsBetweenConnectionTries);
                    }

                    if (NetworkMain.ClientConnection.ConnectionStatus == NetConnectionStatus.Connected)
                    {
                        LunaLog.Log($"[LMP]: Connected to {endpoint.Address}:{endpoint.Port}");
                        MainSystem.NetworkState = ClientState.Connected;
                    }
                    else
                    {
                        if (MainSystem.NetworkState == ClientState.Connecting)
                        {
                            Disconnect("Initial connection timeout");
                        }
                        else
                        {
                            Disconnect("Cancelled connection");
                        }
                    }
                }
                catch (Exception e)
                {
                    NetworkMain.HandleDisconnectException(e);
                }
            }
            else
            {
                LunaLog.LogError("[LMP]: Cannot connect when we are already trying to connect");
            }
        }