Ejemplo n.º 1
0
        /// <inheritdoc />
        protected override Task StopInternalAsync()
        {
            // Simple lock here to guard start and stop phase
            TcpListener?lastListener   = null;
            TcpClient?  lastSendSocket = null;

            lock (_startStopLock)
            {
                if (!_isRunning)
                {
                    throw new InvalidOperationException($"Unable to stop {nameof(TcpPassiveByteStreamHandler)} for port {this.ListeningPort}: This object is stopped already!");
                }

                _isRunning = false;
                _runningLoopCounter++;
                if (_runningLoopCounter > RUNNING_LOOP_COUNTER_MAX)
                {
                    _runningLoopCounter = 1;
                }

                lastListener       = _currentListener;
                lastSendSocket     = _currentSendSocket;
                _currentListener   = null;
                _currentSendSocket = null;
            }

            // Dispose previous sockets
            TcpAsyncUtil.SafeStop(ref lastListener);
            TcpAsyncUtil.SafeDispose(ref lastSendSocket);

            this.Log(LoggingMessageType.Info, "TCP communication stopped");

            return(Task.CompletedTask);
        }
        /// <inheritdoc />
        protected override Task StopInternalAsync()
        {
            // Simple lock here to guard start and stop phase
            UdpClient?lastSendSocket = null;

            lock (_startStopLock)
            {
                if (!_isRunning)
                {
                    throw new InvalidOperationException(
                              $"Unable to stop {nameof(TcpActiveByteStreamHandler)} for host {this.RemoteHost} and port {this.RemotePort}: This object is stopped already!");
                }

                _isRunning = false;
                _connState = ConnectionState.Stopped;
                _runningLoopCounter++;
                if (_runningLoopCounter > RUNNING_LOOP_COUNTER_MAX)
                {
                    _runningLoopCounter = 1;
                }
                lastSendSocket = _udpClient;
                _udpClient     = null;
            }

            // Dispose previous sockets
            TcpAsyncUtil.SafeDispose(ref lastSendSocket);

            this.Log(LoggingMessageType.Info, "UDP communication stopped");

            return(Task.CompletedTask);
        }
Ejemplo n.º 3
0
        private async void RunConnectionMainLoop(int loopId)
        {
            this.Log(LoggingMessageType.Info, "TcpCommunicator started in passive mode");

            // Start main loop
            TcpClient?lastClient = null;
            CancellationTokenSource?lastCancelTokenSource = null;
            TcpListener?            tcpListener           = null;
            var reconnectErrorCount = 0;

            while (loopId == _runningLoopCounter)
            {
                if (tcpListener == null)
                {
                    this.ActualListeningPort = this.ListeningPort;
                    try
                    {
                        if (this.IsLoggerSet)
                        {
                            this.Log(
                                LoggingMessageType.Info,
                                StringBuffer.Format("Creating TcpListener socket for port {0}...", this.ListeningPort));
                        }
                        tcpListener = new TcpListener(this.ListeningIPAddress, this.ListeningPort);
                        tcpListener.Start();
                        this.ActualListeningPort = (ushort)((IPEndPoint)tcpListener.LocalEndpoint).Port;

                        reconnectErrorCount = 0;
                        _currentListener    = tcpListener;

                        if (this.IsLoggerSet)
                        {
                            this.Log(
                                LoggingMessageType.Info,
                                StringBuffer.Format("TcpListener created for port {0}", this.ActualListeningPort));
                        }
                    }
                    catch (Exception ex)
                    {
                        if (this.IsLoggerSet)
                        {
                            this.Log(
                                LoggingMessageType.Error,
                                StringBuffer.Format("Error while creating TcpListener for port {0}: {1}", this.ActualListeningPort, ex.Message),
                                exception: ex);
                        }

                        _currentListener = null;
                        TcpAsyncUtil.SafeStop(ref tcpListener);
                        TcpAsyncUtil.SafeDispose(ref _currentSendSocket);

                        await this.WaitByReconnectWaitTimeAsync(reconnectErrorCount)
                        .ConfigureAwait(false);

                        reconnectErrorCount++;
                    }

                    if (tcpListener == null)
                    {
                        continue;
                    }
                }

                // Wait for incoming connection
                TcpClient? actTcpClient       = null;
                IPEndPoint?actPartnerEndPoint = null;
                IPEndPoint?actLocalEndPoint   = null;
                try
                {
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Info,
                            StringBuffer.Format("Listening for incoming connections on port {0}...",
                                                this.ActualListeningPort));
                    }



                    actTcpClient = await tcpListener.AcceptTcpClientAsync()
                                   .ConfigureAwait(false);

                    actLocalEndPoint   = (IPEndPoint)actTcpClient.Client.LocalEndPoint !;
                    actPartnerEndPoint = (IPEndPoint)actTcpClient.Client.RemoteEndPoint !;

                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Info,
                            StringBuffer.Format(
                                "Got new connection on listening port {0}. Connection established between {1} and {2}",
                                this.ActualListeningPort, actLocalEndPoint.ToString(), actPartnerEndPoint.ToString()));
                    }
                }
                catch (ObjectDisposedException)
                {
                    // Stop may be called in the meanwhile

                    if (!_isRunning)
                    {
                        continue;
                    }
                    if (loopId != _runningLoopCounter)
                    {
                        continue;
                    }
                }
                catch (Exception ex)
                {
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Error,
                            StringBuffer.Format("Error while listening for incoming connections on port {0}: {1}", this.ActualListeningPort, ex.Message),
                            exception: ex);
                    }

                    TcpAsyncUtil.SafeStop(ref tcpListener);
                    TcpAsyncUtil.SafeDispose(ref _currentSendSocket);

                    await this.WaitByReconnectWaitTimeAsync(reconnectErrorCount)
                    .ConfigureAwait(false);

                    reconnectErrorCount++;
                }
                if (tcpListener == null)
                {
                    continue;
                }
                if (actTcpClient == null)
                {
                    continue;
                }

                // New connection request coming in... close the previous one
                if (lastClient != null)
                {
                    lastCancelTokenSource !.Cancel();
                    lastCancelTokenSource = null;
                    lastClient            = null;
                }

                // Register new client
                _currentSendSocket    = actTcpClient;
                lastClient            = actTcpClient;
                lastCancelTokenSource = new CancellationTokenSource();

                // Run receive loop for this client (we don't have to await this because we a listening for a new connection request)
#pragma warning disable 4014
                this.RunReceiveLoopAsync(
                    lastClient, lastClient.Client,
                    actLocalEndPoint !, actPartnerEndPoint !, lastCancelTokenSource.Token);
#pragma warning restore 4014
            }

            if (tcpListener != null)
            {
                TcpAsyncUtil.SafeStop(ref tcpListener);
            }
        }
        /// <summary>
        /// Internal method which reacts on incoming bytes on the currently active socket connection.
        /// Only one of this connection is active at one time.
        /// </summary>
        protected async Task RunReceiveLoopAsync(IDisposable parentDisposable, Socket socket, IPEndPoint localEndPoint, IPEndPoint partnerEndPoint, CancellationToken cancelToken)
        {
            parentDisposable.MustNotBeNull(nameof(parentDisposable));
            socket.MustNotBeNull(nameof(socket));
            localEndPoint.MustNotBeNull(nameof(localEndPoint));
            partnerEndPoint.MustNotBeNull(nameof(partnerEndPoint));

            _lastSuccessfulConnectTimestampUtc = DateTime.UtcNow;

            var localEndPointStr   = localEndPoint.ToString();
            var partnerEndPointStr = partnerEndPoint.ToString();
            var newConnection      = true;

            if (this.IsLoggerSet)
            {
                this.Log(
                    LoggingMessageType.Info,
                    StringBuffer.Format("Starting receive loop for connection {0} to {1}", localEndPointStr, partnerEndPointStr));
            }

            var receiveBuffer = new byte[this.ReceiveBufferSize];

            while (!cancelToken.IsCancellationRequested)
            {
                int lastReceiveResult;
                try
                {
                    // Read next bytes
#if NETSTANDARD2_0
                    var receiveTask = socket.ReceiveAsync(new ArraySegment <byte>(receiveBuffer), SocketFlags.None);
                    if (receiveTask.IsCompleted)
                    {
                        lastReceiveResult = receiveTask.Result;
                    }
                    else if (this.ReceiveTimeout == TimeSpan.Zero)
                    {
                        lastReceiveResult = await receiveTask
                                            .ConfigureAwait(false);
                    }
                    else
                    {
                        var timeoutTask = Task.Delay(this.ReceiveTimeout);
                        await Task.WhenAny(receiveTask, timeoutTask)
                        .ConfigureAwait(false);

                        if (receiveTask.IsCompleted)
                        {
                            lastReceiveResult = receiveTask.Result;
                        }
                        else
                        {
                            _ = receiveTask.ContinueWith(s_dummyReceiveContinuation);

                            if (this.IsLoggerSet)
                            {
                                this.Log(
                                    LoggingMessageType.Error,
                                    StringBuffer.Format(
                                        "Timeout while receiving from {0}!",
                                        partnerEndPointStr));
                            }
                            break;
                        }
                    }
#else
                    var receiveTaskStruct = socket.ReceiveAsync(new Memory <byte>(receiveBuffer), SocketFlags.None);
                    if (receiveTaskStruct.IsCompleted)
                    {
                        lastReceiveResult = receiveTaskStruct.Result;
                    }
                    else if (this.ReceiveTimeout == TimeSpan.Zero)
                    {
                        lastReceiveResult = await receiveTaskStruct
                                            .ConfigureAwait(false);
                    }
                    else
                    {
                        var receiveTask = receiveTaskStruct.AsTask();
                        var timeoutTask = Task.Delay(this.ReceiveTimeout);
                        await Task.WhenAny(receiveTask, timeoutTask)
                        .ConfigureAwait(false);

                        if (receiveTask.IsCompleted)
                        {
                            lastReceiveResult = receiveTask.Result;
                        }
                        else
                        {
                            _ = receiveTask.ContinueWith(s_dummyReceiveContinuation);

                            if (this.IsLoggerSet)
                            {
                                this.Log(
                                    LoggingMessageType.Error,
                                    StringBuffer.Format(
                                        "Timeout while receiving from {0}!",
                                        partnerEndPointStr));
                            }
                            break;
                        }
                    }
#endif

                    // Reset receive result if we where canceled already
                    if (lastReceiveResult == 0)
                    {
                        this.Log(LoggingMessageType.Info, "Connection closed by remote partner");
                    }
                    else if (cancelToken.IsCancellationRequested)
                    {
                        this.Log(LoggingMessageType.Info, "Connection canceled by local program");
                        lastReceiveResult = 0;
                    }
                    else
                    {
                        _lastSuccessfulReceiveTimestampUtc = DateTime.UtcNow;
                    }
                }
                catch (ObjectDisposedException)
                {
                    break;
                }
                catch (SocketException socketException)
                {
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Error,
                            StringBuffer.Format(
                                "Error while receiving bytes from {0}: (Code: {1}) {2}",
                                partnerEndPointStr,
                                socketException.SocketErrorCode.ToString(),
                                socketException.Message),
                            exception: socketException);
                    }
                    break;
                }
                catch (Exception ex)
                {
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Error,
                            StringBuffer.Format(
                                "Error while receiving bytes from {0}: {1}",
                                partnerEndPointStr,
                                ex.Message),
                            exception: ex);
                    }
                    break;
                }

                if (lastReceiveResult <= 0)
                {
                    break;
                }
                this.ProcessReceivedBytes(newConnection, receiveBuffer, lastReceiveResult);

                newConnection = false;
            }

            // Ensure that the socket is closed after ending this method
            TcpAsyncUtil.SafeDispose(parentDisposable);
        }
Ejemplo n.º 5
0
        private async void RunConnectionMainLoop(int loopId)
        {
            this.Log(LoggingMessageType.Info, "TcpCommunicator started in active mode");

            var reconnectErrorCount = 0;
            var remoteAddressStr    = this.RemoteHost;

            while (loopId == _runningLoopCounter)
            {
                TcpClient?newClient = null;
                try
                {
                    _connState = ConnectionState.Connecting;
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Info,
                            StringBuffer.Format("Connecting to host {0} on port {1}", remoteAddressStr,
                                                this.RemotePort));
                    }

                    newClient = new TcpClient();
                    if (!ReferenceEquals(this.RemoteIPAddress, IPAddress.None))
                    {
                        await newClient.ConnectAsync(this.RemoteIPAddress, this.RemotePort);
                    }
                    else
                    {
                        await newClient.ConnectAsync(this.RemoteHost, this.RemotePort);
                    }
                    _currentClient      = newClient;
                    reconnectErrorCount = 0;

                    _connState = ConnectionState.Connected;
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Info,
                            StringBuffer.Format("Successfully connected to host {0} on port {1}", remoteAddressStr,
                                                this.RemotePort));
                    }
                }
                catch (Exception ex)
                {
                    TcpAsyncUtil.SafeDispose(ref newClient);
                    _currentClient = null;

                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Error,
                            StringBuffer.Format("Error while connecting to host {0} on port {1}: {2}",
                                                remoteAddressStr, this.RemotePort, ex.Message),
                            exception: ex);
                    }

                    _connState = ConnectionState.Connecting;
                    await this.WaitByReconnectWaitTimeAsync(reconnectErrorCount)
                    .ConfigureAwait(false);

                    reconnectErrorCount++;
                }
                if (_currentClient == null)
                {
                    continue;
                }

                // Normal receive loop handling
                try
                {
                    await this.RunReceiveLoopAsync(
                        _currentClient, _currentClient.Client,
                        (IPEndPoint)_currentClient.Client.LocalEndPoint !,
                        (IPEndPoint)_currentClient.Client.RemoteEndPoint !, CancellationToken.None);
                }
                catch (Exception ex)
                {
                    if (this.IsLoggerSet)
                    {
                        this.Log(
                            LoggingMessageType.Error,
                            StringBuffer.Format(
                                "Error while running receive loop for host {0} on port {1}: {2}",
                                remoteAddressStr, this.RemotePort, ex.Message),
                            exception: ex);
                    }
                }

                // Client gets already disposed in receive loop
                _currentClient = null;
            }
        }