//
        // Binds a socket to a proxy identified by provided address
        //
        public async Task BindAsync(SocketAddress endpoint, CancellationToken ct)
        {
            if (_cleanedUp)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (endpoint == null)
            {
                throw new ArgumentNullException(nameof(endpoint));
            }
            if (IsListening)
            {
                throw new InvalidOperationException("Socket is listening");
            }
            try {
                await _internal.BindAsync(endpoint, ct).ConfigureAwait(false);

                IsBound = true;
            }
            catch (OperationCanceledException) {
                throw;
            }
            catch (Exception e) {
                throw SocketException.Create($"Exception binding to {endpoint.ToString()}", e);
            }
        }
예제 #2
0
        //
        // Opens the socket and links as active
        //
        public async Task ConnectAsync(SocketAddress endpoint, CancellationToken ct)
        {
            if (_cleanedUp)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }
            if (endpoint == null)
            {
                throw new ArgumentNullException("endpoint");
            }
            if (IsListening)
            {
                throw new InvalidOperationException("Socket is listening");
            }
            try {
                await _internal.ConnectAsync(endpoint, ct).ConfigureAwait(false);

                Connected = true;
                IsBound   = true;
            }
            catch (Exception e) when(!(e is SocketException) && !(e is OperationCanceledException))
            {
                throw new SocketException($"Exception connecting to {endpoint.ToString()}",
                                          e, e.GetSocketError());
            }
        }
예제 #3
0
        /// <summary>
        /// Collate a list of entries into one big host entry
        /// </summary>
        /// <param name="address"></param>
        /// <param name="entries"></param>
        /// <returns></returns>
        internal static DnsHostEntry ToEntry(SocketAddress address,
                                             IEnumerable <DnsHostEntry> entries)
        {
            if (entries == null || !entries.Any())
            {
                return(new DnsHostEntry {
                    HostName = address.ToString(),
                    Aliases = new string[0],
                    AddressList = new SocketAddress[] { address }
                });
            }

            string hostName    = string.Empty;
            var    addressList = new List <SocketAddress>();
            var    aliases     = new List <string>();

            foreach (var entry in entries)
            {
                hostName = entry.HostName;
                if (entry.AddressList != null)
                {
                    addressList.AddRange(entry.AddressList);
                }
                if (entry.Aliases != null)
                {
                    aliases.AddRange(entry.Aliases);
                }
            }
            return(new DnsHostEntry {
                HostName = hostName,
                Aliases = aliases.ToArray(),
                AddressList = addressList.ToArray()
            });
        }
        //
        // Without cancellation token
        //
        public async Task BindAsync(SocketAddress endpoint)
        {
            var cts = new CancellationTokenSource(ConnectTimeout);

            try {
                await BindAsync(endpoint, cts.Token).ConfigureAwait(false);
            }
            catch (OperationCanceledException) when(cts.IsCancellationRequested)
            {
                throw new TimeoutException(
                          $"Timeout after {ConnectTimeout.ToString()} binding to {endpoint.ToString()}.");
            }
        }
 /// <summary>
 /// Match record against address
 /// </summary>
 /// <param name="record"></param>
 /// <param name="address"></param>
 /// <param name="type"></param>
 /// <returns></returns>
 public static bool Matches(this INameRecord record, SocketAddress address,
                            NameRecordType type)
 {
     if (address.Family == AddressFamily.Collection)
     {
         return(Matches(record, (SocketAddressCollection)address, type));
     }
     if (Matches(record, address.ToString(), type))
     {
         return(true);
     }
     if (address.Family == AddressFamily.InterNetworkV6)
     {
         return(Matches(record, Reference.FromSocketAddress((Inet6SocketAddress)address), type));
     }
     return(false);
 }
예제 #6
0
        /// <summary>
        /// Connect to a target on first of bound proxies, or use ping based dynamic lookup
        /// </summary>
        /// <param name="address"></param>
        /// <param name="ct"></param>
        /// <returns></returns>
        public override async Task ConnectAsync(SocketAddress address, CancellationToken ct)
        {
            if (address.Family == AddressFamily.Bound)
            {
                // Unwrap proxy and connect address.  If not bound, use local address to bind to.
                if (_bindList == null)
                {
                    await BindAsync(((BoundSocketAddress)address).LocalAddress, ct);
                }
                address = ((BoundSocketAddress)address).RemoteAddress;
            }

            // Get the named host from the registry if it exists - there should only be one...
            Host = null;
            var hostList = await Provider.NameService.LookupAsync(
                address.ToString(), NameRecordType.Host, ct).ConfigureAwait(false);

            foreach (var host in hostList)
            {
                Host = host;
                break;
            }

            // If there is no host in the registry, create a fake host record for this address
            if (Host == null)
            {
                Host = new NameRecord(NameRecordType.Host, address.ToString());
            }
            else if (!Host.Name.Equals(address.ToString(), StringComparison.CurrentCultureIgnoreCase))
            {
                // Translate the address to host address
                address = new ProxySocketAddress(Host.Name);
            }

            // Set bind list before connecting if it is not already set during Bind
            bool autoBind = _bindList == null;

            if (autoBind)
            {
                var bindList = new HashSet <INameRecord>();
                foreach (var proxyRef in Host.References)
                {
                    var results = await Provider.NameService.LookupAsync(
                        proxyRef, NameRecordType.Proxy, ct).ConfigureAwait(false);

                    bindList.AddRange(results);
                }
                _bindList = bindList.Any() ? bindList : null;
            }

            bool connected = false;

            if (_bindList != null)
            {
                // Try to connect through each proxy in the bind list
                foreach (var proxy in _bindList)
                {
                    connected = await ConnectAsync(address, proxy, ct).ConfigureAwait(false);

                    if (connected)
                    {
                        break;
                    }
                }
                // If there was a bind list and we could not connect through it, throw
                if (!connected && !autoBind)
                {
                    throw new SocketException(SocketError.NoHost);
                }
                _bindList = null;
            }

            if (!connected)
            {
                await PingAsync(address, async (response, proxy, ct2) => {
                    if (connected)
                    {
                        return(Disposition.Done);
                    }
                    if (response.Error == (int)SocketError.Success)
                    {
                        try {
                            connected = await ConnectAsync(address, proxy, ct).ConfigureAwait(false);
                        }
                        catch (Exception) {
                            return(Disposition.Retry);
                        }
                    }
                    return(connected ? Disposition.Done : Disposition.Continue);
                }, (ex) => {
                    if (!connected)
                    {
                        throw new SocketException(
                            "Could not link socket on proxy", ex, SocketError.NoHost);
                    }
                }, ct).ConfigureAwait(false);

                ct.ThrowIfCancellationRequested();
            }

            await Provider.NameService.AddOrUpdateAsync(Host, ct).ConfigureAwait(false);
        }