private async Task <string> ProcessItem(BourneListens bourne, List <TcpClient> clients, Func <TcpClient, int, Task> func, int taskID)
        {
            //You can echo "Hello world!" | nc ::1 2575 to send messages to accept a new connection request
            TcpClient client = await bourne.AcceptTcpClientAsync();

            string remote = client.Client.RemoteEndPoint.ToString();
            var    local  = bourne.LocalEndpoint.ToString();

            _logger.Log(LogLevel.Debug, $"{local} connected to: {remote}");

            if (clients.Count < Connection.maxInboundConnections && _taskManager.CanStart($"{Connection.name}.read"))
            {
                clients.Add(client);
                _logger.Log(LogLevel.Debug, $"{local} added to clients: {remote}");
                var  endpoint  = client.Client.RemoteEndPoint;
                var  newTaskID = _taskManager.NewTaskID();
                Task task      = new Task(new Action(async() => await func(client, newTaskID)), _taskManager.cts.Token);
                await _taskManager.Start(newTaskID, task, $"{Connection.name}.read", $"{Connection.name}.read: {remote}", isLongRunning : false);
            }
            else
            {
                _logger.Log(LogLevel.Warning, $"{local} Max Connections: {Connection.maxInboundConnections} reached.");
                _logger.Log(LogLevel.Debug, $"client connection closed {taskID} due to max connections reached");
                client.Close();
            }

            return(local);
        }
        public async Task Accept(HL7Connection connection, BourneListens bourne, List <TcpClient> clients, Func <TcpClient, int, Task> func, int taskID)
        {
            Connection = connection;

            _logger.Log(LogLevel.Debug, $"{Connection.name} Entering accept on {bourne.LocalEndpoint}");

            string local = string.Empty;

            try
            {
                while (!_taskManager.cts.IsCancellationRequested)
                {
                    if (!bourne.Active())
                    {
                        break;
                    }

                    local = await ProcessItem(bourne, clients, func, taskID);
                }
            }
            catch (TaskCanceledException)
            {
                _logger.Log(LogLevel.Information, $"Task was canceled.");
            }
            catch (SocketException e)
            {
                _logger.Log(LogLevel.Warning, $"{local} SocketException: {e.ErrorCode} {e.Message} {e.StackTrace}");
                if (e.InnerException != null)
                {
                    _logger.Log(LogLevel.Warning, $"Inner Exception: {e.InnerException}");
                }
            }
            catch (ObjectDisposedException e)
            {
                _logger.Log(LogLevel.Warning, $"{local} HL7 Connection is closed.");
                if (e.InnerException != null)
                {
                    _logger.Log(LogLevel.Warning, $"Inner Exception: {e.InnerException}");
                }
            }
            catch (System.InvalidOperationException e)
            {
                _logger.Log(LogLevel.Warning, $"{local} InvalidOperationException: {e.Message} {e.StackTrace}");
                if (e.InnerException != null)
                {
                    _logger.Log(LogLevel.Warning, $"Inner Exception: {e.InnerException}");
                }
            }
            catch (Exception e)
            {
                _logger.LogFullException(e, local);
            }
            finally
            {
                _taskManager.Stop($"{Connection.name}.accept: {bourne.LocalEndpoint}");
            }

            _logger.Log(LogLevel.Warning, $"Cancellation received. Exiting accept.");
        }
Exemplo n.º 3
0
        private async Task StartImpl(HL7Connection Connection, List <BourneListens> listeners, ObservableCollection <BourneListens> deadListeners, List <TcpClient> clients, Func <TcpClient, int, Task> Read)
        {
            RemoveDeadListeners(listeners, deadListeners);

            //frequent DNS lookup required for Cloud and HA environments where a lower TTL results in faster failover.
            //For a listener this means a container might have been moved to another server with different IP.
            var hostEntry = Dns.GetHostEntry(Connection.localHostname);

            foreach (var ip in hostEntry.AddressList)
            {
                _logger.Log(LogLevel.Information, $"{Connection.name} hostEntry: {Connection.localHostname} ip: {ip}");
                BourneListens bourne = null;
                if (ip.AddressFamily == AddressFamily.InterNetworkV6 && Connection.UseIPV6)
                {
                    if (!listeners.Exists(x => x.localaddr.Equals(ip) && x.port.Equals(Connection.localPort)))
                    {
                        bourne = new BourneListens(ip, Connection.localPort);
                        listeners.Add(bourne);

                        //you can verify Start worked on mac by doing lsof -n -i:2575 | grep LISTEN, where 2575 is HL7 or whatever port you want.
                        bourne.Start();
                        _logger.Log(LogLevel.Information, $"{Connection.name} is listening on {bourne.LocalEndpoint}");
                        _logger.Log(LogLevel.Information, $"{Connection.name} Verify with Mac/Linux:lsof -n -i:{Connection.localPort} | grep LISTEN and with echo \"Hello world\" | nc {Connection.localHostname} {Connection.localPort}");
                        _logger.Log(LogLevel.Information, $"{Connection.name} Verify with Windows:netstat -abno (requires elevated privileges)");
                    }
                }

                if ((ip.AddressFamily == AddressFamily.InterNetwork && Connection.UseIPV4 && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ||
                    (ip.AddressFamily == AddressFamily.InterNetwork && Connection.UseIPV4 && !Connection.UseIPV6 && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)))
                {
                    if (!listeners.Exists(x => x.localaddr.Equals(ip) && x.port.Equals(Connection.localPort)))
                    {
                        bourne = new BourneListens(ip, Connection.localPort);
                        listeners.Add(bourne);

                        //you can verify Start worked on mac by doing lsof -n -i:2575 | grep LISTEN, where 2575 is HL7 or whatever port you want.
                        bourne.Start();
                        _logger.Log(LogLevel.Information, $"{Connection.name} is listening on {bourne.LocalEndpoint}");
                        _logger.Log(LogLevel.Information, $"{Connection.name} Verify with Mac/Linux:lsof -n -i:{Connection.localPort} | grep LISTEN and with echo \"Hello world\" | nc {Connection.localHostname} {Connection.localPort}");
                        _logger.Log(LogLevel.Information, $"{Connection.name} Verify with Windows:netstat -abno (requires elevated privileges)");
                    }
                }
            }

            foreach (var listener in listeners)
            {
                if (listener != null && listener.LocalEndpoint != null)
                {
                    if (_taskManager.CanStart($"{Connection.name}.accept: {listener.LocalEndpoint}"))
                    {
                        var  newTaskID = _taskManager.NewTaskID();
                        Task task      = new Task(new Action(async() => await _hl7AcceptService.Accept(Connection, listener, clients, Read, newTaskID)), _taskManager.cts.Token);
                        await _taskManager.Start(newTaskID, task, $"{Connection.name}.accept: {listener.LocalEndpoint}", $"{Connection.name}.accept: {listener.LocalEndpoint}", isLongRunning : true);

                        await Task.Delay(1000);
                    }
                }
                else
                {
                    _logger.Log(LogLevel.Information, $"listener is disposed but still in list. Ignoring");
                }
            }
        }