/// <summary> /// Sends a packet to all of the connections. /// </summary> /// <param name="packet">The packet to send.</param> public void SendPacketToAll(NetOutboundPacket packet) { foreach (NetConnection conn in Connections.Values) { conn.SendPacket(packet.Clone()); } }
void FireEvent(string eventName, NetConnection onConnection, RemoteFlag flags, NetDeliveryMethod deliveryMethod, NetBuffer data, ushort numArgs) { // Create the event packet NetOutboundPacket firePacket = new NetOutboundPacket(deliveryMethod); firePacket.Type = NetPacketType.RemoteEvent; // Handle the flags firePacket.Encrypt = flags.HasFlag(RemoteFlag.Encrypt); if (flags.HasFlag(RemoteFlag.DontCompress)) { firePacket.Compression = NetPacketCompression.None; } firePacket.SendImmediately = flags.HasFlag(RemoteFlag.SendImmediately); // Write the event header firePacket.Write((byte)Type); firePacket.Write(Id); firePacket.Write(eventName); firePacket.Write(numArgs); // Write the data for the event firePacket.WriteBytes(data.data, 0, data.Length); // Send the event packet onConnection.SendPacket(firePacket); }
protected override void HandleConnectionApproved(IPEndPoint from) { if (awaitingConnectionResponse) { lastConnectionApproved = true; awaitingConnectionResponse = false; // Add server NetConnection ServerConnection = new NetConnection(from, this); Connections.TryAdd(from, ServerConnection); if (OnConnected != null) { OnConnected(ServerConnection); } // Tell the server we are ready NetOutboundPacket readyPacket = new NetOutboundPacket(NetDeliveryMethod.Unreliable, NetPacketType.ConnectionReady); //SendInternalPacket(readyPacket, from); ServerConnection.SendPacket(readyPacket); } else { AddWatchedConnection(from, "ConnectionApproved received, but this client is not connecting!"); } base.HandleConnectionApproved(from); }
protected override void HandleConnectionRequest(NetConnectionRequest request) { // Check if the password is correct and if there is room if (Connections.Count < config.MaxConnections && (config.Password == null || config.Password == request.Password)) { if (!connectingMessengers.Add(request.EndPoint)) { NetLogger.LogWarning("Connection request from already connecting client @ {0}! (or an error occured)", request.EndPoint); } else { // Send approval NetOutboundPacket approvalPacket = new NetOutboundPacket(NetDeliveryMethod.Unreliable, NetPacketType.ConnectionApproved); SendInternalPacket(approvalPacket, request.EndPoint); } } else { // Send denial NetOutboundPacket denialPacket = new NetOutboundPacket(NetDeliveryMethod.Unreliable, NetPacketType.ConnectionDenied); denialPacket.Write((byte)(Connections.Count < config.MaxConnections ? NetDenialReason.InvalidPassword : NetDenialReason.ServerFull)); SendInternalPacket(denialPacket, request.EndPoint); } }
/// <summary> /// Sends a packet to the connection. /// </summary> /// <param name="packet">The packet to send.</param> public void SendPacket(NetOutboundPacket packet) { if (packet.HasId) { throw new NetException( "Cannot send packet twice, please create a new packet or clone this one before sending another time."); } // Remove the packets padding packet.RemovePadding(); // Setup the packet and make it ready for sending SetupOutboundPacket(packet); // Write the packet's header and set it's Id WriteOutboundPacketHeader(packet); // Check if this packet needs to be split into a partial if (MTU > 0 && packet.Length > MTU && !packet.isPartial) { // Split the packet into partials NetOutboundPacket[] partials = SplitPacketIntoPartials(packet); for (int i = 0; i < partials.Length; i++) { // Send the partials as seperate packets SendPacket(partials[i]); } // Stop handling the too large packet return; } // Handle the sending based on delivery method if (packet.DeliveryMethod == NetDeliveryMethod.Unreliable) { // No extra work needed, just place in outbound queue AddPacketToChunkQueue(packet); } else if (packet.DeliveryMethod == NetDeliveryMethod.Reliable) { // Create the reliable packet handler and add it to the reliable queue ReliablePacket reliablePacket = new ReliablePacket(packet); if (!reliableOutboundPacketQueue.TryAdd(packet.Id, reliablePacket)) { NetLogger.LogError("Failed to add packet to the reliable outbound queue. Id: {0}, Type: {1}, DeliveryMethod: {2}", packet.Id, packet.Type, packet.DeliveryMethod); } // Attempt first send AddPacketToChunkQueue(packet); } else if (packet.DeliveryMethod == NetDeliveryMethod.ReliableOrdered) { // Create the reliable packet handler and add it to the ordered reliable queue ReliablePacket reliablePacket = new ReliablePacket(packet); reliableOrderedOutboundPacketQueue.Enqueue(reliablePacket); } }
void SendPacketToSocket(NetOutboundPacket packet) { Stats.PhysicalPacketsSent++; Stats.PacketsSent++; physicalPacketsSentInLastSecond++; packetsSentInLastSecond++; messenger.SendDataToSocket(packet.data, EndPoint); }
public virtual bool Connect(IPEndPoint serverAddress, string password, out NetDenialReason?denialReason) { if (IsConnected) { throw new NetException("Client is already connected to a server!"); } if (awaitingConnectionResponse) { throw new NetException("Cannot connect to server, client is already in the middle of connecting!"); } denialReason = null; awaitingConnectionResponse = true; NetOutboundPacket request = new NetOutboundPacket(NetDeliveryMethod.Unreliable, NetPacketType.ConnectionRequest); request.Write(password != null); if (password != null) { request.Write(password); } int tries = 0; while (awaitingConnectionResponse && tries < config.MaxConnectionAttempts) { tries++; SendInternalPacket(request.Clone(), serverAddress); // Block thread while awaiting connection int timeoutAt = NetTime.Now + config.ConnectionAttemptTimeout; while (awaitingConnectionResponse && NetTime.Now < timeoutAt) { Thread.Sleep(1); } } if (awaitingConnectionResponse) { awaitingConnectionResponse = false; denialReason = NetDenialReason.ConnectionTimedOut; return(false); } else { if (!lastConnectionApproved) { denialReason = lastDenialReason; } return(lastConnectionApproved); } }
public bool SendPacket(NetOutboundPacket packet) { if (IsConnected) { ServerConnection.SendPacket(packet); return(true); } else { return(false); } // throw new NetException("Cannot send packet, this client is not connected!"); }
bool TrySendMTU(int size) { NetOutboundPacket msg = new NetOutboundPacket(NetDeliveryMethod.Unreliable); msg.Type = NetPacketType.MTUTest; msg.SendImmediately = true; msg.WriteBytes(new byte[size]); // Have to set the header manually since this isn't technically a legit packet msg.SetId(messenger.AllocatePacketId()); msg.PrependHeader(); return(messenger.SendDataToSocket(msg.data, EndPoint, true)); }
internal static void EncryptPacket(NetOutboundPacket msg) { using (RijndaelManaged rm = new RijndaelManaged()) { rm.Key = key; rm.IV = iv; // Set the packets data to the encrypted bytes msg.data = EncryptBytes(rm, msg.data); // Set position msg.position = msg.data.Length; msg.isEncrypted = true; } }
void SetupOutboundPacket(NetOutboundPacket packet) { // Compress Packet if (packet.Compression != NetPacketCompression.None && !packet.isCompressed && ((packet.Compression == NetPacketCompression.Compress && packet.Length > 40) || (config.AutoCompressPackets && packet.Length > config.CompressPacketAfter))) { NetCompressor.Compress(packet); } // Encrypt Packet if (packet.Encrypt) { NetEncryption.EncryptPacket(packet); } }
internal void SendPingResponse() { if (ignorePing) { return; } // Create the response NetOutboundPacket pingResponse = new NetOutboundPacket(NetDeliveryMethod.Unreliable); pingResponse.SendImmediately = true; // We need accurate results pingResponse.Type = NetPacketType.PingResponse; // Send it SendPacket(pingResponse); }
void ReplyAck(NetInboundPacket packet, IPEndPoint sender) { // Create the ack packet NetOutboundPacket ack = new NetOutboundPacket(NetDeliveryMethod.Unreliable, 3); ack.Type = NetPacketType.AckResponse; ack.Write(packet.Id); // Write the id if (NetLogger.LogAcks) { NetLogger.LogVerbose("[ACK] Replying {0} to {1}", packet.Id, packet.Sender); } // And send packet.Sender.SendPacket(ack); }
internal void Disconnect(string reason, bool connectionLost) { // Create the disconnect packet to let the other side know NetOutboundPacket disconnection = new NetOutboundPacket(NetDeliveryMethod.Unreliable); disconnection.Type = NetPacketType.Disconnected; disconnection.SendImmediately = true; disconnection.Write(reason); disconnection.Write(connectionLost); // Send it SendPacket(disconnection); // Remove this connection from our messenger messenger.DropConnection(EndPoint, reason, connectionLost); }
NetOutboundPacket[] SplitPacketIntoPartials(NetOutboundPacket packet) { packet.position = 0; // Calculate the number of packets to split it into, // and each of their sizes int numPackets = (int)Math.Ceiling((double)(packet.Length) / (MTU - 12)); int newPacketSize = MTU - 12; int packetChunkIndex = 0; ushort id = nextPartialId++; NetOutboundPacket[] partialPackets = new NetOutboundPacket[numPackets]; for (byte i = 0; i < numPackets; i++) { int packetSize = Math.Min(newPacketSize, packet.Length - packetChunkIndex); // Create the new partial NetOutboundPacket partial = packet.Clone(true); partial.isPartial = true; partial.Encrypt = false; partial.Compression = NetPacketCompression.None; partial.Clear(6 + packetSize); // Write the partial header partial.Write(id); partial.Write(i); partial.Write((byte)numPackets); partial.Write((ushort)packetSize); // Write the data allocated to this partial partial.WriteBytes(packet.ReadBytes(packetChunkIndex, packetSize)); // Add it to the list of partials partialPackets[i] = partial; packetChunkIndex += packetSize; } if (NetLogger.LogPartials) { NetLogger.LogVerbose("[Partial] Split Packet into {0} parts; Size: {1}b, Original Size: {2}b", numPackets, newPacketSize, packet.Length); } return(partialPackets); }
internal void SendInternalPacket(NetOutboundPacket packet, IPEndPoint to) { packet.RemovePadding(); packet.SetId(AllocatePacketId()); if (packet.Type == NetPacketType.ConnectionRequest) { NetEncryption.EncryptPacket(packet); } packet.PrependHeader(); if (NetLogger.LogPacketSends && !IsPingPacket(packet.Type)) { NetLogger.LogVerbose("[Outbound:{0}] {1}", to, packet.ToInternalString()); } SendDataToSocket(packet.data, to, false); }
bool CallFunc(string functionName, NetConnection onConnection, RemoteFunctionCallback callback, RemoteFlag flags, NetDeliveryMethod deliveryMethod, NetBuffer data, ushort numArgs) { // Allocate Id ushort callbackId = GetNextCallbackId(); // Create the function packet NetOutboundPacket funcPacket = new NetOutboundPacket(deliveryMethod); funcPacket.Type = NetPacketType.RemoteFunction; // Handle the flags funcPacket.Encrypt = flags.HasFlag(RemoteFlag.Encrypt); if (flags.HasFlag(RemoteFlag.DontCompress)) { funcPacket.Compression = NetPacketCompression.None; } funcPacket.SendImmediately = flags.HasFlag(RemoteFlag.SendImmediately); // Write the function header funcPacket.Write((byte)Type); funcPacket.Write(Id); funcPacket.Write(functionName); funcPacket.Write(callbackId); funcPacket.Write(numArgs); // Write the data for the function funcPacket.WriteBytes(data.data, 0, data.Length); // Add the waiting function for the return value callback if (WaitingFunctions.TryAdd(callbackId, callback)) { // Send the event packet onConnection.SendPacket(funcPacket); return(true); } else { NetLogger.LogError("Failed to call function {0}, this function is already in the middle of being called!", functionName); return(false); } }
void Ping() { if (ignorePing) { return; } // Reset the timer lastPingRequest = NetTime.Now; // Create the request NetOutboundPacket pingRequest = new NetOutboundPacket(NetDeliveryMethod.Unreliable); pingRequest.SendImmediately = true; // We need accurate results pingRequest.Type = NetPacketType.PingRequest; // Send it SendPacket(pingRequest); }
public static void Compress(NetOutboundPacket buffer) { using (MemoryStream ms = new MemoryStream()) using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true)) { // Just incase this wasn't forced, make sure it knows it's compressed buffer.isCompressed = true; byte[] originalData = buffer.Data; int originalPosition = buffer.position; int originalIndex = buffer.unpaddedIndex; // Save original size int originalSize = buffer.data.Length; // Write data to the zip buffer and compress zip.Write(buffer.data, 0, buffer.data.Length); zip.Close(); ms.Position = 0; // Overwrite the packets data with the compressed data buffer.data = new byte[ms.Length + 4]; buffer.position = 0; buffer.Write(originalSize); // Prepend the original size of the data ms.Read(buffer.data, 4, buffer.data.Length - 4); // Write the compressed data // If the compressed version is bigger then, // just revert it back to it's original state if (buffer.data.Length > originalData.Length) { buffer.data = originalData; buffer.position = originalPosition; buffer.unpaddedIndex = originalIndex; buffer.isCompressed = false; } else { buffer.unpaddedIndex = buffer.data.Length; } } }
void TryMarkReliablePacket(NetOutboundPacket packet) { // If this packet is reliable, mark is as a new send if (packet.DeliveryMethod == NetDeliveryMethod.Reliable) { ReliablePacket reliablePacket; if (reliableOutboundPacketQueue.TryGetValue(packet.Id, out reliablePacket)) { reliablePacket.LastSendAttempt = NetTime.Now; reliablePacket.SendAttempts++; } else { // Could be from a connection issue NetLogger.LogError("Reliable packet was attempted to be sent, but it doesnt exist in the queue! Id: {0}", packet.Id); } } else if (packet.DeliveryMethod == NetDeliveryMethod.ReliableOrdered) { ReliablePacket reliablePacket; // Try and get the current ordered packet if (reliableOrderedOutboundPacketQueue.TryPeek(out reliablePacket)) { // Only set if it really is the first if (packet.Id == reliablePacket.Packet.Id) { reliablePacket.LastSendAttempt = NetTime.Now; reliablePacket.SendAttempts++; } else { // Bad news if it is not the current NetLogger.LogError("ReliableOrdered packet was attempted to be sent, without being first in queue! Id: {0}", packet.Id); } } } }
void AddPacketToChunkQueue(NetOutboundPacket packet) { // If it is reliable we need to mark it as a new send TryMarkReliablePacket(packet); // Log send if (NetLogger.LogPacketSends && CanLogSend(packet.Type) && !IsPingPacket(packet.Type)) { NetLogger.LogVerbose("[Outbound:{0}] {1}", EndPoint, packet.ToInternalString()); } // Send packet or add it to queue if (packet.SendImmediately) { // Just send it if needed SendPacketToSocket(packet); // Send } else { // Try to add the packet to the chunked queue if (!packetChunkQueue.Add(packet)) { NetLogger.LogError( "Failed to add packet to the chunk queue. Id: {0}, Type: {1}, DeliveryMethod: {2}, Duplicate Id Added: {3}", packet.Id, packet.Type, packet.DeliveryMethod, packetChunkQueue.Contains(packet)); } else { // Increment the chunks current size currentChunkSize += packet.Length; // If the chunk is too big, send it before any other chunks are added if (currentChunkSize >= maxChunkSize) { SendChunk(); } } } }
void HandleRemoteFunction(NetInboundPacket packet, RemoteChannelBase channel) { // Attempt to locate the function string funcName = packet.ReadString(); RemoteFunction func; if (channel.Functions.TryGetValue(funcName, out func)) { // Get the callback id ushort callbackId = packet.ReadUInt16(); // Call the event ushort numArgs = packet.ReadUInt16(); NetBuffer returnValue = func(packet.Sender, packet, numArgs); // Send the response NetOutboundPacket funcResponse = new NetOutboundPacket(NetDeliveryMethod.Reliable); funcResponse.Type = NetPacketType.RemoteFunctionResponse; funcResponse.Encrypt = packet.isEncrypted; // Write the normal remote header funcResponse.Write((byte)channel.Type); funcResponse.Write(channel.Id); funcResponse.Write(funcName); funcResponse.Write(callbackId); // Write the return value funcResponse.WriteBytes(returnValue.data, 0, returnValue.Length); // Send the response packet.Sender.SendPacket(funcResponse); } else { NetLogger.LogError("Remote Function \"{0}\" was invoked on a {1} channel with the id {2}, but it doesn't exist!", funcName, channel.Type, channel.Id); } }
public ReliablePacket(NetOutboundPacket packet) { Packet = packet; LastSendAttempt = packet.DeliveryMethod == NetDeliveryMethod.ReliableOrdered ? 0 : NetTime.Now; }
void WriteOutboundPacketHeader(NetOutboundPacket packet) { // Allocate the packet's Id and prepend its header packet.SetId(messenger.AllocatePacketId()); packet.PrependHeader(); }
void SendChunk() { lastChunkSend = NetTime.Now; // If theres nothing to send, don't bother! if (packetChunkQueue.Count == 0) { return; } // Safely grab the packets NetOutboundPacket[] packetsToChunk = packetChunkQueue.ToArrayAndClear(); currentChunkSize = 0; // Reset size if (packetsToChunk == null) { NetLogger.LogError("Failed to convert packetChunkQueue to an array!"); // Cannot continue return; } // If there is only one packet to send, // then don't create a chunk, just send it to // save cpu and bandwidth. if (packetsToChunk.Length == 1) { TryMarkReliablePacket(packetsToChunk[0]); SendPacketToSocket(packetsToChunk[0]); } else // Otherwise send it as a chunk { // Log the sends packetsSentInLastSecond += packetsToChunk.Length; Stats.PacketsSent += packetsToChunk.Length; // Create the packet NetOutboundPacket chunkPacket = new NetOutboundPacket(NetDeliveryMethod.Unreliable, 2 + (packetsToChunk.Length * 2) + currentChunkSize); chunkPacket.isChunked = true; // Write the header, the number of chunked packets chunkPacket.Write((ushort)packetsToChunk.Length); // Write each packet for (int i = 0; i < packetsToChunk.Length; i++) { NetOutboundPacket packet = packetsToChunk[i]; // If it is reliable we need to mark it as a new send TryMarkReliablePacket(packet); // Write packet chunkPacket.Write((ushort)packet.Length); // Size chunkPacket.WriteBytes(packet.data, 0, packet.Length); // Packet Data } // Setup header //SetupOutboundPacket(chunkPacket); WriteOutboundPacketHeader(chunkPacket); // And Send SendPacketToSocket(chunkPacket); } }