private void HandleReliable(ENetPeer peer, ENetProtocol packet, bool isFragment, byte[] data) { if (peer.State != ENetPeerState.Connected && peer.State != ENetPeerState.DisconnectLater) return; var channel = peer.Channels[packet.Header.ChannelID]; if (DropSequencedData(channel, packet.Header) || packet.Header.ReliableSequenceNumber == channel.IncomingSequenceNumber) return; if (!isFragment && packet.Header.ReliableSequenceNumber == (channel.IncomingSequenceNumber + 1)) { if (OnData != null) OnData(peer, data); channel.IncomingSequenceNumber++; return; } lock (channel.IncomingCommandLock) { var command = new ENetIncomingCommand(packet.Header.ReliableSequenceNumber); var existingCommand = channel.IncomingCommands.Find(command); //Establish if we already have the packet if (existingCommand != null && !isFragment) return; //We already have the command, ignore it else if (existingCommand != null) { if (existingCommand.Value.FragmentsRemaining == 0) return; } if (isFragment) { command.FragmentsRemaining = packet.SendFragment.FragmentCount - 1; } if(packet.Header.ReliableSequenceNumber == (channel.IncomingSequenceNumber + 1))channel.IncomingCommands.AddFirst() } }
public void Read(hsStream s) { fType = (ENetProtocol)s.ReadByte(); if (s.ReadUShort() != kHeaderSize) throw new NotSupportedException(); fBuildID = s.ReadUInt(); fBuildType = (EBuildType)s.ReadUInt(); fBranchID = s.ReadUInt(); fProductUuid = pnHelpers.ReadUuid(s); }
public void Read(hsStream s) { fType = (ENetProtocol)s.ReadByte(); if (s.ReadUShort() != kHeaderSize) throw new NotSupportedException(); fBuildID = s.ReadUInt(); fProtocolVer = s.ReadUInt(); if (fProtocolVer < 50) fProtocolVer = 50; // <= 50 are the old "Build Type" values... fBranchID = s.ReadUInt(); fProductUuid = pnHelpers.ReadUuid(s); }
private unsafe void ReceiveDatagram(IAsyncResult ar) { IPEndPoint fromAddr = new IPEndPoint(IPAddress.Any, 0); byte[] data = connection.EndReceive(ar, ref fromAddr); if (!shuttingDown) connection.BeginReceive(ReceiveDatagram, null); #region "ENet Structure Handling" var handle = GCHandle.Alloc(data, GCHandleType.Pinned); IntPtr dataStart = handle.AddrOfPinnedObject(); ENetProtocolHeader header = (ENetProtocolHeader)Marshal.PtrToStructure(dataStart, typeof(ENetProtocolHeader)); Util.ToHostOrder(ref header.PeerID); ushort flag = (ushort)(header.PeerID & PROTOCOL_HEADER_FLAG_MASK); header.PeerID &= unchecked((ushort)~(uint)PROTOCOL_HEADER_FLAG_MASK); ENetPeer? peer = null; if (header.PeerID != PROTOCOL_MAXIMUM_PEER_ID) //peer remains null if the first command is expected to be a connect { try { peer = Peers[header.PeerID]; if (peer.Value.State == ENetPeerState.Disconnected || peer.Value.State == ENetPeerState.Zombie || //Don't include ENET_HOST_BROADCAST, it's meant for clients broadcasting the connect packet and communicating with any server that responds !peer.Value.Address.Equals(fromAddr) /* && peer.Value.Address != ENET_HOST_BROADCAST */) { goto finalPacket; //The peer is disconnected, dead or the packets origin doesn't match the peer - Ignore them } } catch (System.Collections.Generic.KeyNotFoundException) { goto finalPacket; //The client doesn't exist and this doesn't follow connection protocol - Ignore them } } int currentDataOffset = ((flag & PROTOCOL_HEADER_FLAG_SENT_TIME) != 0) ? sizeof(ENetProtocolHeader) : sizeof(ENetProtocolHeader) - 2; //sentTime is 2 bytes while (currentDataOffset < data.Length) { ENetProtocol packet = (ENetProtocol)Marshal.PtrToStructure(dataStart + currentDataOffset, typeof(ENetProtocol)); Util.ToHostOrder(ref packet.Header.ReliableSequenceNumber); if (packet.Header.ChannelID >= ChannelLayout.ChannelCount()) continue; ENetCommand command = (ENetCommand)(packet.Header.Command & (byte)ENetCommand.COMMAND_MASK); if(command >= ENetCommand.COUNT) continue; if (peer == null && command != ENetCommand.CONNECT) return; //Peer was following connection protocol but didn't send the connect first currentDataOffset += command.Size(); if (currentDataOffset > data.Length) return; //The ENetCommand is larger than the remaining data switch (command) { case ENetCommand.ACKNOWLEDGE: Util.ToHostOrder(ref packet.Acknowledge.ReceivedReliableSequenceNumber); Util.ToHostOrder(ref packet.Acknowledge.ReceivedSentTime); //TODO: Handle Acknowledge break; case ENetCommand.BANDWIDTH_LIMIT: Util.ToHostOrder(ref packet.BandwidthLimit.IncomingBandwidth); Util.ToHostOrder(ref packet.BandwidthLimit.OutgoingBandwidth); //TODO: Handle Bandwidth Limit break; case ENetCommand.CONNECT: Console.WriteLine("A connected peer sent a connect packet. WTF are they doing?"); Util.ToHostOrder(ref packet.Connect.MTU); Util.ToHostOrder(ref packet.Connect.WindowSize); Util.ToHostOrder(ref packet.Connect.ChannelCount); Util.ToHostOrder(ref packet.Connect.IncomingBandwidth); Util.ToHostOrder(ref packet.Connect.OutgoingBandwidth); Util.ToHostOrder(ref packet.Connect.PacketThrottleInterval); Util.ToHostOrder(ref packet.Connect.PacketThrottleAcceleration); Util.ToHostOrder(ref packet.Connect.PacketThrottleDeceleration); Util.ToHostOrder(ref packet.Connect.SessionID); peer = HandleConnect(fromAddr, packet.Connect); break; case ENetCommand.DISCONNECT: Util.ToHostOrder(ref packet.Disconnect.Data); //TODO: Handle Disconnect break; case ENetCommand.PING: //Ping has no handling in the real ENet break; case ENetCommand.SEND_FRAGMENT: Util.ToHostOrder(ref packet.SendFragment.DataLength); //We have to assume the fragment is the right type for the channel until I figure out how it indicates it Util.ToHostOrder(ref packet.SendFragment.StartSequenceNumber); Util.ToHostOrder(ref packet.SendFragment.FragmentCount); Util.ToHostOrder(ref packet.SendFragment.FragmentNumber); Util.ToHostOrder(ref packet.SendFragment.TotalLength); Util.ToHostOrder(ref packet.SendFragment.FragmentOffset); byte[] fragmentData = new byte[packet.SendFragment.DataLength]; Marshal.Copy(dataStart + currentDataOffset, fragmentData, 0, packet.SendFragment.DataLength); currentDataOffset += packet.SendFragment.DataLength; HandleReliable(peer.Value, packet, true, fragmentData); break; case ENetCommand.SEND_RELIABLE: Util.ToHostOrder(ref packet.SendReliable.DataLength); if ((ChannelLayout[packet.Header.ChannelID] & ENetSendType.RELIABLE) == 0) //Each of the data handlers uses this to quickly discard any data not matching the channels send type { currentDataOffset += packet.SendReliable.DataLength; break; } byte[] reliableData = new byte[packet.SendReliable.DataLength]; Marshal.Copy(dataStart + currentDataOffset, reliableData, 0, packet.SendReliable.DataLength); currentDataOffset += packet.SendReliable.DataLength; HandleReliable(peer.Value, packet, false, reliableData); break; case ENetCommand.SEND_UNRELIABLE: Util.ToHostOrder(ref packet.SendUnreliable.DataLength); if ((ChannelLayout[packet.Header.ChannelID] & ENetSendType.UNRELIABLE) == 0) { currentDataOffset += packet.SendUnreliable.DataLength; break; } Util.ToHostOrder(ref packet.SendUnreliable.UnreliableSequenceNumber); byte[] unreliableData = new byte[packet.SendUnreliable.DataLength]; Marshal.Copy(dataStart + currentDataOffset, unreliableData, 0, packet.SendUnreliable.DataLength); currentDataOffset += packet.SendUnreliable.DataLength; HandleUnreliable(peer.Value, packet.SendUnreliable, unreliableData); break; case ENetCommand.SEND_UNSEQUENCED: Util.ToHostOrder(ref packet.SendUnsequenced.DataLength); if ((ChannelLayout[packet.Header.ChannelID] & ENetSendType.UNSEQUENCED) == 0) { currentDataOffset += packet.SendUnsequenced.DataLength; break; } Util.ToHostOrder(ref packet.SendUnsequenced.UnsequencedGroup); byte[] unsequencedData = new byte[packet.SendUnsequenced.DataLength]; Marshal.Copy(dataStart + currentDataOffset, unsequencedData, 0, packet.SendUnsequenced.DataLength); currentDataOffset += packet.SendUnsequenced.DataLength; HandleUnsequenced(peer.Value, packet.SendUnsequenced, unsequencedData); break; case ENetCommand.THROTTLE_CONFIGURE: Util.ToHostOrder(ref packet.ThrottleConfigure.PacketThrottleInterval); Util.ToHostOrder(ref packet.ThrottleConfigure.PacketThrottleAcceleration); Util.ToHostOrder(ref packet.ThrottleConfigure.PacketThrottleDeceleration); //TODO: Handle Throttle Configure break; case ENetCommand.VERIFY_CONNECT: Util.ToHostOrder(ref packet.VerifyConnect.MTU); Util.ToHostOrder(ref packet.VerifyConnect.WindowSize); Util.ToHostOrder(ref packet.VerifyConnect.ChannelCount); Util.ToHostOrder(ref packet.VerifyConnect.IncomingBandwidth); Util.ToHostOrder(ref packet.VerifyConnect.OutgoingBandwidth); Util.ToHostOrder(ref packet.VerifyConnect.PacketThrottleInterval); Util.ToHostOrder(ref packet.VerifyConnect.PacketThrottleAcceleration); Util.ToHostOrder(ref packet.VerifyConnect.PacketThrottleDeceleration); //TODO: Handle Verify Connect break; default: goto finalPacket; } } finalPacket: handle.Free(); #endregion if (shuttingDown) shutdownComplete.Set(); }
/// <summary> /// Queues a packet to be sent. /// </summary> /// <param name="channelId">channel on which to send</param> /// <param name="packet">packet to send</param> /// <returns> /// 0 on success /// < 0 on failure /// </returns> public int Send(byte channelId, ENetPacket packet) { ENetChannel channel = Channels[channelId]; if (State != ENetPeerState.ENET_PEER_STATE_CONNECTED || channelId >= ChannelCount || packet.DataLength > Host._maximumPacketSize) { return(-1); } uint fragmentLength = Mtu - ENetProtocolHeader.Size - ENetProtocolSendFragment.Size; if (Host._checksum != null) { fragmentLength -= 4; //sizeof(enet_uint32); } if (packet.DataLength > fragmentLength) { uint fragmentCount = (packet.DataLength + fragmentLength - 1) / fragmentLength; byte commandNumber; ushort startSequenceNumber; if (fragmentCount > ENetHost.ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) { return(-1); } if ( (packet.Flags & (ENetPacketFlags.ENET_PACKET_FLAG_RELIABLE | ENetPacketFlags.ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENetPacketFlags.ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && channel.OutgoingUnreliableSequenceNumber < 0xFFFF) { commandNumber = (byte)ENetProtocolCommand.ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT; startSequenceNumber = ENetSocket.ENET_HOST_TO_NET_16((ushort)(channel.OutgoingUnreliableSequenceNumber + 1)); } else { commandNumber = (byte)ENetProtocolCommand.ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | (byte)ENetProtocolFlag.ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; startSequenceNumber = ENetSocket.ENET_HOST_TO_NET_16((ushort)(channel.OutgoingReliableSequenceNumber + 1)); } List <ENetOutgoingCommand> fragments = new List <ENetOutgoingCommand>(); ENetOutgoingCommand fragment; uint fragmentNumber; uint fragmentOffset; for (fragmentNumber = 0, fragmentOffset = 0; fragmentOffset < packet.DataLength; ++fragmentNumber, fragmentOffset += fragmentLength) { if (packet.DataLength - fragmentOffset < fragmentLength) { fragmentLength = packet.DataLength - fragmentOffset; } fragment = new ENetOutgoingCommand(); fragment.FragmentOffset = fragmentOffset; fragment.FragmentLength = (ushort)fragmentLength; fragment.Packet = packet; fragment.Command.Header.Command = commandNumber; fragment.Command.Header.ChannelId = channelId; fragment.Command.SendFragment.StartSequenceNumber = startSequenceNumber; fragment.Command.SendFragment.DataLength = ENetSocket.ENET_HOST_TO_NET_16((ushort)fragmentLength); fragment.Command.SendFragment.FragmentCount = ENetSocket.ENET_HOST_TO_NET_32(fragmentCount); fragment.Command.SendFragment.FragmentNumber = ENetSocket.ENET_HOST_TO_NET_32(fragmentNumber); fragment.Command.SendFragment.TotalLength = ENetSocket.ENET_HOST_TO_NET_32(packet.DataLength); fragment.Command.SendFragment.FragmentOffset = ENetSocket.ENET_NET_TO_HOST_32(fragmentOffset); fragments.Add(fragment); } packet.ReferenceCount += fragmentNumber; foreach (ENetOutgoingCommand currentFragment in fragments) { Host.enet_peer_setup_outgoing_command(this, currentFragment); } return(0); } ENetProtocol command = new ENetProtocol(); command.Header.ChannelId = channelId; if ((packet.Flags & (ENetPacketFlags.ENET_PACKET_FLAG_RELIABLE | ENetPacketFlags.ENET_PACKET_FLAG_UNSEQUENCED)) == ENetPacketFlags.ENET_PACKET_FLAG_UNSEQUENCED) { // packetFlags.HasFlag(ENET_PACKET_FLAG_UNSEQUENCED) && !packetFlags.HasFlag(ENET_PACKET_FLAG_RELIABLE) command.Header.Command = (byte)ENetProtocolCommand.ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | (byte)ENetProtocolFlag.ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; command.SendUnsequenced.DataLength = ENetSocket.ENET_HOST_TO_NET_16((ushort)packet.DataLength); } else if ((packet.Flags & ENetPacketFlags.ENET_PACKET_FLAG_RELIABLE) != 0 || channel.OutgoingUnreliableSequenceNumber >= 0xFFFF) { // if(0) == if(false) / if(1) == if(true) // packetFlags.HasFlag(ENET_PACKET_FLAG_RELIABLE) command.Header.Command = (byte)ENetProtocolCommand.ENET_PROTOCOL_COMMAND_SEND_RELIABLE | (byte)ENetProtocolFlag.ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; command.SendReliable.DataLength = ENetSocket.ENET_HOST_TO_NET_16((ushort)packet.DataLength); } else { command.Header.Command = (byte)ENetProtocolCommand.ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE; command.SendUnreliable.DataLength = ENetSocket.ENET_HOST_TO_NET_16((ushort)packet.DataLength); } if (Host.enet_peer_queue_outgoing_command(this, command, packet, 0, (ushort)packet.DataLength) == null) { return(-1); } return(0); }