public string GetAckMessage(HL7Connection Connection, string controlId)
        {
            Throw.IfNull(Connection);

            var response = new Message();

            var msh = new Segment("MSH");

            msh.Field(2, "^~\\&");
            msh.Field(7, DateTime.Now.ToString("yyyyMMddhhmmssfff"));
            msh.Field(9, Connection.ack);  //  "ACK");
            msh.Field(10, Guid.NewGuid().ToString());
            msh.Field(11, "P");
            msh.Field(12, "2.5.1");
            response.Add(msh);

            var msa = new Segment("MSA");

            msa.Field(1, "AA");
            msa.Field(2, controlId);   //  msg.MessageControlId());
            response.Add(msa);


            // Put response message into an MLLP frame ( <VT> data <FS><CR> )
            //
            var frame = new StringBuilder();

            frame.Append((char)0x0B);
            frame.Append(response.Serialize());
            frame.Append((char)0x0D);
            frame.Append((char)0x1C);
            frame.Append((char)0x0D);

            return(frame.ToString());
        }
        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
        public MedicationTO refillPrescription(string pwd, string sitecode, string mpiPid, string rxId)
        {
            MedicationTO result = new MedicationTO();

            if (String.IsNullOrEmpty(pwd))
            {
                result.fault = new FaultTO("Missing pwd");
            }
            else if (String.IsNullOrEmpty(sitecode))
            {
                result.fault = new FaultTO("Missing site ID");
            }
            else if (String.IsNullOrEmpty(mpiPid))
            {
                result.fault = new FaultTO("Missing patient ID");
            }
            else if (String.IsNullOrEmpty(rxId))
            {
                result.fault = new FaultTO("Missing Rx ID");
            }

            if (result.fault != null)
            {
                return(result);
            }

            try
            {
                Site       hl7Site = mySession.SiteTable.getSite(sitecode);
                DataSource hl7Src  = null;
                foreach (DataSource src in hl7Site.Sources)
                {
                    if (String.Equals(src.Protocol, "HL7", StringComparison.CurrentCultureIgnoreCase))
                    {
                        hl7Src = src;
                        break;
                    }
                }
                if (hl7Src == null)
                {
                    throw new gov.va.medora.mdo.exceptions.MdoException("No HL7 data source in site table for that site ID");
                }
                HL7Connection cxn = new HL7Connection(hl7Src);
                cxn.connect();
                cxn.Pid = mpiPid;
                result  = new MedicationTO(new MedsApi().refillPrescription(cxn, rxId));
            }
            catch (Exception exc)
            {
                result.fault = new FaultTO(exc);
            }

            return(result);
        }
 public void Clean(HL7Connection Connection, List <TcpClient> clients)
 {
     foreach (var client in clients.ToArray())
     {
         if (!client.Connected)
         {
             _logger.Log(LogLevel.Debug, $"{Connection.name} Disconnected");
             client.Dispose();
             clients.Remove(client);
         }
         else
         {
             _logger.Log(LogLevel.Debug, $"{Connection.name} Connected: {client.Client.RemoteEndPoint}");
         }
     }
 }
Exemplo n.º 5
0
 public async Task Start(HL7Connection Connection, List <BourneListens> listeners, ObservableCollection <BourneListens> deadListeners, List <TcpClient> clients, Func <TcpClient, int, Task> Read)
 {
     try
     {
         await StartImpl(Connection, listeners, deadListeners, clients, Read);
     }
     catch (TaskCanceledException)
     {
         _logger.Log(LogLevel.Information, $"Task was canceled.");
     }
     catch (SocketException e)
     {
         _logger.Log(LogLevel.Warning, $"{e.Message} {e.StackTrace}");
     }
     catch (ObjectDisposedException e)
     {
         _logger.LogFullException(e);
     }
     catch (Exception e)
     {
         _logger.LogFullException(e);
     }
 }
Exemplo n.º 6
0
        public override AbstractConnection getConnection(DataSource dataSource)
        {
            HL7Connection cxn = new HL7Connection(dataSource);

            return(cxn);
        }
Exemplo n.º 7
0
        public async Task SendToHL7(int taskID, HL7Connection connection)
        {
            Connection = connection;

            var taskInfo = $"task: {taskID} connection: {Connection.name}";

            TcpClient tcpclnt = new TcpClient(Connection.remoteHostname, Connection.remotePort);

            _logger.Log(LogLevel.Debug, $"HL7 tcpclient connection {Connection.name} opened - task = {Task.CurrentId} connected = {tcpclnt.Connected}");

            Stream stm = null;

            SslStream sslStream = null;

            try
            {
                switch (Connection.useTLS)
                {
                case true:
                {
                    sslStream = new SslStream(tcpclnt.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
                    sslStream.AuthenticateAsClient(Connection.remoteHostname);
                    break;
                }

                default:
                {
                    stm = tcpclnt.GetStream();
                    break;
                }
                }

                var temp = Connection.ToHL7.ToArray();
                foreach (var routedItem in temp)
                {
                    try
                    {
                        await ProcessItem(routedItem, sslStream, stm, taskInfo);
                    }
                    catch (Exception e)
                    {
                        _logger.LogFullException(e, taskInfo);
                    }
                }

                await Task.Delay(5000).ConfigureAwait(false); //give the socket enough time to clear.

                tcpclnt.Close();

                _logger.Log(LogLevel.Debug, "Regular HL7 tcpclient connection {name} closed - task = {Task.CurrentId} completed = {Task.CompletedTask}");

                foreach (var hl7 in temp)
                {
                    _routedItemManager.Init(hl7);
                    _routedItemManager.Dequeue(Connection, Connection.ToHL7, nameof(Connection.ToHL7), error: false);
                }
            }
            catch (Exception e)
            {
                _logger.LogFullException(e);
            }
            finally
            {
                switch (Connection.useTLS)
                {
                case true:
                    sslStream.Close();
                    break;

                default:
                    stm.Close();
                    break;
                }
                tcpclnt.Close();
                _logger.Log(LogLevel.Debug, "Final HL7 tcpclient connection {name} closed - task =  {Task.CurrentId}  completed = {Task.CompletedTask}");
            }
        }
Exemplo n.º 8
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");
                }
            }
        }
        public async Task Read(TcpClient client, int taskID, HL7Connection connection)
        {
            Connection = connection;
            Stopwatch idle     = new Stopwatch();
            var       taskInfo = $"task: {taskID} connection: {Connection.name} {client?.Client?.RemoteEndPoint}";
            Stream    stream   = null;

            try
            {
                NetworkStream networkStream = client.GetStream();

                if (Connection.useTLS)
                {
                    SslStream ssls = new SslStream(networkStream, false);
                    ssls.AuthenticateAsServer(_x509CertificateService.GetServerCertificate(Connection.name), false, SslProtocols.Tls12, true);
                    stream = ssls;
                }
                else
                {
                    stream = networkStream;
                }

                if (client.Connected)
                {
                    //read the stream if avail, acknowledge, throw into hl7 receive array for other async processing
                    do
                    {
                        byte[] buffer = new byte[client.ReceiveBufferSize];
                        if (stream.CanRead)
                        {
                            var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, _taskManager.cts.Token);

                            if (bytesRead > 0)
                            {
                                idle.Stop();
                                string controlId = "";
                                byte[] tmp       = new byte[bytesRead];
                                Array.Copy(buffer, tmp, bytesRead);

                                var dir = _profileStorage.Current.tempPath +
                                          Path.DirectorySeparatorChar +
                                          Connection.name +
                                          Path.DirectorySeparatorChar +
                                          Constants.Dirs.ToRules;

                                Directory.CreateDirectory(dir);
                                var filename = dir + Path.DirectorySeparatorChar + Connection.name + "_" +
                                               DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss.ffff") + ".hl7";
                                await File.WriteAllBytesAsync(filename, buffer);

                                RoutedItem routedItem = new RoutedItem(Connection.name, filename, taskID)
                                {
                                    type = RoutedItem.Type.HL7
                                };

                                string msg = Encoding.Default.GetString(tmp);
                                if (msg.StartsWith('\v'))
                                {
                                    msg = msg.Substring(1);
                                }

                                if (msg.Length >= 4 && msg.StartsWith("MSH"))
                                {
                                    List <KeyValuePair <string, List <string> > > segments = new List <KeyValuePair <string, List <string> > >();
                                    List <string> temp = null;
                                    if (msg.Contains("\r\n"))
                                    {
                                        temp = msg.Split("\r\n").ToList();
                                    }
                                    else if (msg.Contains("\n"))
                                    {
                                        temp = msg.Split("\n").ToList();
                                    }
                                    else if (msg.Contains("\r"))
                                    {
                                        temp = msg.Split("\r").ToList();
                                    }
                                    else
                                    {
                                        _logger.Log(LogLevel.Error, $"Unknown segment delimiter");
                                    }

                                    foreach (var segment in temp)
                                    {
                                        if (segment.Length >= 4)
                                        {
                                            segments.Add(new KeyValuePair <string, List <string> >(segment.Substring(0, 3),
                                                                                                   segment.Split((char)msg[3]).ToList()));
                                        }
                                    }

                                    routedItem.hl7 = segments;

                                    //string[] fields = msg.Split((char)tmp[4]);
                                    var msh = segments.Find(e => e.Key == "MSH");
                                    if (msh.Value.Count >= 10)
                                    {
                                        controlId = msh.Value[9];
                                    }


                                    //determine the patientID and accession number and populate the ID field
                                    try
                                    {
                                        var pid = segments.Find(e => e.Key == "PID");
                                        if (pid.Value[3].IndexOf("^") > 0)
                                        {
                                            routedItem.PatientID = pid.Value[3].Substring(0, pid.Value[3].IndexOf("^"));
                                        }
                                        else
                                        {
                                            routedItem.PatientID = pid.Value[3];
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        _logger.Log(LogLevel.Critical, $"{taskInfo} Error Parsing PID: {e.Message} {e.StackTrace}");
                                    }

                                    try
                                    {
                                        var obr = segments.Find(e => e.Key == "OBR");
                                        if (obr.Value[3].IndexOf("^") > 0)
                                        {
                                            routedItem.AccessionNumber =
                                                obr.Value[3].Substring(0, obr.Value[3].IndexOf("^"));
                                        }
                                        else
                                        {
                                            routedItem.AccessionNumber = obr.Value[3];
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        _logger.Log(LogLevel.Critical,
                                                    $"{taskInfo} Error Parsing OBR: {e.Message} {e.StackTrace}");
                                    }

                                    routedItem.id = $"PID:{routedItem.PatientID}, AN:{routedItem.AccessionNumber}"; //, UID:{routedItem.Study}";
                                }

                                _routedItemManager.Init(routedItem);
                                _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules));

                                _logger.Log(LogLevel.Debug, $"{taskInfo} {msg}");

                                byte[] serverResponseBytes = null;
                                switch (Connection.ackMode)
                                {
                                case AckMode.Original:
                                {
                                    //process message and return response bytes
                                    break;
                                }

                                case AckMode.Enhanced:
                                {
                                    //process message and return response bytes
                                    break;
                                }

                                case AckMode.Custom:
                                {
                                    serverResponseBytes = Encoding.UTF8.GetBytes(GetAckMessage(controlId));
                                    break;
                                }
                                }

                                if (serverResponseBytes != null)
                                {
                                    await stream.WriteAsync(serverResponseBytes, 0, serverResponseBytes.Length);

                                    _logger.Log(LogLevel.Debug, $"{taskInfo} {Encoding.Default.GetString(serverResponseBytes)}");
                                }
                                else
                                {
                                    _logger.Log(LogLevel.Debug, $"{taskInfo} serverResponseBytes is null.  Please verify ackMode and ack values.");
                                }
                            }

                            //await stream.FlushAsync();
                        }
                        else
                        {
                            break;
                        }
                    } while (networkStream.DataAvailable);
                    // await Task.Delay(10000);  //if no data avail then sleep on socke
                }
            }
            catch (TaskCanceledException)
            {
                _logger.Log(LogLevel.Information, $"{taskInfo} Task was canceled.");
            }
            catch (Exception e)
            {
                _logger.LogFullException(e, taskInfo);
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }

                if (client != null)
                {
                    client.Close();
                    _logger.Log(LogLevel.Debug, "Inbound HL7 tcpclient connection {name} closed - task = {Task.CurrentId} completed = {Task.CompletedTask}");
                }

                // note: do not call this logic inside method. It should be outside
                //Clean();   // cleanup the connection, remove from list
                //LITETask.Stop($"{Connection.name}.read");
            }
        }