예제 #1
0
        /// <summary>
        /// Encodes a call of the specified <paramref name="action"/> with the given <paramref name="inParamValues"/> and
        /// returns the resulting SOAP XML string.
        /// </summary>
        /// <param name="action">Action to be called.</param>
        /// <param name="inParamValues">List of parameter values which must match the action's signature.
        /// Can be <c>null</c> if the parameter list is empty.</param>
        /// <param name="upnpVersion">UPnP version to use for the encoding.</param>
        /// <returns>XML string which contains the SOAP document.</returns>
        public static string EncodeCall(CpAction action, IList <object> inParamValues, UPnPVersion upnpVersion)
        {
            bool          targetSupportsUPnP11 = upnpVersion.VerMin >= 1;
            StringBuilder result = new StringBuilder(5000);

            using (StringWriterWithEncoding stringWriter = new StringWriterWithEncoding(result, UPnPConsts.UTF8_NO_BOM))
                using (XmlWriter writer = XmlWriter.Create(stringWriter, UPnPConfiguration.DEFAULT_XML_WRITER_SETTINGS))
                {
                    SoapHelper.WriteSoapEnvelopeStart(writer, true);
                    writer.WriteStartElement("u", action.Name, action.ParentService.ServiceTypeVersion_URN);

                    // Check input parameters
                    IList <CpArgument> formalArguments = action.InArguments;
                    if (inParamValues == null)
                    {
                        inParamValues = EMPTY_OBJECT_LIST;
                    }
                    if (inParamValues.Count != formalArguments.Count)
                    {
                        throw new ArgumentException("Invalid argument count");
                    }
                    for (int i = 0; i < formalArguments.Count; i++)
                    {
                        CpArgument argument = formalArguments[i];
                        object     value    = inParamValues[i];
                        writer.WriteStartElement(argument.Name);
                        argument.SoapSerializeArgument(value, !targetSupportsUPnP11, writer);
                        writer.WriteEndElement(); // argument.Name
                    }
                    SoapHelper.WriteSoapEnvelopeEndAndClose(writer);
                }
            return(result.ToString());
        }
예제 #2
0
        protected static IList <object> ParseResult(TextReader textReader, CpAction action, bool sourceSupportsUPnP11)
        {
            object[] outParameterValues = new object[action.OutArguments.Count];
            using (XmlReader reader = XmlReader.Create(textReader, UPnPConfiguration.DEFAULT_XML_READER_SETTINGS))
            {
                reader.MoveToContent();
                // Parse SOAP envelope
                reader.ReadStartElement("Envelope", UPnPConsts.NS_SOAP_ENVELOPE);
                reader.ReadStartElement("Body", UPnPConsts.NS_SOAP_ENVELOPE);
                // Reader is positioned at the action element
                string serviceTypeVersion_URN = reader.NamespaceURI;
                string type;
                int    version;
                // Parse service and action
                if (!ParserHelper.TryParseTypeVersion_URN(serviceTypeVersion_URN, out type, out version))
                {
                    throw new ArgumentException("Invalid service type or version");
                }
                string actionName = reader.LocalName;
                if (!actionName.EndsWith("Response") ||
                    actionName.Substring(0, actionName.Length - "Response".Length) != action.Name)
                {
                    throw new ArgumentException("Invalid action name in result message");
                }

                // UPnP spec says we have to be able to handle return values being out
                // of order to support UPnP 1.0 devices. See UPnP-arch-DeviceArchitecture-v1.1
                // section 2.5.4. We need a dictionary to make this easy.
                IDictionary <string, int> formalArgIdxDictionary = new Dictionary <string, int>();
                for (int i = 0; i < action.OutArguments.Count; i++)
                {
                    formalArgIdxDictionary.Add(action.OutArguments[i].Name, i);
                }

                int outArgCount = 0;
                if (!SoapHelper.ReadEmptyStartElement(reader))
                {
                    // Parse and check output parameters
                    while (reader.NodeType != XmlNodeType.EndElement)
                    {
                        string argumentName = reader.Name; // Arguments don't have a namespace, so take full name
                        int    formalArgumentIndex;
                        if (!formalArgIdxDictionary.TryGetValue(argumentName, out formalArgumentIndex))
                        {
                            throw new ArgumentException("Invalid argument name");
                        }
                        CpArgument formalArgument = action.OutArguments[formalArgumentIndex];

                        // Get the argument value and store it in the correct position in the return list.
                        object value = null;
                        if (!SoapHelper.ReadNull(reader))
                        {
                            formalArgument.SoapParseArgument(reader, !sourceSupportsUPnP11, out value);
                        }
                        outParameterValues[formalArgumentIndex] = value;
                        outArgCount++;

                        // Don't allow duplicates of the same argument.
                        formalArgIdxDictionary.Remove(formalArgument.Name);
                    }
                }
                if (outArgCount != action.OutArguments.Count) // Too few arguments
                {
                    throw new ArgumentException("Invalid out argument count");
                }
            }
            return(outParameterValues);
        }