/// <summary> /// This method transmits a raw datagram to a socket. /// </summary> /// <param name="Address">Supplies the message recipient.</param> /// <param name="Builder">Supplies the message body.</param> /// <param name="Socket">Supplies the socket to send to.</param> private void SendRawDataToSocket(IPEndPoint Address, ExoBuildBuffer Builder, SocketInfo Socket) { unsafe { byte* ByteStream; uint ByteStreamLength; byte* BitStream; uint BitStreamLength; byte[] CompositeBuffer; uint CompositeBufferLength; Builder.GetBuffer( out ByteStream, out ByteStreamLength, out BitStream, out BitStreamLength); CompositeBufferLength = ByteStreamLength + BitStreamLength; if (CompositeBufferLength == 0) return; // // Allocate a contiguous message buffer, and fail here and now // if we can't. // try { CompositeBuffer = new byte[CompositeBufferLength]; // // Assemble the discrete components into a single // contiguous composite buffer for outbound trnasmission. // Marshal.Copy( (IntPtr)ByteStream, CompositeBuffer, 0, (int)ByteStreamLength); for (uint i = 0; i < BitStreamLength; i += 1) { CompositeBuffer[ByteStreamLength + i] = BitStream[i]; } // // Transmit the underlying message now that we have // captured it into a flat buffer consumable by the I/O // system. // IAsyncResult Result = Socket.Socket.BeginSendTo( CompositeBuffer, 0, (int)CompositeBufferLength, SocketFlags.None, Address, SendCompletionCallback, new SocketSendState(Address, Socket.Socket)); } catch (Exception e) { Logger.Log(LogLevel.Error, "NWMasterServer.SendRawDataToSocket(): Failed to send data to Mst client {0}: Exception: {1}", Address, e); } } }
/// <summary> /// This method transmits a raw datagram to a master server client, /// such as a game server or game client. The message is sent using /// the NAT duplicate detector socket. /// </summary> /// <param name="Address">Supplies the message recipient.</param> /// <param name="Builder">Supplies the message body.</param> private void SendRawDataToMstClientNATDuplicate(IPEndPoint Address, ExoBuildBuffer Builder) { SendRawDataToSocket(Address, Builder, MasterServerNATDuplicateSocket); }
/// <summary> /// This method transmits a raw datagram to a GameSpy server client, /// such as a game client. /// </summary> /// <param name="Address">Supplies the message recipient.</param> /// <param name="Builder">Supplies the message body.</param> private void SendRawDataToGameSpyClient(IPEndPoint Address, ExoBuildBuffer Builder) { SendRawDataToSocket(Address, Builder, GameSpySocket); }
/// <summary> /// This method sends a server description request to a server. /// </summary> /// <param name="Address">Supplies the game server address.</param> public void SendServerDescriptionRequest(IPEndPoint Address) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteDWORD((uint)ConnAuthCmd.ServerDescriptionRequest); Builder.WriteWORD((ushort)MasterServerPort); Logger.Log(LogLevel.Verbose, "NWMasterServer.SendServerDescriptionRequest(): Sending server description request to {0}.", Address); SendRawDataToMstClientNATDuplicate(Address, Builder); } }
/// <summary> /// This method sends a GameSpy server status acknowledgement back to /// a GameSpy client, informing the client that GameSpy services should /// be considered as available and operational. /// </summary> /// <param name="Address">Supplies the recipient address.</param> public void SendGameSpyCheckServerStatusResponse(IPEndPoint Address) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteWORD(0xFDFE); Builder.WriteBYTE((byte)GameSpyCmd.CheckServerStatus); Builder.WriteDWORD(0); Logger.Log(LogLevel.Verbose, "NWMasterServer.SendGameSpyCheckServerStatusResponse(): Sending GameSpy aliveness acknowledgement to {0}.", Address); SendRawDataToGameSpyClient(Address, Builder); } }
/// <summary> /// This method sends a master server status response message to a game /// server, or game client. /// </summary> /// <param name="Address">Supplies the message recipient.</param> /// <param name="StatusFlags">Supplies the master server status flags. /// </param> public void SendMstStatusResponse(IPEndPoint Address, MstStatus StatusFlags) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteDWORD((uint)MstCmd.StatusResponse); Builder.WriteDWORD((ushort)StatusFlags); Logger.Log(LogLevel.Verbose, "NWMasterServer.SendMstStatusResponse(): Sending status response to {0}.", Address); SendRawDataToMstClient(Address, Builder); } }
/// <summary> /// This method sends a server name request to a server. /// </summary> /// <param name="Address">Supplies the game server address.</param> public void SendServerNameRequest(IPEndPoint Address) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteDWORD((uint)ConnAuthCmd.ServerNameRequest); Builder.WriteWORD((ushort)MasterServerPort); Builder.WriteBYTE(0); // Request correlation cookie. Logger.Log(LogLevel.Verbose, "NWMasterServer.SendServerNameRequest(): Sending server name request to {0}.", Address); SendRawDataToMstClientNATDuplicate(Address, Builder); } }
/// <summary> /// This method sends the current build number to a game server, or /// game client. /// </summary> /// <param name="Address">Supplies the message recipient.</param> /// <param name="BuildNumber">Supplies the build number string.</param> public void SendMstVersion(IPEndPoint Address, string BuildNumber) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteDWORD((uint)MstCmd.VersionResponse); Builder.WriteSmallString(BuildNumber, 16); Logger.Log(LogLevel.Verbose, "NWMasterServer.SendMstVersion(): Sending version to {0}.", Address); SendRawDataToMstClient(Address, Builder); } }
/// <summary> /// This method sends the message of the day to a game server, or game /// client. /// </summary> /// <param name="Address">Supplies the message recipient.</param> /// <param name="Message">Supplies the announcement message.</param> public void SendMstMOTD(IPEndPoint Address, string Message) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteDWORD((uint)MstCmd.MOTDResponse); Builder.WriteSmallString(Message, 16); Logger.Log(LogLevel.Verbose, "NWMasterServer.SendMstMOTD(): Sending MOTD to {0}.", Address); SendRawDataToMstClient(Address, Builder); } }
/// <summary> /// This method sends a heartbeat request to a game server, requesting /// that it reply with a list of current players. This confirms that /// the server is, in fact, still up and responding. /// </summary> /// <param name="Address">Supplies the message recipient.</param> public void SendMstDemandHeartbeat(IPEndPoint Address) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteDWORD((uint)MstCmd.DemandHeartbeat); Logger.Log(LogLevel.Verbose, "NWMasterServer.SendMstDemandHeartbeat(): Requesting heartbeat for server {0}.", Address); SendRawDataToMstClient(Address, Builder); } }
/// <summary> /// This method sends a CD-Key authorization response to a game server, /// or game client (for initial login). /// </summary> /// <param name="Address">Supplies the message recipient.</param> /// <param name="CDKeys">Supplies the CD-Key list.</param> public void SendMstCDKeyAuthorization(IPEndPoint Address, IList<CDKeyInfo> CDKeys) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteDWORD((uint)MstCmd.CDKeyAuthorization); Builder.WriteWORD((ushort)CDKeys.Count); foreach (CDKeyInfo CDKey in CDKeys) { Builder.WriteSmallString(CDKey.PublicCDKey, 16); Builder.WriteWORD(CDKey.AuthStatus); Builder.WriteWORD(CDKey.Product); } Logger.Log(LogLevel.Verbose, "NWMasterServer.SendMstCDKeyAuthorization(): Authorizing {0} CD-Keys for server {1}.", CDKeys, Address); SendRawDataToMstClient(Address, Builder); } }
/// <summary> /// This method sends a community account authorization response to a /// game server, or game client (for initial login). /// </summary> /// <param name="Address">Supplies the message recipient.</param> /// <param name="AccountName">Supplies the account name.</param> /// <param name="Status">Supplies the authorization status /// code.</param> public void SendMstCommunityAccountAuthorization(IPEndPoint Address, string AccountName, ConnectStatus Status) { using (ExoBuildBuffer Builder = new ExoBuildBuffer()) { Builder.WriteDWORD((uint)MstCmd.CommunityAuthorization); Builder.WriteSmallString(AccountName, 16); Builder.WriteWORD((ushort)Status); Logger.Log(LogLevel.Verbose, "NWMasterServer.SendMstCommunityAccountAuthorization(): Authorizing account {0} for server {1} with status {2}.", AccountName, Address, Status); SendRawDataToMstClient(Address, Builder); } }