Ejemplo n.º 1
0
        private async Task HandleIncoming()
        {
            while (!_cts.IsCancellationRequested)
            {
                try
                {
                    UdpReceiveResult data;
                    try
                    {
                        data = await _socket.ReceiveAsync();

                        _logger.LogDebug("Received DTLS Packet from {EndPoint}", data.RemoteEndPoint);
                    }
                    catch (ObjectDisposedException)
                    {
                        // Happens when the Connection is being closed
                        continue;
                    }
                    catch (SocketException sockEx)
                    {
                        // Some clients send an ICMP Port Unreachable when they receive data after they stopped listening.
                        // If we knew from which client it came we could get rid of the connection, but we can't, so we just ignore the exception.
                        if (sockEx.SocketErrorCode == SocketError.ConnectionReset)
                        {
                            _logger.LogInformation("Connection Closed by remote host");
                            continue;
                        }
                        _logger.LogError("SocketException with SocketErrorCode {SocketErrorCode}", sockEx.SocketErrorCode);
                        throw;
                    }

                    // if there is an existing session, we pass the datagram to the session.
                    if (_sessions.TryGetValue(data.RemoteEndPoint, out CoapDtlsServerClientEndPoint session))
                    {
                        session.EnqueueDatagram(data.Buffer);
                        continue;
                    }

                    // if there isn't an existing session for this remote endpoint, we start a new one and pass the first datagram to the session
                    var transport = new QueueDatagramTransport(NetworkMtu, bytes => _sendQueue.Add(new UdpSendPacket(bytes, data.RemoteEndPoint)));
                    session = new CoapDtlsServerClientEndPoint(data.RemoteEndPoint, transport, DateTime.UtcNow);
                    session.EnqueueDatagram(data.Buffer);

                    _sessions.TryAdd(data.RemoteEndPoint, session);
                    try
                    {
                        _logger.LogInformation("New connection from {EndPoint}; Active Sessions: {ActiveSessions}", data.RemoteEndPoint, _sessions.Count);

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
                        Task.Factory.StartNew(() => HandleSession(session), TaskCreationOptions.LongRunning);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Exception while starting session handler!");
                        _sessions.TryRemove(session.EndPoint, out _);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error while handling incoming datagrams");
                }
            }
        }
Ejemplo n.º 2
0
        private async Task HandleSession(CoapDtlsServerClientEndPoint session)
        {
            var state = new Dictionary <string, object>
            {
                { "RemoteEndPoint", session?.EndPoint }
            };

            using (_logger.BeginScope(state))
            {
                try
                {
                    _logger.LogDebug("Trying to accept TLS connection from {EndPoint}", session.EndPoint);

                    var server = _tlsServerFactory.Create();

                    session.Accept(_serverProtocol, server);

                    if (session.ConnectionInfo != null)
                    {
                        _logger.LogInformation("New TLS connection from {EndPoint}, Server Info: {ServerInfo}", session.EndPoint, session.ConnectionInfo);
                    }
                    else
                    {
                        _logger.LogInformation("New TLS connection from {EndPoint}", session.EndPoint);
                    }

                    var connectionInfo = new CoapDtlsConnectionInformation
                    {
                        LocalEndpoint  = _endPoint,
                        RemoteEndpoint = session,
                        TlsServer      = server
                    };

                    while (!session.IsClosed && !_cts.IsCancellationRequested)
                    {
                        var packet = await session.ReceiveAsync(_cts.Token);

                        _logger.LogDebug("Handling CoAP Packet from {EndPoint}", session.EndPoint);
                        await _coapHandler.ProcessRequestAsync(connectionInfo, packet.Payload);

                        _logger.LogDebug("CoAP request from {EndPoint} handled!", session.EndPoint);
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (DtlsConnectionClosedException)
                {
                }
                catch (TlsFatalAlert tlsAlert)
                {
                    if (!(tlsAlert.InnerException is DtlsConnectionClosedException) && tlsAlert.AlertDescription != AlertDescription.user_canceled)
                    {
                        _logger.LogWarning(tlsAlert, "TLS Error");
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error while handling session");
                }
                finally
                {
                    _logger.LogInformation("Connection from {EndPoint} closed", session.EndPoint);
                    _sessions.TryRemove(session.EndPoint, out _);
                }
            }
        }