Example #1
0
static int send_bye_packet(struct rtcp_sess *sess)
{
	const uint32_t ssrc = rtp_sess_ssrc(sess->rs);
	struct mbuf *mb;
	int err;

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

	mb->pos = RTCP_HEADROOM;

	err  = rtcp_encode(mb, RTCP_BYE, 1, &ssrc, "Adjo");
	err |= mk_sdes(sess, mb);
	if (err)
		goto out;

	mb->pos = RTCP_HEADROOM;

	err = rtcp_send(sess->rs, mb);

 out:
	mem_deref(mb);
	return err;
}
Example #2
0
static int sdes_encode_handler(struct mbuf *mb, void *arg)
{
	struct rtcp_sess *sess = arg;

	return rtcp_sdes_encode(mb, rtp_sess_ssrc(sess->rs), 1,
				RTCP_SDES_CNAME, sess->cname);
}
Example #3
0
/** Create a Sender Report */
static int mk_sr(struct rtcp_sess *sess, struct mbuf *mb)
{
	struct ntp_time ntp = {0, 0};
	struct txstat txstat;
	uint32_t dur = 0, rtp_ts = 0;
	int err;

	err = ntp_time_get(&ntp);
	if (err)
		return err;

	lock_read_get(sess->lock);
	txstat = sess->txstat;
	lock_rel(sess->lock);

	if (txstat.start) {
		dur = (uint32_t)(time(NULL) - txstat.start);
		rtp_ts = txstat.ts_offset + dur * sess->srate_tx;
	}

	err = rtcp_encode(mb, RTCP_SR, sess->senderc, rtp_sess_ssrc(sess->rs),
			  ntp.hi, ntp.lo, rtp_ts, txstat.psent, txstat.osent,
			  encode_handler, sess->members);
	if (err)
		return err;

	return err;
}
Example #4
0
static int media_alloc(struct menc_media **stp, struct menc_sess *sess,
		       struct rtp_sock *rtp,
		       int proto, void *rtpsock, void *rtcpsock,
		       struct sdp_media *sdpm)
{
	struct menc_media *st;
	zrtp_status_t s;
	int layer = 10; /* above zero */
	int err = 0;
	(void)rtcpsock;

	if (!stp || !sess || proto != IPPROTO_UDP)
		return EINVAL;

	st = *stp;
	if (st)
		goto start;

	st = mem_zalloc(sizeof(*st), media_destructor);
	if (!st)
		return ENOMEM;

	st->sess = sess;
	st->rtpsock = mem_ref(rtpsock);

	err = udp_register_helper(&st->uh, rtpsock, layer,
				  udp_helper_send, udp_helper_recv, st);
	if (err)
		goto out;

	s = zrtp_stream_attach(sess->zrtp_session, &st->zrtp_stream);
	if (s != zrtp_status_ok) {
		warning("zrtp: zrtp_stream_attach failed (status=%d)\n", s);
		err = EPROTO;
		goto out;
	}

	zrtp_stream_set_userdata(st->zrtp_stream, st);

 out:
	if (err) {
		mem_deref(st);
		return err;
	}
	else
		*stp = st;

 start:
	if (sa_isset(sdp_media_raddr(sdpm), SA_ALL)) {
		st->raddr = *sdp_media_raddr(sdpm);

		s = zrtp_stream_start(st->zrtp_stream, rtp_sess_ssrc(rtp));
		if (s != zrtp_status_ok) {
			warning("zrtp: zrtp_stream_start: status = %d\n", s);
		}
	}

	return err;
}
Example #5
0
/**
 * RTCP Debug handler, use with fmt %H
 *
 * @param pf Print function
 * @param rs RTP Socket
 *
 * @return 0 if success, otherwise errorcode
 */
int rtcp_debug(struct re_printf *pf, const struct rtp_sock *rs)
{
	const struct rtcp_sess *sess = rtp_rtcp_sess(rs);
	int err = 0;

	if (!sess)
		return 0;

	err |= re_hprintf(pf, "----- RTCP Session: -----\n");
	err |= re_hprintf(pf, "  cname=%s SSRC=0x%08x/%u rx=%uHz\n",
			  sess->cname,
			  rtp_sess_ssrc(sess->rs), rtp_sess_ssrc(sess->rs),
			  sess->srate_rx);

	hash_apply(sess->members, debug_handler, pf);

	lock_read_get(sess->lock);
	err |= re_hprintf(pf, "  TX: packets=%u, octets=%u\n",
			  sess->txstat.psent, sess->txstat.osent);
	lock_rel(sess->lock);

	return err;
}
Example #6
0
void stream_send_fir(struct stream *s, bool pli)
{
	int err;

	if (!s)
		return;

	if (pli)
		err = rtcp_send_pli(s->rtp, s->ssrc_rx);
	else
		err = rtcp_send_fir(s->rtp, rtp_sess_ssrc(s->rtp));

	if (err) {
		DEBUG_WARNING("Send FIR: %m\n", err);
	}
}
Example #7
0
void stream_send_fir(struct stream *s, bool pli)
{
	int err;

	if (!s)
		return;

	if (pli)
		err = rtcp_send_pli(s->rtp, s->ssrc_rx);
	else
		err = rtcp_send_fir(s->rtp, rtp_sess_ssrc(s->rtp));

	if (err) {
		s->metric_tx.n_err++;

		warning("stream: failed to send RTCP %s: %m\n",
			pli ? "PLI" : "FIR", err);
	}
}
Example #8
0
int stream_alloc(struct stream **sp, const struct config_avt *cfg,
		 struct call *call, struct sdp_session *sdp_sess,
		 const char *name, int label,
		 const struct mnat *mnat, struct mnat_sess *mnat_sess,
		 const struct menc *menc, struct menc_sess *menc_sess,
		 const char *cname,
		 stream_rtp_h *rtph, stream_rtcp_h *rtcph, void *arg)
{
	struct stream *s;
	int err;

	if (!sp || !cfg || !call || !rtph)
		return EINVAL;

	s = mem_zalloc(sizeof(*s), stream_destructor);
	if (!s)
		return ENOMEM;

	s->cfg   = *cfg;
	s->call  = call;
	s->rtph  = rtph;
	s->rtcph = rtcph;
	s->arg   = arg;
	s->pseq  = -1;
	s->rtcp  = s->cfg.rtcp_enable;

	err = stream_sock_alloc(s, call_af(call));
	if (err) {
		warning("stream: failed to create socket for media '%s'"
			" (%m)\n", name, err);
		goto out;
	}

	err = str_dup(&s->cname, cname);
	if (err)
		goto out;

	/* Jitter buffer */
	if (cfg->jbuf_del.min && cfg->jbuf_del.max) {

		err = jbuf_alloc(&s->jbuf, cfg->jbuf_del.min,
				 cfg->jbuf_del.max);
		if (err)
			goto out;
	}

	err = sdp_media_add(&s->sdp, sdp_sess, name,
			    sa_port(rtp_local(s->rtp)),
			    (menc && menc->sdp_proto) ? menc->sdp_proto :
			    sdp_proto_rtpavp);
	if (err)
		goto out;

	if (label) {
		err |= sdp_media_set_lattr(s->sdp, true,
					   "label", "%d", label);
	}

	/* RFC 5506 */
	if (s->rtcp)
		err |= sdp_media_set_lattr(s->sdp, true, "rtcp-rsize", NULL);

	/* RFC 5576 */
	if (s->rtcp) {
		err |= sdp_media_set_lattr(s->sdp, true,
					   "ssrc", "%u cname:%s",
					   rtp_sess_ssrc(s->rtp), cname);
	}

	/* RFC 5761 */
	if (cfg->rtcp_mux)
		err |= sdp_media_set_lattr(s->sdp, true, "rtcp-mux", NULL);

	if (err)
		goto out;

	if (mnat) {
		err = mnat->mediah(&s->mns, mnat_sess, IPPROTO_UDP,
				   rtp_sock(s->rtp),
				   s->rtcp ? rtcp_sock(s->rtp) : NULL,
				   s->sdp);
		if (err)
			goto out;
	}

	if (menc) {
		s->menc  = menc;
		s->mencs = mem_ref(menc_sess);
		err = menc->mediah(&s->mes, menc_sess,
				   s->rtp,
				   IPPROTO_UDP,
				   rtp_sock(s->rtp),
				   s->rtcp ? rtcp_sock(s->rtp) : NULL,
				   s->sdp);
		if (err)
			goto out;
	}

	if (err)
		goto out;

	s->pt_enc = -1;

	metric_init(&s->metric_tx);
	metric_init(&s->metric_rx);

	list_append(call_streaml(call), &s->le, s);

 out:
	if (err)
		mem_deref(s);
	else
		*sp = s;

	return err;
}