示例#1
0
        protected override void OnReceive(int nErrorCode)
        {
            byte[]   buffer   = new byte[5000];
            byte[]   pBuffer  = buffer;
            EndPoint endpoint = null;

            int length = ReceiveFrom(buffer, ref endpoint);

            if (length != SOCKET_ERROR)
            {
                IPEndPoint ipEndPoint  = endpoint as IPEndPoint;
                int        nPayLoadLen = length;
                ED2KServer pServer     =
                    MuleApplication.Instance.ServerList.GetServerByIPUDP(BitConverter.ToUInt32(ipEndPoint.Address.GetAddressBytes(), 0),
                                                                         (ushort)IPAddress.NetworkToHostOrder(ipEndPoint.Port), true);
                if (pServer != null && MuleApplication.Instance.Preference.IsServerCryptLayerUDPEnabled &&
                    ((pServer.ServerKeyUDP != 0 && pServer.DoesSupportsObfuscationUDP) ||
                     (pServer.CryptPingReplyPending && pServer.Challenge != 0)))
                {
                    // TODO
                    uint dwKey = 0;
                    if (pServer.CryptPingReplyPending && pServer.Challenge != 0 /* && pServer.GetPort() == ntohs(sockAddr.sin_port) - 12 */)
                    {
                        dwKey = pServer.Challenge;
                    }
                    else
                    {
                        dwKey = pServer.ServerKeyUDP;
                    }

                    Debug.Assert(dwKey != 0);
                    nPayLoadLen = DecryptReceivedServer(buffer, length, out pBuffer, dwKey,
                                                        BitConverter.ToUInt32(ipEndPoint.Address.GetAddressBytes(), 0));
                }

                if (pBuffer[0] == MuleConstants.PROTOCOL_EDONKEYPROT)
                {
                    ProcessPacket(pBuffer, 2, nPayLoadLen - 2, pBuffer[1],
                                  BitConverter.ToUInt32(ipEndPoint.Address.GetAddressBytes(), 0),
                                  (ushort)IPAddress.NetworkToHostOrder(ipEndPoint.Port));
                }
            }
            else
            {
                IPEndPoint ipEndPoint = endpoint as IPEndPoint;

                if (ipEndPoint != null)
                {
                    ED2KServer pServer =
                        MuleApplication.Instance.ServerList.GetServerByIPUDP(BitConverter.ToUInt32(ipEndPoint.Address.GetAddressBytes(), 0),
                                                                             (ushort)IPAddress.NetworkToHostOrder(ipEndPoint.Port), true);
                    if (pServer != null &&
                        !pServer.CryptPingReplyPending &&
                        MpdUtilities.GetTickCount() - pServer.LastPinged >= MuleConstants.ONE_SEC_MS * 30)
                    {
                        pServer.AddFailedCount();
                    }
                }
            }
        }
示例#2
0
 public ED2KServerImpl(ED2KServer pOld)
 {
     Port                  = pOld.Port;
     IP                    = pOld.IP;
     IsStaticMember        = pOld.IsStaticMember;
     FileCount             = pOld.FileCount;
     UserCount             = pOld.UserCount;
     Priority              = pOld.Priority;
     Ping                  = pOld.Ping;
     FailedCount           = pOld.FailedCount;
     LastPinged            = pOld.LastPinged;
     LastPingedTime        = pOld.LastPingedTime;
     MaxUsers              = pOld.MaxUsers;
     SoftFiles             = pOld.SoftFiles;
     HardFiles             = pOld.HardFiles;
     LastDescPingedCount   = pOld.LastDescPingedCount;
     Description           = pOld.Description;
     ServerName            = pOld.ServerName;
     DynIP                 = pOld.DynIP;
     Version               = pOld.Version;
     TCPFlags              = pOld.TCPFlags;
     UDPFlags              = pOld.UDPFlags;
     DescReqChallenge      = pOld.DescReqChallenge;
     LowIDUsers            = pOld.LowIDUsers;
     Challenge             = pOld.Challenge;
     ServerKeyUDP          = pOld.ServerKeyUDP;
     CryptPingReplyPending = pOld.CryptPingReplyPending;
     ServerKeyUDPIP        = pOld.ServerKeyUDPIP;
     ObfuscationPortTCP    = pOld.ObfuscationPortTCP;
     ObfuscationPortUDP    = pOld.ObfuscationPortUDP;
     RealLastPingedTime    = pOld.RealLastPingedTime;
 }
示例#3
0
        public ED2KServer GetNextServer(bool bOnlyObfuscated)
        {
            if (serverpos_ >= (uint)servers_.Count)
            {
                return(null);
            }

            ED2KServer nextserver = null;
            int        i          = 0;

            while (nextserver == null && i < servers_.Count)
            {
                uint posIndex = serverpos_;
                if (serverpos_ >= (uint)servers_.Count)
                {       // check if search position is still valid (could be corrupted by server delete operation)
                    posIndex   = 0;
                    serverpos_ = 0;
                }

                serverpos_++;
                i++;
                if (!bOnlyObfuscated || servers_[(int)posIndex].DoesSupportsObfuscationTCP)
                {
                    nextserver = servers_[(int)posIndex];
                }
                else if (serverpos_ >= (uint)servers_.Count)
                {
                    return(null);
                }
            }
            return(nextserver);
        }
示例#4
0
        public bool AddServerMetToList(List <ServerAddress> list)
        {
            list.ForEach(serverAddress =>
            {
                IPAddress ip = null;

                if (IPAddress.TryParse(serverAddress.Address, out ip))
                {
                    ED2KServer server =
                        MuleApplication.Instance.ED2KObjectManager.CreateED2KServer((ushort)serverAddress.Port,
                                                                                    serverAddress.Address);
                    server.ServerName     = serverAddress.Name;
                    server.IsStaticMember = serverAddress.IsStatic;
                    switch (serverAddress.Priority)
                    {
                    case (uint)ED2KServerPriorityEnum.SRV_PR_HIGH:
                        server.Priority = ED2KServerPriorityEnum.SRV_PR_HIGH;
                        break;

                    case (uint)ED2KServerPriorityEnum.SRV_PR_LOW:
                        server.Priority = ED2KServerPriorityEnum.SRV_PR_LOW;
                        break;

                    case (uint)ED2KServerPriorityEnum.SRV_PR_NORMAL:
                    default:
                        server.Priority = ED2KServerPriorityEnum.SRV_PR_NORMAL;
                        break;
                    }
                    servers_.Add(server);
                }
            }
                         );

            return(true);
        }
示例#5
0
 public bool IsGoodServerIP(ED2KServer pServer)
 {
     if (pServer.HasDynIP)
     {
         return(true);
     }
     return(MpdUtilities.IsGoodIPPort(pServer.IP, pServer.Port));
 }
示例#6
0
        public void MoveServerDown(ED2KServer pServer)
        {
            if (!servers_.Contains(pServer))
            {
                return;
            }

            servers_.Remove(pServer);
            servers_.Add(pServer);
        }
示例#7
0
        public void RemoveServer(ED2KServer pServer)
        {
            if (!servers_.Contains(pServer))
            {
                return;
            }

            servers_.Remove(pServer);
            delservercount_++;
            if (MuleApplication.Instance.DownloadQueue.CurrentUDPServer == pServer)
            {
                MuleApplication.Instance.DownloadQueue.CurrentUDPServer = null;
            }
        }
示例#8
0
        private void ProcessPacketError(uint size, uint opcode, uint nIP, ushort nUDPPort,
                                        Exception ex)
        {
            string     strName = string.Empty;
            ED2KServer pServer = MuleApplication.Instance.ServerList.GetServerByIPUDP(nIP, nUDPPort);

            if (pServer != null)
            {
                strName = " (" + pServer.ServerName + ")";
            }
            MpdUtilities.DebugLogWarning(false,
                                         string.Format("Error: Failed to process server UDP packet from {0}:{1}{2} opcode=0x{3} size={4} - {5}",
                                                       MpdUtilities.IP2String(nIP), nUDPPort, strName, opcode, size, ex.Message), ex);
        }
示例#9
0
        public bool AddServer(ED2KServer pServer, bool bAddTail)
        {
            if (!IsGoodServerIP(pServer))
            {
                // check for 0-IP, localhost and optionally for LAN addresses
                return(false);
            }

            if (MuleApplication.Instance.Preference.IsFilterServerByIP)
            {
                // IP-Filter: We don't need to reject dynIP-servers here. After the DN was
                // resolved, the IP will get filtered and the server will get removed. This applies
                // for TCP-connections as well as for outgoing UDP-packets because for both protocols
                // we resolve the DN and filter the received IP.
                //if (pServer.HasDynIP())
                //	return false;
                if (MuleApplication.Instance.IPFilter.IsFiltered(pServer.IP))
                {
                    return(false);
                }
            }

            ED2KServer pFoundServer = GetServerByAddress(pServer.Address, pServer.Port);

            // Avoid duplicate (dynIP) servers: If the server which is to be added, is a dynIP-server
            // but we don't know yet it's DN, we need to search for an already available server with
            // that IP.
            if (pFoundServer == null && pServer.IP != 0)
            {
                pFoundServer = GetServerByIPTCP(pServer.IP, pServer.Port);
            }

            if (pFoundServer != null)
            {
                pFoundServer.ResetFailedCount();
                return(false);
            }

            if (bAddTail)
            {
                servers_.Add(pServer);
            }
            else
            {
                servers_.Insert(0, pServer);
            }
            return(true);
        }
示例#10
0
 public void RemoveDuplicatesByAddress(ED2KServer pExceptThis)
 {
     foreach (ED2KServer pServer in servers_)
     {
         if (pServer == pExceptThis)
         {
             continue;
         }
         if (string.Compare(pServer.Address, pExceptThis.Address, true) == 0 &&
             pServer.Port == pExceptThis.Port)
         {
             servers_.Remove(pServer);
             return;
         }
     }
 }
示例#11
0
 public void RemoveDuplicatesByIP(ED2KServer pExceptThis)
 {
     foreach (ED2KServer pServer in servers_)
     {
         if (pServer == pExceptThis)
         {
             continue;
         }
         if (pServer.IP == pExceptThis.IP &&
             pServer.Port == pExceptThis.Port)
         {
             servers_.Remove(pServer);
             return;
         }
     }
 }
示例#12
0
 public bool Disconnect()
 {
     if (IsConnected && connectedSocket_ != null)
     {
         MuleApplication.Instance.SharedFiles.ClearED2KPublishInfo();
         IsConnected = false;
         ED2KServer pServer =
             MuleApplication.Instance.ServerList.GetServerByAddress(connectedSocket_.CurrentServer.Address, connectedSocket_.CurrentServer.Port);
         MuleApplication.Instance.PublicIP = 0;
         DestroySocket(connectedSocket_);
         connectedSocket_ = null;
         MuleApplication.Instance.Statistics.ServerConnectTime = 0;
         MuleApplication.Instance.Statistics.Add2TotalServerDuration();
         return(true);
     }
     return(false);
 }
示例#13
0
        public void TryAnotherConnectionRequest()
        {
            if (connectionAttemps_.Count < (MuleApplication.Instance.Preference.IsSafeServerConnectEnabled ? 1 : 2))
            {
                ED2KServer next_server =
                    MuleApplication.Instance.ServerList.GetNextServer(tryObfuscated_);
                if (next_server == null)
                {
                    if (connectionAttemps_.Count == 0)
                    {
                        if (tryObfuscated_ && !MuleApplication.Instance.Preference.IsClientCryptLayerRequired)
                        {
                            // try all servers on the non-obfuscated port next
                            tryObfuscated_ = false;
                            ConnectToAnyServer(0, true, true, true);
                        }
                        else if (retryTimer_ == null)
                        {
                            // 05-Nov-2003: If we have a very short server list, we could put serious load on those few servers
                            // if we start the next connection tries without waiting.
                            startAutoConnectPos_ = 0; // default: start at 0
                        }
                    }
                    return;
                }

                // Barry - Only auto-connect to static server option
                if (MuleApplication.Instance.Preference.DoesAutoConnectToStaticServersOnly)
                {
                    if (next_server.IsStaticMember)
                    {
                        ConnectToServer(next_server, true, !tryObfuscated_);
                    }
                }
                else
                {
                    ConnectToServer(next_server, true, !tryObfuscated_);
                }
            }
        }
示例#14
0
        public override bool Equals(object obj)
        {
            if (obj is ED2KServer)
            {
                ED2KServer pServer = obj as ED2KServer;

                if (Port != pServer.Port)
                {
                    return(false);
                }
                if (HasDynIP && pServer.HasDynIP)
                {
                    return(string.Compare(DynIP, pServer.DynIP, true) == 0);
                }
                if (HasDynIP || pServer.HasDynIP)
                {
                    return(false);
                }
                return(IP == pServer.IP);
            }

            return(base.Equals(obj));
        }
示例#15
0
        public ED2KServer GetSuccServer(ED2KServer lastserver)
        {
            if (servers_.Count == 0)
            {
                return(null);
            }
            if (lastserver == null)
            {
                return(servers_[0]);
            }

            int index = servers_.IndexOf(lastserver);

            if (index < 0)
            {
                return(servers_[0]);
            }

            if (index + 1 >= servers_.Count)
            {
                return(null);
            }
            return(servers_[index + 1]);
        }
示例#16
0
        public ED2KServer GetNextStatServer()
        {
            ED2KServer nextserver = null;
            int        i          = 0;

            while (nextserver == null && i < servers_.Count)
            {
                uint posIndex = statserverpos_;
                if (statserverpos_ >= (uint)servers_.Count)
                {       // check if search position is still valid (could be corrupted by server delete operation)
                    posIndex       = 0;
                    statserverpos_ = 0;
                }

                nextserver = servers_[(int)posIndex];
                statserverpos_++;
                i++;
                if (statserverpos_ == (uint)servers_.Count)
                {
                    statserverpos_ = 0;
                }
            }
            return(nextserver);
        }
示例#17
0
 public ED2KServer CreateED2KServer(ED2KServer server)
 {
     return(new ED2KServerImpl(server));
 }
示例#18
0
 public void ConnectToServer(ED2KServer toConnect, bool multiconnect)
 {
     ConnectToServer(toConnect, multiconnect, false);
 }
示例#19
0
 public void ConnectToServer(ED2KServer toConnect)
 {
     ConnectToServer(toConnect, false, false);
 }
示例#20
0
        public void SendPacket(Packet packet,
                               Mule.ED2K.ED2KServer pServer,
                               ushort nSpecialPort, byte[] pInRawPacket, uint nRawLen)
        {
            // Create raw UDP packet
            byte[] pRawPacket;
            uint   uRawPacketSize;
            ushort nPort = 0;

            if (packet != null)
            {
                pRawPacket = new byte[packet.Size + 2];
                Array.Copy(packet.UDPHeader, pRawPacket, 2);
                Array.Copy(packet.Buffer, 0, pRawPacket, 2, packet.Size);
                uRawPacketSize = packet.Size + 2;
                if (MuleApplication.Instance.Preference.IsServerCryptLayerUDPEnabled &&
                    pServer.ServerKeyUDP != 0 &&
                    pServer.DoesSupportsObfuscationUDP)
                {
                    uRawPacketSize = (uint)EncryptSendServer(ref pRawPacket, (int)uRawPacketSize, pServer.ServerKeyUDP);
                    nPort          = pServer.ObfuscationPortUDP;
                }
                else
                {
                    nPort = (ushort)(pServer.Port + 4);
                }
            }
            else if (pInRawPacket != null)
            {
                // we don't encrypt rawpackets (!)
                pRawPacket = new byte[nRawLen];
                Array.Copy(pInRawPacket, pRawPacket, nRawLen);
                uRawPacketSize = nRawLen;
                nPort          = (ushort)(pServer.Port + 4);
            }
            else
            {
                Debug.Assert(false);
                return;
            }
            nPort = (nSpecialPort == 0) ? nPort : nSpecialPort;
            Debug.Assert(nPort != 0);

            // Do we need to resolve the DN of this server?
            IPAddress ipAddr = IPAddress.None;

            IPAddress.TryParse(pServer.Address, out ipAddr);
            if (ipAddr == IPAddress.None)
            {
                IPHostEntry hostEntry = Dns.GetHostEntry(pServer.Address);
                // Get the IP value
                uint nIP = 0;
                if (hostEntry != null && hostEntry.AddressList.Length > 0)
                {
                    nIP = BitConverter.ToUInt32(hostEntry.AddressList[0].GetAddressBytes(), 0);
                }

                if (nIP != 0)
                {
                    bool bRemoveServer = false;
                    if (!MpdUtilities.IsGoodIP(nIP))
                    {
                        // However, if we are currently connected to a "not-good-ip", that IP can't
                        // be that bad -- may only happen when debugging in a LAN.
                        ED2KServer pConnectedServer = MuleApplication.Instance.ServerConnect.CurrentServer;
                        if (pConnectedServer != null || pConnectedServer.IP != nIP)
                        {
                            bRemoveServer = true;
                        }
                    }
                    if (!bRemoveServer && MuleApplication.Instance.Preference.IsFilterServerByIP &&
                        MuleApplication.Instance.IPFilter.IsFiltered(nIP))
                    {
                        bRemoveServer = true;
                    }

                    ED2KServer pTempServer =
                        MuleApplication.Instance.ServerList.GetServerByAddress(pServer.Address, pServer.Port);
                    if (pTempServer != null)
                    {
                        pServer.IP = nIP;
                        // If we already have entries in the server list (dynIP-servers without a DN)
                        // with the same IP as this dynIP-server, remove the duplicates.
                        MuleApplication.Instance.ServerList.RemoveDuplicatesByIP(pServer);
                    }

                    if (bRemoveServer)
                    {
                        return;
                    }

                    // Send all of the queued packets for this server.
                    SendBuffer(nIP, nPort, pRawPacket, uRawPacketSize);
                }
            }
            else
            {
                // No DNS query needed for this server. Just send the packet.
                SendBuffer(BitConverter.ToUInt32(ipAddr.GetAddressBytes(), 0),
                           nPort, pRawPacket, uRawPacketSize);
            }
        }
示例#21
0
        public void ServerStats()
        {
            // Update the server list even if we are connected to Kademlia only. The idea is for both networks to keep
            // each other up to date.. Kad network can get you back into the ED2K network.. And the ED2K network can get
            // you back into the Kad network..
            if (MuleApplication.Instance.ServerConnect.IsConnected &&
                MuleApplication.Instance.ServerConnect.IsUDPSocketAvailable &&
                servers_.Count > 0)
            {
                ED2KServer ping_server = GetNextStatServer();
                if (ping_server == null)
                {
                    return;
                }

                uint       tNow = MpdUtilities.Time();
                ED2KServer test = ping_server;
                while (ping_server.LastPingedTime != 0 &&
                       (tNow - ping_server.LastPingedTime) < MuleConstants.UDPSERVSTATREASKTIME)
                {
                    ping_server = GetNextStatServer();
                    if (ping_server == test)
                    {
                        return;
                    }
                }
                // IP-filter: We do not need to IP-filter any servers here, even dynIP-servers are not
                // needed to get filtered here. See also comments in 'CServerSocket::ConnectTo'.
                if (ping_server.FailedCount >= MuleApplication.Instance.Preference.DeadServerRetries)
                {
                    RemoveServer(ping_server);
                    return;
                }

                Random rand = new Random((int)tNow);
                ping_server.RealLastPingedTime = tNow; // this is not used to calcualte the next ping, but only to ensure a minimum delay for premature pings
                if (!ping_server.CryptPingReplyPending &&
                    (tNow - ping_server.LastPingedTime) >= MuleConstants.UDPSERVSTATREASKTIME &&
                    MuleApplication.Instance.PublicIP != 0 &&
                    MuleApplication.Instance.Preference.IsServerCryptLayerUDPEnabled)
                {
                    // we try a obfsucation ping first and wait 20 seconds for an answer
                    // if it doesn'T get responsed, we don't count it as error but continue with a normal ping
                    ping_server.CryptPingReplyPending = true;
                    int    nPacketLen  = 4 + (byte)(rand.Next() % 16); // max padding 16 bytes
                    byte[] pRawPacket  = new byte[nPacketLen];
                    int    dwChallenge = (rand.Next() << 17) | (rand.Next() << 2) | (rand.Next() & 0x03);
                    if (dwChallenge == 0)
                    {
                        dwChallenge++;
                    }
                    Array.Copy(BitConverter.GetBytes(dwChallenge), pRawPacket, 4);
                    for (uint i = 4; i < nPacketLen; i++) // fillung up the remaining bytes with random data
                    {
                        pRawPacket[i] = (byte)rand.Next();
                    }

                    ping_server.Challenge      = (uint)dwChallenge;
                    ping_server.LastPinged     = MpdUtilities.GetTickCount();
                    ping_server.LastPingedTime =
                        ((tNow - (uint)MuleConstants.UDPSERVSTATREASKTIME) + 20); // give it 20 seconds to respond

                    MuleApplication.Instance.Statistics.AddUpDataOverheadServer((uint)nPacketLen);
                    MuleApplication.Instance.ServerConnect.SendUDPPacket(null,
                                                                         ping_server, true, (ushort)(ping_server.Port + 12), pRawPacket, (uint)nPacketLen);
                }
                else if (ping_server.CryptPingReplyPending ||
                         MuleApplication.Instance.PublicIP == 0 ||
                         !MuleApplication.Instance.Preference.IsServerCryptLayerUDPEnabled)
                {
                    // our obfsucation ping request was not answered, so probably the server doesn'T supports obfuscation
                    // continue with a normal request
                    ping_server.CryptPingReplyPending = false;
                    Packet packet     = MuleApplication.Instance.NetworkObjectManager.CreatePacket(OperationCodeEnum.OP_GLOBSERVSTATREQ, 4);
                    int    uChallenge = 0x55AA0000 + MpdUtilities.GetRandomUInt16();
                    ping_server.Challenge = (uint)uChallenge;
                    Array.Copy(BitConverter.GetBytes(uChallenge), packet.Buffer, 4);
                    ping_server.LastPinged     = MpdUtilities.GetTickCount();
                    ping_server.LastPingedTime = (uint)(tNow - (rand.Next() % MuleConstants.ONE_HOUR_SEC));
                    ping_server.AddFailedCount();
                    MuleApplication.Instance.Statistics.AddUpDataOverheadServer(packet.Size);
                    MuleApplication.Instance.ServerConnect.SendUDPPacket(packet, ping_server, true);
                }
                else
                {
                    Debug.Assert(false);
                }
            }
        }
示例#22
0
 public int GetPositionOfServer(ED2KServer pServer)
 {
     return(servers_.IndexOf(pServer));
 }
示例#23
0
 public bool AddServer(ED2KServer pServer)
 {
     return(AddServer(pServer, true));
 }
示例#24
0
        private bool ProcessPacket(byte[] buffer, int offset, int size, uint opcode, uint nIP, ushort nUDPPort)
        {
            try
            {
                MuleApplication.Instance.Statistics.AddDownDataOverheadServer((uint)size);
                ED2KServer pServer = MuleApplication.Instance.ServerList.GetServerByIPUDP(nIP, nUDPPort, true);
                if (pServer != null)
                {
                    pServer.ResetFailedCount();
                }

                switch ((OperationCodeEnum)opcode)
                {
                case OperationCodeEnum.OP_GLOBSEARCHRES:
                {
                    SafeMemFile data = MpdObjectManager.CreateSafeMemFile(buffer, size);
                    // process all search result packets
                    int iLeft;
                    do
                    {
                        uint uResultCount = MuleApplication.Instance.SearchList.ProcessUDPSearchAnswer(data, true /*pServer.GetUnicodeSupport()*/, nIP, nUDPPort - 4);

                        // check if there is another source packet
                        iLeft = (int)(data.Length - data.Position);
                        if (iLeft >= 2)
                        {
                            byte protocol = data.ReadUInt8();
                            iLeft--;
                            if (protocol != MuleConstants.PROTOCOL_EDONKEYPROT)
                            {
                                data.Seek(-1, System.IO.SeekOrigin.Current);
                                iLeft += 1;
                                break;
                            }

                            byte opcode1 = data.ReadUInt8();
                            iLeft--;
                            if (opcode1 != (byte)OperationCodeEnum.OP_GLOBSEARCHRES)
                            {
                                data.Seek(-2, System.IO.SeekOrigin.Current);
                                iLeft += 2;
                                break;
                            }
                        }
                    }while (iLeft > 0);
                    break;
                }

                case OperationCodeEnum.OP_GLOBFOUNDSOURCES:
                {
                    SafeMemFile data = MpdObjectManager.CreateSafeMemFile(buffer, size);
                    // process all source packets
                    int iLeft;
                    do
                    {
                        byte[] fileid = new byte[16];
                        data.ReadHash16(fileid);
                        PartFile file = MuleApplication.Instance.DownloadQueue.GetFileByID(fileid);
                        if (file != null)
                        {
                            file.AddSources(data, nIP, (ushort)(nUDPPort - 4), false);
                        }
                        else
                        {
                            // skip sources for that file
                            uint count = data.ReadUInt8();
                            data.Seek(count * (4 + 2), System.IO.SeekOrigin.Current);
                        }

                        // check if there is another source packet
                        iLeft = (int)(data.Length - data.Position);
                        if (iLeft >= 2)
                        {
                            byte protocol = data.ReadUInt8();
                            iLeft--;
                            if (protocol != MuleConstants.PROTOCOL_EDONKEYPROT)
                            {
                                data.Seek(-1, System.IO.SeekOrigin.Current);
                                iLeft += 1;
                                break;
                            }

                            byte opcode1 = data.ReadUInt8();
                            iLeft--;
                            if (opcode1 != (byte)OperationCodeEnum.OP_GLOBFOUNDSOURCES)
                            {
                                data.Seek(-2, System.IO.SeekOrigin.Current);
                                iLeft += 2;
                                break;
                            }
                        }
                    }while (iLeft > 0);

                    break;
                }

                case OperationCodeEnum.OP_GLOBSERVSTATRES:
                {
                    if (size < 12 || pServer == null)
                    {
                        return(true);
                    }
                    uint challenge = BitConverter.ToUInt32(buffer, 0);
                    if (challenge != pServer.Challenge)
                    {
                        return(true);
                    }
                    if (pServer != null)
                    {
                        pServer.Challenge             = 0;
                        pServer.CryptPingReplyPending = false;
                        uint   tNow = MpdUtilities.Time();
                        Random rand = new Random();
                        // if we used Obfuscated ping, we still need to reset the time properly
                        pServer.LastPingedTime =
                            Convert.ToUInt32(tNow - (rand.Next() % MuleConstants.ONE_HOUR_SEC));
                    }
                    uint   cur_user            = BitConverter.ToUInt32(buffer, 4);
                    uint   cur_files           = BitConverter.ToUInt32(buffer, 8);
                    uint   cur_maxusers        = 0;
                    uint   cur_softfiles       = 0;
                    uint   cur_hardfiles       = 0;
                    uint   uUDPFlags           = 0;
                    uint   uLowIDUsers         = 0;
                    uint   dwServerUDPKey      = 0;
                    ushort nTCPObfuscationPort = 0;
                    ushort nUDPObfuscationPort = 0;

                    if (size >= 16)
                    {
                        cur_maxusers = BitConverter.ToUInt32(buffer, 12);
                    }
                    if (size >= 24)
                    {
                        cur_softfiles = BitConverter.ToUInt32(buffer, 16);
                        cur_hardfiles = BitConverter.ToUInt32(buffer, 20);
                    }
                    if (size >= 28)
                    {
                        uUDPFlags = BitConverter.ToUInt32(buffer, 24);
                    }
                    if (size >= 32)
                    {
                        uLowIDUsers = BitConverter.ToUInt32(buffer, 28);
                    }
                    if (size >= 40)
                    {
                        // TODO debug check if this packet was encrypted if it has a key
                        nUDPObfuscationPort = BitConverter.ToUInt16(buffer, 32);
                        nTCPObfuscationPort = BitConverter.ToUInt16(buffer, 34);;
                        dwServerUDPKey      = BitConverter.ToUInt32(buffer, 36);
                    }
                    if (pServer != null)
                    {
                        pServer.Ping               = MpdUtilities.GetTickCount() - pServer.LastPinged;
                        pServer.UserCount          = cur_user;
                        pServer.FileCount          = cur_files;
                        pServer.MaxUsers           = cur_maxusers;
                        pServer.SoftFiles          = cur_softfiles;
                        pServer.HardFiles          = cur_hardfiles;
                        pServer.ServerKeyUDP       = dwServerUDPKey;
                        pServer.ObfuscationPortTCP = nTCPObfuscationPort;
                        pServer.ObfuscationPortUDP = nUDPObfuscationPort;
                        // if the received UDP flags do not match any already stored UDP flags,
                        // reset the server version string because the version (which was determined by last connecting to
                        // that server) is most likely not accurat any longer.
                        // this may also give 'false' results because we don't know the UDP flags when connecting to a server
                        // with TCP.
                        //if (pServer.GetUDPFlags() != uUDPFlags)
                        //	pServer.Version(_T = "");
                        pServer.UDPFlags   = (ED2KServerUdpFlagsEnum)uUDPFlags;
                        pServer.LowIDUsers = uLowIDUsers;

                        pServer.SetLastDescPingedCount(false);
                        if (pServer.LastDescPingedCount < 2)
                        {
                            // eserver 16.45+ supports a new OP_SERVER_DESC_RES answer, if the OP_SERVER_DESC_REQ contains a uint
                            // challenge, the server returns additional info with OP_SERVER_DESC_RES. To properly distinguish the
                            // old and new OP_SERVER_DESC_RES answer, the challenge has to be selected carefully. The first 2 bytes
                            // of the challenge (in network byte order) MUST NOT be a valid string-len-int16!
                            Packet packet1 =
                                MuleApplication.Instance.NetworkObjectManager.CreatePacket(OperationCodeEnum.OP_SERVER_DESC_REQ, 4);
                            uint uDescReqChallenge =
                                ((uint)MpdUtilities.GetRandomUInt16() << 16) +
                                MuleConstants.INV_SERV_DESC_LEN;         // 0xF0FF = an 'invalid' string length.
                            pServer.DescReqChallenge = uDescReqChallenge;
                            Array.Copy(BitConverter.GetBytes(uDescReqChallenge), packet1.Buffer, 4);
                            MuleApplication.Instance.Statistics.AddUpDataOverheadServer(packet1.Size);
                            MuleApplication.Instance.ServerConnect.SendUDPPacket(packet1, pServer, true);
                        }
                        else
                        {
                            pServer.SetLastDescPingedCount(true);
                        }
                    }
                    break;
                }

                case OperationCodeEnum.OP_SERVER_DESC_RES:
                {
                    if (pServer == null)
                    {
                        return(true);
                    }

                    // old packet: <name_len 2><name name_len><desc_len 2 desc_en>
                    // new packet: <challenge 4><taglist>
                    //
                    // NOTE: To properly distinguish between the two packets which are both useing the same opcode...
                    // the first two bytes of <challenge> (in network byte order) have to be an invalid <name_len> at least.

                    SafeMemFile srvinfo = MpdObjectManager.CreateSafeMemFile(buffer, size);
                    if (size >= 8 && BitConverter.ToUInt16(buffer, 0) == MuleConstants.INV_SERV_DESC_LEN)
                    {
                        if (pServer.DescReqChallenge != 0 && BitConverter.ToUInt32(buffer, 0) == pServer.DescReqChallenge)
                        {
                            pServer.DescReqChallenge = 0;
                            srvinfo.ReadUInt32();         // skip challenge
                            uint uTags = srvinfo.ReadUInt32();
                            for (uint i = 0; i < uTags; i++)
                            {
                                Tag tag = MpdObjectManager.CreateTag(srvinfo, true /*pServer.GetUnicodeSupport()*/);
                                if (tag.NameID == MuleConstants.ST_SERVERNAME && tag.IsStr)
                                {
                                    pServer.ServerName = tag.Str;
                                }
                                else if (tag.NameID == MuleConstants.ST_DESCRIPTION && tag.IsStr)
                                {
                                    pServer.Description = tag.Str;
                                }
                                else if (tag.NameID == MuleConstants.ST_DYNIP && tag.IsStr)
                                {
                                    // Verify that we really received a DN.
                                    IPAddress address;


                                    if (!IPAddress.TryParse(tag.Str, out address) ||
                                        address == IPAddress.None)
                                    {
                                        string strOldDynIP = pServer.DynIP;
                                        pServer.DynIP = tag.Str;
                                        // If a dynIP-server changed its address or, if this is the
                                        // first time we get the dynIP-address for a server which we
                                        // already have as non-dynIP in our list, we need to remove
                                        // an already available server with the same 'dynIP:port'.
                                        if (string.Compare(strOldDynIP, pServer.DynIP, true) != 0)
                                        {
                                            MuleApplication.Instance.ServerList.RemoveDuplicatesByAddress(pServer);
                                        }
                                    }
                                }
                                else if (tag.NameID == MuleConstants.ST_VERSION && tag.IsStr)
                                {
                                    pServer.Version = tag.Str;
                                }
                                else if (tag.NameID == MuleConstants.ST_VERSION && tag.IsInt)
                                {
                                    pServer.Version =
                                        string.Format("{0}.{1}", tag.Int >> 16, tag.Int & 0xFFFF);
                                }
                            }
                        }
                        else
                        {
                            // A server sent us a new server description packet (including a challenge) although we did not
                            // ask for it. This may happen, if there are multiple servers running on the same machine with
                            // multiple IPs. If such a server is asked for a description, the server will answer 2 times,
                            // but with the same IP.
                        }
                    }
                    else
                    {
                        string strName = srvinfo.ReadString(true /*pServer.GetUnicodeSupport()*/);
                        string strDesc = srvinfo.ReadString(true /*pServer.GetUnicodeSupport()*/);
                        pServer.Description = strDesc;
                        pServer.ServerName  = strName;
                    }

                    break;
                }

                default:
                    return(false);
                }

                return(true);
            }
            catch (Exception error)
            {
                ProcessPacketError((uint)size, (uint)opcode, nIP, nUDPPort, error);
                if (opcode == (byte)OperationCodeEnum.OP_GLOBSEARCHRES ||
                    opcode == (byte)OperationCodeEnum.OP_GLOBFOUNDSOURCES)
                {
                    return(true);
                }
            }
            return(false);
        }
示例#25
0
        public void ConnectionEstablished(Mule.Network.ServerSocket sender)
        {
            if (!IsConnecting)
            {
                // we are already IsConnected to another server
                DestroySocket(sender);
                return;
            }

            InitLocalIP();
            if (sender.ConnectionState == ConnectionStateEnum.CS_WAITFORLOGIN)
            {
                ED2KServer pServer =
                    MuleApplication.Instance.ServerList.GetServerByAddress(sender.CurrentServer.Address,
                                                                           sender.CurrentServer.Port);
                if (pServer != null)
                {
                    pServer.ResetFailedCount();
                }

                // Send login packet
                SafeMemFile data = MpdObjectManager.CreateSafeMemFile(256);
                data.WriteHash16(MuleApplication.Instance.Preference.UserHash);
                data.WriteUInt32(ClientID);
                data.WriteUInt16(MuleApplication.Instance.Preference.Port);

                uint tagcount = 4;
                data.WriteUInt32(tagcount);

                Tag tagName = MpdObjectManager.CreateTag(TagTypeEnum.CT_NAME,
                                                         MuleApplication.Instance.Preference.UserNick);
                tagName.WriteTagToFile(data);

                Tag tagVersion = MpdObjectManager.CreateTag(TagTypeEnum.CT_VERSION, VersionsEnum.EDONKEYVERSION);
                tagVersion.WriteTagToFile(data);

                ServerFlagsEnum dwCryptFlags = 0;
                if (MuleApplication.Instance.Preference.IsClientCryptLayerSupported)
                {
                    dwCryptFlags |= ServerFlagsEnum.SRVCAP_SUPPORTCRYPT;
                }
                if (MuleApplication.Instance.Preference.IsClientCryptLayerRequested)
                {
                    dwCryptFlags |= ServerFlagsEnum.SRVCAP_REQUESTCRYPT;
                }
                if (MuleApplication.Instance.Preference.IsClientCryptLayerRequired)
                {
                    dwCryptFlags |= ServerFlagsEnum.SRVCAP_REQUIRECRYPT;
                }

                Tag tagFlags = MpdObjectManager.CreateTag(TagTypeEnum.CT_SERVER_FLAGS,
                                                          ServerFlagsEnum.SRVCAP_ZLIB | ServerFlagsEnum.SRVCAP_NEWTAGS |
                                                          ServerFlagsEnum.SRVCAP_LARGEFILES |
                                                          ServerFlagsEnum.SRVCAP_UNICODE | dwCryptFlags);

                tagFlags.WriteTagToFile(data);

                // eMule Version (14-Mar-2004: requested by lugdunummaster (need for LowID clients which have no chance
                // to send an Hello packet to the server during the callback test))
                Tag tagMuleVersion = MpdObjectManager.CreateTag(TagTypeEnum.CT_EMULE_VERSION,
                                                                (MuleApplication.Instance.Version.Major << 17) |
                                                                (MuleApplication.Instance.Version.Minor << 10) |
                                                                (MuleApplication.Instance.Version.Build << 7));
                tagMuleVersion.WriteTagToFile(data);

                Packet packet = MuleApplication.Instance.NetworkObjectManager.CreatePacket(data);
                packet.OperationCode = OperationCodeEnum.OP_LOGINREQUEST;
                MuleApplication.Instance.Statistics.AddUpDataOverheadServer(packet.Size);
                SendPacket(packet, true, sender);
            }
            else if (sender.ConnectionState == ConnectionStateEnum.CS_CONNECTED)
            {
                MuleApplication.Instance.Statistics.Reconnects++;
                MuleApplication.Instance.Statistics.ServerConnectTime = MpdUtilities.GetTickCount();
                IsConnected      = true;
                connectedSocket_ = sender;
                StopConnectionTry();
                MuleApplication.Instance.SharedFiles.ClearED2KPublishInfo();
                MuleApplication.Instance.SharedFiles.SendListToServer();

                if (MuleApplication.Instance.Preference.DoesAddServersFromServer)
                {
                    Packet packet =
                        MuleApplication.Instance.NetworkObjectManager.CreatePacket(
                            OperationCodeEnum.OP_GETSERVERLIST, 0);
                    MuleApplication.Instance.Statistics.AddUpDataOverheadServer(packet.Size);
                    SendPacket(packet, true);
                }
            }
        }
示例#26
0
 public bool IsEqual(ED2KServer pServer)
 {
     return(Equals(pServer));
 }
示例#27
0
        public void ConnectionFailed(Mule.Network.ServerSocket sender)
        {
            if (!IsConnecting && sender != connectedSocket_)
            {
                // just return, cleanup is done by the socket itself
                return;
            }

            ED2KServer pServer = MuleApplication.Instance.ServerList.GetServerByAddress(sender.CurrentServer.Address, sender.CurrentServer.Port);

            switch (sender.ConnectionState)
            {
            case ConnectionStateEnum.CS_FATALERROR:
                //TODO:Log
                break;

            case ConnectionStateEnum.CS_DISCONNECTED:
                MuleApplication.Instance.SharedFiles.ClearED2KPublishInfo();
                break;

            case ConnectionStateEnum.CS_SERVERDEAD:
                if (pServer != null)
                {
                    pServer.AddFailedCount();
                }
                break;

            case ConnectionStateEnum.CS_ERROR:
                break;

            case ConnectionStateEnum.CS_SERVERFULL:
                break;

            case ConnectionStateEnum.CS_NOTCONNECTED:
                break;
            }

            // IMPORTANT: mark this socket not to be deleted in StopConnectionTry(),
            // because it will delete itself after this function!
            sender.IsDeleting = true;

            switch (sender.ConnectionState)
            {
            case ConnectionStateEnum.CS_FATALERROR:
            {
                bool autoretry = !IsSingleConnect;
                StopConnectionTry();
                if (MuleApplication.Instance.Preference.IsReconnect && autoretry &&
                    retryTimer_ == null)
                {
                    // There are situations where we may get Winsock error codes which indicate
                    // that the network is down, although it is not. Those error codes may get
                    // thrown only for particular IPs. If the first server in our list has such
                    // an IP and will therefor throw such an error we would never connect to
                    // any server at all. To circumvent that, start the next auto-connection
                    // attempt with a different server (use the next server in the list).
                    startAutoConnectPos_ = 0;         // default: start at 0
                    if (pServer != null)
                    {
                        // If possible, use the "next" server.
                        int iPosInList =
                            MuleApplication.Instance.ServerList.GetPositionOfServer(pServer);
                        if (iPosInList >= 0)
                        {
                            startAutoConnectPos_ = (uint)((iPosInList + 1) %
                                                          MuleApplication.Instance.ServerList.ServerCount);
                        }
                    }

                    retryTimer_ =
                        new Timer(new TimerCallback(RetryConnectTimer),
                                  this, 0,
                                  MuleConstants.ONE_SEC_MS * MuleConstants.CS_RETRYCONNECTTIME);
                }
                break;
            }

            case ConnectionStateEnum.CS_DISCONNECTED:
            {
                MuleApplication.Instance.SharedFiles.ClearED2KPublishInfo();
                IsConnected = false;
                if (connectedSocket_ != null)
                {
                    connectedSocket_.Close();
                    connectedSocket_ = null;
                }
                MuleApplication.Instance.Statistics.ServerConnectTime = 0;
                MuleApplication.Instance.Statistics.Add2TotalServerDuration();
                if (MuleApplication.Instance.Preference.IsReconnect && !IsConnecting)
                {
                    ConnectToAnyServer();
                }
                break;
            }

            case ConnectionStateEnum.CS_ERROR:
            case ConnectionStateEnum.CS_NOTCONNECTED:
            {
                if (!IsConnecting)
                {
                    break;
                }
            }
                goto case ConnectionStateEnum.CS_SERVERDEAD;

            case ConnectionStateEnum.CS_SERVERDEAD:
            case ConnectionStateEnum.CS_SERVERFULL:
            {
                if (!IsConnecting)
                {
                    break;
                }
                if (IsSingleConnect)
                {
                    if (pServer != null && sender.IsServerCryptEnabledConnection &&
                        !MuleApplication.Instance.Preference.IsClientCryptLayerRequired)
                    {
                        // try reconnecting without obfuscation
                        ConnectToServer(pServer, false, true);
                        break;
                    }
                    StopConnectionTry();
                    break;
                }

                Dictionary <ulong, ServerSocket> .Enumerator pos = connectionAttemps_.GetEnumerator();
                while (pos.MoveNext())
                {
                    if (pos.Current.Value == sender)
                    {
                        connectionAttemps_.Remove(pos.Current.Key);
                        break;
                    }
                }
                TryAnotherConnectionRequest();
            }
            break;
            }
        }