Beispiel #1
0
 public AsyncConnectState(TorrentManager manager, Peer peer, IConnection connection, AsyncConnect callback)
 {
     Manager = manager;
     Peer = peer;
     Connection = connection;
     Callback = callback;
 }
 /// <summary>
 /// Create connect probe
 /// </summary>
 /// <param name="index"></param>
 /// <param name="probe"></param>
 /// <param name="logger"></param>
 protected BaseConnectProbe(int index, IAsyncProbe probe, ILogger logger)
 {
     _probe  = probe ?? throw new ArgumentNullException(nameof(probe));
     _index  = index;
     _logger = logger;
     _lock   = new SemaphoreSlim(1, 1);
     _arg    = new AsyncConnect(this);
 }
        /// <summary>
        /// Initiates a connection to the server
        /// </summary>
        /// <param name="callback">AsyncCallback method</param>
        /// <param name="state">State object</param>
        /// <returns>IAsyncResult</returns>
        /// <example><code source="..\Examples\BeginConnect.cs" lang="cs" /></example>
        public IAsyncResult BeginConnect(AsyncCallback callback, object state)
        {
            AsyncConnect func;
            IAsyncResult ar;

            lock (m_asyncmethods) {
                ar = (func = new AsyncConnect(Connect)).BeginInvoke(callback, state);
                m_asyncmethods.Add(ar, func);
            }

            return(ar);
        }
        /// <summary>
        /// Begin connecting to next endpoint
        /// </summary>
        private void OnBegin()
        {
            var exit = false;

            _lock.Wait();
            try {
                while (!_cts.IsCancellationRequested && !exit)
                {
                    IPEndPoint ep      = null;
                    var        timeout = 3000;
                    try {
                        if (!Next(out ep, out timeout))
                        {
                            exit = true;
                            break;
                        }
                    }
                    catch (OperationCanceledException) {
                        exit = true;
                        break;
                    }
                    catch (InvalidOperationException) {
                        continue;
                    }
                    catch (Exception ex) {
                        _logger.Error(ex, "Error getting endpoint for probe {index}",
                                      _index);
                        exit = true;
                        break;
                    }

                    if (_arg != null && _arg.IsRunning)
                    {
                        // Reset args since it is in running state and cannot be used...
                        _logger.Verbose("Disposing args in running state.");
                        DisposeArgsNoLock();
                    }

                    while (!_cts.IsCancellationRequested)
                    {
                        if (_arg == null)
                        {
                            _arg = new AsyncConnect(this);
                        }
                        try {
                            if (_arg.BeginConnect(ep, timeout))
                            {
                                // Completed synchronously - go to next candidate
                                break;
                            }
                            return;
                        }
                        catch (ObjectDisposedException) {
                            // Try again
                        }
                        catch (InvalidOperationException) {
                            // Operation in progress - try again
                        }
                        catch (SocketException sex) {
                            if (sex.SocketErrorCode == SocketError.NoBufferSpaceAvailable ||
                                sex.SocketErrorCode == SocketError.TooManyOpenSockets)
                            {
                                if (ShouldGiveUp())
                                {
                                    // Exit only until we hit (approx.) min probe count.
                                    exit = true;
                                    break;
                                }
                                // Otherwise retry...
                            }
                            else
                            {
                                _logger.Error(sex, "{code} in connect of probe {index}...",
                                              sex.SocketErrorCode, _index);
                            }
                        }
                        catch (Exception ex) {
                            // Unexpected - shut probe down
                            _logger.Error(ex,
                                          "Probe {index} has unexpected exception during connect.",
                                          _index);
                            exit = true;
                            break;
                        }

                        // Retry same endpoint address with new args
                        DisposeArgsNoLock();
                    }

                    if (exit)
                    {
                        // We failed, requeue the endpoint and kill this probe
                        OnFail(ep);
                        break;
                    }
                }

                if (_cts.IsCancellationRequested)
                {
                    return;
                }
            }
            finally {
                _lock.Release();
            }

            if (exit)
            {
                //
                // We are here because we either...
                //
                // a) failed to dequeue
                // b) The producer has completed
                // c) Connect failed due to lack of ephimeral ports.
                // d) A non socket exception occurred.
                //
                // Notify of exit.
                //
                OnExit();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="settings"></param>
        public ConnectionManager(ClientEngine engine)
        {
            this.engine = engine;

            this.endCheckEncryptionCallback = delegate(IAsyncResult result) { ClientEngine.MainLoop.Queue(delegate { EndCheckEncryption(result); }); };
            this.endSendMessageCallback = delegate(bool s, int c, object o) { ClientEngine.MainLoop.Queue(delegate { EndSendMessage(s, c, o); }); };
            this.endCreateConnectionCallback = delegate(bool succeeded, object state) { ClientEngine.MainLoop.Queue(delegate { EndCreateConnection(succeeded, state); }); };
            this.incomingConnectionAcceptedCallback = delegate(bool s, int c, object o) { ClientEngine.MainLoop.Queue(delegate { IncomingConnectionAccepted(s, c, o); }); };

            this.bitfieldSentCallback = new MessagingCallback(PeerBitfieldSent);
            this.handshakeSentCallback = new MessagingCallback(this.PeerHandshakeSent);
            this.handshakeReceievedCallback = delegate(bool s, int c, object o) { ClientEngine.MainLoop.Queue(delegate { PeerHandshakeReceived(s, c, o); }); };
            this.messageSentCallback = new MessagingCallback(this.PeerMessageSent);

            this.torrents = new MonoTorrentCollection<TorrentManager>();
        }