Example #1
0
        /// <summary>
        /// Send an Http request containing an mtom message to an endpoint and waits for a response.
        /// </summary>
        /// <param name="bodyParts">A reference to the WsMtomBodyParts collection used to generate a mime multipart message.</param>
        /// <param name="endpointAddress">A string containing the endpoint address of a service that will receive
        /// <param name="isOneway">True = don't wait for response, false means wait for a response.</param>
        /// <param name="isChuncked">If true true the message will be chunk encoded.</param>
        /// <returns>
        /// A DpwSoapResponse object containing a WsWsaHeader and an XmlReader or null if no response is received
        /// or parsing fails.
        /// </returns>
        public DpwsSoapResponse SendRequest(ref WsMtomBodyParts bodyParts, string endpointAddress, bool isOneWay, bool isChuncked)
        {
            WsMtomParams mtomParams = new WsMtomParams();
            if (bodyParts.Boundary == null)
                bodyParts.Boundary = Guid.NewGuid().ToString() + '-' + Guid.NewGuid().ToString().Substring(0, 33);
            mtomParams.start = bodyParts.Start;
            mtomParams.boundary = bodyParts.Boundary;
            WsMtom mtom = new WsMtom();
            byte[] message = mtom.CreateMessage(bodyParts);
            WsMessage response = SendRequest(message, endpointAddress, isOneWay, isChuncked, mtomParams);
            if (isOneWay)
                return null;

            XmlReader reader;
            WsWsaHeader header;
            try
            {
                reader = WsSoapMessageParser.ParseSoapMessage(response.Message, out header);
                bodyParts = response.BodyParts;
            }
            catch
            {
                System.Ext.Console.Write("ParseSoapMessage failed.");
                return null;
            }

            return new DpwsSoapResponse(header, reader);
        }
        /// <summary>
        /// Processes a message 
        /// </summary>
        /// <param name="msg">The message being processed.</param>
        /// <param name="ctx">The context associated with the message.</param>
        /// <returns>The handling status for this operation.</returns>
        protected override ChainResult OnProcessOutputMessage( ref WsMessage msg, BindingContext ctx )
        {
            byte[] data = null;

            // if the body is a byte[] then it is already serialized (UDP stuff)
            if (msg == null || (msg.Body != null && msg.Body is byte[])) return ChainResult.Continue;

            // Build response message
            using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                WsSoapMessageWriter smw = new WsSoapMessageWriter(ctx.Version);

                // Write start message up to body element content
                smw.WriteSoapMessageStart(xmlWriter, msg, ctx.Version.IncludeSoapHeaders);

                if (msg.Body != null && msg.Serializer != null)
                {
                    DataContractSerializer ser = (DataContractSerializer)msg.Serializer;
                    // Serialize the body element
                    ser.WriteObject(xmlWriter, msg.Body);

                    if(ser.BodyParts != null && ser.BodyParts.Count > 0)
                    {
                        msg.BodyParts = ser.BodyParts;
                    }
                }

                // Write end message
                smw.WriteSoapMessageEnd(xmlWriter);

                data = xmlWriter.ToArray();
            }

            WsMtomBodyParts bodyParts = msg.BodyParts;

            if (bodyParts != null)
            {
                DataContractSerializer reqDcs = (DataContractSerializer)msg.Serializer;

                bodyParts.Start = "<soap@soap>";
                bodyParts.AddStart(reqDcs.CreateNewBodyPart(data, bodyParts.Start));
                if (reqDcs.BodyParts.Count > 0)
                {
                    bodyParts.Add(reqDcs.BodyParts[0]);
                }

                WsMtomParams mtomParams = new WsMtomParams();
                if (bodyParts.Boundary == null)
                    bodyParts.Boundary = Guid.NewGuid().ToString() + '-' + Guid.NewGuid().ToString().Substring(0, 33);
                mtomParams.start = bodyParts.Start;
                mtomParams.boundary = bodyParts.Boundary;
                msg.MtomPropeties = mtomParams;
                WsMtom mtom = new WsMtom();
                data = mtom.CreateMessage(bodyParts);
            }

            msg.Body = data;

            return ChainResult.Continue;
        }
Example #3
0
        /// <summary>
        /// Method used to send a soap request over http to a service endpoint.
        /// </summary>
        /// <param name="soapMessage">A byte array contining a soap request message.</param>
        /// <param name="endpointAddress">A string containing the endpoint address of a service that will receive
        /// the request. This must be a transport address in the format http://ip_address:port/service_address.</param>
        /// <param name="isOneway">True = don't wait for response, false means wait for a response.</param>
        /// <param name="isChuncked">If true true the message will be chunk encoded.</param>
        /// <param name="mtomParams">If not null contains parameters required to fix up the http header for mime multipart.</param>
        /// <returns>WsMessage object containing the soap response returned from a service endpoint.</returns>
        private WsMessage SendRequest(byte[] soapMessage, string endpointAddress, bool isOneway, bool isChuncked, WsMtomParams mtomParams)
        {
            if (soapMessage == null)
                throw new ArgumentNullException("DpwsHttpClient.SendRequest - soapMessage must not be null.");
            if (endpointAddress == null)
                throw new ArgumentNullException("DpwsHttpClient.SendRequest - endpointAddress must not be null.");

            // Send the request
            WsMessage response = m_httpClient.SendRequest(soapMessage, endpointAddress, isOneway, isChuncked, mtomParams);

            return response;
        }
Example #4
0
        /// <summary>
        /// Verifies values of specific headers.
        /// </summary>
        /// <returns>True if parsing is successful</returns>
        private bool ProcessKnownHeaders()
        {
            HttpStatusCode errorCode = 0;
            string errorName = "";
            // The HTTP methid should be GET or POST
            if (m_httpRequest.HttpMethod != "POST" && m_httpRequest.HttpMethod != "GET")
            {
                errorCode = HttpStatusCode.NotImplemented;
            }

            // HTTP version should be 1.1
            if (m_httpRequest.ProtocolVersion != HttpVersion.Version11)
            {
                errorCode = HttpStatusCode.BadRequest;
            }

            if (m_httpRequest.ContentLength64 > WsHttpServiceHost.MaxReadPayload)
            {
                errorCode = HttpStatusCode.Forbidden; // 403
                errorName = HttpKnownHeaderNames.ContentLength;
            }

            WebHeaderCollection webHeaders = (System.Net.WebHeaderCollection)m_httpRequest.Headers;
            string strChunked = webHeaders[HttpKnownHeaderNames.TransferEncoding];
            if (strChunked != null)
            {
                if (strChunked == "chunked")
                {
                    m_chunked = true;
                }
                else
                {
                    errorCode = HttpStatusCode.NotFound; // 404
                    errorName = HttpKnownHeaderNames.TransferEncoding;
                }
            }

            string strContentType = m_httpRequest.ContentType;
            if (strContentType != null)
            {
                strContentType = strContentType.ToLower();
                
                if (strContentType.IndexOf("multipart/related;") == 0)
                {
                    // Create the mtom header class
                    m_mtomHeader = new WsMtomParams();

                    // Parse Mtom Content-Type parameters
                    string[] fields = strContentType.Substring(18).Split(';');
                    int fieldsLen = fields.Length;
                    for (int i = 0; i < fieldsLen; ++i)
                    {
                        string[] param = fields[i].Split('=');
                        if (param.Length > 1)
                        {
                            switch (param[0].ToUpper())
                            {
                                case "BOUNDARY":
                                    if (param[1].Length > 72)
                                        throw new ArgumentException("Mime boundary element length exceeded.", "boundary");
                                    m_mtomHeader.boundary = param[1];
                                    break;
                                case "TYPE":
                                    m_mtomHeader.type = param[1];
                                    break;
                                case "START":
                                    m_mtomHeader.start = param[1];
                                    break;
                                case "START-INFO":
                                    m_mtomHeader.startInfo = param[1];
                                    break;
                                default:
                                    break;
                            }
                        }
                    }

                    // Check required Mtom fields
                    if (m_mtomHeader.boundary == null || m_mtomHeader.type == null || m_mtomHeader.start == null)
                    {
                        errorCode = HttpStatusCode.NotFound;
                        errorName = HttpKnownHeaderNames.ContentType;
                    }
                }
                else if (strContentType.IndexOf("application/soap+xml") != 0)
                {
                    errorCode = HttpStatusCode.NotFound;
                    errorName = HttpKnownHeaderNames.ContentType;
                }
            }

            string strMimeVersion = webHeaders["Mime-Version"];
            if (strMimeVersion != null)
            {
                if (strMimeVersion != "1.0")
                {
                    errorCode = HttpStatusCode.NotFound;
                    errorName = "Mime-Version";
                }
            }

            if (errorCode != 0)
            {
                SendError((int)errorCode, errorName);
                return false;
            }

            return true;
        }
Example #5
0
 /// <summary>
 /// Releases all resources used by the HttpProcess object.
 /// </summary>
 public void Dispose()
 {
     m_mtomHeader = null;
     m_httpResponse.Close();
     GC.SuppressFinalize(this);
 }
Example #6
0
        /// <summary>
        /// Send an Http request to an endpoint and waits for a response.
        /// </summary>
        /// <param name="soapMessage">A byte array containing the soap message to be sent.</param>
        /// <param name="remoteEndpoint">A sting containing the name of a remote listening endpoint.</param>
        /// <param name="isOneWay">A parameter used to specify if this is a one way transaction.</param>
        /// <param name="isChuncked">If true true the message will be chunk encoded.</param>
        /// <param name="mtomParams">If not null contains parameters required to fix up the http header for mime multipart.</param>
        /// <returns>WsMessage object containing the soap response returned from a service endpoint.</returns>
        internal WsMessage SendRequest(byte[] soapMessage, string remoteEndpoint, bool isOneWay, bool isChuncked, WsMtomParams mtomParams)
        {
            System.Ext.Console.Write("Executing Send Request");

            HttpWebRequest request = HttpWebRequest.Create(remoteEndpoint) as HttpWebRequest;

            request.Timeout = RequestTimeout;
            request.ReadWriteTimeout = (ReceiveTimeout > SendTimeOut) ? ReceiveTimeout : SendTimeOut;
            
            // Post method
            request.Method = "POST";

            // If the message is Mtom
            if (mtomParams != null)
            {
                request.Headers.Add("Mime-Version", "1.0");
                request.ContentType = "Multipart/Related;boundary=" +
                    mtomParams.boundary +
                    ";type=\"application/xop+xml\";start=\"" +
                    mtomParams.start +
                    "\";start-info=\"application/soap+xml\"";
                request.Headers.Add("Content-Description", "WSDAPI MIME multipart");
            }
            else
            {
                request.ContentType = "application/soap+xml; charset=utf-8";
            }

            request.UserAgent = "MFWsAPI";
            request.KeepAlive = !isOneWay;

            request.Headers.Add("Cache-Control", "no-cache");
            request.Headers.Add("Pragma", "no-cache");

            // Not chunked. We know the full length of the content and send in one chunk.
            if (!isChuncked)
            {
                request.ContentLength = soapMessage.Length;

            }
            else // Set chunked property or content length on request.
            {
                System.Ext.Console.Write("Not supported");

            }

            // Now sending the message. GetRequestStream actually sends the headers.
            
            using(Stream reqStream = request.GetRequestStream())
            {
                // Write soap message
                reqStream.Write(soapMessage, 0, soapMessage.Length);
                // Flush the stream and force a write
                reqStream.Flush();
            
                // Reset the encoding flags
                m_mtomHeader = null;

                if (!isOneWay)
                {   // Get response, check the fields

                    HttpWebResponse resp = request.GetResponse() as HttpWebResponse;
                   
                    if (resp == null)
                    {
                        throw new WebException("No response was received on the HTTP channel", WebExceptionStatus.ReceiveFailure);
                    }
                    
                    try                    
                    {
                        if (resp.ProtocolVersion != HttpVersion.Version11)
                        {
                            throw new IOException("Invalid http version in response line.");
                        }

                        if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.Accepted)
                        {
                            throw new IOException("Bad status code in response: " + resp.StatusCode);
                        }

                        if (resp.ContentLength > 0)
                        {
                            
                            // Return the soap response.
                            byte[] soapResponse = new byte[resp.ContentLength];
                            Stream respStream = resp.GetResponseStream();

                            // Now need to read all data. We read in the loop until resp.ContentLength or zero bytes read.
                            // Zero bytes read means there was error on server and it did not send all data.
                            int respLength = (int)resp.ContentLength;
                            for (int totalBytesRead = 0; totalBytesRead < respLength; )
                            {
                                int bytesRead = respStream.Read(soapResponse, totalBytesRead, (int)resp.ContentLength - totalBytesRead);
                                // If nothing is read - means server closed connection or timeout. In this case no retry.
                                if (bytesRead == 0)
                                {
                                    break;
                                }

                                // Adds number of bytes read on this iteration.
                                totalBytesRead += bytesRead;
                            }

                            // If this is Mtom process the header
                            if (resp.Headers[HttpKnownHeaderNames.ContentType].ToLower().IndexOf("multipart/related;") != -1)
                            {
                                m_mtomHeader = ProcessMtomHeader(resp.Headers[HttpKnownHeaderNames.ContentType]);
                            }

                            WsMessage message;
                            if (m_mtomHeader != null)
                                message = new WsMessage(soapResponse, m_mtomHeader.boundary, m_mtomHeader.start);
                            else
                                message = new WsMessage(soapResponse);

                            return message;
                        }
                        //
                        // ContentLenght == 0 is OK
                        //
                        else if(resp.ContentLength < 0)
                        {
                            throw new ProtocolViolationException("Invalid http header, content length: " + resp.ContentLength);
                        }
                    }
                    finally
                    {
                        if(resp != null)
                        {
                            resp.Dispose();
                        }
                    }
                }
            }

            return null;
        }
Example #7
0
        WsMtomParams ProcessMtomHeader(string mtomHeaderValue)
        {
            // Create the mtom header class
            WsMtomParams mtomHeader = new WsMtomParams();

            // Parse Mtom Content-Type parameters
            string[] fields = mtomHeaderValue.Substring(18).Split(';');
            int fieldsLen = fields.Length;
            for (int i = 0; i < fieldsLen; ++i)
            {
                string[] param = fields[i].Split('=');
                if (param.Length > 1)
                {
                    switch (param[0].ToUpper())
                    {
                        case "BOUNDARY":
                            if (param[1].Length > 72)
                                throw new ArgumentException("Mime boundary element length exceeded.", "boundary");
                            mtomHeader.boundary = param[1];
                            break;
                        case "TYPE":
                            mtomHeader.type = param[1];
                            break;
                        case "START":
                            mtomHeader.start = param[1];
                            break;
                        case "START-INFO":
                            mtomHeader.startInfo = param[1];
                            break;
                        default:
                            break;
                    }
                }
            }

            // Check required Mtom fields
            if (mtomHeader.boundary == null || mtomHeader.type == null || mtomHeader.start == null)
            {
                throw new ArgumentException("Bad content-type http response header. ErrorCode: 404");
            }

            return mtomHeader;
        }