Пример #1
0
 def handle(self):
     try:
         request_data = self.rfile.read()
         # LOGGER.debug('Received message from address: {}; Data:\n{}', self.client_address, request_data)
         # Todo: check MX value and wait until about half of timeout, and ignore all others same requests
         if request_data.startswith(
                 b'M-SEARCH'
         ) and b'urn:dial-multiscreen-org:service:dial:1' in request_data:
             LOGGER_UDP.debug(
                 'Received [M-SEARCH] message from address: {}; Data:\n{}',
                 self.client_address, request_data)
             # Build the M-SEARCH response message
             response_data = ssdp_msgs.SEARCH_RESPONSE.format(
                 ip_addr=kodi_ops.get_local_ip(),
                 port=G.DIAL_SERVER_PORT,  # G.SSDP_SERVER_PORT,
                 date_timestamp=formatdate(timeval=None,
                                           localtime=False,
                                           usegmt=True),
                 device_uuid=G.DEVICE_UUID,
                 boot_id=G.sp_upnp_boot_id)
             # Send reply to the client
             LOGGER_UDP.debug('Sending reply message to {}; Data:\n{}',
                              self.client_address, response_data)
             self.wfile.write(
                 utils.fix_return_chars(response_data).encode('ascii'))
             # G.sp_upnp_boot_id += 1
     except Exception as exc:
         LOGGER_UDP.error(
             'An error occurred while processing the request\nError: {}\nAddress: {}',
             exc, self.client_address)
Пример #2
0
def handle_dd(server):
    """Handle SSDP HTTP request for device descriptor xml"""
    data = ssdp_msgs.DD_XML.format(ip_addr=kodi_ops.get_local_ip(),
                                   dial_port=G.DIAL_SERVER_PORT,
                                   friendly_name=G.SP_FRIENDLY_NAME,
                                   manufacturer_name=G.SP_MANUFACTURER_NAME,
                                   model_name=G.SP_MODEL_NAME,
                                   device_uuid=G.DEVICE_UUID)
    server.call_response(utils.fix_return_chars(data))
Пример #3
0
 def server_bind(self):
     try:  # Allow multiple sockets to use the same port
         if hasattr(socket, "SO_REUSEADDR"):
             self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
                                    1)
     except Exception as exc:
         LOGGER_UDP.error('Set socket option SO_REUSEADDR error: {}', exc)
     self.socket.bind(('0.0.0.0', G.SSDP_UPNP_PORT))
     self.socket.setsockopt(
         socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
         socket.inet_aton(G.SSDP_BROADCAST_ADDR) +
         socket.inet_aton(kodi_ops.get_local_ip()))
Пример #4
0
def handle_app_start(server, app_name, origin_header):
    additional_data_param = None
    if not MUTEX.acquire(False):
        server.call_error(500, '500 Internal Server Error')
        return
    app = find_app(app_name)
    if not app:
        server.call_error(404, 'Not found')
        MUTEX.release()
        return
    elif server.body_data_size > DIAL_MAX_PAYLOAD:
        server.call_error(413, '413 Request Entity Too Large')
    # Checks if a payload string contains invalid characters (unprintable or non-ASCII character)
    elif not utils.is_ascii(server.body_data):
        server.call_error(400, '400 Bad Request')
    else:
        if app.USE_ADDITIONAL_DATA:
            # Construct additionalDataUrl=http://host:port/apps/app_name/dial_data
            additional_data_param = 'http://127.0.0.1:{port}/apps/{app_name}/dial_data'.format(
                port=G.DIAL_SERVER_PORT, app_name=app_name)
            if utils.get_string_size(
                    additional_data_param) > DIAL_MAX_ADDITIONALURL:
                LOGGER.error('Exceeded maximum size for additional_data_param')
                server.call_error(500, '500 Internal Server Error')
                MUTEX.release()
                return
        payload = server.body_data.decode('utf-8')
        LOGGER.debug('Starting app {} with params {}', app_name, payload)
        app.state = app.dial_cb_start(deepcopy(payload), server.query_params,
                                      additional_data_param)
        if app.state == DialStatus.RUNNING:
            server.call_response(
                CREATED_RESPONSE.format(address=kodi_ops.get_local_ip(),
                                        dial_port=G.DIAL_SERVER_PORT,
                                        app_name=app_name,
                                        origin=origin_header))
            # Make a backup copy of the payload
            app.last_payload = payload
        elif app.state == DialStatus.ERROR_FORBIDDEN:
            server.call_error(400, '403 Forbidden')
        elif app.state == DialStatus.ERROR_UNAUTH:
            server.call_error(401, '401 Unauthorized')
        elif app.state == DialStatus.ERROR_NOT_IMPLEMENTED:
            server.call_error(501, '501 Not Implemented')
        else:
            server.call_error(503, '503 Service Unavailable')
    MUTEX.release()
Пример #5
0
def send_advertisement(message):
    """Broadcast SSDP message"""
    # NOTICE: These messages are not handled by all mobile apps,
    #         some apps handle server status changes "themselves" and other apps wait these messages,
    #         all standard UPnP header fields seem not required
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
                           socket.IPPROTO_UDP) as sock:
            try:  # Allow multiple sockets to use the same port
                if hasattr(socket, "SO_REUSEADDR"):
                    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            except Exception as exc:
                LOGGER_UDP.error('Set socket option SO_REUSEADDR error: {}',
                                 exc)
            sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
            sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
            sock.settimeout(3)
            sock.connect((G.SSDP_BROADCAST_ADDR, G.SSDP_UPNP_PORT))
            # Fill the key parameters of the message
            # (we add all the keys for all types of messages, only those needed for the message will be taken)
            data = message.format_map(
                utils.FormatMapSubCls(
                    udp_ip_addr=G.SSDP_BROADCAST_ADDR,
                    udp_port=G.SSDP_UPNP_PORT,
                    ip_addr=kodi_ops.get_local_ip(),
                    port=G.DIAL_SERVER_PORT,  # G.SSDP_SERVER_PORT,
                    device_uuid=G.DEVICE_UUID))
            sock.sendall(utils.fix_return_chars(data).encode('ascii'))
            LOGGER_UDP.debug('Sent advertisement message with data:\n{}', data)
    except socket.timeout as exc:
        LOGGER_UDP.error('Socket timeout error on send advertisement message')
        LOGGER_UDP.debug('Error: {}\nOn sending data:\n{}', exc, message)
    except socket.error as exc:
        LOGGER_UDP.error('Socket error on send advertisement message')
        LOGGER_UDP.debug('Error: {}\nOn sending data:\n{}', exc, message)
    except Exception as exc:
        LOGGER_UDP.error('Error: {}\nOn sending data:\n{}', exc, message)