示例#1
0
        public override void SendRaw(byte eventId, PacketFlags flags, byte[] rawData, long?presetPacketId = null)
        {
            byte[] buffer   = new byte[12 + rawData.Length];
            long   packetId = presetPacketId.HasValue ? presetPacketId.Value : DateTime.UtcNow.Ticks;

            // PACKET HEADER CONSTRUCTION: 12 BYTES
            /* 0x00 1           EVENT_ID    */ buffer[0] = eventId;
            /* 0x01 1           FLAGS       */ buffer[1] = (byte)flags;
            /* 0x02 8           PACKET_ID   */ BitConverter.GetBytes(packetId).CopyTo(buffer, 2);
            /* 0x0A 2           DATA_LENGTH */ BitConverter.GetBytes((ushort)rawData.Length).CopyTo(buffer, 10);

            /* 0x0C DATA_LENGTH DATA        */ rawData.CopyTo(buffer, 12);

            try
            {
                socket.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, endPoint, new AsyncCallback(SendToEvent), null);
                NetBase.WriteDebug($"Send data to {IPEndPoint}: {PacketToStringRep(buffer)}");

                if (flags.HasFlag(PacketFlags.Reliable) && !flags.HasFlag(PacketFlags.ReservedA))
                {
                    lock (sentReliableDataLock)
                    {
                        sentReliablePacketInfo.Add(packetId);
                    }
                    new Task(() => ResendReliable(new ReliablePacketInfo(eventId, flags, rawData, packetId))).Start();
                }
            }
            catch (Exception ex)
            {
                NetBase.WriteDebug(ex.ToString());
            }
        }
示例#2
0
 public Packet(byte[] data, PacketFlags flags)
 {
     Flags = flags;
     if (flags.HasFlag(PacketFlags.NO_ALLOCATE))
     {
         Data = data;
     }
     else
     {
         Data = new byte[data.Length];
         data.CopyTo(Data, 0);
     }
 }
示例#3
0
        /// <summary>Used internally by the netcode to process a received packet.</summary>
        private async Task Receive(IPEndPoint remote, byte[] buffer, int length)
        {
            byte[] bufferDecompress = null;
            try {
                // Notify listener
                Listener.OnHostReceiveSocket(remote, buffer, length);

                // Discard if empty
                if (length < 1)
                {
                    return;
                }

                // Extract packet information
                PacketType          type   = (PacketType)(buffer[0] & (byte)PacketType.Mask);
                PacketFlags         flags  = (PacketFlags)(buffer[0] & (byte)PacketFlags.Mask);
                ArraySegment <byte> packet = new ArraySegment <byte>(buffer, 1, length - 1);

                // Peer packets
                if (type == PacketType.Connected || type == PacketType.Reject || type == PacketType.Accept)
                {
                    Peer peer = FindPeer(remote);
                    if (peer == null)
                    {
                        throw new FormatException(string.Format(
                                                      "No peer to receive packet {0} ({1}) from {2}", type, flags, remote
                                                      ));
                    }
                    else
                    {
                        await peer.OnReceiveAsync(buffer, length);

                        return;
                    }
                }

                // Discard if unused packet type
                if (type == PacketType.Unused1 || type == PacketType.Unused2)
                {
                    throw new FormatException(string.Format(
                                                  "Unused packet {0} ({1} received from {2}", type, flags, remote
                                                  ));
                }

                // Fragmentation, multiple messages and timing not supported
                if (flags.HasFlag(PacketFlags.Fragmented))
                {
                    throw new FormatException(string.Format(
                                                  "Packet {0} ({1}) from {2} length {3} is fragmented", flags, type, remote, length
                                                  ));
                }
                else if (flags.HasFlag(PacketFlags.Combined))
                {
                    throw new FormatException(string.Format(
                                                  "Packet {0} ({1}) from {2} length {3} has multiple messages", flags, type, remote, length
                                                  ));
                }
                else if (flags.HasFlag(PacketFlags.Timed))
                {
                    throw new FormatException(string.Format(
                                                  "Packet {0} ({1}) from {2} length {3} is timed", flags, type, remote, length
                                                  ));
                }

                // Verify CRC32
                if (flags.HasFlag(PacketFlags.Verified))
                {
                    if (packet.Count < 4)
                    {
                        throw new FormatException(string.Format(
                                                      "Packet {0} ({1}) from {2} with length {3} is too short for CRC32",
                                                      type, flags, remote, length
                                                      ));
                    }
                    else if (Config.CRC32)
                    {
                        uint computed = CRC32.Compute(packet.Array, packet.Offset + 4, packet.Count - 4);
                        uint received = Serializer.ReadUInt32(packet.Array, packet.Offset);
                        if (computed != received)
                        {
                            throw new FormatException(string.Format(
                                                          "CRC32 {0} does not match {1} in packet {2} ({3}) from {4} with length {5}",
                                                          received, computed, type, flags, remote, length
                                                          ));
                        }
                    }
                    packet = new ArraySegment <byte>(packet.Array, packet.Offset + 4, packet.Count - 4);
                }

                // Decompress
                if (flags.HasFlag(PacketFlags.Compressed))
                {
                    bufferDecompress = Allocator.CreateMessage(packet.Count);
                    int len = Compressor.Decompress(packet, ref bufferDecompress, 0);
                    packet = new ArraySegment <byte>(bufferDecompress, 0, len);
                }

                // Process packet based on type
                switch (type)
                {
                case PacketType.Request:
                    ReceiveRequest(remote, packet);
                    break;

                case PacketType.Unconnected:
                    using (Reader reader = new Reader(packet.Array, 0, packet.Count)) {
                        Listener.OnHostReceiveUnconnected(remote, reader);
                    }
                    break;

                case PacketType.Broadcast:
                    using (Reader reader = new Reader(packet.Array, 0, packet.Count)) {
                        Listener.OnHostReceiveBroadcast(remote, reader);
                    }
                    break;
                }
            } catch (Exception exception) {
                Listener.OnHostException(remote, exception);
            } finally {
                Allocator.ReturnPacket(ref buffer);
                Allocator.ReturnMessage(ref bufferDecompress);
                ReceiveSemaphore.Release();
            }
        }
示例#4
0
        private async Task ProcessData(byte[] data, EndPoint clientEndPoint)
        {
            try
            {
                NetBase.WriteDebug($"Server received data: {PacketToStringRep(data)}");

                UdpClient clientRef = clientList.Find(c => c.EndPoint.Equals(clientEndPoint));
                if (clientRef == null)
                {
                    if (data.Length != 4 || BitConverter.ToUInt32(data, 0) != Secret)
                    {
                        NetBase.WriteDebug($"Client attempted to connect from {clientEndPoint} with a bad secret.");

                        return;
                    }
                    UdpClient rCl = new UdpClient(socket, clientEndPoint);

                    rCl.ReliableResendDelay        = this.ReliableResendDelay;
                    rCl.MaxResendAttempts          = this.MaxResendAttempts;
                    rCl.DisconnectOnFailedResponse = this.DisconnectOnFailedResponse;

                    rCl.ClientDisconnected += c => DisconnectEventHandler(c);
                    rCl.SendRaw(254, PacketFlags.None, BitConverter.GetBytes(Secret));
                    clientList.Add(rCl);

                    if (ClientConnected != null)
                    {
                        Array.ForEach(ClientConnected.GetInvocationList(), d => d.DynamicInvoke(rCl));
                    }
                }
                else
                {
                    if (data.Length < 12)
                    {
                        return;
                    }

                    byte        eventId     = data[0];
                    PacketFlags packetFlags = (PacketFlags)data[1];
                    long        packetId    = BitConverter.ToInt64(data, 2);
                    ushort      dataLength  = BitConverter.ToUInt16(data, 10);
                    byte[]      netData     = data.Skip(12).ToArray();

                    if (dataLength != netData.Length)
                    {
                        return;
                    }

                    Dictionary <byte, MethodInfo> eventsRef = packetFlags.HasFlag(PacketFlags.SystemMessage) ? systemDataEvents : netDataEvents;

                    if (packetFlags.HasFlag(PacketFlags.Reliable))
                    {
                        clientRef.SendF(2, PacketFlags.SystemMessage, packetId);
                    }


                    if (eventsRef.ContainsKey(eventId) && !clientRef.receivedReliablePacketInfo.Contains(packetId))
                    {
                        if (packetFlags.HasFlag(PacketFlags.Reliable))
                        {
                            if (!clientRef.receivedReliablePacketInfo.Contains(packetId))
                            {
                                lock (clientRef.receivedReliableDataLock)
                                {
                                    clientRef.receivedReliablePacketInfo.Add(packetId);
                                }
                            }
                        }

                        clientRef.lastMessageReceived = DateTime.UtcNow;

                        MethodInfo      netEventMethod = eventsRef[eventId];
                        ParameterInfo[] parameters     = netEventMethod.GetParameters().Skip(1).ToArray();
                        Type[]          parameterTypes = (from p in parameters
                                                          select p.ParameterType).ToArray();

                        object[] instances            = DynamicPacket.GetInstancesFromData(netData, converterInstance, parameterTypes);
                        object[] instancesWithNetBase = new object[1 + instances.Length];
                        instancesWithNetBase[0] = clientRef;
                        instances.CopyTo(instancesWithNetBase, 1);
                        netEventMethod.Invoke(netEventMethod.IsStatic ? null : this, instancesWithNetBase);
                    }
                }
            }
            catch (Exception ex)
            {
                NetBase.WriteDebug(ex.ToString());
            }
        }
示例#5
0
        private async Task ProcessData(byte[] data)
        {
            try
            {
                NetBase.WriteDebug($"Client received data: {PacketToStringRep(data)}");

                if (data.Length < 12)
                {
                    return;
                }

                byte        eventId     = data[0];
                PacketFlags packetFlags = (PacketFlags)data[1];
                long        packetId    = BitConverter.ToInt64(data, 2);
                ushort      dataLength  = BitConverter.ToUInt16(data, 10);
                byte[]      netData     = data.Skip(12).ToArray();

                if (dataLength != netData.Length)
                {
                    return;
                }

                Dictionary <byte, MethodInfo> eventsRef = packetFlags.HasFlag(PacketFlags.SystemMessage) ? systemDataEvents : netDataEvents;

                if (packetFlags.HasFlag(PacketFlags.Reliable))
                {
                    SendF(2, PacketFlags.SystemMessage, packetId);
                }

                if (eventsRef.ContainsKey(eventId) && !receivedReliablePacketInfo.Contains(packetId))
                {
                    if (packetFlags.HasFlag(PacketFlags.Reliable))
                    {
                        if (!receivedReliablePacketInfo.Contains(packetId))
                        {
                            lock (receivedReliableDataLock)
                            {
                                receivedReliablePacketInfo.Add(packetId);
                            }
                        }
                    }

                    lastMessageReceived = DateTime.UtcNow;

                    MethodInfo      netEventMethod = eventsRef[eventId];
                    ParameterInfo[] parameters     = netEventMethod.GetParameters().Skip(1).ToArray();
                    Type[]          parameterTypes = (from p in parameters
                                                      select p.ParameterType).ToArray();

                    object[] instances = DynamicPacket.GetInstancesFromData(netData, converterInstance, parameterTypes);

                    object[] instancesWithNetBase = new object[1 + instances.Length];
                    instancesWithNetBase[0] = this;
                    instances.CopyTo(instancesWithNetBase, 1);
                    netEventMethod.Invoke(netEventMethod.IsStatic ? null : this, instancesWithNetBase);
                }
            }
            catch (Exception ex)
            {
                NetBase.WriteDebug(ex.ToString());
            }
        }