Source code for coherence.upnp.core.msearch

# Licensed under the MIT license
# http://opensource.org/licenses/mit-license.php
#
# Copyright (C) 2006 Fluendo, S.A. (www.fluendo.com).
# Copyright 2006, Frank Scholz <coherence@beebits.net>

import socket
import time

from twisted.internet import reactor
from twisted.internet import task
from twisted.internet.protocol import DatagramProtocol

import coherence.extern.louie as louie
from coherence.upnp.core import utils

SSDP_PORT = 1900
SSDP_ADDR = '239.255.255.250'

from coherence import log


[docs]class MSearch(DatagramProtocol, log.LogAble): logCategory = 'msearch' def __init__(self, ssdp_server, test=False): log.LogAble.__init__(self) self.ssdp_server = ssdp_server if not test: self.port = reactor.listenUDP(0, self) self.double_discover_loop = task.LoopingCall(self.double_discover) self.double_discover_loop.start(120.0)
[docs] def datagramReceived(self, data, xxx_todo_changeme): (host, port) = xxx_todo_changeme if isinstance(data, bytes): data = data.decode('utf-8') cmd, headers = utils.parse_http_response(data) self.info('datagramReceived from %s:%d, protocol %s code %s', host, port, cmd[0], cmd[1]) if cmd[0].startswith('HTTP/1.') and cmd[1] == '200': self.msg('for %r', headers['usn']) if not self.ssdp_server.isKnown(headers['usn']): self.info('register as remote %s, %s, %s', headers['usn'], headers['st'], headers['location']) self.ssdp_server.register( 'remote', headers['usn'], headers['st'], headers['location'], headers['server'], headers['cache-control'], host=host) else: self.ssdp_server.known[headers['usn']][ 'last-seen'] = time.time() self.debug('updating last-seen for %r', headers['usn']) # make raw data available # send out the signal after we had a chance to register the device louie.send('UPnP.SSDP.datagram_received', None, data, host, port)
[docs] def double_discover(self): " Because it's worth it (with UDP's reliability) " self.info('send out discovery for ssdp:all') self.discover() self.discover()
[docs] def discover(self): req = ['M-SEARCH * HTTP/1.1', 'HOST: %s:%d' % (SSDP_ADDR, SSDP_PORT), 'MAN: "ssdp:discover"', 'MX: 5', 'ST: ssdp:all', '', ''] req = '\r\n'.join(req).encode('ascii') try: self.transport.write(req, (SSDP_ADDR, SSDP_PORT)) except socket.error as msg: self.info("failure sending out the discovery message: %r", msg)