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; }
/// <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; }
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; }
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); }
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); }
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(); }
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; } }
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)"); } } }
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); }
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); }
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; } }
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); }
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; } } }
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)"); } }