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); }
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); } }
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); } }
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); }
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 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); } }
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); }
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 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); } }