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; }
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); }
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(); } }
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); }