void __anoubis_dump(struct anoubis_msg * m, const char * pre, char **pstr) { uint32_t opcode; __dstr = malloc(BUFSIZ); if (!__dstr) return; memset(__dstr, 0, BUFSIZ); snprintf(DSTR, DLEN, "%s:", pre?pre:"(null)"); ASSERT(VERIFY_FIELD(m, general, type)); ASSERT(m->length < INT_MAX); ASSERT(crc32_check(m->u.buf, (int) m->length)); opcode = get_value(m->u.general->type); switch(opcode) { CASE(ANOUBIS_REPLY, ack) CASE(ANOUBIS_N_DELEGATE, ack) CASE(ANOUBIS_C_HELLO, hello) CASE(ANOUBIS_C_VERSEL, versel) CASE(ANOUBIS_C_AUTH, general) CASE(ANOUBIS_C_AUTHREPLY, authreply) CASE(ANOUBIS_C_OPTREQ, stringlist) CASE(ANOUBIS_C_OPTACK, stringlist) CASE(ANOUBIS_C_PROTOSEL, stringlist) CASE(ANOUBIS_C_CLOSEREQ, general) CASE(ANOUBIS_C_CLOSEACK, general) CASE2(ANOUBIS_N_NOTIFY, notify, 0) CASE2(ANOUBIS_N_ASK, notify, 0) CASE2(ANOUBIS_N_LOGNOTIFY, notify, 1) CASE(ANOUBIS_N_POLICYCHANGE, policychange) CASE(ANOUBIS_N_PGCHANGE, pgchange) CASE(ANOUBIS_N_STATUSNOTIFY, statusnotify) CASE(ANOUBIS_N_REGISTER, notifyreg) CASE(ANOUBIS_N_UNREGISTER, notifyreg) CASE(ANOUBIS_N_RESYOU, notifyresult) CASE(ANOUBIS_N_RESOTHER, notifyresult) CASE(ANOUBIS_P_REQUEST, policyrequest) CASE(ANOUBIS_P_REPLY, policyreply) CASE(ANOUBIS_P_CSUMREQUEST, checksumrequest) CASE(ANOUBIS_P_CSUM_LIST, checksumpayload) CASE(ANOUBIS_P_CSMULTIREQUEST, csmultireq) CASE(ANOUBIS_P_CSMULTIREPLY, csmultireply) CASE(ANOUBIS_P_VERSION, general) CASE(ANOUBIS_P_VERSIONREPLY, version) CASE(ANOUBIS_P_LISTREQ, listreq) CASE(ANOUBIS_P_LISTREP, listreply) default: snprintf(DSTR, DLEN, " type = %x", opcode); dump_general(m->u.general, m->length-CSUM_LEN); } if (pstr) { *pstr = __dstr; } else { printf("%s\n", __dstr); free(__dstr); } }
/** * ts_parse_packet - Parse a transport stream packet. Called by the backend's process() function. */ int ts_parse_packet(const struct ts_header *header, const char *payload, struct demuxfs_data *priv) { int ret = 0; uint8_t pointer_field = 0; uint16_t section_length = 0; const char *payload_end; const char *payload_start = payload; parse_function_t parse_function; if (header->sync_byte != TS_SYNC_BYTE) { TS_WARNING("sync_byte != %#x (%#x)", TS_SYNC_BYTE, header->sync_byte); return -EBADMSG; } if (header->adaptation_field == 0x00) { /* ITU-T Rec. H.222.0 decoders shall discard this packet */ return 0; } else if (header->adaptation_field == 0x01) { /* No adaptation field, payload only */ } else if (header->adaptation_field == 0x02) { /* Adaptation field only, no payload */ return 0; } else if (header->adaptation_field == 0x03) { /* Adaptation field followed by payload */ uint8_t adaptation_field_length = payload[0]; payload_start += 1 + adaptation_field_length; if ((payload_start - payload) > priv->options.packet_size) { TS_WARNING("adaptation_field length is bigger than a TS packet: %d", adaptation_field_length); return -ENOBUFS; } /* TODO: parse adaptation field */ } struct user_options *opt = &priv->options; payload_end = payload + opt->packet_size - 4 - 1 - opt->packet_error_correction_bytes; //ts_dump_header(header); //ts_dump_payload(payload, payload_end-payload_start); struct buffer *buffer = NULL; if (ts_is_psi_packet(header->pid, priv)) { const char *start = payload_start; const char *end = payload_end; bool is_new_packet = false; bool pusi = header->payload_unit_start_indicator; uint8_t table_id; if (pusi) { /* The first byte of the payload carries the pointer_field */ pointer_field = payload_start[0]; start = payload_start + 1; if ((payload_start + pointer_field) > payload_end) { TS_WARNING("pointer_field > TS packet size (%d)", pointer_field); return -ENOBUFS; } section_length = CONVERT_TO_16(start[1], start[2]) & 0x0fff; if ((int) pointer_field > 0) { end = payload_start + pointer_field; } else { is_new_packet = true; end = ((payload_start + 3 + section_length) <= payload_end) ? payload_start + 3 + section_length : payload_end; } } while (start <= payload_end) { buffer = hashtable_get(priv->packet_buffer, header->pid); if (! buffer && is_new_packet) { buffer = buffer_create(header->pid, section_length + 3, false); if (! buffer) return 0; buffer->continuity_counter = header->continuity_counter; hashtable_add(priv->packet_buffer, header->pid, buffer, NULL); } else if (buffer && ! continuity_counter_is_ok(header, buffer, true, priv)) { return 0; } else if (buffer && buffer->current_size == 0 && ! is_new_packet) { /* * Cannot start appending data if we don't have PUSI set and there are * no contents in the buffer yet. */ if (! pusi) return 0; /* * The second half of the packet can very well have valid data. * Just invalidate the buffer to return to the beginning of the loop. */ buffer = NULL; } if (is_new_packet && IS_STUFFING_PACKET(start)) buffer = NULL; if (buffer) { int ret = buffer_append(buffer, start, end - start + 1); if (ret >= 0 && buffer_contains_full_psi_section(buffer)) { table_id = buffer->data[0]; if (! crc32_check(buffer->data, buffer->current_size) && priv->options.verbose_mask & CRC_ERROR) TS_WARNING("CRC error on PID %d(%#x), table_id %d(%#x)", header->pid, header->pid, table_id, table_id); else if ((parse_function = ts_get_psi_parser(header, table_id, priv))) /* Invoke the PSI parser for this packet */ ret = parse_function(header, buffer->data, buffer->current_size, priv); buffer_reset_size(buffer); } } if (! pusi || pointer_field == 0) break; if (buffer) buffer_reset_size(buffer); start = end + 1; if (start >= (payload_end-1)) /* No more data to parse */ break; section_length = CONVERT_TO_16(start[1], start[2]) & 0x0fff; if (IS_STUFFING_PACKET(start) || section_length == 0) /* Nothing to parse */ break; end = ((start + section_length + 2) <= payload_end) ? start + section_length + 2 : payload_end; pusi = false; is_new_packet = true; } } else if (ts_is_pes_packet(header->pid, priv)) { uint16_t size; bool pusi = header->payload_unit_start_indicator; buffer = hashtable_get(priv->packet_buffer, header->pid); if (! buffer) { if (! pusi || (payload_end - payload_start <= 6)) return 0; size = CONVERT_TO_16(payload_start[4], payload_start[5]); buffer = buffer_create(header->pid, size, true); if (! buffer) return 0; buffer->continuity_counter = header->continuity_counter; hashtable_add(priv->packet_buffer, header->pid, buffer, NULL); } else if (!continuity_counter_is_ok(header, buffer, false, priv) || (buffer_get_current_size(buffer) == 0 && !buffer_is_unbounded(buffer) && (!pusi || (payload_end - payload_start <= 6)))) { return 0; } buffer_append(buffer, payload_start, payload_end - payload_start + 1); if (buffer_contains_full_pes_section(buffer)) { /* Invoke the PES parser for this packet */ if ((parse_function = (parse_function_t) hashtable_get(priv->pes_parsers, header->pid))) ret = parse_function(header, buffer->data, buffer->current_size, priv); buffer_reset_size(buffer); } } if (buffer) buffer->continuity_counter = header->continuity_counter; return ret; }