Exemplo n.º 1
0
        /// <summary>
        /// Handles all default <see cref="Packet"/>s that are in the library.
        /// </summary>
        /// <param name="packet">The <see cref="Packet"/> to be handled.</param>
        private void HandleDefaultPackets(Packet packet)
        {
            if (packet.GetType().Equals(typeof(PingRequest)))
            {
                Send(new PingResponse());
                return;
            }
            else if (packet.GetType().Equals(typeof(PingResponse)))
            {
                long elapsedTime = currentPingStopWatch.ElapsedMilliseconds;
                currentPingStopWatch.Reset();
                nextPingStopWatch.Restart();

                Ping = elapsedTime / 2;
                RTT  = elapsedTime;
                return;
            }
            else if (packet.GetType().Equals(typeof(CloseRequest)))
            {
                CloseRequest closeRequest = (CloseRequest)packet;
                ExternalClose(closeRequest.CloseReason);
                return;
            }
            else if (packet.GetType().Equals(typeof(EstablishUdpRequest)))
            {
                EstablishUdpRequest establishUdpRequest = (EstablishUdpRequest)packet;
                IPEndPoint          udpEndPoint         = new IPEndPoint(IPAddress.Any, GetFreePort());
                Send(new EstablishUdpResponse(udpEndPoint.Port, establishUdpRequest));
                UdpConnection udpConnection = CreateUdpConnection(udpEndPoint,
                                                                  new IPEndPoint(IPRemoteEndPoint.Address, establishUdpRequest.UdpPort), true);
                pendingUDPConnections.Enqueue(udpConnection);
                connectionEstablished?.Invoke((TcpConnection)this, udpConnection);
                return;
            }
            else if (packet.GetType().Equals(typeof(EstablishUdpResponseACK)))
            {
                UdpConnection udpConnection = null;
                while (!pendingUDPConnections.TryDequeue(out udpConnection))
                {
                    Thread.Sleep(IntPerformance);
                }
                udpConnection.AcknowledgePending = false;
                return;
            }
            else if (packet.GetType().Equals(typeof(AddPacketTypeRequest)))
            {
                Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName == ((AddPacketTypeRequest)packet).AssemblyName).SingleOrDefault();
                if (assembly == null)
                {
                    CloseHandler(Enums.CloseReason.AssemblyDoesNotExist);
                }
                else
                {
                    AddExternalPackets(assembly);
                }
                Send(new AddPacketTypeResponse(typeByte.Values.ToList(), (AddPacketTypeRequest)packet));
                return;
            }
            else if (packet.GetType().Equals(typeof(AddPacketTypeResponse)))
            {
                List <Tuple <Packet, object> > internalSendQueue     = new List <Tuple <Packet, object> >();
                AddPacketTypeResponse          addPacketTypeResponse = (AddPacketTypeResponse)packet;
                //Remove all packets of this type and send them :)
                while (true)
                {
                    Tuple <Packet, object> toSend = null;
                    while (!pendingUnknownPackets.TryPeek(out toSend) && pendingUnknownPackets.Count > 0)
                    {
                        Thread.Sleep(IntPerformance); //Wait till we got a result.
                    }
                    //If the other connection contains that packet, send it.
                    if (toSend != null && addPacketTypeResponse.LocalDict.Contains(typeByte[toSend.Item1.GetType()]))
                    {
                        while (!pendingUnknownPackets.TryDequeue(out toSend))
                        {
                            Thread.Sleep(IntPerformance); //Wait till we got a result.
                        }
                        internalSendQueue.Add(new Tuple <Packet, object>(toSend.Item1, toSend.Item2));
                        continue;
                    }

                    //Now the pendingUnknownPackets queue doesn't contain those elements any more.
                    internalSendQueue.ForEach(i => Send(i.Item1, i.Item2));
                    return;
                }
            }
            //Receiving raw data from the connection.
            else if (packet.GetType().Equals(typeof(RawData)))
            {
                RawData rawData = (RawData)packet;
                if (packetHandlerMap[rawData.Key] == null)
                {
                    Logger.Log($"RawData packet has no listener. Key: {rawData.Key}", LogLevel.Warning);
                }
                else
                {
                    packetHandlerMap[rawData.Key].DynamicInvoke(new object[] { packet, this });
                }
                return;
            }

            try
            {
                if (packet.GetType().IsSubclassOf(typeof(ResponsePacket)) && packetHandlerMap[packet.ID] != null)
                {
                    packetHandlerMap[packet.ID].DynamicInvoke(new object[] { packet, this });
                }
                else if (packetHandlerMap[packet.GetType()] != null)
                {
                    packetHandlerMap[packet.GetType()].DynamicInvoke(new object[] { packet, this });
                }
                else
                {
                    PacketWithoutHandlerReceived(packet);
                }
            }
            catch (Exception exception)
            {
                Logger.Log("Provided delegate contains a bug. Packet invocation thread crashed.", exception, LogLevel.Exception);
            }
        }