Example #1
0
        /// <summary>
        /// Creates a negative acknowledgement message.
        /// </summary>
        /// <param name="request">The request message to use to create the response message.</param>
        /// <param name="responseCode">The response code of the message.</param>
        /// <param name="errCode">The error code of the message.</param>
        /// <param name="errDescription">The error description of the message.</param>
        /// <returns>Returns the created negative acknowledgement message instance.</returns>
        public static IMessage CreateNack(IMessage request, string responseCode, string errCode, string errDescription)
        {
            MessageUtil.tracer.TraceEvent(TraceEventType.Warning, 0, $"NACK Condition : {errDescription}");

            if (request.Version == "2.3.1")
            {
                var ack = new ACK();

                var terser = new Terser(ack);

                terser.Set("/MSA-1", responseCode);
                terser.Set("/MSA-3", "Error occurred");
                terser.Set("/MSA-6-1", errCode);
                terser.Set("/MSA-6-2", errDescription);

                UpdateMSH(terser, request);

                return(ack);
            }
            else
            {
                var ack = new NHapi.Model.V25.Message.ACK();

                var terser = new Terser(ack);

                terser.Set("/MSA-1", responseCode);

                UpdateMSH(terser, request);

                terser.Set("/ERR-3-1", errCode);
                terser.Set("/ERR-3-2", errDescription);

                return(ack);
            }
        }
Example #2
0
        /// <summary>
        /// Create NACK
        /// </summary>
        internal static IMessage CreateNack(IMessage request, string responseCode, string errCode, string errDescription, ISystemConfigurationService config)
        {
            System.Diagnostics.Trace.TraceWarning(String.Format("NACK Condition : {0}", errDescription));

            if (request.Version == "2.3.1")
            {
                NHapi.Model.V231.Message.ACK ack = new NHapi.Model.V231.Message.ACK();
                Terser terser = new Terser(ack);
                terser.Set("/MSA-1", responseCode);
                terser.Set("/MSA-3", "Error occurred");
                terser.Set("/MSA-6-1", errCode);
                terser.Set("/MSA-6-2", errDescription);
                MessageUtil.UpdateMSH(terser, request, config);
                return(ack);
            }
            else
            {
                NHapi.Model.V25.Message.ACK ack = new NHapi.Model.V25.Message.ACK();
                Terser terser = new Terser(ack);
                terser.Set("/MSA-1", responseCode);
                MessageUtil.UpdateMSH(terser, request, config);
                terser.Set("/ERR-3-1", errCode);
                terser.Set("/ERR-3-2", errDescription);
                return(ack);
            }
        }
Example #3
0
        /// <summary>
        /// Receive and process message
        /// </summary>
        protected virtual void OnReceiveMessage(object client)
        {
            using (TcpClient tcpClient = client as TcpClient)
            {
                this.m_traceSource.TraceEvent(EventLevel.Verbose, "Accepted connection on {0} from {1}", this.m_listener.LocalEndpoint, tcpClient.Client.RemoteEndPoint);
                NetworkStream stream = tcpClient.GetStream();
                try
                {
                    // Now read to a string
                    DateTime lastReceive = DateTime.Now;

                    while (DateTime.Now.Subtract(lastReceive) < this.m_timeout)
                    {
                        if (!stream.DataAvailable)
                        {
                            Thread.Sleep(10);
                            continue;
                        }

                        // Read LLP head byte
                        int llpByte = stream.ReadByte();
                        if (llpByte != START_TX) // first byte must be HT
                        {
                            throw new InvalidOperationException("Invalid LLP First Byte");
                        }

                        // Standard stream stuff, read until the stream is exhausted
                        StringBuilder messageData = new StringBuilder();
                        byte[]        buffer = new byte[1024];
                        bool          receivedEOF = false, scanForCr = false;

                        while (!receivedEOF)
                        {
                            if (DateTime.Now.Subtract(lastReceive) > this.m_timeout)
                            {
                                throw new TimeoutException("Data not received in the specified amount of time. Increase the timeout or check the network connection");
                            }

                            if (!stream.DataAvailable)
                            {
                                Thread.Sleep(10);
                                continue;
                            }

                            int br = stream.Read(buffer, 0, 1024);
                            messageData.Append(System.Text.Encoding.UTF8.GetString(buffer, 0, br));

                            // Need to check for CR?
                            if (scanForCr)
                            {
                                receivedEOF = buffer[0] == END_TXNL;
                            }
                            else
                            {
                                // Look for FS
                                int fsPos = Array.IndexOf(buffer, (byte)END_TX);

                                if (fsPos == -1) // not found
                                {
                                    continue;
                                }
                                else if (fsPos < buffer.Length - 1) // more room to read
                                {
                                    receivedEOF = buffer[fsPos + 1] == END_TXNL;
                                }
                                else
                                {
                                    scanForCr = true; // Cannot check the end of message for CR because there is no more room in the message buffer
                                }
                                // so need to check on the next loop
                            }
                        }

                        // Use the nHAPI parser to process the data
                        Hl7MessageReceivedEventArgs messageArgs = null;
                        String originalVersion = null;

                        // Setup local and remote receive endpoint data for auditing
                        var localEp        = tcpClient.Client.LocalEndPoint as IPEndPoint;
                        var remoteEp       = tcpClient.Client.RemoteEndPoint as IPEndPoint;
                        Uri localEndpoint  = new Uri(String.Format("llp://{0}:{1}", localEp.Address, localEp.Port));
                        Uri remoteEndpoint = new Uri(String.Format("llp://{0}:{1}", remoteEp.Address, remoteEp.Port));

                        foreach (var messagePart in messageData.ToString().Split((char)END_TX))
                        {
                            if (messagePart == "\r")
                            {
                                continue;
                            }

                            try
                            {
                                this.m_traceSource.TraceInfo("Received message from llp://{0}:{1} : {2}", remoteEp.Address, remoteEp.Port, messagePart);
                                // HACK: nHAPI doesn't like URLs ... Will fix this later
                                string messageString = messagePart.Replace("|URL|", "|ST|");

                                var message = MessageUtils.ParseMessage(messageString, out originalVersion);
                                messageArgs = new Hl7MessageReceivedEventArgs(message, localEndpoint, remoteEndpoint, DateTime.Now);

                                HL7OperationContext.Current = new HL7OperationContext(messageArgs);

                                // Call any bound event handlers that there is a message available
                                OnMessageReceived(messageArgs);
                            }
                            catch (Exception e)
                            {
                                this.m_traceSource.TraceError("Error processing HL7 message: {0}", e);
                                if (messageArgs != null)
                                {
                                    var nack = new NHapi.Model.V25.Message.ACK();
                                    nack.MSH.SetDefault(messageArgs.Message.GetStructure("MSH") as NHapi.Model.V25.Segment.MSH);
                                    nack.MSA.AcknowledgmentCode.Value = "AE";
                                    nack.MSA.TextMessage.Value        = $"FATAL - {e.Message}";
                                    nack.MSA.MessageControlID.Value   = (messageArgs.Message.GetStructure("MSH") as NHapi.Model.V25.Segment.MSH).MessageControlID.Value;
                                    messageArgs.Response = nack;

                                    var icomps = PipeParser.Encode(messageArgs.Message.GetStructure("MSH") as NHapi.Base.Model.ISegment, new EncodingCharacters('|', "^~\\&")).Split('|');
                                    var ocomps = PipeParser.Encode(messageArgs.Response.GetStructure("MSH") as NHapi.Base.Model.ISegment, new EncodingCharacters('|', "^~\\&")).Split('|');
                                    AuditUtil.AuditNetworkRequestFailure(e, messageArgs.ReceiveEndpoint, Enumerable.Range(1, icomps.Length).ToDictionary(o => $"MSH-{o}", o => icomps[o - 1]), Enumerable.Range(1, icomps.Length).ToDictionary(o => $"MSH-{o}", o => ocomps[o - 1]));
                                }
                                else
                                {
                                    AuditUtil.AuditNetworkRequestFailure(e, localEndpoint, new System.Collections.Specialized.NameValueCollection(), new System.Collections.Specialized.NameValueCollection());
                                }
                            }
                            finally
                            {
                                // Send the response back
                                using (MemoryStream memoryWriter = new MemoryStream())
                                {
                                    using (StreamWriter streamWriter = new StreamWriter(memoryWriter))
                                    {
                                        memoryWriter.Write(new byte[] { START_TX }, 0, 1); // header
                                        if (messageArgs != null && messageArgs.Response != null)
                                        {
                                            var strMessage = MessageUtils.EncodeMessage(messageArgs.Response, originalVersion);
                                            this.m_traceSource.TraceInfo("Sending message to llp://{0} : {1}", tcpClient.Client.RemoteEndPoint, strMessage);
                                            // Since nHAPI only emits a string we just send that along the stream
                                            streamWriter.Write(strMessage);
                                            streamWriter.Flush();
                                        }
                                        memoryWriter.Write(new byte[] { END_TX, END_TXNL }, 0, 2); // Finish the stream with FSCR
                                        stream.Write(memoryWriter.ToArray(), 0, (int)memoryWriter.Position);
                                        stream.Flush();
                                    }
                                }
                                lastReceive = DateTime.Now; // Update the last receive time so the timeout function works
                            }
                        }

                        if (!stream.DataAvailable)
                        {
                            return;
                        }
                    }
                }
                catch (Exception e)
                {
                    this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString());
                }
                finally
                {
                    stream.Close();
                    tcpClient.Close();
                    HL7OperationContext.Current = null;
                }
            }
        }