Exemplo n.º 1
0
            public override sealed Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress)
            {
                // todo: handle cancellation
                AbstractSocketChannel ch = this.Channel;

                if (!ch.Open)
                {
                    return(this.CreateClosedChannelExceptionTask());
                }

                try
                {
                    if (ch.connectPromise != null)
                    {
                        throw new InvalidOperationException("connection attempt already made");
                    }

                    bool wasActive = this.channel.Active;
                    if (ch.DoConnect(remoteAddress, localAddress))
                    {
                        this.FulfillConnectPromise(wasActive);
                        return(TaskEx.Completed);
                    }
                    else
                    {
                        if (!wasActive)
                        {
                            ch.SetState(StateFlags.ActivationPending);
                        }
                        ch.connectPromise = new TaskCompletionSource(remoteAddress);

                        // Schedule connect timeout.
                        TimeSpan connectTimeout = ch.Configuration.ConnectTimeout;
                        if (connectTimeout > TimeSpan.Zero)
                        {
                            CancellationTokenSource cts = ch.connectCancellation = new CancellationTokenSource();

                            ch.EventLoop.Schedule(
                                c =>
                            {
                                // todo: make static / cache delegate?..
                                var self = (AbstractSocketChannel)c;
                                // todo: call Socket.CancelConnectAsync(...)
                                TaskCompletionSource promise = ch.connectPromise;
                                var cause =
                                    new ConnectTimeoutException("connection timed out: " + remoteAddress);
                                if (promise != null && promise.TrySetException(cause))
                                {
                                    self.CloseAsync();
                                }
                            },
                                this.channel,
                                connectTimeout,
                                cts.Token);
                        }

                        ch.connectPromise.Task.ContinueWith(t =>
                        {
                            if (ch.connectCancellation != null)
                            {
                                ch.connectCancellation.Cancel();
                            }
                            ch.connectPromise = null;
                            this.channel.CloseAsync();
                        },
                                                            TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);

                        return(ch.connectPromise.Task);
                    }
                }
                catch (Exception ex)
                {
                    this.CloseIfClosed();
                    return(TaskEx.FromException(this.AnnotateConnectException(ex, remoteAddress)));
                }
            }