internal void InvokeIncomingConnection(RUDPChannel channel)
 {
     OnIncomingConnection?.Invoke(channel);
 }
 internal void InvokeConnected(RUDPChannel channel)
 {
     OnConnected?.Invoke(channel);
 }
 internal void InvokePacketReceived(RUDPChannel channel, RUDPPacket p)
 {
     OnPacketReceived?.Invoke(channel, p);
 }
        private void ProcessChannelData(IPEndPoint ep, byte[] data, int length)
        {
            RUDPPacket         p;
            RUDPChannel        channel;
            RUDPInternalPacket ip;
            DateTime           dtNow = DateTime.Now;

            Trace("RECV: {0}", Encoding.ASCII.GetString(data));

            string strEp            = ep.ToString();
            bool   isNormalPacket   = length >= PacketHeader.Length && data.Take(PacketHeader.Length).SequenceEqual(PacketHeader);
            bool   isInternalPacket = length >= PacketHeaderInternal.Length && data.Take(PacketHeaderInternal.Length).SequenceEqual(PacketHeaderInternal);

            if (isInternalPacket)
            {
                ip = RUDPInternalPacket.Deserialize(PacketHeaderInternal, data);
                Trace("INTERNAL RECV <- {0}: {1}", ep, ip);

                if (ip.Channel == 0)
                {
                    switch (ip.Type)
                    {
                    case RUDPInternalPacket.RUDPInternalPacketType.CHANNELREQUEST:
                        string channelName = ip.ExtraData;
                        int    channelId   = RequestFreeChannel(ep, channelName);
                        Trace("Assigning channel {0} as {1}", channelId, channelName);
                        ip = new RUDPInternalPacket()
                        {
                            Type = RUDPInternalPacket.RUDPInternalPacketType.CHANNELASSIGN, Channel = 0, Data = channelId, ExtraData = channelName
                        };
                        _socket.SendBytes(ep, ip.Serialize(PacketHeaderInternal));
                        break;

                    case RUDPInternalPacket.RUDPInternalPacketType.CHANNELASSIGN:
                        if (!_channels.ContainsKey(strEp))
                        {
                            _channels[strEp] = new List <RUDPChannel>();
                        }
                        Trace("Channel {0} assigned as {1}", ip.ExtraData, ip.Data);
                        RUDPChannel c = new RUDPChannel()
                        {
                            Connection = this,
                            Id         = ip.Data,
                            Name       = ip.ExtraData,
                            IsServer   = false,
                            EndPoint   = ep
                        }.Init();
                        _channels[strEp].Add(c);
                        OnChannelAssigned?.Invoke(c);
                        break;

                    case RUDPInternalPacket.RUDPInternalPacketType.PING:
                        channel = _channels[strEp].Where(x => x.Id == ip.Channel).SingleOrDefault();
                        if (!(channel == null || channel.State >= State.CLOSING))
                        {
                            if (ip.Data == 0)
                            {
                                _socket.SendBytes(ep, new RUDPInternalPacket()
                                {
                                    Type = RUDPInternalPacket.RUDPInternalPacketType.PING, Channel = channel.Id, Data = 1
                                }.Serialize(PacketHeaderInternal));
                            }
                            channel.LastKeepAliveReceived = DateTime.Now;
                        }
                        break;
                    }
                }
                else
                {
                    channel = _channels[strEp].Where(x => x.Id == ip.Channel).SingleOrDefault();
                    if (channel == null || channel.State >= State.CLOSING)
                    {
                        Trace("Channel {0} not found for {1} or channel is CLOSING", ip.Channel, strEp);
                        return;
                    }

                    switch (ip.Type)
                    {
                    case RUDPInternalPacket.RUDPInternalPacketType.ACK:
                        channel.LastKeepAliveReceived = DateTime.Now;
                        channel.AcknowledgePacket(ip.Data);
                        break;
                    }
                }
            }
            else if (isNormalPacket)
            {
                p       = Serializer.Deserialize(PacketHeader, data);
                channel = _channels[strEp].Where(x => x.Id == p.Channel).SingleOrDefault();
                if (channel != null)
                {
                    p.Src        = ep;
                    p.Serializer = Serializer;
                    Trace("ADDRECV: {0}", p);
                    channel.AddReceivedPacket(p);
                    channel.LastKeepAliveReceived = DateTime.Now;
                    ip = new RUDPInternalPacket()
                    {
                        Type = RUDPInternalPacket.RUDPInternalPacketType.ACK, Channel = p.Channel, Data = p.Seq
                    };
                    Trace("INTERNAL SEND -> {0}: {1}", ep, ip);
                    _socket.SendBytes(ep, ip.Serialize(PacketHeaderInternal));
                }
                else
                {
                    Trace("Unknown channel {0} for {1}", p.Channel, p);
                }
            }
        }