Ejemplo n.º 1
0
        /**
         * Used to assemble an EbXmlMessage from the given Stream, which has been accepted from the network.
         * This expects to get the inbound HTTP stream (or at least an SslStream) from the start, because it
         * begins processing with the HTTP POST.
         */
        public EbXmlMessage(Stream instream)
        {
            // Assemble from network - note that Spine messages are NOT chunked
            //
            string headerline = null;
            Dictionary <string, string> headers = new Dictionary <string, string>();

            while ((headerline = readLine(instream)).Trim().Length != 0)
            {
                if (headerline.StartsWith("POST"))
                {
                    int firstSpace  = headerline.IndexOf(' ');
                    int secondSpace = headerline.IndexOf(' ', firstSpace + 1);
                    if ((firstSpace == -1) || (secondSpace == -1))
                    {
                        throw new Exception("Malformed HTTP request line, can't parse POST context path");
                    }
                    receivedContextPath = headerline.Substring(firstSpace, secondSpace - firstSpace);
                }
                else
                {
                    int colon = headerline.IndexOf(":");
                    if (colon == -1)
                    {
                        throw new Exception("Malformed HTTP header - no field/data delimiter colon");
                    }
                    headers.Add(headerline.Substring(0, colon).ToUpper(), headerline.Substring(colon + 1).Trim());
                }
            }
            string ctype = headers["CONTENT-TYPE"];

            if (ctype == null)
            {
                throw new Exception("Malformed HTTP headers - no Content-Type found");
            }
            if (ctype.Contains("multipart/related"))
            {
                mimeboundary = setMimeBoundary(ctype);
            }
            receivedHost = headers["HOST"];
            string clen = headers["CONTENT-LENGTH"];

            if (clen == null)
            {
                throw new Exception("Malformed HTTP headers - no Content-Length found");
            }
            int contentlength = Int32.Parse(clen);

            soapAction = headers["SOAPACTION"];
            soapAction = soapAction.Replace('"', ' ').Trim();

            // There is a bug in Spine-hosted services that turns a SOAPaction starting with
            // "urn:" into "urn:urn:" - fix this if we find it.
            //
            if (soapAction.StartsWith("urn:urn:"))
            {
                soapAction = soapAction.Substring(4);
            }

            // Read content-length bytes and parse out the various parts of the
            // received message.
            // TODO: Put in proper handling.
            //
            Byte[] wire      = new Byte[contentlength];
            int    bytesRead = 0;

            while (bytesRead < contentlength)
            {
                bytesRead += instream.Read(wire, bytesRead, contentlength - bytesRead);
            }
            string msg = Encoding.UTF8.GetString(wire);

            // Split on the mimeboundary. "msg" doesn't contain the HTTP headers so we should
            // just be able to walk through the attachments. If we can't, report an exception
            //
            int startPosition = msg.IndexOf(mimeboundary, 0);

            if (startPosition == -1)
            {
                // Need to handle the case where the content is
                // actually an asynchronous ebXML ack.
                //
                // If content-type is text/xml and soapaction contains Acknowledgment or MessageError,
                // it is an ack/nack. If we get one of these we need to log it and tell the connection
                // manager about it. But we don't need to do any further processing.
                //
                if (ctype.ToLower().StartsWith("text/xml"))
                {
                    if (soapAction.Contains("Acknowledgment"))
                    {
                        // Remove from requests, and exit
                        string a = EbXmlAcknowledgment.getAckedMessageId(msg);
                        if (a == null)
                        {
                            EventLog logger = new EventLog("Application");
                            logger.Source = ConnectionManager.LOGSOURCE;
                            StringBuilder sb = new StringBuilder("Failed to extract message id reference from Acknowledgment: ");
                            sb.Append(msg);
                            logger.WriteEntry(sb.ToString(), EventLogEntryType.Error);
                            return;
                        }
                        ConnectionManager cm = ConnectionManager.getInstance();
                        cm.registerAck(a);
                        return;
                    }
                    if (soapAction.Contains("MessageError"))
                    {
                        // Remove from requests, and exit
                        string a = EbXmlAcknowledgment.getAckedMessageId(msg);
                        if (a == null)
                        {
                            EventLog logger = new EventLog("Application");
                            logger.Source = ConnectionManager.LOGSOURCE;
                            StringBuilder sb = new StringBuilder("Failed to extract message id reference from MessageError: ");
                            sb.Append(msg);
                            logger.WriteEntry(sb.ToString(), EventLogEntryType.Error);
                            return;
                        }
                        EventLog l = new EventLog("Application");
                        l.Source = ConnectionManager.LOGSOURCE;
                        StringBuilder sbe = new StringBuilder("EbXML MessageError received: ");
                        sbe.Append(msg);
                        l.WriteEntry(sbe.ToString(), EventLogEntryType.Error);

                        ConnectionManager cm = ConnectionManager.getInstance();
                        cm.registerAck(a);
                        return;
                    }
                }
                throw new Exception("Malformed message");
            }
            int  endPosition    = 0;
            int  partCount      = 0;
            bool gotEndBoundary = false;

            do
            {
                startPosition += mimeboundary.Length;
                endPosition    = msg.IndexOf(mimeboundary, startPosition);
                if (endPosition == -1)
                {
                    gotEndBoundary = true;
                }
                else
                {
                    switch (partCount)
                    {
                    case 0:
                        header = new EbXmlHeader(msg.Substring(startPosition, endPosition - startPosition));
                        if (header.Timestamp != null)
                        {
                            started = DateTime.Parse(header.Timestamp);
                            // We don't know how many attempts were actually made, so assume
                            // only one try at the start time.
                            //
                            lastTry = DateTime.Parse(header.Timestamp);
                            tries   = 1;
                        }
                        break;

                    case 1:
                        hl7message = new SpineHL7Message(msg.Substring(startPosition, endPosition - startPosition));
                        break;

                    default:
                        if (attachments == null)
                        {
                            attachments = new List <Attachment>();
                        }
                        // IMPROVEMENT: Make this more flexible to be able to support multiple types of
                        // ITK trunk message, just in case
                        //
                        if (soapAction.Contains("COPC_IN000001GB01"))
                        {
                            attachments.Add(new ITKDistributionEnvelopeAttachment(msg.Substring(startPosition, endPosition - startPosition)));
                        }
                        else
                        {
                            attachments.Add(new GeneralAttachment(msg.Substring(startPosition, endPosition - startPosition)));
                        }
                        break;
                    }
                    partCount++;
                    startPosition = endPosition;
                }
            }while (!gotEndBoundary);
//            persistDuration = (int)(ConnectionManager.getInstance().getPersistDuration(header.SvcIA).TotalSeconds);
        }
Ejemplo n.º 2
0
        /**
         * Checks to see if the given EbXmlMessage is acknowledged asynchronously, and just returns
         * if not. Otherwise, constructs an EbXMLAcknowledgment addressed to the sender of "msg",
         * and calls the ConnectionManager to send it.
         *
         * @param EbXmlMessage to acknowledge
         */
        private void doAsynchronousAck(EbXmlMessage msg)
        {
            if (msg == null)
                return;
            if (!msg.Header.DuplicateElimination)
                return;
            if (msg.Header.SyncReply)
                return;

            StringBuilder a = new StringBuilder(makeEbXmlAck(msg, false));
            ConnectionManager cm = ConnectionManager.getInstance();
            SDSconnection sds = cm.SdsConnection;
            string ods = msg.Header.FromPartyKey.Substring(0, msg.Header.FromPartyKey.IndexOf("-"));
            List<SdsTransmissionDetails> sdsdetails = sds.getTransmissionDetails(ACKSERVICE, ods, null, msg.Header.FromPartyKey);
            a.Replace("__CPA_ID__", sdsdetails[0].CPAid);
            EbXmlAcknowledgment ack = new EbXmlAcknowledgment(a.ToString());
            ack.setHost(sdsdetails[0].Url);
            cm.send(ack, sdsdetails[0]);
        }