protected override void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg)
        {
            LidgrenConnection lidgrenConn           = conn as LidgrenConnection;
            NetDeliveryMethod lidgrenDeliveryMethod = NetDeliveryMethod.Unreliable;

            switch (deliveryMethod)
            {
            case DeliveryMethod.Unreliable:
                lidgrenDeliveryMethod = NetDeliveryMethod.Unreliable;
                break;

            case DeliveryMethod.Reliable:
                lidgrenDeliveryMethod = NetDeliveryMethod.ReliableUnordered;
                break;

            case DeliveryMethod.ReliableOrdered:
                lidgrenDeliveryMethod = NetDeliveryMethod.ReliableOrdered;
                break;
            }

            NetOutgoingMessage lidgrenMsg = netServer.CreateMessage();

            lidgrenMsg.Write(msg.Buffer, 0, msg.LengthBytes);
            NetSendResult result = netServer.SendMessage(lidgrenMsg, lidgrenConn.NetConnection, lidgrenDeliveryMethod);

            if (result != NetSendResult.Sent && result != NetSendResult.Queued)
            {
                DebugConsole.NewMessage("Failed to send message to " + conn.Name + ": " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow);
            }
        }
예제 #2
0
        public override void Start(object endPoint, int ownerKey)
        {
            if (isActive)
            {
                return;
            }

            netPeerConfiguration = new NetPeerConfiguration("barotrauma");

            netPeerConfiguration.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt
                                                    | NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error);

            netClient = new NetClient(netPeerConfiguration);

            incomingLidgrenMessages = new List <NetIncomingMessage>();

            initializationStep = ConnectionInitialization.SteamTicketAndVersion;

            IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Loopback, Steam.SteamManager.STEAMP2P_OWNER_PORT);

            netClient.Start();
            ServerConnection        = new LidgrenConnection("Server", netClient.Connect(ipEndPoint), 0);
            ServerConnection.Status = NetworkConnectionStatus.Connected;

            remotePeers = new List <RemotePeer>();

            Steam.SteamManager.Instance.Networking.OnIncomingConnection = OnIncomingConnection;
            Steam.SteamManager.Instance.Networking.OnP2PData            = OnP2PData;
            Steam.SteamManager.Instance.Networking.SetListenChannel(0, true);
            Steam.SteamManager.Instance.Auth.OnAuthChange = OnAuthChange;

            isActive = true;
        }
예제 #3
0
        public override void Start(object endPoint, int ownerKey)
        {
            if (isActive)
            {
                return;
            }

            this.ownerKey = ownerKey;

            contentPackageOrderReceived = false;

            netPeerConfiguration = new NetPeerConfiguration("barotrauma")
            {
                UseDualModeSockets = GameMain.Config.UseDualModeSockets
            };

            netPeerConfiguration.DisableMessageType(NetIncomingMessageType.DebugMessage | NetIncomingMessageType.WarningMessage | NetIncomingMessageType.Receipt
                                                    | NetIncomingMessageType.ErrorMessage | NetIncomingMessageType.Error);

            netClient = new NetClient(netPeerConfiguration);

            if (SteamManager.IsInitialized)
            {
                steamAuthTicket = SteamManager.GetAuthSessionTicket();
                //TODO: wait for GetAuthSessionTicketResponse_t

                if (steamAuthTicket == null)
                {
                    throw new Exception("GetAuthSessionTicket returned null");
                }
            }

            incomingLidgrenMessages = new List <NetIncomingMessage>();

            initializationStep = ConnectionInitialization.SteamTicketAndVersion;

            if (!(endPoint is IPEndPoint ipEndPoint))
            {
                throw new InvalidCastException("endPoint is not IPEndPoint");
            }
            if (ServerConnection != null)
            {
                throw new InvalidOperationException("ServerConnection is not null");
            }

            netClient.Start();
            ServerConnection = new LidgrenConnection("Server", netClient.Connect(ipEndPoint), 0)
            {
                Status = NetworkConnectionStatus.Connected
            };

            isActive = true;
        }
        protected override void CheckOwnership(PendingClient pendingClient)
        {
            LidgrenConnection l = pendingClient.Connection as LidgrenConnection;

            if (OwnerConnection == null &&
                IPAddress.IsLoopback(l.NetConnection.RemoteEndPoint.Address.MapToIPv4NoThrow()) &&
                ownerKey != null && pendingClient.OwnerKey != 0 && pendingClient.OwnerKey == ownerKey)
            {
                ownerKey        = null;
                OwnerConnection = pendingClient.Connection;
            }
        }
예제 #5
0
        private void HandleDataMessage(NetIncomingMessage inc)
        {
            if (netServer == null)
            {
                return;
            }

            PendingClient pendingClient = pendingClients.Find(c => c.Connection == inc.SenderConnection);

            byte incByte      = inc.ReadByte();
            bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
            bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;

            if (isConnectionInitializationStep && pendingClient != null)
            {
                ReadConnectionInitializationStep(pendingClient, inc);
            }
            else if (!isConnectionInitializationStep)
            {
                LidgrenConnection conn = connectedClients.Find(c => c.NetConnection == inc.SenderConnection);
                if (conn == null)
                {
                    if (pendingClient != null)
                    {
                        RemovePendingClient(pendingClient, DisconnectReason.AuthenticationRequired, "Received data message from unauthenticated client");
                    }
                    else if (inc.SenderConnection.Status != NetConnectionStatus.Disconnected &&
                             inc.SenderConnection.Status != NetConnectionStatus.Disconnecting)
                    {
                        inc.SenderConnection.Disconnect(DisconnectReason.AuthenticationRequired.ToString() + "/ Received data message from unauthenticated client");
                    }
                    return;
                }
                if (pendingClient != null)
                {
                    pendingClients.Remove(pendingClient);
                }
                if (serverSettings.BanList.IsBanned(conn.IPEndPoint.Address, conn.SteamID, out string banReason))
                {
                    Disconnect(conn, DisconnectReason.Banned.ToString() + "/ " + banReason);
                    return;
                }
                UInt16 length = inc.ReadUInt16();

                //DebugConsole.NewMessage(isCompressed + " " + isConnectionInitializationStep + " " + (int)incByte + " " + length);

                IReadMessage msg = new ReadOnlyMessage(inc.Data, isCompressed, inc.PositionInBytes, length, conn);
                OnMessageReceived?.Invoke(conn, msg);
            }
        }
예제 #6
0
        private void OnAuthChange(Steamworks.SteamId steamID, Steamworks.SteamId ownerID, Steamworks.AuthResponse status)
        {
            if (netServer == null)
            {
                return;
            }

            PendingClient pendingClient = pendingClients.Find(c => c.SteamID == steamID);

            DebugConsole.Log(steamID + " validation: " + status + ", " + (pendingClient != null));

            if (pendingClient == null)
            {
                if (status != Steamworks.AuthResponse.OK)
                {
                    LidgrenConnection connection = connectedClients.Find(c => c.SteamID == steamID) as LidgrenConnection;
                    if (connection != null)
                    {
                        Disconnect(connection, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam authentication status changed: " + status.ToString());
                    }
                }
                return;
            }

            LidgrenConnection pendingConnection = pendingClient.Connection as LidgrenConnection;
            string            banReason;

            if (serverSettings.BanList.IsBanned(pendingConnection.NetConnection.RemoteEndPoint.Address, steamID, ownerID, out banReason))
            {
                RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason);
                return;
            }

            if (status == Steamworks.AuthResponse.OK)
            {
                pendingClient.OwnerSteamID       = ownerID;
                pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.ContentPackageOrder;
                pendingClient.UpdateTime         = Timing.TotalTime;
            }
            else
            {
                RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam authentication failed: " + status.ToString());
                return;
            }
        }
예제 #7
0
        private void OnAuthChange(ulong steamID, ulong ownerID, ServerAuth.Status status)
        {
            if (netServer == null)
            {
                return;
            }

            PendingClient pendingClient = pendingClients.Find(c => c.SteamID == steamID);

            DebugConsole.Log(steamID + " validation: " + status + ", " + (pendingClient != null));

            if (pendingClient == null)
            {
                if (status != ServerAuth.Status.OK)
                {
                    LidgrenConnection connection = connectedClients.Find(c => c.SteamID == steamID);
                    if (connection != null)
                    {
                        Disconnect(connection, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam authentication status changed: " + status.ToString());
                    }
                }
                return;
            }

            if (serverSettings.BanList.IsBanned(pendingClient.Connection.RemoteEndPoint.Address, steamID))
            {
                RemovePendingClient(pendingClient, DisconnectReason.Banned, "SteamID banned");
                return;
            }

            if (status == ServerAuth.Status.OK)
            {
                pendingClient.InitializationStep = serverSettings.HasPassword ? ConnectionInitialization.Password : ConnectionInitialization.Success;
                pendingClient.UpdateTime         = Timing.TotalTime;
            }
            else
            {
                RemovePendingClient(pendingClient, DisconnectReason.SteamAuthenticationFailed, "Steam authentication failed: " + status.ToString());
                return;
            }
        }
예제 #8
0
        private void HandleStatusChanged(NetIncomingMessage inc)
        {
            if (netServer == null)
            {
                return;
            }

            switch (inc.SenderConnection.Status)
            {
            case NetConnectionStatus.Disconnected:
                string            disconnectMsg;
                LidgrenConnection conn = connectedClients.Find(c => c.NetConnection == inc.SenderConnection);
                if (conn != null)
                {
                    if (conn == OwnerConnection)
                    {
                        DebugConsole.NewMessage("Owner disconnected: closing the server...");
                        GameServer.Log("Owner disconnected: closing the server...", ServerLog.MessageType.ServerMessage);
                        Close(DisconnectReason.ServerShutdown.ToString() + "/ Owner disconnected");
                    }
                    else
                    {
                        disconnectMsg = $"ServerMessage.HasDisconnected~[client]={conn.Name}";
                        Disconnect(conn, disconnectMsg);
                    }
                }
                else
                {
                    PendingClient pendingClient = pendingClients.Find(c => c.Connection == inc.SenderConnection);
                    if (pendingClient != null)
                    {
                        disconnectMsg = $"ServerMessage.HasDisconnected~[client]={pendingClient.Name}";
                        RemovePendingClient(pendingClient, disconnectMsg);
                    }
                }
                break;
            }
        }
예제 #9
0
        private void UpdatePendingClient(PendingClient pendingClient, float deltaTime)
        {
            if (netServer == null)
            {
                return;
            }

            if (serverSettings.BanList.IsBanned(pendingClient.Connection.RemoteEndPoint.Address, pendingClient.SteamID ?? 0, out string banReason))
            {
                RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason);
                return;
            }

            //DebugConsole.NewMessage("pending client status: " + pendingClient.InitializationStep);

            if (connectedClients.Count >= serverSettings.MaxPlayers)
            {
                RemovePendingClient(pendingClient, DisconnectReason.ServerFull, "");
            }

            if (pendingClient.InitializationStep == ConnectionInitialization.Success)
            {
                LidgrenConnection newConnection = new LidgrenConnection(pendingClient.Name, pendingClient.Connection, pendingClient.SteamID ?? 0)
                {
                    Status = NetworkConnectionStatus.Connected
                };
                connectedClients.Add(newConnection);
                pendingClients.Remove(pendingClient);

                if (OwnerConnection == null &&
                    IPAddress.IsLoopback(pendingClient.Connection.RemoteEndPoint.Address.MapToIPv4NoThrow()) &&
                    ownerKey != null && pendingClient.OwnerKey != 0 && pendingClient.OwnerKey == ownerKey)
                {
                    ownerKey        = null;
                    OwnerConnection = newConnection;
                }

                OnInitializationComplete?.Invoke(newConnection);
                return;
            }


            pendingClient.TimeOut -= deltaTime;
            if (pendingClient.TimeOut < 0.0)
            {
                RemovePendingClient(pendingClient, DisconnectReason.Unknown, Lidgren.Network.NetConnection.NoResponseMessage);
            }

            if (Timing.TotalTime < pendingClient.UpdateTime)
            {
                return;
            }
            pendingClient.UpdateTime = Timing.TotalTime + 1.0;

            NetOutgoingMessage outMsg = netServer.CreateMessage();

            outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
            outMsg.Write((byte)pendingClient.InitializationStep);
            switch (pendingClient.InitializationStep)
            {
            case ConnectionInitialization.ContentPackageOrder:
                var mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent).ToList();
                outMsg.WriteVariableInt32(mpContentPackages.Count);
                for (int i = 0; i < mpContentPackages.Count; i++)
                {
                    outMsg.Write(mpContentPackages[i].MD5hash.Hash);
                }
                break;

            case ConnectionInitialization.Password:
                outMsg.Write(pendingClient.PasswordSalt == null); outMsg.WritePadBits();
                if (pendingClient.PasswordSalt == null)
                {
                    pendingClient.PasswordSalt = CryptoRandom.Instance.Next();
                    outMsg.Write(pendingClient.PasswordSalt.Value);
                }
                else
                {
                    outMsg.Write(pendingClient.Retries);
                }
                break;
            }
#if DEBUG
            netPeerConfiguration.SimulatedDuplicatesChance = GameMain.Server.SimulatedDuplicatesChance;
            netPeerConfiguration.SimulatedMinimumLatency   = GameMain.Server.SimulatedMinimumLatency;
            netPeerConfiguration.SimulatedRandomLatency    = GameMain.Server.SimulatedRandomLatency;
            netPeerConfiguration.SimulatedLoss             = GameMain.Server.SimulatedLoss;
#endif
            NetSendResult result = netServer.SendMessage(outMsg, pendingClient.Connection, NetDeliveryMethod.ReliableUnordered);
            if (result != NetSendResult.Sent && result != NetSendResult.Queued)
            {
                DebugConsole.NewMessage("Failed to send initialization step " + pendingClient.InitializationStep.ToString() + " to pending client: " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow);
            }
            //DebugConsole.NewMessage("sent update to pending client: " + pendingClient.InitializationStep);
        }
예제 #10
0
        private void UpdatePendingClient(PendingClient pendingClient, float deltaTime)
        {
            if (netServer == null)
            {
                return;
            }

            if (serverSettings.BanList.IsBanned(pendingClient.Connection.RemoteEndPoint.Address, pendingClient.SteamID ?? 0))
            {
                RemovePendingClient(pendingClient, DisconnectReason.Banned.ToString());
                return;
            }

            //DebugConsole.NewMessage("pending client status: " + pendingClient.InitializationStep);

            if (connectedClients.Count >= serverSettings.MaxPlayers)
            {
                RemovePendingClient(pendingClient, DisconnectReason.ServerFull.ToString());
            }

            if (pendingClient.InitializationStep == ConnectionInitialization.Success)
            {
                LidgrenConnection newConnection = new LidgrenConnection(pendingClient.Name, pendingClient.Connection, pendingClient.SteamID ?? 0);
                newConnection.Status = NetworkConnectionStatus.Connected;
                connectedClients.Add(newConnection);
                pendingClients.Remove(pendingClient);

                if (OwnerConnection == null &&
                    IPAddress.IsLoopback(pendingClient.Connection.RemoteEndPoint.Address.MapToIPv4()) &&
                    ownerKey != null && pendingClient.OwnerKey != 0 && pendingClient.OwnerKey == ownerKey)
                {
                    ownerKey        = null;
                    OwnerConnection = newConnection;
                }

                OnInitializationComplete?.Invoke(newConnection);
                return;
            }


            pendingClient.TimeOut -= deltaTime;
            if (pendingClient.TimeOut < 0.0)
            {
                RemovePendingClient(pendingClient, Lidgren.Network.NetConnection.NoResponseMessage);
            }

            if (Timing.TotalTime < pendingClient.UpdateTime)
            {
                return;
            }
            pendingClient.UpdateTime = Timing.TotalTime + 1.0;

            NetOutgoingMessage outMsg = netServer.CreateMessage();

            outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
            outMsg.Write((byte)pendingClient.InitializationStep);
            switch (pendingClient.InitializationStep)
            {
            case ConnectionInitialization.Password:
                outMsg.Write(pendingClient.PasswordSalt == null); outMsg.WritePadBits();
                if (pendingClient.PasswordSalt == null)
                {
                    pendingClient.PasswordSalt = CryptoRandom.Instance.Next();
                    outMsg.Write(pendingClient.PasswordSalt.Value);
                }
                else
                {
                    outMsg.Write(pendingClient.Retries);
                }
                break;
            }

            NetSendResult result = netServer.SendMessage(outMsg, pendingClient.Connection, NetDeliveryMethod.ReliableUnordered);

            if (result != NetSendResult.Sent && result != NetSendResult.Queued)
            {
                DebugConsole.NewMessage("Failed to send initialization step " + pendingClient.InitializationStep.ToString() + " to pending client: " + result.ToString(), Microsoft.Xna.Framework.Color.Yellow);
            }
            //DebugConsole.NewMessage("sent update to pending client: "+result);
        }