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