예제 #1
0
    def __call__(self, *args, **kwargs):
        msg = SoapMessage(self.service.serviceType, self.name)

        # see it there is an async flag, defaults to False
        async = bool('async' in kwargs and kwargs.pop('async'))

        # there may be a starting deferred also; only relevant
        # if in async mode
        deferred = (async and 'deferred' in kwargs) and kwargs.pop('deferred') or None

        # update the message with input argument values
        for arg in self.inargs:
            val = kwargs.get(arg.name)
            if val is None:
                raise KeyError('Missing IN argument: %s' % (arg.name, ))
            msg.set_arg(arg.name, val)

        # send the message
        result = self._soap_sender(self.service.device, self.service.controlURL,
                                   msg, async=async, deferred=deferred)

        if async:
            # assume it's a Deferred
            result.addCallback(decode_soap, self.outargs)
            return result
        else:
            return decode_soap(result, self.outargs)
예제 #2
0
def send_soap_message(url, msg, mpost=False):
    """
    Send a SOAP message to the given URL.
    
    The HTTP headers mandated by the UPnP specification are added. Also, if
    posting fails with a 405 error, another attempt is made with slightly
    different headers and method set to M-POST.

    Return a SoapMessage or a SoapError, depending on the outcome of the call.

    Raise a urllib2.URLError or a urllib2.HTTPError if something goes wrong.

    """
    req = MPOSTRequest(url) if mpost else urllib2.Request(url)

    # add headers to the request
    req.add_header('CONTENT-TYPE', 'text/xml; charset="utf-8"')
    req.add_header('USER-AGENT', 'OS/1.0 UPnP/1.0 airpnp/1.0')
    if mpost:
        req.add_header('MAN',
                       '"http://schemas.xmlsoap.org/soap/envelope/"; ns=01')
        req.add_header('01-SOAPACTION', msg.get_header())
    else:
        req.add_header('SOAPACTION', msg.get_header())

    # add the SOAP message as data
    req.add_data(msg.tostring().encode("utf-8"))

    try:
        handle = urllib2.urlopen(req)
        response = SoapMessage.parse(handle)
    except urllib2.HTTPError, err:
        if err.code == 405 and not mpost:
            log.msg('Got 405 response in response to SOAP message, trying' +
                    'the M-POST way', ll=2)
            return send_soap_message(url, msg, True)
        elif err.code == 500:
            # SOAP error
            response = SoapError.parse(err.read())
        else:
            log.err(err, 'Failed to send SOAP message')
            raise err