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);
        }
예제 #2
0
        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);
            }
        }
예제 #3
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);
     }
 }
        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);
        }
예제 #9
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 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);
            }
        }