int stream_send(struct stream *s, bool marker, int pt, uint32_t ts, struct mbuf *mb) { int err = 0; if (!s) return EINVAL; if (!sa_isset(sdp_media_raddr(s->sdp), SA_ALL)) return 0; if (sdp_media_dir(s->sdp) != SDP_SENDRECV) return 0; metric_add_packet(&s->metric_tx, mbuf_get_left(mb)); if (pt < 0) pt = s->pt_enc; if (pt >= 0) { err = rtp_send(s->rtp, sdp_media_raddr(s->sdp), marker, pt, ts, mb); if (err) s->metric_tx.n_err++; } rtpkeep_refresh(s->rtpkeep, ts); return err; }
int stream_send(struct stream *s, bool marker, int pt, uint32_t ts, struct mbuf *mb) { int err = 0; if (!s) return EINVAL; if (!sa_isset(sdp_media_raddr(s->sdp), SA_ALL)) return 0; if (sdp_media_dir(s->sdp) != SDP_SENDRECV) return 0; s->stats.b_tx += mbuf_get_left(mb); if (pt < 0) pt = s->pt_enc; if (pt >= 0) { err = rtp_send(s->rtp, sdp_media_raddr(s->sdp), marker, pt, ts, mb); } rtpkeep_refresh(s->rtpkeep, ts); ++s->stats.n_tx; return err; }
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; }
int bfcp_start(struct bfcp *bfcp) { const struct sa *paddr; uint32_t confid = 0; uint16_t userid = 0; int err = 0; if (!bfcp) return EINVAL; if (!sdp_media_rport(bfcp->sdpm)) { info("bfcp channel is disabled\n"); return 0; } if (bfcp->active) { paddr = sdp_media_raddr(bfcp->sdpm); confid = sdp_media_rattr_u32(bfcp->sdpm, "confid"); userid = sdp_media_rattr_u32(bfcp->sdpm, "userid"); err = bfcp_request(bfcp->conn, paddr, BFCP_VER2, BFCP_HELLO, confid, userid, bfcp_resp_handler, bfcp, 0); } return err; }
static int update(struct mnat_sess *sess) { struct le *le; int err = 0; if (!sess) return EINVAL; for (le=sess->medial.head; le; le=le->next) { struct mnat_media *m = le->data; struct sa raddr1, raddr2; raddr1 = *sdp_media_raddr(m->sdpm); sdp_media_raddr_rtcp(m->sdpm, &raddr2); if (m->turnc1 && sa_isset(&raddr1, SA_ALL)) err |= turnc_add_chan(m->turnc1, &raddr1, NULL, NULL); if (m->turnc2 && sa_isset(&raddr2, SA_ALL)) err |= turnc_add_chan(m->turnc2, &raddr2, NULL, NULL); } return err; }
/* * Reference: * * https://www.avm.de/de/Extern/files/x-rtp/xrtpv32.pdf */ int audio_print_rtpstat(struct re_printf *pf, const struct audio *a) { const struct stream *s; const struct rtcp_stats *rtcp; int srate_tx = 8000; int srate_rx = 8000; int err; if (!a) return 1; s = a->strm; rtcp = &s->rtcp_stats; if (!rtcp->tx.sent) return 1; if (a->tx.ac) srate_tx = get_srate(a->tx.ac); if (a->rx.ac) srate_rx = get_srate(a->rx.ac); err = re_hprintf(pf, "EX=BareSip;" /* Reporter Identifier */ "CS=%d;" /* Call Setup in milliseconds */ "CD=%d;" /* Call Duration in seconds */ "PR=%u;PS=%u;" /* Packets RX, TX */ "PL=%d,%d;" /* Packets Lost RX, TX */ "PD=%d,%d;" /* Packets Discarded, RX, TX */ "JI=%.1f,%.1f;" /* Jitter RX, TX in timestamp units */ "IP=%J,%J" /* Local, Remote IPs */ , call_setup_duration(s->call) * 1000, call_duration(s->call), s->metric_rx.n_packets, s->metric_tx.n_packets, rtcp->rx.lost, rtcp->tx.lost, s->metric_rx.n_err, s->metric_tx.n_err, /* timestamp units (ie: 8 ts units = 1 ms @ 8KHZ) */ 1.0 * rtcp->rx.jit/1000 * (srate_rx/1000), 1.0 * rtcp->tx.jit/1000 * (srate_tx/1000), sdp_media_laddr(s->sdp), sdp_media_raddr(s->sdp) ); if (a->tx.ac) { err |= re_hprintf(pf, ";EN=%s/%d", a->tx.ac->name, srate_tx ); } if (a->rx.ac) { err |= re_hprintf(pf, ";DE=%s/%d", a->rx.ac->name, srate_rx ); } return err; }
/* print SDP status */ static void update_media(void) { const struct sdp_format *fmt; re_printf("SDP peer address: %J\n", sdp_media_raddr(sdp_media)); fmt = sdp_media_rformat(sdp_media, NULL); if (!fmt) { re_printf("no common media format found\n"); return; } re_printf("SDP media format: %s/%u/%u (payload type: %u)\n", fmt->name, fmt->srate, fmt->ch, fmt->pt); }
int stream_debug(struct re_printf *pf, const struct stream *s) { struct sa rrtcp; int err; if (!s) return 0; err = re_hprintf(pf, " %s dir=%s pt_enc=%d\n", sdp_media_name(s->sdp), sdp_dir_name(sdp_media_dir(s->sdp)), s->pt_enc); sdp_media_raddr_rtcp(s->sdp, &rrtcp); err |= re_hprintf(pf, " remote: %J/%J\n", sdp_media_raddr(s->sdp), &rrtcp); err |= rtp_debug(pf, s->rtp); err |= jbuf_debug(pf, s->jbuf); return err; }
static void stream_remote_set(struct stream *s) { struct sa rtcp; if (!s) return; /* RFC 5761 */ if (s->cfg.rtcp_mux && sdp_media_rattr(s->sdp, "rtcp-mux")) { if (!s->rtcp_mux) info("%s: RTP/RTCP multiplexing enabled\n", sdp_media_name(s->sdp)); s->rtcp_mux = true; } rtcp_enable_mux(s->rtp, s->rtcp_mux); sdp_media_raddr_rtcp(s->sdp, &rtcp); rtcp_start(s->rtp, s->cname, s->rtcp_mux ? sdp_media_raddr(s->sdp): &rtcp); }
static void stream_remote_set(struct stream *s, const char *cname) { struct sa rtcp; if (!s) return; /* RFC 5761 */ if (config.avt.rtcp_mux && sdp_media_rattr(s->sdp, "rtcp-mux")) { if (!s->rtcp_mux) (void)re_printf("%s: RTP/RTCP multiplexing enabled\n", sdp_media_name(s->sdp)); s->rtcp_mux = true; } rtcp_enable_mux(s->rtp, s->rtcp_mux); sdp_media_raddr_rtcp(s->sdp, &rtcp); rtcp_start(s->rtp, cname, s->rtcp_mux ? sdp_media_raddr(s->sdp): &rtcp); }
int call_accept(struct call *call, struct sipsess_sock *sess_sock, const struct sip_msg *msg) { bool got_offer; int err; if (!call || !msg) return EINVAL; call->outgoing = false; got_offer = (mbuf_get_left(msg->mb) > 0); err = pl_strdup(&call->peer_uri, &msg->from.auri); if (err) return err; if (pl_isset(&msg->from.dname)) { err = pl_strdup(&call->peer_name, &msg->from.dname); if (err) return err; } if (got_offer) { struct sdp_media *m; const struct sa *raddr; err = sdp_decode(call->sdp, msg->mb, true); if (err) return err; call->got_offer = true; /* * Each media description in the SDP answer MUST * use the same network type as the corresponding * media description in the offer. * * See RFC 6157 */ m = stream_sdpmedia(audio_strm(call->audio)); raddr = sdp_media_raddr(m); if (sa_af(raddr) != call->af) { info("call: incompatible address-family" " (local=%s, remote=%s)\n", net_af2name(call->af), net_af2name(sa_af(raddr))); sip_treply(NULL, uag_sip(), msg, 488, "Not Acceptable Here"); call_event_handler(call, CALL_EVENT_CLOSED, "Wrong address family"); return 0; } /* Check if we have any common audio codecs, after * the SDP offer has been parsed */ if (!have_common_audio_codecs(call)) { info("call: no common audio codecs - rejected\n"); sip_treply(NULL, uag_sip(), msg, 488, "Not Acceptable Here"); call_event_handler(call, CALL_EVENT_CLOSED, "No audio codecs"); return 0; } } err = sipsess_accept(&call->sess, sess_sock, msg, 180, "Ringing", ua_cuser(call->ua), "application/sdp", NULL, auth_handler, call->acc, true, sipsess_offer_handler, sipsess_answer_handler, sipsess_estab_handler, sipsess_info_handler, sipsess_refer_handler, sipsess_close_handler, call, "Allow: %s\r\n", uag_allowed_methods()); if (err) { warning("call: sipsess_accept: %m\n", err); return err; } set_state(call, STATE_INCOMING); /* New call */ tmr_start(&call->tmr_inv, LOCAL_TIMEOUT*1000, invite_timeout, call); if (!call->acc->mnat) call_event_handler(call, CALL_EVENT_INCOMING, call->peer_uri); return err; }
int test_sdp_all(void) { struct sdp_session *sess = NULL; struct sdp_media *audio = NULL; struct mbuf *desc = NULL; struct sa ref; const struct sdp_format *rc = NULL, *sc; struct sa laddr; int err; (void)sa_set_str(&laddr, ref_host, 0); err = sdp_session_alloc(&sess, &laddr); if (err) goto out; err = sdp_media_add(&audio, sess, sdp_media_audio, 5004, sdp_proto_rtpavp); if (err) goto out; err = sdp_format_add(NULL, audio, false, ref_pt, ref_cname, ref_srate, 1, NULL, NULL, NULL, false, NULL); err |= sdp_format_add(NULL, audio, false, "110", cname_speex, 16000, 2, NULL, NULL, NULL, false, NULL); if (err) goto out; /* find codec - expected */ sc = sdp_media_format(audio, true, NULL, 0, "PCMU", 8000, 1); if (!sc) { DEBUG_WARNING("codec not found\n"); err = ENOENT; goto out; } sc = sdp_media_format(audio, true, NULL, 110, "Speex", 16000, 2); if (!sc) { DEBUG_WARNING("codec not found: speex\n"); err = ENOENT; goto out; } /* find codec - not expected */ sc = sdp_media_format(audio, true, NULL, -1, "Speex", 8000, 1); if (sc) { DEBUG_WARNING("unexpected codec found\n"); err = EINVAL; goto out; } err = sdp_encode(&desc, sess, true); if (err) goto out; if (!sdp_cmp(desc, ref_msg)) { DEBUG_WARNING("ref: %s\n", ref_msg); DEBUG_WARNING("sdp: %b\n", desc->buf, desc->end); err = EBADMSG; goto out; } err = sdp_decode(sess, desc, false); if (err) goto out; rc = sdp_media_rformat(audio, NULL); if (!rc) { err = ENOENT; goto out; } err = sa_set_str(&ref, ref_host, ref_port); if (err) goto out; err = EINVAL; if (!sa_cmp(sdp_media_raddr(audio), &ref, SA_ALL)) goto out; if (!rc) goto out; if (0 != strcmp(rc->id, ref_pt)) goto out; if (0 != strcmp(ref_cname, rc->name)) goto out; if (rc->srate != ref_srate) goto out; err = 0; out: mem_deref(audio); mem_deref(sess); mem_deref(desc); return err; }