Пример #1
0
		private void MakeTried(AddressInfo info, int nId)
		{
			// remove the entry from all new buckets
			for(int bucket = 0 ; bucket < ADDRMAN_NEW_BUCKET_COUNT ; bucket++)
			{
				int pos = info.GetBucketPosition(nKey, true, bucket);
				if(vvNew[bucket, pos] == nId)
				{
					vvNew[bucket, pos] = -1;
					info.nRefCount--;
				}
			}
			nNew--;

			assert(info.nRefCount == 0);

			// which tried bucket to move the entry to
			int nKBucket = info.GetTriedBucket(nKey);
			int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);

			// first make space to add it (the existing tried entry there is moved to new, deleting whatever is there).
			if(vvTried[nKBucket, nKBucketPos] != -1)
			{
				// find an item to evict
				int nIdEvict = vvTried[nKBucket, nKBucketPos];
				assert(mapInfo.ContainsKey(nIdEvict));
				AddressInfo infoOld = mapInfo[nIdEvict];

				// Remove the to-be-evicted item from the tried set.
				infoOld.fInTried = false;
				vvTried[nKBucket, nKBucketPos] = -1;
				nTried--;

				// find which new bucket it belongs to
				int nUBucket = infoOld.GetNewBucket(nKey);
				int nUBucketPos = infoOld.GetBucketPosition(nKey, true, nUBucket);
				ClearNew(nUBucket, nUBucketPos);
				assert(vvNew[nUBucket, nUBucketPos] == -1);

				// Enter it into the new set again.
				infoOld.nRefCount = 1;
				vvNew[nUBucket, nUBucketPos] = nIdEvict;
				nNew++;
			}
			assert(vvTried[nKBucket, nKBucketPos] == -1);

			vvTried[nKBucket, nKBucketPos] = nId;
			nTried++;
			info.fInTried = true;
		}
Пример #2
0
		private AddressInfo Create(NetworkAddress addr, IPAddress addrSource, out int pnId)
		{
			int nId = nIdCount++;
			mapInfo[nId] = new AddressInfo(addr, addrSource);
			mapAddr[addr.Endpoint.Address] = nId;
			mapInfo[nId].nRandomPos = vRandom.Count;
			vRandom.Add(nId);
			pnId = nId;
			return mapInfo[nId];
		}
 internal static int GetAddrInfo(string nodename, string servicename, ref AddressInfo hints, out SafeFreeAddrInfo outAddrInfo)
 {
     return UnsafeNclNativeMethods.SafeNetHandlesXPOrLater.getaddrinfo(nodename, servicename, ref hints, out outAddrInfo);
 }
Пример #4
0
		public void ReadWrite(BitcoinStream stream)
		{
			lock(cs)
			{
				Check();
				if(!stream.Serializing)
					Clear();
				stream.ReadWrite(ref nVersion);
				stream.ReadWrite(ref nKeySize);
				if(!stream.Serializing && nKeySize != 32)
					throw new FormatException("Incorrect keysize in addrman deserialization");
				stream.ReadWrite(ref nKey);
				stream.ReadWrite(ref nNew);
				stream.ReadWrite(ref nTried);

				int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
				stream.ReadWrite(ref nUBuckets);
				if(nVersion != 0)
				{
					nUBuckets ^= (1 << 30);
				}
				if(!stream.Serializing)
				{
					// Deserialize entries from the new table.
					for(int n = 0 ; n < nNew ; n++)
					{
						AddressInfo info = new AddressInfo();
						info.ReadWrite(stream);
						mapInfo.Add(n, info);
						mapAddr[info.Address.Endpoint.Address] = n;
						info.nRandomPos = vRandom.Count;
						vRandom.Add(n);
						if(nVersion != 1 || nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
						{
							// In case the new table data cannot be used (nVersion unknown, or bucket count wrong),
							// immediately try to give them a reference based on their primary source address.
							int nUBucket = info.GetNewBucket(nKey);
							int nUBucketPos = info.GetBucketPosition(nKey, true, nUBucket);
							if(vvNew[nUBucket, nUBucketPos] == -1)
							{
								vvNew[nUBucket, nUBucketPos] = n;
								info.nRefCount++;
							}
						}
					}

					nIdCount = nNew;

					// Deserialize entries from the tried table.
					int nLost = 0;
					for(int n = 0 ; n < nTried ; n++)
					{
						AddressInfo info = new AddressInfo();
						info.ReadWrite(stream);
						int nKBucket = info.GetTriedBucket(nKey);
						int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
						if(vvTried[nKBucket, nKBucketPos] == -1)
						{
							info.nRandomPos = vRandom.Count;
							info.fInTried = true;
							vRandom.Add(nIdCount);
							mapInfo[nIdCount] = info;
							mapAddr[info.Address.Endpoint.Address] = nIdCount;
							vvTried[nKBucket, nKBucketPos] = nIdCount;
							nIdCount++;
						}
						else
						{
							nLost++;
						}
					}

					nTried -= nLost;

					// Deserialize positions in the new table (if possible).
					for(int bucket = 0 ; bucket < nUBuckets ; bucket++)
					{
						int nSize = 0;
						stream.ReadWrite(ref nSize);
						for(int n = 0 ; n < nSize ; n++)
						{
							int nIndex = 0;
							stream.ReadWrite(ref nIndex);
							if(nIndex >= 0 && nIndex < nNew)
							{
								AddressInfo info = mapInfo[nIndex];
								int nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
								if(nVersion == 1 && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket, nUBucketPos] == -1 && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
								{
									info.nRefCount++;
									vvNew[bucket, nUBucketPos] = nIndex;
								}
							}
						}
					}

					// Prune new entries with refcount 0 (as a result of collisions).
					int nLostUnk = 0;
					foreach(var kv in mapInfo.ToList())
					{
						if(kv.Value.fInTried == false && kv.Value.nRefCount == 0)
						{
							Delete(kv.Key);
							nLostUnk++;
						}
					}
				}
				else
				{
					Dictionary<int, int> mapUnkIds = new Dictionary<int, int>();
					int nIds = 0;
					foreach(var kv in mapInfo)
					{
						mapUnkIds[kv.Key] = nIds;
						AddressInfo info = kv.Value;
						if(info.nRefCount != 0)
						{
							assert(nIds != nNew); // this means nNew was wrong, oh ow
							info.ReadWrite(stream);
							nIds++;
						}
					}
					nIds = 0;
					foreach(var kv in mapInfo)
					{
						AddressInfo info = kv.Value;
						if(info.fInTried)
						{
							assert(nIds != nTried); // this means nTried was wrong, oh ow
							info.ReadWrite(stream);
							nIds++;
						}
					}

					for(int bucket = 0 ; bucket < ADDRMAN_NEW_BUCKET_COUNT ; bucket++)
					{
						int nSize = 0;
						for(int i = 0 ; i < ADDRMAN_BUCKET_SIZE ; i++)
						{
							if(vvNew[bucket, i] != -1)
								nSize++;
						}
						stream.ReadWrite(ref nSize);
						for(int i = 0 ; i < ADDRMAN_BUCKET_SIZE ; i++)
						{
							if(vvNew[bucket, i] != -1)
							{
								int nIndex = mapUnkIds[vvNew[bucket, i]];
								stream.ReadWrite(ref nIndex);
							}
						}
					}
				}
				Check();
			}
		}
Пример #5
0
        public static unsafe SocketError TryGetAddrInfo(string name, out IPHostEntry hostinfo, out int nativeErrorCode)
        {
            //
            // Use SocketException here to show operation not supported
            // if, by some nefarious means, this method is called on an
            // unsupported platform.
            //
            SafeFreeAddrInfo root = null;
            var    addresses      = new List <IPAddress>();
            string canonicalname  = null;

            AddressInfo hints = new AddressInfo();

            hints.ai_flags  = AddressInfoHints.AI_CANONNAME;
            hints.ai_family = AddressFamily.Unspecified;   // gets all address families

            nativeErrorCode = 0;

            //
            // Use try / finally so we always get a shot at freeaddrinfo
            //
            try
            {
                SocketError errorCode = (SocketError)SafeFreeAddrInfo.GetAddrInfo(name, null, ref hints, out root);
                if (errorCode != SocketError.Success)
                { // Should not throw, return mostly blank hostentry
                    hostinfo = NameResolutionUtilities.GetUnresolvedAnswer(name);
                    return(errorCode);
                }

                AddressInfo *pAddressInfo = (AddressInfo *)root.DangerousGetHandle();
                //
                // Process the results
                //
                while (pAddressInfo != null)
                {
                    SocketAddress sockaddr;
                    //
                    // Retrieve the canonical name for the host - only appears in the first AddressInfo
                    // entry in the returned array.
                    //
                    if (canonicalname == null && pAddressInfo->ai_canonname != null)
                    {
                        canonicalname = Marshal.PtrToStringUni((IntPtr)pAddressInfo->ai_canonname);
                    }
                    //
                    // Only process IPv4 or IPv6 Addresses. Note that it's unlikely that we'll
                    // ever get any other address families, but better to be safe than sorry.
                    // We also filter based on whether IPv6 is supported on the current
                    // platform / machine.
                    //
                    if ((pAddressInfo->ai_family == AddressFamily.InterNetwork) || // Never filter v4
                        (pAddressInfo->ai_family == AddressFamily.InterNetworkV6 && SocketProtocolSupportPal.OSSupportsIPv6))
                    {
                        sockaddr = new SocketAddress(pAddressInfo->ai_family, pAddressInfo->ai_addrlen);
                        //
                        // Push address data into the socket address buffer
                        //
                        for (int d = 0; d < pAddressInfo->ai_addrlen; d++)
                        {
                            sockaddr[d] = *(pAddressInfo->ai_addr + d);
                        }
                        //
                        // NOTE: We need an IPAddress now, the only way to create it from a
                        //       SocketAddress is via IPEndPoint. This ought to be simpler.
                        //
                        if (pAddressInfo->ai_family == AddressFamily.InterNetwork)
                        {
                            addresses.Add(((IPEndPoint)IPEndPointStatics.Any.Create(sockaddr)).Address);
                        }
                        else
                        {
                            addresses.Add(((IPEndPoint)IPEndPointStatics.IPv6Any.Create(sockaddr)).Address);
                        }
                    }
                    //
                    // Next addressinfo entry
                    //
                    pAddressInfo = pAddressInfo->ai_next;
                }
            }
            finally
            {
                if (root != null)
                {
                    root.Dispose();
                }
            }

            //
            // Finally, put together the IPHostEntry
            //
            hostinfo = new IPHostEntry();

            hostinfo.HostName    = canonicalname != null ? canonicalname : name;
            hostinfo.Aliases     = Array.Empty <string>();
            hostinfo.AddressList = addresses.ToArray();

            return(SocketError.Success);
        }