Exemple #1
0
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);
	}
}
Exemple #2
0
/**
 * 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;
}