Пример #1
0
        /// <summary>
        /// Receive and process message
        /// </summary>
        protected virtual void OnReceiveMessage(object client)
        {
            TcpClient     tcpClient = client as TcpClient;
            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;
                    try
                    {
                        // 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));

#if DEBUG
                        this.m_traceSource.TraceInfo("Received message from llp://{0}:{1} : {2}", remoteEp.Address, remoteEp.Port, messageData);
#endif

                        // HACK: nHAPI doesn't like URLs ... Will fix this later
                        string messageString = messageData.ToString().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);
                    }
                    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);
#if DEBUG
                                    this.m_traceSource.TraceInfo("Sending message to llp://{0} : {1}", tcpClient.Client.RemoteEndPoint, strMessage);
#endif
                                    // 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
                    }
                }
            }
            catch (Exception e)
            {
                this.m_traceSource.TraceEvent(EventLevel.Error, e.ToString());
            }
            finally
            {
                stream.Close();
                tcpClient.Close();
                HL7OperationContext.Current = null;
            }
        }
Пример #2
0
        /// <summary>
        /// Send a message and receive the message
        /// </summary>
        public IMessage SendAndReceive(IMessage message)
        {
            // Encode the message
            var strMessage = MessageUtils.EncodeMessage(message, (message.GetStructure("MSH") as NHapi.Model.V25.Segment.MSH).VersionID.VersionID.Value);

#if DEBUG
            this.tracer.TraceEvent(EventLevel.Informational, strMessage);
#endif

            // Open a TCP port
            using (var client = new TcpClient(AddressFamily.InterNetwork))
            {
                try
                {
                    // Connect on the socket
                    client.Connect(this.endpoint.Host, this.endpoint.Port);

                    // Get the stream
                    using (var stream = client.GetStream())
                    {
                        Stream realStream = stream;

                        if (this.clientCertificate != null)
                        {
                            realStream = new SslStream(stream, false, this.RemoteCertificateValidation);

                            var collection = new X509CertificateCollection
                            {
                                this.clientCertificate
                            };

                            ((SslStream)realStream).AuthenticateAsClient(this.endpoint.ToString(), collection, System.Security.Authentication.SslProtocols.Tls, true);
                        }

                        // Write message in ASCII encoding
                        byte[] buffer     = Encoding.UTF8.GetBytes(strMessage);
                        byte[] sendBuffer = new byte[buffer.Length + 3];

                        sendBuffer[0] = 0x0b;

                        Array.Copy(buffer, 0, sendBuffer, 1, buffer.Length);
                        Array.Copy(new byte[] { 0x1c, 0x0d }, 0, sendBuffer, sendBuffer.Length - 2, 2);

                        stream.Write(sendBuffer, 0, sendBuffer.Length);

                        // Write end message
                        stream.Flush();                         // Ensure all bytes get sent down the wire

                        // Now read the response
                        StringBuilder response = new StringBuilder();

                        buffer = new byte[1024];

                        while (!buffer.Contains((byte)0x1c))                         // HACK: Keep reading until the buffer has the FS character
                        {
                            int br = stream.Read(buffer, 0, 1024);

                            int ofs = 0;

                            if (buffer[ofs] == '\v')
                            {
                                ofs = 1;
                                br  = br - 1;
                            }

                            response.Append(Encoding.UTF8.GetString(buffer, ofs, br));
                        }

#if DEBUG
                        this.tracer.TraceEvent(EventLevel.Informational, response.ToString());
#endif
                        String version = null;
                        return(MessageUtils.ParseMessage(response.ToString(), out version));
                    }
                }
                catch (Exception e)
                {
#if DEBUG
                    this.tracer.TraceEvent(EventLevel.Error, e.StackTrace);
#endif
                    this.tracer.TraceEvent(EventLevel.Error, e.Message);

                    throw;
                }
            }
        }
Пример #3
0
 /// <summary>
 /// Represent message as string
 /// </summary>
 public static String ToString(IMessage msg)
 {
     return(MessageUtils.EncodeMessage(msg, "2.5"));
 }
Пример #4
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;
                }
            }
        }