コード例 #1
0
ファイル: atsc.py プロジェクト: arantius/tvheadend-locast
    def update_sdt_names(self, _sdt_msg, _service_provider, _service_name):
        # must start with x474011  (pid for SDT is x0011
        # update the full msg length 2 bytes with first 4 bits as xF at position 7-8  (includes crc)
        # update descriptor length lower 12 bits at position 20-21 (remaining bytes - crc)
        # x48 service descriptor tag
        # 1 byte length of service provider
        # byte string of the service provider
        # 1 byte length of service name
        # byte string of the service name
        # crc
        if _sdt_msg[:3] != b'\x47\x40\x11':
            self.logger.info('WRONG ATSC MSG {}'.format(bytes(_sdt_msg[:20]).hex()))
            return _sdt_msg

        descr = b'\x01' \
                + utils.set_str(_service_provider, False) \
                + utils.set_str(_service_name, False)
        descr = b'\x48' + utils.set_u8(len(descr)) + descr
        msg = _sdt_msg[8:20] + utils.set_u8(len(descr)) + descr
        length = utils.set_u16(len(msg) + 4 + 0xF000)
        msg = ATSC_SERVICE_DESCR_TABLE_TAG + length + msg
        crc = self.gen_crc_mpeg(msg)
        msg = _sdt_msg[:5] + msg + crc
        msg = msg.ljust(len(_sdt_msg), b'\xFF')
        return msg
コード例 #2
0
    def datagram_received(self, _data, _host_port):
        """Handle a received multicast datagram."""

        (host, port) = _host_port
        if self.config['hdhomerun']['udp_netmask'] is None:
            is_allowed = True
        else:
            net = IPv4Network(self.config['hdhomerun']['udp_netmask'])
            is_allowed = IPv4Address(host) in net

        if is_allowed:
            self.logger.debug('UDP: from {}:{}'.format(host, port))
            try:
                (frame_type, msg_len, device_type, sub_dt_len, sub_dt, device_id, sub_did_len, sub_did) = \
                    struct.unpack('>HHBBIBBI', _data[0:-4])
                (crc, ) = struct.unpack('<I', _data[-4:])
            except ValueError as err:
                self.logger.error('UDP: {}'.format(err))
                return

            if frame_type != HDHOMERUN_TYPE_DISCOVER_REQ:
                self.logger.error(
                    'UDP: Unknown from type = {}'.format(frame_type))
            else:
                msg_type = bytes.fromhex('0003')
                header = bytes.fromhex('010400000001')
                device_id = bytes.fromhex('0204' +
                                          self.config['hdhomerun']['hdhr_id'])
                base_url = 'http://' + \
                           self.config['main']['plex_accessible_ip'] + \
                           ':' + str(self.config['main']['web_admin_port'])
                base_url_msg = b'\x2a' + utils.set_str(base_url.encode(),
                                                       False)
                tuner_count = b'\x10\x01' + utils.set_u8(
                    self.config['main']['tuner_count'])

                lineup_url = base_url + '/lineup.json'
                lineup_url = b'\x27' + utils.set_str(lineup_url.encode(),
                                                     False)
                msg = header + device_id + base_url_msg + tuner_count + lineup_url
                msg_len = utils.set_u16(len(msg))
                response = msg_type + msg_len + msg

                x = zlib.crc32(response)
                crc = struct.pack('<I', x)
                response += crc
                self.logger.debug('UDP Response={} {}'.format(
                    _host_port, response))
                self.sock_multicast.sendto(response, _host_port)
コード例 #3
0
 def gen_err_response(self, _frame_type, _tag, _text):
     # This is a tag type of HDHOMERUN_ERROR_MESSAGE
     # does not include the crc
     msg = msgs[_tag].format(*_text).encode()
     tag = utils.set_u8(HDHOMERUN_ERROR_MESSAGE)
     err_resp = utils.set_str(msg, True)
     msg_len = utils.set_u16(len(tag) + len(err_resp))
     response = _frame_type + msg_len + tag + err_resp
     return response
コード例 #4
0
ファイル: atsc.py プロジェクト: arantius/tvheadend-locast
 def gen_multiple_string_structure(self, _names):
     # Table 6.39 Multiple String Structure
     # event titles, long channel names, the ETT messages, and RRT text items
     # allows for upto 255 character strings
     # 8bit = array size
     # for each name
     #    3byte ISO_639_language_string = 'eng'
     #    1byte segments = normally 0x01
     #    for each segment
     #        1byte compression = 0x00 (not compression)
     #        1byte mode = 0x00 (used with unicode 2 byte letters, assume ASCII)
     #        1byte length in bytes = calculated
     #        string in byte format.  1 byte per character
     msg = utils.set_u8(len(_names))
     for name in _names:
         lang = self.gen_lang(b'eng')
         segment_len = utils.set_u8(1)
         compress_mode = utils.set_u16(0)
         name_bytes = utils.set_str(name.encode(), False)
         msg += lang + segment_len + compress_mode + name_bytes
     return msg
コード例 #5
0
    def create_getset_response(self, _req_dict, _address):
        (host, port) = _address
        frame_type = utils.set_u16(HDHOMERUN_TYPE_GETSET_RSP)
        name = _req_dict[HDHOMERUN_GETSET_NAME]
        name_str = name.decode('utf-8')
        if HDHOMERUN_GETSET_VALUE in _req_dict.keys():
            value = _req_dict[HDHOMERUN_GETSET_VALUE]
        else:
            value = None

        if name == b'/sys/model':
            # required to id the device
            name_resp = utils.set_u8(HDHOMERUN_GETSET_NAME) + utils.set_str(
                name, True)
            value_resp = utils.set_u8(HDHOMERUN_GETSET_VALUE) + utils.set_str(
                b'hdhomerun4_atsc', True)
            msg_len = utils.set_u16(len(name_resp) + len(value_resp))
            response = frame_type + msg_len + name_resp + value_resp
            x = zlib.crc32(response)
            crc = struct.pack('<I', x)
            response += crc
            return response

        elif name_str.startswith('/tuner'):
            tuner_index = int(name_str[6])
            if name_str.endswith('/lockkey'):
                self.logger.error(
                    'TCP: NOT IMPLEMENTED GETSET LOCKKEY MSG REQUEST: {} '.
                    format(_req_dict))
                response = self.gen_err_response(frame_type, 'lockedErrMsg',
                                                 [host])
                x = zlib.crc32(response)
                crc = struct.pack('<I', x)
                response += crc
                return response
            elif name_str.endswith('/status'):
                tuner_status = self.tuners[tuner_index]['status']
                if tuner_status == 'Scan':
                    response = self.gen_err_response(frame_type, 'scanErrMsg',
                                                     [host])
                else:
                    value_resp = utils.set_u8(HDHOMERUN_GETSET_VALUE) \
                                 + utils.set_str(tuner_status_msg[tuner_status], True)
                    name_resp = utils.set_u8(
                        HDHOMERUN_GETSET_NAME) + utils.set_str(name, True)
                    msg_len = utils.set_u16(len(name_resp) + len(value_resp))
                    response = frame_type + msg_len + name_resp + value_resp
                x = zlib.crc32(response)
                crc = struct.pack('<I', x)
                response += crc
                return response

            elif name_str.endswith('/vchannel'):
                tuner_status = self.tuners[tuner_index]['status']
                if tuner_status == 'Stream':
                    value_resp = utils.set_u8(HDHOMERUN_GETSET_VALUE) \
                                 + utils.set_str(self.tuners[tuner_index]['channel'].encode(), True)
                else:
                    value_resp = utils.set_u8(HDHOMERUN_GETSET_VALUE) \
                                 + utils.set_str('none', True)
                name_resp = utils.set_u8(
                    HDHOMERUN_GETSET_NAME) + utils.set_str(name, True)
                msg_len = utils.set_u16(len(name_resp) + len(value_resp))
                response = frame_type + msg_len + name_resp + value_resp
                x = zlib.crc32(response)
                crc = struct.pack('<I', x)
                response += crc
                return response

            else:
                self.logger.error(
                    'TCP: NOT IMPLEMENTED GETSET MSG REQUEST: {} '.format(
                        _req_dict))
                return None
        else:
            self.logger.error(
                'TCP: 3 UNKNOWN GETSET MSG REQUEST: {} '.format(_req_dict))
            return None