/// <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);
        }
示例#4
0
 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));
        }
示例#10
0
        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);
        }
示例#19
0
        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);
            }
        }