def _parse(self, stream, context, path):
        b = byte2int(stream_read(stream, 1, path))
        extrabytes, mask = [
            # lookup table
            [0, 0xff],  # (0b0xxxxxxx)
            [0, 0xff],  # (0b0xxxxxxx)
            [1, 0x7f],  # 0x80 (0b10xxxxxx)
            [2, 0x00]  # 0xC0 (0b11xxxxxx)
        ][b >> 6]

        num = b & mask
        for _ in range(extrabytes):
            num = (num << 8) + byte2int(stream_read(stream, 1, path))

        return num
Esempio n. 2
0
 def query_blob(self, player_number, slot, item_id, request_type, location=8):
   sock = self.getSocket(player_number)
   slot_id = byte2int(packets.PlayerSlot.build(slot))
   query = {
     "transaction_id": self.getTransactionId(player_number),
     "type": request_type,
     "args": [
       {"type": "int32", "value": self.own_player_number<<24 | location<<16 | slot_id<<8 | 1},
       {"type": "int32", "value": item_id}
     ]
   }
   # request-specific argument agumentations
   if request_type == "waveform_request":
     query["args"].append({"type": "int32", "value": 0})
   elif request_type == "preview_waveform_request":
     query["args"].insert(1, {"type": "int32", "value": 4})
     query["args"].append({"type": "int32", "value": 0})
   logging.debug("DBClient: {} query {}".format(request_type, query))
   data = packets.DBMessage.build(query)
   self.socksnd(sock, data)
   try:
     reply = self.receive_dbmessage(sock)
   except (RangeError, FieldError, MappingError, KeyError, TypeError) as e:
     logging.error("DBClient: %s query parse error: %s", request_type, str(e))
     return None
   if reply is None:
     return None
   if reply["type"] == "invalid_request" or len(reply["args"])<3 or reply["args"][2]["value"] == 0:
     logging.error("DBClient: %s blob query failed on player %d (got %s)", query["type"], player_number, reply["type"])
     return None
   blob = reply["args"][3]["value"]
   logging.debug("DBClient: got %d bytes of blob data", len(blob))
   return blob
    def _parse(self, stream, context, path):
        b = byte2int(stream_read(stream, 1, path))
        extrabytes, mask = [
            [0, 0xff],
            [0, 0xff],
            [0, 0xff],
            [0, 0xff],  # (0b0..xxxxx)
            [1, 0x7f],
            [1, 0x7f],  # 0x80 (0b10.xxxxx)
            [3, 0x3f],  # 0xC0 (0b110xxxxx)
            [4, 0x00]  # 0xE0 (0b111xxxxx)
        ][b >> 5]

        num = b & mask
        for _ in range(extrabytes):
            num = (num << 8) + byte2int(stream_read(stream, 1, path))

        return num
 def _parse(self, stream, context, path):
     acc = []
     while True:
         b = byte2int(stream_read(stream, 1))
         acc.append(b & 0b01111111)
         if not b & 0b10000000:
             break
     num = 0
     for b in acc:
         num = (num << 7) | b
     return num
Esempio n. 5
0
 def query_link_info(self, player_number, slot):
     cl = self.prodj.cl.getClient(player_number)
     if cl is None:
         logging.warning("Failed to get player %d", player_number)
         return
     slot_id = byte2int(packets.PlayerSlot.build(slot))
     cmd = {
         "type": "link_query",
         "model": self.model,
         "player_number": self.player_number,
         "source_ip": self.ip_addr,
         "remote_player_number": player_number,
         "slot": slot_id
     }
     data = packets.StatusPacket.build(cmd)
     logging.debug("query link info to %s struct %s", cl.ip_addr, str(cmd))
     self.prodj.status_sock.sendto(data,
                                   (cl.ip_addr, self.prodj.status_port))
Esempio n. 6
0
 def _parse(self, stream, context, path):
     result = 0
     sign = 1
     i = 0
     depth = 0
     while True:
         length = self.lengths[i]
         bits = byte2int(stream_read(stream, 1, path))
         mask = self._get_data_mask(length)
         data = bits & mask
         more = self._get_more_bit(length) & bits
         if (i == 0) and (self.negative_bit & bits):
             sign = -1
         result |= data << depth
         if not more:
             break
         i += 1
         depth += length
     return sign * result
Esempio n. 7
0
 def command_load_track(self, player_number, load_player_number, load_slot,
                        load_track_id):
     cl = self.prodj.cl.getClient(player_number)
     if cl is None:
         logging.warning("Failed to get player %d", player_number)
         return
     load_slot_id = byte2int(packets.PlayerSlot.build(load_slot))
     cmd = {
         "type": "load_cmd",
         "model": self.model,
         "player_number": self.
         player_number,  # our player number -> we receive confirmation packet
         "player_number2": self.
         player_number,  # our player number -> we receive confirmation packet
         "load_player_number": load_player_number,
         "load_slot": load_slot_id,
         "load_track_id": load_track_id
     }
     data = packets.StatusPacket.build(cmd)
     logging.debug("send load packet to %s struct %s", cl.ip_addr, str(cmd))
     self.prodj.status_sock.sendto(data,
                                   (cl.ip_addr, self.prodj.status_port))
Esempio n. 8
0
    def query_list(self, player_number, slot, sort_mode, id_list,
                   request_type):
        sock = self.getSocket(player_number)
        slot_id = byte2int(
            packets.PlayerSlot.build(slot)) if slot is not None else 0
        if sort_mode is None:
            sort_id = 0  # 0 for root_menu, playlist folders
        else:
            if sort_mode not in sort_types:
                logging.warning("DBClient: unknown sort mode %s", sort_mode)
                return None
            sort_id = sort_types[sort_mode]
        query = {
            "transaction_id":
            self.getTransactionId(player_number),
            "type":
            request_type,
            "args": [{
                "type":
                "int32",
                "value":
                self.own_player_number << 24 | 1 << 16 | slot_id << 8 | 1
            }]
        }
        # request-specific argument agumentations
        if request_type == "root_menu_request":
            query["args"].append({"type": "int32", "value": 0})
            query["args"].append({"type": "int32", "value": 0xffffff})
        elif request_type in [
                "metadata_request", "track_data_request", "track_info_request"
        ]:
            query["args"].append({"type": "int32", "value": id_list[0]})
        elif request_type == "playlist_request":
            query["args"].append({"type": "int32", "value": sort_id})
            query["args"].append({
                "type":
                "int32",
                "value":
                id_list[1] if id_list[1] > 0 else id_list[0]
            })
            query["args"].append({
                "type": "int32",
                "value": 0 if id_list[1] > 0 else 1
            })  # 1 -> get folder, 0 -> get playlist
        else:  # for any (non-playlist) "*_by_*_request"
            query["args"].append({"type": "int32", "value": sort_id})
            for item_id in id_list:
                if item_id == 0:  # we use id 0 for "ALL", dbserver expects all bits set
                    item_id = 0xffffffff
                query["args"].append({"type": "int32", "value": item_id})
        data = packets.DBMessage.build(query)
        logging.debug("DBClient: query_list request: {}".format(query))
        self.socksnd(sock, data)

        try:
            reply = self.receive_dbmessage(sock)
        except (RangeError, MappingError, KeyError) as e:
            logging.error(
                "DBClient: parsing %s query failed on player %d failed: %s",
                query["type"], player_number, str(e))
            return None
        if reply is None or reply["type"] != "success":
            logging.error("DBClient: %s failed on player %d (got %s)",
                          query["type"], player_number,
                          "NONE" if reply is None else reply["type"])
            return None
        entry_count = reply["args"][1]["value"]
        if entry_count == 0:
            logging.warning("DBClient: %s empty (0 entries)", request_type)
            return []
        logging.debug("DBClient: query_list %s: %d entries available",
                      request_type, entry_count)

        # i could successfully receive hundreds of entries at once on xdj 1000
        # thus i do not fragment render requests here
        query = {
            "transaction_id":
            self.getTransactionId(player_number),
            "type":
            "render",
            "args": [
                {
                    "type":
                    "int32",
                    "value":
                    self.own_player_number << 24 | 1 << 16 | slot_id << 8 | 1
                },
                {
                    "type": "int32",
                    "value": 0
                },  # entry offset
                {
                    "type": "int32",
                    "value": entry_count
                },  # entry count
                {
                    "type": "int32",
                    "value": 0
                },
                {
                    "type": "int32",
                    "value": entry_count
                },  # entry count
                {
                    "type": "int32",
                    "value": 0
                }
            ]
        }
        data = packets.DBMessage.build(query)
        logging.debug("DBClient: render query {}".format(query))
        self.socksnd(sock, data)
        parse_errors = 0
        receive_timeouts = 0
        data = b""
        while parse_errors < self.parse_error_count and receive_timeouts < self.receive_timeout_count:
            new_data = sockrcv(sock, 4096, 1)
            if len(new_data) == 0:
                receive_timeouts += 1
                continue
            data += new_data
            try:
                reply = packets.ManyDBMessages.parse(data)
            except (RangeError, FieldError, MappingError, KeyError,
                    TypeError) as e:
                logging.debug(
                    "DBClient: failed to parse %s render reply (%d bytes), trying to receive more",
                    request_type, len(data))
                parse_errors += 1
            else:
                if reply[-1]["type"] != "menu_footer":
                    logging.debug(
                        "DBClient: %s rendering without menu_footer @ %d bytes, trying to receive more",
                        request_type, len(data))
                    parse_errors += 1
                else:
                    break
        if parse_errors >= self.parse_error_count or receive_timeouts >= self.receive_timeout_count:
            raise dataprovider.FatalQueryError(
                "DBClient: Failed to receive {} render reply after {} timeouts, {} parse errors"
                .format(request_type, receive_timeouts, parse_errors))

        # basically, parse_metadata returns a single dict whereas parse_list returns a list of dicts
        if request_type in [
                "metadata_request", "mount_info_request", "track_info_request"
        ]:
            parsed = self.parse_metadata(reply)
        else:
            parsed = self.parse_list(reply)
        return parsed