예제 #1
0
파일: rtp.c 프로젝트: hbowden/re
static void udp_recv_handler(const struct sa *src, struct mbuf *mb, void *arg)
{
	struct rtp_sock *rs = arg;
	struct rtp_header hdr;
	int err;

	/* Handle RTCP multiplexed on RTP-port */
	if (rs->rtcp_mux) {
		uint8_t pt;

		if (mbuf_get_left(mb) < 2)
			return;

		pt = mbuf_buf(mb)[1] & 0x7f;

		if (64 <= pt && pt <= 95) {
			rtcp_recv_handler(src, mb, arg);
			return;
		}
	}

	err = rtp_decode(rs, mb, &hdr);
	if (err)
		return;

	if (rs->rtcp) {
		rtcp_sess_rx_rtp(rs->rtcp, hdr.seq, hdr.ts,
				 hdr.ssrc, mbuf_get_left(mb), src);
	}

	if (rs->recvh)
		rs->recvh(src, &hdr, mb, rs->arg);
}
예제 #2
0
/* read from incoming RTP/RTCP socket */
static int rtp_socket_read(struct rtp_socket *rs, struct rtp_sub_socket *rss)
{
	int rc;
	struct msgb *msg = msgb_alloc(RTP_ALLOC_SIZE, "RTP/RTCP");
	struct msgb *new_msg;
	struct rtp_sub_socket *other_rss;

	if (!msg)
		return -ENOMEM;

	rc = read(rss->bfd.fd, msg->data, RTP_ALLOC_SIZE);
	if (rc <= 0) {
		rss->bfd.when &= ~BSC_FD_READ;
		return rc;
	}

	msgb_put(msg, rc);

	switch (rs->rx_action) {
	case RTP_PROXY:
		if (!rs->proxy.other_sock) {
			rc = -EIO;
			goto out_free;
		}
		if (rss->bfd.priv_nr == RTP_PRIV_RTP)
			other_rss = &rs->proxy.other_sock->rtp;
		else if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
			other_rss = &rs->proxy.other_sock->rtcp;
			/* modify RTCP SDES CNAME */
			rc = rtcp_mangle(msg, rs);
			if (rc < 0)
				goto out_free;
		} else {
			rc = -EINVAL;
			goto out_free;
		}
		msgb_enqueue(&other_rss->tx_queue, msg);
		other_rss->bfd.when |= BSC_FD_WRITE;
		break;

	case RTP_RECV_UPSTREAM:
		if (!rs->receive.callref || !rs->receive.net) {
			rc = -EIO;
			goto out_free;
		}
		if (rss->bfd.priv_nr == RTP_PRIV_RTCP) {
			if (!mangle_rtcp_cname) {
				msgb_free(msg);
				break;
			}
			/* modify RTCP SDES CNAME */
			rc = rtcp_mangle(msg, rs);
			if (rc < 0)
				goto out_free;
			msgb_enqueue(&rss->tx_queue, msg);
			rss->bfd.when |= BSC_FD_WRITE;
			break;
		}
		if (rss->bfd.priv_nr != RTP_PRIV_RTP) {
			rc = -EINVAL;
			goto out_free;
		}
		rc = rtp_decode(msg, rs->receive.callref, &new_msg);
		if (rc < 0)
			goto out_free;
		msgb_free(msg);
		msgb_enqueue(&rs->receive.net->upqueue, new_msg);
		break;

	case RTP_NONE: /* if socket exists, but disabled by app */
		msgb_free(msg);
		break;
	}

	return 0;

out_free:
	msgb_free(msg);
	return rc;
}
예제 #3
0
int test_rtp(void)
{
	struct rtp_sock *rtp = NULL;
	struct mbuf *mb = NULL;
	uint8_t payload[PAYLOAD_SIZE];
	int j;
	int err;

	memset(payload, 0, sizeof(payload));

	mb = mbuf_alloc(RTP_HEADER_SIZE);
	if (!mb)
		return ENOMEM;

	err = rtp_alloc(&rtp);
	if (err)
		goto out;

	for (j=0; j<100; j++) {
		struct rtp_header hdr, hdr2;

		memset(&hdr, 0, sizeof(hdr));

		hdr.m  = rand_u16() & 0x01;
		hdr.pt = rand_u16() & 0x7f;
		hdr.ts = rand_u32();
		rand_bytes(payload, sizeof(payload));

		mb->pos = mb->end = RTP_HEADER_SIZE;
		err = mbuf_write_mem(mb, payload, sizeof(payload));
		if (err)
			break;

		mb->pos = 0;
		err = rtp_encode(rtp, hdr.m, hdr.pt, hdr.ts, mb);
		if (err)
			break;

		mb->pos = 0;

		err = rtp_decode(rtp, mb, &hdr2);
		if (err)
			break;

		if (hdr.m != hdr2.m) {
			DEBUG_WARNING("marker bit mismatch (%d != %d)\n",
				      hdr.m, hdr2.m);
			err = EBADMSG;
			break;
		}

		if (hdr.pt != hdr2.pt) {
			DEBUG_WARNING("payload type mismatch (%u != %u)\n",
				      hdr.pt, hdr2.pt);
			err = EBADMSG;
			break;
		}

		if (hdr.ts != hdr2.ts) {
			DEBUG_WARNING("timestamp mismatch (%lu != %lu)\n",
				      hdr.ts, hdr2.ts);
			err = EBADMSG;
			break;
		}

		if (hdr2.pad) {
			DEBUG_WARNING("unexpected padding bit\n");
			err = EBADMSG;
			break;
		}

		if (hdr2.ext) {
			DEBUG_WARNING("unexpected extension bit\n");
			err = EBADMSG;
			break;
		}

		if (RTP_HEADER_SIZE != mb->pos ||
		    (RTP_HEADER_SIZE + PAYLOAD_SIZE) != mb->end) {
			DEBUG_WARNING("invalid mbuf size (pos=%u end=%u)\n",
				      mb->pos, mb->end);
			err = EBADMSG;
			break;
		}

		if (0 != memcmp(mbuf_buf(mb), payload, sizeof(payload))) {
			DEBUG_WARNING("RTP payload mismatch\n");
			err = EBADMSG;
			break;
		}
	}

 out:
	mem_deref(rtp);
	mem_deref(mb);

	return err;
}