public override void Send(IWriteMessage msg, NetworkConnection conn, DeliveryMethod deliveryMethod)
        {
            if (!started)
            {
                return;
            }

            if (!(conn is SteamP2PConnection steamp2pConn))
            {
                return;
            }
            if (!connectedClients.Contains(steamp2pConn) && conn != OwnerConnection)
            {
                DebugConsole.ThrowError("Tried to send message to unauthenticated connection: " + steamp2pConn.SteamID.ToString());
                return;
            }

            IWriteMessage msgToSend = new WriteOnlyMessage();

            byte[] msgData = new byte[msg.LengthBytes];
            msg.PrepareForSending(ref msgData, out bool isCompressed, out int length);
            msgToSend.Write(conn.SteamID);
            msgToSend.Write((byte)deliveryMethod);
            msgToSend.Write((byte)((isCompressed ? PacketHeader.IsCompressed : PacketHeader.None) | PacketHeader.IsServerMessage));
            msgToSend.Write((UInt16)length);
            msgToSend.Write(msgData, 0, length);

            byte[] bufToSend = (byte[])msgToSend.Buffer.Clone();
            Array.Resize(ref bufToSend, msgToSend.LengthBytes);
            ChildServerRelay.Write(bufToSend);
        }
        public override void Close(string msg = null)
        {
            if (!isActive)
            {
                return;
            }

            SteamManager.LeaveLobby();

            isActive = false;

            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write((byte)DeliveryMethod.Reliable);
            outMsg.Write((byte)PacketHeader.IsDisconnectMessage);
            outMsg.Write(msg ?? "Disconnected");

            SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes,
                                                           Facepunch.Steamworks.Networking.SendType.Reliable);

            Thread.Sleep(100);

            Steam.SteamManager.Instance.Networking.OnIncomingConnection = null;
            Steam.SteamManager.Instance.Networking.OnP2PData            = null;
            Steam.SteamManager.Instance.Networking.SetListenChannel(0, false);

            Steam.SteamManager.Instance.Networking.CloseSession(hostSteamId);

            steamAuthTicket?.Cancel(); steamAuthTicket = null;
            hostSteamId = 0;

            OnDisconnect?.Invoke();
        }
        public override void Close(string msg = null, bool disableReconnect = false)
        {
            if (!isActive)
            {
                return;
            }

            SteamManager.LeaveLobby();

            isActive = false;

            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write((byte)DeliveryMethod.Reliable);
            outMsg.Write((byte)PacketHeader.IsDisconnectMessage);
            outMsg.Write(msg ?? "Disconnected");

            Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
            sentBytes += outMsg.LengthBytes;

            Thread.Sleep(100);

            Steamworks.SteamNetworking.ResetActions();

            Steamworks.SteamNetworking.CloseP2PSessionWithUser(hostSteamId);

            steamAuthTicket?.Cancel(); steamAuthTicket = null;
            hostSteamId = 0;

            OnDisconnect?.Invoke(disableReconnect);
        }
        protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg)
        {
            Steamworks.P2PSend sendType;
            switch (deliveryMethod)
            {
            case DeliveryMethod.Reliable:
            case DeliveryMethod.ReliableOrdered:
                //the documentation seems to suggest that the Reliable send type
                //enforces packet order (TODO: verify)
                sendType = Steamworks.P2PSend.Reliable;
                break;

            default:
                sendType = Steamworks.P2PSend.Unreliable;
                break;
            }

            IWriteMessage msgToSend = new WriteOnlyMessage();

            msgToSend.Write((byte)deliveryMethod);
            msgToSend.Write(msg.Buffer, 0, msg.LengthBytes);

            heartbeatTimer = 5.0;
            Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, msgToSend.Buffer, msgToSend.LengthBytes, 0, sendType);
            sentBytes += msg.LengthBytes;
        }
Beispiel #5
0
        /// <summary>
        /// Write the events to the outgoing message. The recipient parameter is only needed for ServerEntityEventManager
        /// </summary>
        protected void Write(IWriteMessage msg, List <NetEntityEvent> eventsToSync, out List <NetEntityEvent> sentEvents, Client recipient = null)
        {
            //write into a temporary buffer so we can write the number of events before the actual data
            IWriteMessage tempBuffer = new WriteOnlyMessage();

            sentEvents = new List <NetEntityEvent>();

            int eventCount = 0;

            foreach (NetEntityEvent e in eventsToSync)
            {
                //write into a temporary buffer so we can write the length before the actual data
                IWriteMessage tempEventBuffer = new WriteOnlyMessage();
                try
                {
                    WriteEvent(tempEventBuffer, e, recipient);
                }

                catch (Exception exception)
                {
                    DebugConsole.ThrowError("Failed to write an event for the entity \"" + e.Entity + "\"", exception);
                    GameAnalyticsManager.AddErrorEventOnce("NetEntityEventManager.Write:WriteFailed" + e.Entity.ToString(),
                                                           GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                           "Failed to write an event for the entity \"" + e.Entity + "\"\n" + exception.StackTrace.CleanupStackTrace());

                    //write an empty event to avoid messing up IDs
                    //(otherwise the clients might read the next event in the message and think its ID
                    //is consecutive to the previous one, even though we skipped over this broken event)
                    tempBuffer.Write(Entity.NullEntityID);
                    tempBuffer.WritePadBits();
                    eventCount++;
                    continue;
                }

                if (eventCount > 0 &&
                    msg.LengthBytes + tempBuffer.LengthBytes + tempEventBuffer.LengthBytes > MaxEventBufferLength)
                {
                    //no more room in this packet
                    break;
                }

                tempBuffer.Write(e.EntityID);
                tempBuffer.WriteVariableUInt32((uint)tempEventBuffer.LengthBytes);
                tempBuffer.Write(tempEventBuffer.Buffer, 0, tempEventBuffer.LengthBytes);
                tempBuffer.WritePadBits();
                sentEvents.Add(e);

                eventCount++;
            }

            if (eventCount > 0)
            {
                msg.Write(eventsToSync[0].ID);
                msg.Write((byte)eventCount);
                msg.Write(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
            }
        }
        public override void Update(float deltaTime)
        {
            if (!isActive)
            {
                return;
            }

            timeout        -= deltaTime;
            heartbeatTimer -= deltaTime;

            if (heartbeatTimer < 0.0)
            {
                IWriteMessage outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)DeliveryMethod.Unreliable);
                outMsg.Write((byte)PacketHeader.IsHeartbeatMessage);

                SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes,
                                                               Facepunch.Steamworks.Networking.SendType.Unreliable);

                heartbeatTimer = 5.0;
            }

            if (timeout < 0.0)
            {
                Close("Timed out");
                return;
            }

            if (initializationStep != ConnectionInitialization.Success)
            {
                if (incomingDataMessages.Count > 0)
                {
                    OnInitializationComplete?.Invoke();
                    initializationStep = ConnectionInitialization.Success;
                }
                else
                {
                    foreach (IReadMessage inc in incomingInitializationMessages)
                    {
                        ReadConnectionInitializationStep(inc);
                    }
                }
            }

            if (initializationStep == ConnectionInitialization.Success)
            {
                foreach (IReadMessage inc in incomingDataMessages)
                {
                    OnMessageReceived?.Invoke(inc);
                }
            }

            incomingInitializationMessages.Clear();
            incomingDataMessages.Clear();
        }
        protected override void SendMsgInternal(NetworkConnection conn, DeliveryMethod deliveryMethod, IWriteMessage msg)
        {
            IWriteMessage msgToSend = new WriteOnlyMessage();

            msgToSend.Write(conn.SteamID);
            msgToSend.Write((byte)deliveryMethod);
            msgToSend.Write(msg.Buffer, 0, msg.LengthBytes);
            byte[] bufToSend = (byte[])msgToSend.Buffer.Clone();
            Array.Resize(ref bufToSend, msgToSend.LengthBytes);
            ChildServerRelay.Write(bufToSend);
        }
        public override void Start()
        {
            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write(OwnerSteamID);
            outMsg.Write((byte)DeliveryMethod.Reliable);
            outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep | PacketHeader.IsServerMessage));

            byte[] msgToSend = (byte[])outMsg.Buffer.Clone();
            Array.Resize(ref msgToSend, outMsg.LengthBytes);
            ChildServerRelay.Write(msgToSend);

            started = true;
        }
        public override void Start(object endPoint, int ownerKey)
        {
            contentPackageOrderReceived = false;

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

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

            if (!(endPoint is UInt64 steamIdEndpoint))
            {
                throw new InvalidCastException("endPoint is not UInt64");
            }

            hostSteamId = steamIdEndpoint;

            Steamworks.SteamNetworking.ResetActions();
            Steamworks.SteamNetworking.OnP2PSessionRequest   = OnIncomingConnection;
            Steamworks.SteamNetworking.OnP2PConnectionFailed = OnConnectionFailed;

            Steamworks.SteamNetworking.AllowP2PPacketRelay(true);

            ServerConnection = new SteamP2PConnection("Server", hostSteamId);
            ServerConnection.SetOwnerSteamIDIfUnknown(hostSteamId);

            incomingInitializationMessages = new List <IReadMessage>();
            incomingDataMessages           = new List <IReadMessage>();

            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write((byte)DeliveryMethod.Reliable);
            outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
            outMsg.Write((byte)ConnectionInitialization.ConnectionStarted);

            Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
            sentBytes += outMsg.LengthBytes;

            initializationStep = ConnectionInitialization.SteamTicketAndVersion;

            timeout               = NetworkConnection.TimeoutThreshold;
            heartbeatTimer        = 1.0;
            connectionStatusTimer = 0.0;

            isActive = true;
        }
Beispiel #10
0
        public void SendToClients(List <Client> clients)
        {
            foreach (VoipQueue queue in queues)
            {
                if (queue.LastReadTime < DateTime.Now - VoipConfig.SEND_INTERVAL)
                {
                    continue;
                }

                if (lastSendTime.ContainsKey(queue))
                {
                    if ((lastSendTime[queue] + VoipConfig.SEND_INTERVAL) > DateTime.Now)
                    {
                        continue;
                    }
                    lastSendTime[queue] = DateTime.Now;
                }
                else
                {
                    lastSendTime.Add(queue, DateTime.Now);
                }

                Client sender = clients.Find(c => c.VoipQueue == queue);

                foreach (Client recipient in clients)
                {
                    if (recipient == sender)
                    {
                        continue;
                    }

                    if (!CanReceive(sender, recipient))
                    {
                        continue;
                    }

                    IWriteMessage msg = new WriteOnlyMessage();

                    msg.Write((byte)ServerPacketHeader.VOICE);
                    msg.Write((byte)queue.QueueID);
                    queue.Write(msg);

                    netServer.Send(msg, recipient.Connection, DeliveryMethod.Unreliable);
                }
            }
        }
        public override void Start(object endPoint, int ownerKey)
        {
            steamAuthTicket = SteamManager.GetAuthSessionTicket();
            //TODO: wait for GetAuthSessionTicketResponse_t

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

            if (!(endPoint is UInt64 steamIdEndpoint))
            {
                throw new InvalidCastException("endPoint is not UInt64");
            }

            hostSteamId = steamIdEndpoint;

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

            ServerConnection = new SteamP2PConnection("Server", hostSteamId);

            incomingInitializationMessages = new List <IReadMessage>();
            incomingDataMessages           = new List <IReadMessage>();

            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write((byte)DeliveryMethod.Reliable);
            outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
            outMsg.Write((byte)ConnectionInitialization.ConnectionStarted);

            SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes,
                                                           Facepunch.Steamworks.Networking.SendType.Reliable);

            initializationStep = ConnectionInitialization.SteamTicketAndVersion;

            timeout        = NetworkConnection.TimeoutThreshold;
            heartbeatTimer = 1.0;

            isActive = true;
        }
Beispiel #12
0
        public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod)
        {
            if (!isActive)
            {
                return;
            }

            IWriteMessage msgToSend = new WriteOnlyMessage();

            byte[] msgData = new byte[msg.LengthBytes];
            msg.PrepareForSending(ref msgData, out bool isCompressed, out int length);
            msgToSend.Write(selfSteamID);
            msgToSend.Write((byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None));
            msgToSend.Write((UInt16)length);
            msgToSend.Write(msgData, 0, length);

            byte[] bufToSend = (byte[])msgToSend.Buffer.Clone();
            Array.Resize(ref bufToSend, msgToSend.LengthBytes);
            ChildServerRelay.Write(bufToSend);
        }
Beispiel #13
0
        private void DisconnectPeer(RemotePeer peer, string msg)
        {
            if (!string.IsNullOrWhiteSpace(msg))
            {
                if (peer.DisconnectTime == null)
                {
                    peer.DisconnectTime = Timing.TotalTime + 1.0;
                }

                IWriteMessage outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)(PacketHeader.IsServerMessage | PacketHeader.IsDisconnectMessage));
                outMsg.Write(msg);

                Steamworks.SteamNetworking.SendP2PPacket(peer.SteamID, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
            }
            else
            {
                ClosePeerSession(peer);
            }
        }
        private void SendDisconnectMessage(UInt64 steamId, string msg)
        {
            if (!started)
            {
                return;
            }
            if (string.IsNullOrWhiteSpace(msg))
            {
                return;
            }

            IWriteMessage msgToSend = new WriteOnlyMessage();

            msgToSend.Write(steamId);
            msgToSend.Write((byte)DeliveryMethod.Reliable);
            msgToSend.Write((byte)(PacketHeader.IsDisconnectMessage | PacketHeader.IsServerMessage));
            msgToSend.Write(msg);

            byte[] bufToSend = (byte[])msgToSend.Buffer.Clone();
            Array.Resize(ref bufToSend, msgToSend.LengthBytes);
            ChildServerRelay.Write(bufToSend);
        }
Beispiel #15
0
        public override void SendPassword(string password)
        {
            if (!isActive)
            {
                return;
            }

            if (initializationStep != ConnectionInitialization.Password)
            {
                return;
            }
            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write((byte)DeliveryMethod.Reliable);
            outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
            outMsg.Write((byte)ConnectionInitialization.Password);
            byte[] saltedPw = ServerSettings.SaltPassword(Encoding.UTF8.GetBytes(password), passwordSalt);
            outMsg.Write((byte)saltedPw.Length);
            outMsg.Write(saltedPw, 0, saltedPw.Length);

            heartbeatTimer = 5.0;
            Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
        }
        public void SendToServer()
        {
            if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Disabled)
            {
                if (VoipCapture.Instance != null)
                {
                    storedBufferID = VoipCapture.Instance.LatestBufferID;
                    VoipCapture.Instance.Dispose();
                }
                return;
            }
            else
            {
                if (VoipCapture.Instance == null)
                {
                    VoipCapture.Create(GameMain.Config.VoiceCaptureDevice, storedBufferID);
                }
                if (VoipCapture.Instance == null || VoipCapture.Instance.EnqueuedTotalLength <= 0)
                {
                    return;
                }
            }

            if (DateTime.Now >= lastSendTime + VoipConfig.SEND_INTERVAL)
            {
                IWriteMessage msg = new WriteOnlyMessage();

                msg.Write((byte)ClientPacketHeader.VOICE);
                msg.Write((byte)VoipCapture.Instance.QueueID);
                VoipCapture.Instance.Write(msg);

                netClient.Send(msg, DeliveryMethod.Unreliable);

                lastSendTime = DateTime.Now;
            }
        }
        public override void SendPassword(string password)
        {
            if (!isActive)
            {
                return;
            }

            if (initializationStep != ConnectionInitialization.Password)
            {
                return;
            }
            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write((byte)DeliveryMethod.Reliable);
            outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
            outMsg.Write((byte)ConnectionInitialization.Password);
            byte[] saltedPw = ServerSettings.SaltPassword(Lidgren.Network.NetUtility.ComputeSHAHash(Encoding.UTF8.GetBytes(password)), passwordSalt);
            outMsg.Write((byte)saltedPw.Length);
            outMsg.Write(saltedPw, 0, saltedPw.Length);

            heartbeatTimer = 5.0;
            SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes,
                                                           Facepunch.Steamworks.Networking.SendType.Reliable);
        }
        private void ReadConnectionInitializationStep(IReadMessage inc)
        {
            if (!isActive)
            {
                return;
            }

            ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();

            //DebugConsole.NewMessage(step + " " + initializationStep);
            switch (step)
            {
            case ConnectionInitialization.SteamTicketAndVersion:
                if (initializationStep != ConnectionInitialization.SteamTicketAndVersion)
                {
                    return;
                }
                IWriteMessage outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)DeliveryMethod.Reliable);
                outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
                outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
                outMsg.Write(Name);
                outMsg.Write(SteamManager.GetSteamID());
                outMsg.Write((UInt16)steamAuthTicket.Data.Length);
                outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);

                outMsg.Write(GameMain.Version.ToString());

                IEnumerable <ContentPackage> mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
                outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count());
                foreach (ContentPackage contentPackage in mpContentPackages)
                {
                    outMsg.Write(contentPackage.Name);
                    outMsg.Write(contentPackage.MD5hash.Hash);
                }

                heartbeatTimer = 5.0;
                SteamManager.Instance.Networking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes,
                                                               Facepunch.Steamworks.Networking.SendType.Reliable);
                break;

            case ConnectionInitialization.Password:
                if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
                {
                    initializationStep = ConnectionInitialization.Password;
                }
                if (initializationStep != ConnectionInitialization.Password)
                {
                    return;
                }
                bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
                int  retries      = 0;
                if (incomingSalt)
                {
                    passwordSalt = inc.ReadInt32();
                }
                else
                {
                    retries = inc.ReadInt32();
                }
                OnRequestPassword?.Invoke(passwordSalt, retries);
                break;
            }
        }
        public override void Update(float deltaTime)
        {
            if (!isActive)
            {
                return;
            }

            timeout        -= deltaTime;
            heartbeatTimer -= deltaTime;

            if (initializationStep != ConnectionInitialization.Password &&
                initializationStep != ConnectionInitialization.ContentPackageOrder &&
                initializationStep != ConnectionInitialization.Success)
            {
                connectionStatusTimer -= deltaTime;
                if (connectionStatusTimer <= 0.0)
                {
                    var state = Steamworks.SteamNetworking.GetP2PSessionState(hostSteamId);
                    if (state == null)
                    {
                        Close("SteamP2P connection could not be established");
                        OnDisconnectMessageReceived?.Invoke("SteamP2P connection could not be established");
                    }
                    else
                    {
                        if (state?.P2PSessionError != Steamworks.P2PSessionError.None)
                        {
                            Close($"SteamP2P error code: {state?.P2PSessionError}");
                            OnDisconnectMessageReceived?.Invoke($"SteamP2P error code: {state?.P2PSessionError}");
                        }
                    }
                    connectionStatusTimer = 1.0f;
                }
            }

            for (int i = 0; i < 100; i++)
            {
                if (!Steamworks.SteamNetworking.IsP2PPacketAvailable())
                {
                    break;
                }
                var packet = Steamworks.SteamNetworking.ReadP2PPacket();
                if (packet.HasValue)
                {
                    OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0);
                    receivedBytes += packet?.Data.Length ?? 0;
                }
            }

            GameMain.Client?.NetStats?.AddValue(NetStats.NetStatType.ReceivedBytes, receivedBytes);
            GameMain.Client?.NetStats?.AddValue(NetStats.NetStatType.SentBytes, sentBytes);

            if (heartbeatTimer < 0.0)
            {
                IWriteMessage outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)DeliveryMethod.Unreliable);
                outMsg.Write((byte)PacketHeader.IsHeartbeatMessage);

                Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Unreliable);
                sentBytes += outMsg.LengthBytes;

                heartbeatTimer = 5.0;
            }

            if (timeout < 0.0)
            {
                Close("Timed out");
                OnDisconnectMessageReceived?.Invoke("");
                return;
            }

            if (initializationStep != ConnectionInitialization.Success)
            {
                if (incomingDataMessages.Count > 0)
                {
                    OnInitializationComplete?.Invoke();
                    initializationStep = ConnectionInitialization.Success;
                }
                else
                {
                    foreach (IReadMessage inc in incomingInitializationMessages)
                    {
                        ReadConnectionInitializationStep(inc);
                    }
                }
            }

            if (initializationStep == ConnectionInitialization.Success)
            {
                foreach (IReadMessage inc in incomingDataMessages)
                {
                    OnMessageReceived?.Invoke(inc);
                }
            }

            incomingInitializationMessages.Clear();
            incomingDataMessages.Clear();
        }
Beispiel #20
0
        protected void ReadConnectionInitializationStep(IReadMessage inc)
        {
            ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();

            IWriteMessage outMsg;

            switch (step)
            {
            case ConnectionInitialization.SteamTicketAndVersion:
                if (initializationStep != ConnectionInitialization.SteamTicketAndVersion)
                {
                    return;
                }
                outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
                outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
                outMsg.Write(Name);
                outMsg.Write(ownerKey);
                outMsg.Write(SteamManager.GetSteamID());
                if (steamAuthTicket == null)
                {
                    outMsg.Write((UInt16)0);
                }
                else
                {
                    outMsg.Write((UInt16)steamAuthTicket.Data.Length);
                    outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);
                }
                outMsg.Write(GameMain.Version.ToString());
                outMsg.Write(GameMain.Config.Language);

                SendMsgInternal(DeliveryMethod.Reliable, outMsg);
                break;

            case ConnectionInitialization.ContentPackageOrder:
                if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
                    initializationStep == ConnectionInitialization.Password)
                {
                    initializationStep = ConnectionInitialization.ContentPackageOrder;
                }
                if (initializationStep != ConnectionInitialization.ContentPackageOrder)
                {
                    return;
                }
                outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
                outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);

                string serverName = inc.ReadString();

                UInt32 cpCount = inc.ReadVariableUInt32();
                ServerContentPackage        corePackage     = null;
                List <ServerContentPackage> regularPackages = new List <ServerContentPackage>();
                List <ServerContentPackage> missingPackages = new List <ServerContentPackage>();
                for (int i = 0; i < cpCount; i++)
                {
                    string name       = inc.ReadString();
                    string hash       = inc.ReadString();
                    UInt64 workshopId = inc.ReadUInt64();
                    var    pkg        = new ServerContentPackage(name, hash, workshopId);
                    if (pkg.CorePackage != null)
                    {
                        corePackage = pkg;
                    }
                    else if (pkg.RegularPackage != null)
                    {
                        regularPackages.Add(pkg);
                    }
                    else
                    {
                        missingPackages.Add(pkg);
                    }
                }

                if (missingPackages.Count > 0)
                {
                    var nonDownloadable = missingPackages.Where(p => p.WorkshopId == 0);

                    if (nonDownloadable.Any())
                    {
                        string disconnectMsg;
                        if (nonDownloadable.Count() == 1)
                        {
                            disconnectMsg = $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}";
                        }
                        else
                        {
                            List <string> packageStrs = new List <string>();
                            nonDownloadable.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
                            disconnectMsg = $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}";
                        }
                        Close(disconnectMsg, disableReconnect: true);
                        OnDisconnectMessageReceived?.Invoke(DisconnectReason.MissingContentPackage + "/" + disconnectMsg);
                    }
                    else
                    {
                        Close(disableReconnect: true);

                        string missingModNames   = "\n";
                        int    displayedModCount = 0;
                        foreach (ServerContentPackage missingPackage in missingPackages)
                        {
                            missingModNames += "\n- " + GetPackageStr(missingPackage);
                            displayedModCount++;
                            if (GUI.Font.MeasureString(missingModNames).Y > GameMain.GraphicsHeight * 0.5f)
                            {
                                missingModNames += "\n\n" + TextManager.GetWithVariable("workshopitemdownloadprompttruncated", "[number]", (missingPackages.Count - displayedModCount).ToString());
                                break;
                            }
                        }
                        missingModNames += "\n\n";

                        var msgBox = new GUIMessageBox(
                            TextManager.Get("WorkshopItemDownloadTitle"),
                            TextManager.GetWithVariable("WorkshopItemDownloadPrompt", "[items]", missingModNames),
                            new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
                        msgBox.Buttons[0].OnClicked = (yesBtn, userdata) =>
                        {
                            GameMain.ServerListScreen.Select();
                            GameMain.ServerListScreen.DownloadWorkshopItems(missingPackages.Select(p => p.WorkshopId), serverName, ServerConnection.EndPointString);
                            return(true);
                        };
                        msgBox.Buttons[0].OnClicked += msgBox.Close;
                        msgBox.Buttons[1].OnClicked  = msgBox.Close;
                    }

                    return;
                }

                if (!contentPackageOrderReceived)
                {
                    GameMain.Config.BackUpModOrder();
                    GameMain.Config.SwapPackages(corePackage.CorePackage, regularPackages.Select(p => p.RegularPackage).ToList());
                    contentPackageOrderReceived = true;
                }

                SendMsgInternal(DeliveryMethod.Reliable, outMsg);
                break;

            case ConnectionInitialization.Password:
                if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
                {
                    initializationStep = ConnectionInitialization.Password;
                }
                if (initializationStep != ConnectionInitialization.Password)
                {
                    return;
                }
                bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
                int  retries      = 0;
                if (incomingSalt)
                {
                    passwordSalt = inc.ReadInt32();
                }
                else
                {
                    retries = inc.ReadInt32();
                }
                OnRequestPassword?.Invoke(passwordSalt, retries);
                break;
            }
        }
Beispiel #21
0
        public void Update(float deltaTime)
        {
            activeTransfers.RemoveAll(t => t.Connection.Status != NetworkConnectionStatus.Connected);

            var endedTransfers = activeTransfers.FindAll(t =>
                                                         t.Connection.Status != NetworkConnectionStatus.Connected ||
                                                         t.Status == FileTransferStatus.Finished ||
                                                         t.Status == FileTransferStatus.Canceled ||
                                                         t.Status == FileTransferStatus.Error);

            foreach (FileTransferOut transfer in endedTransfers)
            {
                activeTransfers.Remove(transfer);
                OnEnded(transfer);
            }

            foreach (FileTransferOut transfer in activeTransfers)
            {
                transfer.WaitTimer -= deltaTime;
                if (transfer.WaitTimer > 0.0f)
                {
                    continue;
                }

                transfer.WaitTimer = 0.05f;// transfer.Connection.AverageRoundtripTime;

                // send another part of the file
                long remaining     = transfer.Data.Length - transfer.SentOffset;
                int  sendByteCount = (remaining > chunkLen ? chunkLen : (int)remaining);

                IWriteMessage message;

                try
                {
                    //first message; send length, file name etc
                    //wait for acknowledgement before sending data
                    if (!transfer.Acknowledged)
                    {
                        message = new WriteOnlyMessage();
                        message.Write((byte)ServerPacketHeader.FILE_TRANSFER);

                        //if the recipient is the owner of the server (= a client running the server from the main exe)
                        //we don't need to send anything, the client can just read the file directly
                        if (transfer.Connection == GameMain.Server.OwnerConnection)
                        {
                            message.Write((byte)FileTransferMessageType.TransferOnSameMachine);
                            message.Write((byte)transfer.ID);
                            message.Write((byte)transfer.FileType);
                            message.Write(transfer.FilePath);
                            peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
                            transfer.Status = FileTransferStatus.Finished;
                        }
                        else
                        {
                            message.Write((byte)FileTransferMessageType.Initiate);
                            message.Write((byte)transfer.ID);
                            message.Write((byte)transfer.FileType);
                            //message.Write((ushort)chunkLen);
                            message.Write(transfer.Data.Length);
                            message.Write(transfer.FileName);
                            peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);

                            transfer.Status = FileTransferStatus.Sending;

                            if (GameSettings.VerboseLogging)
                            {
                                DebugConsole.Log("Sending file transfer initiation message: ");
                                DebugConsole.Log("  File: " + transfer.FileName);
                                DebugConsole.Log("  Size: " + transfer.Data.Length);
                                DebugConsole.Log("  ID: " + transfer.ID);
                            }
                        }
                        return;
                    }

                    message = new WriteOnlyMessage();
                    message.Write((byte)ServerPacketHeader.FILE_TRANSFER);
                    message.Write((byte)FileTransferMessageType.Data);

                    message.Write((byte)transfer.ID);
                    message.Write(transfer.SentOffset);

                    byte[] sendBytes = new byte[sendByteCount];
                    Array.Copy(transfer.Data, transfer.SentOffset, sendBytes, 0, sendByteCount);

                    message.Write((ushort)sendByteCount);
                    message.Write(sendBytes, 0, sendByteCount);

                    transfer.SentOffset += sendByteCount;
                    if (transfer.SentOffset > transfer.KnownReceivedOffset + chunkLen * 5 ||
                        transfer.SentOffset >= transfer.Data.Length)
                    {
                        transfer.SentOffset = transfer.KnownReceivedOffset;
                    }

                    peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
                }

                catch (Exception e)
                {
                    DebugConsole.ThrowError("FileSender threw an exception when trying to send data", e);
                    GameAnalyticsManager.AddErrorEventOnce(
                        "FileSender.Update:Exception",
                        GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                        "FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace);
                    transfer.Status = FileTransferStatus.Error;
                    break;
                }

                if (GameSettings.VerboseLogging)
                {
                    DebugConsole.Log("Sending " + sendByteCount + " bytes of the file " + transfer.FileName + " (" + transfer.SentOffset + "/" + transfer.Data.Length + " sent)");
                }
            }
        }
Beispiel #22
0
        public void ClientAdminWrite(NetFlags dataToSend, int missionType = 0, float?levelDifficulty = null, bool?autoRestart = null, int traitorSetting = 0, int botCount = 0, int botSpawnMode = 0, bool?useRespawnShuttle = null)
        {
            if (!GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
            {
                return;
            }

            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write((byte)ClientPacketHeader.SERVER_SETTINGS);

            outMsg.Write((byte)dataToSend);

            if (dataToSend.HasFlag(NetFlags.Name))
            {
                if (GameMain.NetLobbyScreen.ServerName.Text != ServerName)
                {
                    ServerName = GameMain.NetLobbyScreen.ServerName.Text;
                }
                outMsg.Write(ServerName);
            }

            if (dataToSend.HasFlag(NetFlags.Message))
            {
                if (GameMain.NetLobbyScreen.ServerMessage.Text != ServerMessageText)
                {
                    ServerMessageText = GameMain.NetLobbyScreen.ServerMessage.Text;
                }
                outMsg.Write(ServerMessageText);
            }

            if (dataToSend.HasFlag(NetFlags.Properties))
            {
                //TODO: split this up?
                WriteExtraCargo(outMsg);

                IEnumerable <KeyValuePair <UInt32, NetPropertyData> > changedProperties = netProperties.Where(kvp => kvp.Value.ChangedLocally);
                UInt32 count = (UInt32)changedProperties.Count();
                bool   changedMonsterSettings = tempMonsterEnabled != null && tempMonsterEnabled.Any(p => p.Value != MonsterEnabled[p.Key]);

                outMsg.Write(count);
                foreach (KeyValuePair <UInt32, NetPropertyData> prop in changedProperties)
                {
                    DebugConsole.NewMessage(prop.Value.Name, Color.Lime);
                    outMsg.Write(prop.Key);
                    prop.Value.Write(outMsg, prop.Value.GUIComponentValue);
                }

                outMsg.Write(changedMonsterSettings); outMsg.WritePadBits();
                if (changedMonsterSettings)
                {
                    WriteMonsterEnabled(outMsg, tempMonsterEnabled);
                }
                BanList.ClientAdminWrite(outMsg);
                Whitelist.ClientAdminWrite(outMsg);
            }

            if (dataToSend.HasFlag(NetFlags.Misc))
            {
                outMsg.Write((byte)(missionType + 1));
                outMsg.Write((byte)(traitorSetting + 1));
                outMsg.Write((byte)(botCount + 1));
                outMsg.Write((byte)(botSpawnMode + 1));

                outMsg.Write(levelDifficulty ?? -1000.0f);

                outMsg.Write(useRespawnShuttle ?? UseRespawnShuttle);

                outMsg.Write(autoRestart != null);
                outMsg.Write(autoRestart ?? false);
                outMsg.WritePadBits();
            }

            if (dataToSend.HasFlag(NetFlags.LevelSeed))
            {
                outMsg.Write(GameMain.NetLobbyScreen.SeedBox.Text);
            }

            GameMain.Client.ClientPeer.Send(outMsg, DeliveryMethod.Reliable);
        }
Beispiel #23
0
        protected void UpdatePendingClient(PendingClient pendingClient)
        {
            if (IsPendingClientBanned(pendingClient, out string banReason))
            {
                RemovePendingClient(pendingClient, DisconnectReason.Banned, banReason);
                return;
            }

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

            if (pendingClient.InitializationStep == ConnectionInitialization.Success)
            {
                NetworkConnection newConnection = pendingClient.Connection;
                connectedClients.Add(newConnection);
                pendingClients.Remove(pendingClient);

                CheckOwnership(pendingClient);

                OnInitializationComplete?.Invoke(newConnection);
            }

            pendingClient.TimeOut -= Timing.Step;
            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;

            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep |
                                PacketHeader.IsServerMessage));
            outMsg.Write((byte)pendingClient.InitializationStep);
            switch (pendingClient.InitializationStep)
            {
            case ConnectionInitialization.ContentPackageOrder:
                outMsg.Write(GameMain.Server.ServerName);

                var mpContentPackages = GameMain.Config.AllEnabledPackages.Where(cp => cp.HasMultiplayerIncompatibleContent).ToList();
                outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count);
                for (int i = 0; i < mpContentPackages.Count; i++)
                {
                    outMsg.Write(mpContentPackages[i].Name);
                    outMsg.Write(mpContentPackages[i].MD5hash.Hash);
                    outMsg.Write(mpContentPackages[i].SteamWorkshopId);
                }
                break;

            case ConnectionInitialization.Password:
                outMsg.Write(pendingClient.PasswordSalt == null); outMsg.WritePadBits();
                if (pendingClient.PasswordSalt == null)
                {
                    pendingClient.PasswordSalt = Lidgren.Network.CryptoRandom.Instance.Next();
                    outMsg.Write(pendingClient.PasswordSalt.Value);
                }
                else
                {
                    outMsg.Write(pendingClient.Retries);
                }
                break;
            }

            SendMsgInternal(pendingClient.Connection, DeliveryMethod.Reliable, outMsg);
        }
Beispiel #24
0
        private void ReadConnectionInitializationStep(IReadMessage inc)
        {
            if (!isActive)
            {
                return;
            }

            ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();

            IWriteMessage outMsg;

            //DebugConsole.NewMessage(step + " " + initializationStep);
            switch (step)
            {
            case ConnectionInitialization.SteamTicketAndVersion:
                if (initializationStep != ConnectionInitialization.SteamTicketAndVersion)
                {
                    return;
                }
                outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)DeliveryMethod.Reliable);
                outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
                outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
                outMsg.Write(Name);
                outMsg.Write(SteamManager.GetSteamID());
                outMsg.Write((UInt16)steamAuthTicket.Data.Length);
                outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);

                outMsg.Write(GameMain.Version.ToString());

                IEnumerable <ContentPackage> mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
                outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count());
                foreach (ContentPackage contentPackage in mpContentPackages)
                {
                    outMsg.Write(contentPackage.Name);
                    outMsg.Write(contentPackage.MD5hash.Hash);
                }

                heartbeatTimer = 5.0;
                Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
                sentBytes += outMsg.LengthBytes;
                break;

            case ConnectionInitialization.ContentPackageOrder:
                if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
                    initializationStep == ConnectionInitialization.Password)
                {
                    initializationStep = ConnectionInitialization.ContentPackageOrder;
                }
                if (initializationStep != ConnectionInitialization.ContentPackageOrder)
                {
                    return;
                }
                outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)DeliveryMethod.Reliable);
                outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
                outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);

                UInt32 cpCount = inc.ReadVariableUInt32();
                List <ContentPackage> serverContentPackages = new List <ContentPackage>();
                for (int i = 0; i < cpCount; i++)
                {
                    string hash = inc.ReadString();
                    serverContentPackages.Add(GameMain.Config.SelectedContentPackages.Find(cp => cp.MD5hash.Hash == hash));
                }

                if (!contentPackageOrderReceived)
                {
                    GameMain.Config.ReorderSelectedContentPackages(cp => serverContentPackages.Contains(cp) ?
                                                                   serverContentPackages.IndexOf(cp) :
                                                                   serverContentPackages.Count + GameMain.Config.SelectedContentPackages.IndexOf(cp));
                    contentPackageOrderReceived = true;
                }

                Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
                sentBytes += outMsg.LengthBytes;
                break;

            case ConnectionInitialization.Password:
                if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
                {
                    initializationStep = ConnectionInitialization.Password;
                }
                if (initializationStep != ConnectionInitialization.Password)
                {
                    return;
                }
                bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
                int  retries      = 0;
                if (incomingSalt)
                {
                    passwordSalt = inc.ReadInt32();
                }
                else
                {
                    retries = inc.ReadInt32();
                }
                OnRequestPassword?.Invoke(passwordSalt, retries);
                break;
            }
        }
Beispiel #25
0
        public override void Update(float deltaTime)
        {
            if (!isActive)
            {
                return;
            }

            timeout        -= deltaTime;
            heartbeatTimer -= deltaTime;

            for (int i = 0; i < 100; i++)
            {
                if (!Steamworks.SteamNetworking.IsP2PPacketAvailable())
                {
                    break;
                }
                var packet = Steamworks.SteamNetworking.ReadP2PPacket();
                if (packet.HasValue)
                {
                    OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0, 0);
                }
            }

            if (heartbeatTimer < 0.0)
            {
                IWriteMessage outMsg = new WriteOnlyMessage();
                outMsg.Write((byte)DeliveryMethod.Unreliable);
                outMsg.Write((byte)PacketHeader.IsHeartbeatMessage);

                Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Unreliable);

                heartbeatTimer = 5.0;
            }

            if (timeout < 0.0)
            {
                Close("Timed out");
                OnDisconnectMessageReceived?.Invoke("");
                return;
            }

            if (initializationStep != ConnectionInitialization.Success)
            {
                if (incomingDataMessages.Count > 0)
                {
                    OnInitializationComplete?.Invoke();
                    initializationStep = ConnectionInitialization.Success;
                }
                else
                {
                    foreach (IReadMessage inc in incomingInitializationMessages)
                    {
                        ReadConnectionInitializationStep(inc);
                    }
                }
            }

            if (initializationStep == ConnectionInitialization.Success)
            {
                foreach (IReadMessage inc in incomingDataMessages)
                {
                    OnMessageReceived?.Invoke(inc);
                }
            }

            incomingInitializationMessages.Clear();
            incomingDataMessages.Clear();
        }
        private void UpdatePendingClient(PendingClient pendingClient)
        {
            if (!started)
            {
                return;
            }

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

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

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

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

            pendingClient.TimeOut -= Timing.Step;
            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;

            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write(pendingClient.SteamID);
            outMsg.Write((byte)DeliveryMethod.Reliable);
            outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep |
                                PacketHeader.IsServerMessage));
            outMsg.Write((byte)pendingClient.InitializationStep);
            switch (pendingClient.InitializationStep)
            {
            case ConnectionInitialization.ContentPackageOrder:
                var mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent).ToList();
                outMsg.WriteVariableUInt32((UInt32)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 = Lidgren.Network.CryptoRandom.Instance.Next();
                    outMsg.Write(pendingClient.PasswordSalt.Value);
                }
                else
                {
                    outMsg.Write(pendingClient.Retries);
                }
                break;
            }

            byte[] msgToSend = (byte[])outMsg.Buffer.Clone();
            Array.Resize(ref msgToSend, outMsg.LengthBytes);
            ChildServerRelay.Write(msgToSend);
        }
Beispiel #27
0
        private void HandleDataMessage(IReadMessage inc)
        {
            if (!isActive)
            {
                return;
            }

            UInt64         recipientSteamId = inc.ReadUInt64();
            DeliveryMethod deliveryMethod   = (DeliveryMethod)inc.ReadByte();

            int p2pDataStart = inc.BytePosition;

            byte incByte = inc.ReadByte();

            bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
            bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
            bool isDisconnectMessage            = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0;
            bool isServerMessage    = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
            bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;

            if (recipientSteamId != selfSteamID)
            {
                if (!isServerMessage)
                {
                    DebugConsole.ThrowError("Received non-server message meant for remote peer");
                    return;
                }

                RemotePeer peer = remotePeers.Find(p => p.SteamID == recipientSteamId);

                if (peer == null)
                {
                    return;
                }

                if (isDisconnectMessage)
                {
                    DisconnectPeer(peer, inc.ReadString());
                    return;
                }

                Steamworks.P2PSend sendType;
                switch (deliveryMethod)
                {
                case DeliveryMethod.Reliable:
                case DeliveryMethod.ReliableOrdered:
                    //the documentation seems to suggest that the Reliable send type
                    //enforces packet order (TODO: verify)
                    sendType = Steamworks.P2PSend.Reliable;
                    break;

                default:
                    sendType = Steamworks.P2PSend.Unreliable;
                    break;
                }

                byte[] p2pData;

                if (isConnectionInitializationStep)
                {
                    p2pData    = new byte[inc.LengthBytes - p2pDataStart + 8];
                    p2pData[0] = inc.Buffer[p2pDataStart];
                    Lidgren.Network.NetBitWriter.WriteUInt64(SteamManager.CurrentLobbyID, 64, p2pData, 8);
                    Array.Copy(inc.Buffer, p2pDataStart + 1, p2pData, 9, inc.LengthBytes - p2pDataStart - 1);
                }
                else
                {
                    p2pData = new byte[inc.LengthBytes - p2pDataStart];
                    Array.Copy(inc.Buffer, p2pDataStart, p2pData, 0, p2pData.Length);
                }

                if (p2pData.Length + 4 >= MsgConstants.MTU)
                {
                    DebugConsole.Log("WARNING: message length comes close to exceeding MTU, forcing reliable send (" + p2pData.Length.ToString() + " bytes)");
                    sendType = Steamworks.P2PSend.Reliable;
                }

                bool successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId, p2pData, p2pData.Length, 0, sendType);
                sentBytes += p2pData.Length;

                if (!successSend)
                {
                    if (sendType != Steamworks.P2PSend.Reliable)
                    {
                        DebugConsole.Log("WARNING: message couldn't be sent unreliably, forcing reliable send (" + p2pData.Length.ToString() + " bytes)");
                        sendType    = Steamworks.P2PSend.Reliable;
                        successSend = Steamworks.SteamNetworking.SendP2PPacket(recipientSteamId, p2pData, p2pData.Length, 0, sendType);
                        sentBytes  += p2pData.Length;
                    }
                    if (!successSend)
                    {
                        DebugConsole.ThrowError("Failed to send message to remote peer! (" + p2pData.Length.ToString() + " bytes)");
                    }
                }
            }
            else
            {
                if (isDisconnectMessage)
                {
                    DebugConsole.ThrowError("Received disconnect message from owned server");
                    return;
                }
                if (!isServerMessage)
                {
                    DebugConsole.ThrowError("Received non-server message from owned server");
                    return;
                }
                if (isHeartbeatMessage)
                {
                    return; //timeout is handled by Lidgren, ignore this message
                }
                if (isConnectionInitializationStep)
                {
                    IWriteMessage outMsg = new WriteOnlyMessage();
                    outMsg.Write(selfSteamID);
                    outMsg.Write((byte)(PacketHeader.IsConnectionInitializationStep));
                    outMsg.Write(Name);

                    byte[] msgToSend = (byte[])outMsg.Buffer.Clone();
                    Array.Resize(ref msgToSend, outMsg.LengthBytes);
                    ChildServerRelay.Write(msgToSend);
                    return;
                }
                else
                {
                    if (initializationStep != ConnectionInitialization.Success)
                    {
                        OnInitializationComplete?.Invoke();
                        initializationStep = ConnectionInitialization.Success;
                    }
                    UInt16       length = inc.ReadUInt16();
                    IReadMessage msg    = new ReadOnlyMessage(inc.Buffer, isCompressed, inc.BytePosition, length, ServerConnection);
                    OnMessageReceived?.Invoke(msg);

                    return;
                }
            }
        }
Beispiel #28
0
        private void OnP2PData(ulong steamId, byte[] data, int dataLength, int channel)
        {
            if (!isActive)
            {
                return;
            }

            RemotePeer remotePeer = remotePeers.Find(p => p.SteamID == steamId);

            if (remotePeer == null || remotePeer.DisconnectTime != null)
            {
                return;
            }

            IWriteMessage outMsg = new WriteOnlyMessage();

            outMsg.Write(steamId);
            outMsg.Write(data, 1, dataLength - 1);

            DeliveryMethod deliveryMethod = (DeliveryMethod)data[0];

            byte incByte      = data[1];
            bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
            bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
            bool isDisconnectMessage            = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0;
            bool isServerMessage    = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
            bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;

            if (!remotePeer.Authenticated)
            {
                if (!remotePeer.Authenticating)
                {
                    if (isConnectionInitializationStep)
                    {
                        remotePeer.DisconnectTime = null;

                        IReadMessage             authMsg            = new ReadOnlyMessage(data, isCompressed, 2, dataLength - 2, null);
                        ConnectionInitialization initializationStep = (ConnectionInitialization)authMsg.ReadByte();
                        //Console.WriteLine("received init step from "+steamId.ToString()+" ("+initializationStep.ToString()+")");
                        if (initializationStep == ConnectionInitialization.SteamTicketAndVersion)
                        {
                            remotePeer.Authenticating = true;

                            authMsg.ReadString(); //skip name
                            authMsg.ReadInt32();  //skip owner key
                            authMsg.ReadUInt64(); //skip steamid
                            UInt16 ticketLength = authMsg.ReadUInt16();
                            byte[] ticket       = authMsg.ReadBytes(ticketLength);

                            Steamworks.BeginAuthResult authSessionStartState = Steam.SteamManager.StartAuthSession(ticket, steamId);
                            if (authSessionStartState != Steamworks.BeginAuthResult.OK)
                            {
                                DisconnectPeer(remotePeer, DisconnectReason.SteamAuthenticationFailed.ToString() + "/ Steam auth session failed to start: " + authSessionStartState.ToString());
                                return;
                            }
                        }
                    }
                }
            }

            if (remotePeer.Authenticating)
            {
                remotePeer.UnauthedMessages.Add(new RemotePeer.UnauthedMessage()
                {
                    DeliveryMethod = deliveryMethod, Message = outMsg
                });
            }
            else
            {
                byte[] msgToSend = (byte[])outMsg.Buffer.Clone();
                Array.Resize(ref msgToSend, outMsg.LengthBytes);
                ChildServerRelay.Write(msgToSend);
            }
        }
        private void Send(FileTransferOut transfer)
        {
            // send another part of the file
            long remaining     = transfer.Data.Length - transfer.SentOffset;
            int  sendByteCount = (remaining > chunkLen ? chunkLen : (int)remaining);

            IWriteMessage message;

            try
            {
                //first message; send length, file name etc
                //wait for acknowledgement before sending data
                if (!transfer.Acknowledged)
                {
                    message = new WriteOnlyMessage();
                    message.Write((byte)ServerPacketHeader.FILE_TRANSFER);

                    //if the recipient is the owner of the server (= a client running the server from the main exe)
                    //we don't need to send anything, the client can just read the file directly
                    if (transfer.Connection == GameMain.Server.OwnerConnection)
                    {
                        message.Write((byte)FileTransferMessageType.TransferOnSameMachine);
                        message.Write((byte)transfer.ID);
                        message.Write((byte)transfer.FileType);
                        message.Write(transfer.FilePath);
                        peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
                        transfer.Status = FileTransferStatus.Finished;
                    }
                    else
                    {
                        message.Write((byte)FileTransferMessageType.Initiate);
                        message.Write((byte)transfer.ID);
                        message.Write((byte)transfer.FileType);
                        //message.Write((ushort)chunkLen);
                        message.Write(transfer.Data.Length);
                        message.Write(transfer.FileName);
                        peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);

                        transfer.Status = FileTransferStatus.Sending;

                        if (GameSettings.VerboseLogging)
                        {
                            DebugConsole.Log("Sending file transfer initiation message: ");
                            DebugConsole.Log("  File: " + transfer.FileName);
                            DebugConsole.Log("  Size: " + transfer.Data.Length);
                            DebugConsole.Log("  ID: " + transfer.ID);
                        }
                    }
                    transfer.WaitTimer = 0.1f;
                    return;
                }

                message = new WriteOnlyMessage();
                message.Write((byte)ServerPacketHeader.FILE_TRANSFER);
                message.Write((byte)FileTransferMessageType.Data);

                message.Write((byte)transfer.ID);
                message.Write(transfer.SentOffset);

                byte[] sendBytes = new byte[sendByteCount];
                Array.Copy(transfer.Data, transfer.SentOffset, sendBytes, 0, sendByteCount);

                message.Write((ushort)sendByteCount);
                message.Write(sendBytes, 0, sendByteCount);

                transfer.SentOffset += sendByteCount;
                if (transfer.SentOffset > transfer.KnownReceivedOffset + chunkLen * 10 ||
                    transfer.SentOffset >= transfer.Data.Length)
                {
                    transfer.SentOffset = transfer.KnownReceivedOffset;
                    transfer.WaitTimer  = 0.5f;
                }

                peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
            }

            catch (Exception e)
            {
                DebugConsole.ThrowError("FileSender threw an exception when trying to send data", e);
                GameAnalyticsManager.AddErrorEventOnce(
                    "FileSender.Update:Exception",
                    GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                    "FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
                transfer.Status = FileTransferStatus.Error;
                return;
            }

            if (GameSettings.VerboseLogging)
            {
                DebugConsole.Log($"Sending {sendByteCount} bytes of the file {transfer.FileName} ({transfer.SentOffset / 1000}/{transfer.Data.Length / 1000} kB sent)");
            }
        }