static int sig_hash_encode(struct zrtp_stream_t *stream, struct sdp_media *m) { char buf[ZRTP_SIGN_ZRTP_HASH_LENGTH + 1]; zrtp_status_t s; int err = 0; s = zrtp_signaling_hash_get(stream, buf, sizeof(buf)); if (s != zrtp_status_ok) { warning("zrtp: zrtp_signaling_hash_get: status = %d\n", s); return EINVAL; } err = sdp_media_set_lattr(m, true, "zrtp-hash", "%s %s", ZRTP_PROTOCOL_VERSION, buf); if (err) { warning("zrtp: sdp_media_set_lattr: %d\n", err); } return err; }
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; }
int stream_alloc(struct stream **sp, 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, stream_rtp_h *rtph, stream_rtcp_h *rtcph, void *arg) { struct stream *s; int err; if (!sp || !call || !rtph) return EINVAL; s = mem_zalloc(sizeof(*s), stream_destructor); if (!s) return ENOMEM; MAGIC_INIT(s); tmr_init(&s->tmr_stats); s->call = call; if (!str_casecmp(name, "audio")) s->type = STREAM_AUDIO; else if (!str_casecmp(name, "video")) s->type = STREAM_VIDEO; else s->type = STREAM_UNKNOWN; s->rtph = rtph; s->rtcph = rtcph; s->arg = arg; s->pseq = -1; s->rtcp = config.avt.rtcp_enable; err = stream_sock_alloc(s, call_af(call)); if (err) goto out; /* Jitter buffer */ if (config.avt.jbuf_del.min && config.avt.jbuf_del.max) { err = jbuf_alloc(&s->jbuf, config.avt.jbuf_del.min, config.avt.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 5761 */ if (config.avt.rtcp_mux) err |= sdp_media_set_lattr(s->sdp, true, "rtcp-mux", NULL); if (mnat) { err |= mnat->mediah(&s->mns, mnat_sess, IPPROTO_UDP, rtp_sock(s->rtp), (s->rtcp && !config.avt.rtcp_mux) ? rtcp_sock(s->rtp) : NULL, s->sdp); } if (menc) { s->menc = menc; s->mencs = mem_ref(menc_sess); err |= menc->mediah(&s->mes, menc_sess, IPPROTO_UDP, rtp_sock(s->rtp), s->rtcp ? rtcp_sock(s->rtp) : NULL, s->sdp); } if (err) goto out; s->pt_enc = -1; list_append(call_streaml(call), &s->le, s); out: if (err) mem_deref(s); else *sp = s; return err; }
int audio_alloc(struct audio **ap, const struct config *cfg, struct call *call, struct sdp_session *sdp_sess, int label, const struct mnat *mnat, struct mnat_sess *mnat_sess, const struct menc *menc, struct menc_sess *menc_sess, uint32_t ptime, const struct list *aucodecl, audio_event_h *eventh, audio_err_h *errh, void *arg) { struct audio *a; struct autx *tx; struct aurx *rx; struct le *le; int err; if (!ap || !cfg) return EINVAL; a = mem_zalloc(sizeof(*a), audio_destructor); if (!a) return ENOMEM; MAGIC_INIT(a); a->cfg = cfg->audio; tx = &a->tx; rx = &a->rx; err = stream_alloc(&a->strm, &cfg->avt, call, sdp_sess, "audio", label, mnat, mnat_sess, menc, menc_sess, stream_recv_handler, NULL, a); if (err) goto out; stream_set_bw(a->strm, AUDIO_BANDWIDTH); err = sdp_media_set_lattr(stream_sdpmedia(a->strm), true, "ptime", "%u", ptime); if (err) goto out; /* Audio codecs */ for (le = list_head(aucodecl); le; le = le->next) { err = add_audio_codec(a, stream_sdpmedia(a->strm), le->data); if (err) goto out; } tx->mb = mbuf_alloc(STREAM_PRESZ + 4096); tx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL); rx->sampv = mem_zalloc(AUDIO_SAMPSZ * 2, NULL); if (!tx->mb || !tx->sampv || !rx->sampv) { err = ENOMEM; goto out; } err = telev_alloc(&a->telev, TELEV_PTIME); if (err) goto out; err = add_telev_codec(a); if (err) goto out; tx->ptime = ptime; tx->ts = 160; tx->marker = true; rx->pt = -1; rx->ptime = ptime; a->eventh = eventh; a->errh = errh; a->arg = arg; if (a->cfg.txmode == AUDIO_MODE_TMR) tmr_init(&tx->u.tmr); out: if (err) mem_deref(a); else *ap = a; return err; }
int bfcp_alloc(struct bfcp **bfcpp, struct sdp_session *sdp_sess, const char *proto, bool offerer, const struct mnat *mnat, struct mnat_sess *mnat_sess) { struct bfcp *bfcp; struct sa laddr; enum bfcp_transp transp; int err; if (!bfcpp || !sdp_sess) return EINVAL; transp = str2tp(proto); bfcp = mem_zalloc(sizeof(*bfcp), destructor); if (!bfcp) return ENOMEM; bfcp->active = offerer; sa_init(&laddr, AF_INET); err = bfcp_listen(&bfcp->conn, transp, &laddr, uag_tls(), bfcp_msg_handler, bfcp); if (err) goto out; err = sdp_media_add(&bfcp->sdpm, sdp_sess, "application", sa_port(&laddr), bfcp_sdp_transp(transp)); if (err) goto out; err = sdp_format_add(NULL, bfcp->sdpm, false, "*", NULL, 0, 0, NULL, NULL, NULL, false, NULL); if (err) goto out; err |= sdp_media_set_lattr(bfcp->sdpm, true, "floorctrl", "c-s"); err |= sdp_media_set_lattr(bfcp->sdpm, true, "setup", bfcp->active ? "active" : "actpass"); if (bfcp->active) { err |= sdp_media_set_lattr(bfcp->sdpm, true, "connection", "new"); } else { bfcp->lconfid = 1000 + (rand_u16() & 0xf); bfcp->luserid = 1 + (rand_u16() & 0x7); err |= sdp_media_set_lattr(bfcp->sdpm, true, "confid", "%u", bfcp->lconfid); err |= sdp_media_set_lattr(bfcp->sdpm, true, "userid", "%u", bfcp->luserid); } if (err) goto out; if (mnat) { info("bfcp: enabled medianat '%s' on UDP socket\n", mnat->id); err = mnat->mediah(&bfcp->mnat_st, mnat_sess, IPPROTO_UDP, bfcp_sock(bfcp->conn), NULL, bfcp->sdpm); if (err) goto out; } info("bfcp: %s BFCP agent protocol '%s' on port %d\n", bfcp->active ? "Active" : "Passive", proto, sa_port(&laddr)); out: if (err) mem_deref(bfcp); else *bfcpp = bfcp; return err; }
/** Test BFCP in SDP -- RFC 4583 */ int test_sdp_bfcp(void) { static const char *msg_offer = "v=0\r\n" "o=alice 2890844526 2890844526 IN IP4 1.2.3.4\r\n" "s=-\r\n" "c=IN IP4 1.2.3.4\r\n" "t=0 0\r\n" "m=application 50000 TCP/BFCP *\r\n" "a=sendrecv\r\n" "a=setup:passive\r\n" "a=connection:new\r\n" "a=floorctrl:s-only\r\n" "a=confid:4321\r\n" "a=userid:1234\r\n" "a=floorid:1 m-stream:10\r\n" "a=floorid:2 m-stream:11\r\n" "m=audio 50002 RTP/AVP 0\r\n" "a=sendrecv\r\n" "a=label:10\r\n" "m=video 50004 RTP/AVP 31\r\n" "a=sendrecv\r\n" "a=label:11\r\n" ; struct sdp_session *alice = NULL, *bob = NULL; struct sdp_media *bfcp, *audio, *video; struct mbuf *mbo = NULL, *mba = NULL; struct sa laddr; int err; /* create sessions */ (void)sa_set_str(&laddr, "1.2.3.4", 0); err = sdp_session_alloc(&alice, &laddr); if (err) goto out; err = sdp_media_add(&bfcp, alice, "application", 50000, "TCP/BFCP"); if (err) goto out; err |= sdp_media_set_lattr(bfcp, true, "setup", "passive"); err |= sdp_media_set_lattr(bfcp, true, "connection", "new"); err |= sdp_media_set_lattr(bfcp, true, "floorctrl", "s-only"); err |= sdp_media_set_lattr(bfcp, true, "confid", "4321"); err |= sdp_media_set_lattr(bfcp, true, "userid", "1234"); err |= sdp_media_set_lattr(bfcp, false, "floorid", "1 m-stream:10"); sdp_media_del_lattr(bfcp, "floorid"); /* test attr delete */ err |= sdp_media_set_lattr(bfcp, false, "floorid", "1 m-stream:10"); err |= sdp_media_set_lattr(bfcp, false, "floorid", "2 m-stream:11"); if (err) goto out; err = sdp_media_add(&audio, alice, "audio", 50002, "RTP/AVP"); if (err) goto out; err = sdp_media_add(&video, alice, "video", 50004, "RTP/AVP"); if (err) goto out; err |= sdp_media_set_lattr(audio, true, "label", "10"); err |= sdp_media_set_lattr(video, true, "label", "11"); if (err) goto out; err = sdp_format_add(NULL, bfcp, false, "*", NULL, 0, 0, NULL, NULL, NULL, false, NULL); err |= sdp_format_add(NULL, audio, false, "0", NULL, 0, 0, NULL, NULL, NULL, false, NULL); err |= sdp_format_add(NULL, video, false, "31", NULL, 0, 0, NULL, NULL, NULL, false, NULL); if (err) goto out; /* create and send offer, compare offer */ err = sdp_encode(&mbo, alice, true); if (err) goto out; if (!sdp_cmp(mbo, msg_offer)) { DEBUG_WARNING("offer failed:\n%b", mbo->buf, mbo->end); err = EBADMSG; goto out; } out: mem_deref(alice); mem_deref(bob); mem_deref(mbo); mem_deref(mba); return err; }