static int encode(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src) { int len; if (!mbuf_get_left(src)) return 0; if (mbuf_get_left(src) != st->fsize) { DEBUG_WARNING("encode: got %d bytes, expected %d\n", mbuf_get_left(src), st->fsize); return EINVAL; } if (mbuf_get_space(dst) < MAX_PACKET) { int err = mbuf_resize(dst, dst->pos + MAX_PACKET); if (err) return err; } len = opus_encode(st->enc, (short *)mbuf_buf(src), st->frame_size, mbuf_buf(dst), (int)mbuf_get_space(dst)); if (len < 0) { DEBUG_WARNING("encode error: %d (%u bytes)\n", len, mbuf_get_left(src)); return EPROTO; } src->pos = src->end; dst->end = dst->pos + len; return 0; }
static bool udp_helper_send(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct menc_media *st = arg; unsigned int length; zrtp_status_t s; (void)dst; length = (unsigned int)mbuf_get_left(mb); s = zrtp_process_rtp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); if (s != zrtp_status_ok) { warning("zrtp: zrtp_process_rtp failed (status = %d)\n", s); return false; } /* make sure target buffer is large enough */ if (length > mbuf_get_space(mb)) { warning("zrtp: zrtp_process_rtp: length > space (%u > %u)\n", length, mbuf_get_space(mb)); *err = ENOMEM; } mb->end = mb->pos + length; return false; }
static bool udp_helper_send(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct menc_media *st = arg; unsigned int length; zrtp_status_t s; const char *proto_name = "rtp"; enum pkt_type ptype = get_packet_type(mb); if (drop_packets(st)) return true; length = (unsigned int)mbuf_get_left(mb); /* only RTP/RTCP packets should be processed */ if (ptype == PKT_TYPE_RTCP) { proto_name = "rtcp"; s = zrtp_process_rtcp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); } else if (ptype == PKT_TYPE_RTP) { s = zrtp_process_rtp(st->zrtp_stream, (char *)mbuf_buf(mb), &length); } else return false; if (s != zrtp_status_ok) { if (s == zrtp_status_drop) return true; warning("zrtp: send(port=%d): zrtp_process_%s failed" " (status = %d '%s')\n", sa_port(dst), proto_name, s, zrtp_log_status2str(s)); return false; } /* make sure target buffer is large enough */ if (length > mbuf_get_space(mb)) { warning("zrtp: zrtp_process_%s: length > space (%u > %u)\n", proto_name, length, mbuf_get_space(mb)); *err = ENOMEM; } mb->end = mb->pos + length; return false; }
/* src=NULL means lost packet */ static int decode(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src) { int r; if (!mbuf_get_left(src) && !st->got_packet) return 0; /* Make sure there is enough space in the buffer */ if (mbuf_get_space(dst) < st->fsize) { int err = mbuf_resize(dst, dst->pos + st->fsize); if (err) return err; } r = opus_decode(st->dec, mbuf_buf(src), (int)mbuf_get_left(src), (short *)mbuf_buf(dst), st->frame_size, 0); if (r <= 0) { DEBUG_WARNING("opus_decode: r=%d (%u bytes)\n", r, mbuf_get_left(src)); return EBADMSG; } if (src) src->pos = src->end; dst->end += 2 * r * aucodec_ch(st->ac); st->got_packet = true; return 0; }
static int decode_frame(struct aucodec_st *st, struct mbuf *dst, struct mbuf *src, uint16_t src_len) { int ret, err; if (mbuf_get_left(src) < src_len) { DEBUG_WARNING("dec: corrupt frame %u < %u\n", mbuf_get_left(src), src_len); return EPROTO; } /* Make sure there is enough space in the buffer */ if (mbuf_get_space(dst) < st->fsize) { err = mbuf_resize(dst, dst->size + st->fsize); if (err) return err; } ret = celt_decode(st->dec, mbuf_buf(src), src_len, (short *)mbuf_buf(dst), st->frame_size); if (CELT_OK != ret) { DEBUG_WARNING("celt_decode: ret=%d\n", ret); } DEBUG_INFO("decode: %u -> %u\n", src_len, st->fsize); if (src) mbuf_advance(src, src_len); dst->end += st->fsize; return 0; }
/** * Encoder audio and send via stream * * @note This function has REAL-TIME properties */ static void encode_rtp_send(struct audio *a, struct autx *tx, int16_t *sampv, size_t sampc) { size_t len; int err; if (!tx->ac) return; tx->mb->pos = tx->mb->end = STREAM_PRESZ; len = mbuf_get_space(tx->mb); err = tx->ac->ench(tx->enc, mbuf_buf(tx->mb), &len, sampv, sampc); if (err) { DEBUG_WARNING("%s encode error: %d samples (%m)\n", tx->ac->name, sampc, err); goto out; } tx->mb->pos = STREAM_PRESZ; tx->mb->end = STREAM_PRESZ + len; if (mbuf_get_left(tx->mb)) { err = stream_send(a->strm, tx->marker, -1, tx->ts, tx->mb); if (err) goto out; } tx->ts += (uint32_t)(tx->is_g722 ? sampc/2 : sampc); out: tx->marker = false; }
/* PLC is only valid for Decoding (RX) */ static int dec(struct aufilt_st *st, struct mbuf *mb) { int nsamp = (int)mbuf_get_left(mb) / 2; if (nsamp) { nsamp = plc_rx(&st->plc, (int16_t *)mbuf_buf(mb), nsamp); if (nsamp >= 0) mb->end = mb->pos + (2*nsamp); } else { nsamp = (int)st->psize / 2; re_printf("plc: concealing %u bytes\n", st->psize); if (mbuf_get_space(mb) < st->psize) { int err = mbuf_resize(mb, st->psize); if (err) return err; } nsamp = plc_fillin(&st->plc, (int16_t *)mbuf_buf(mb), nsamp); mb->end = mb->pos + 2 * nsamp; } return 0; }
static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct dtls_flow *flow = arg; uint8_t b; int r, n; if (mbuf_get_left(mb) < 1) return false; /* ignore non-DTLS packets */ b = mb->buf[mb->pos]; if (b < 20 || b > 63) return false; if (!sa_cmp(src, &flow->peer, SA_ALL)) return false; /* feed SSL data to the BIO */ r = BIO_write(flow->sbio_in, mbuf_buf(mb), (int)mbuf_get_left(mb)); if (r <= 0) return true; n = SSL_read(flow->ssl, mbuf_buf(mb), (int)mbuf_get_space(mb)); if (n <= 0) { ERR_clear_error(); } if (!flow->up && SSL_state(flow->ssl) == SSL_ST_OK) { struct key client_key, server_key; char profile[256]; int err; flow->up = true; err = get_srtp_key_info(flow, profile, sizeof(profile), &client_key, &server_key); if (err) { warning("dtls: SRTP key info: %m\n", err); return true; } flow->estabh(0, flow, profile, &client_key, &server_key, flow->arg); } return true; }
static void read_handler(int flags, void *arg) { struct ausrc_st *st = arg; struct mbuf *mb = st->mb; int n; (void)flags; n = read(st->fd, mbuf_buf(mb), mbuf_get_space(mb)); if (n <= 0) return; mb->pos += n; if (mb->pos < mb->size) return; st->rh(mb->buf, mb->size, st->arg); mb->pos = 0; }
/** * Encoder audio and send via stream * * @note This function has REAL-TIME properties * * @param a Audio object * @param tx Audio transmit object * @param sampv Audio samples * @param sampc Number of audio samples */ static void encode_rtp_send(struct audio *a, struct autx *tx, int16_t *sampv, size_t sampc) { size_t frame_size; /* number of samples per channel */ size_t len; int err; if (!tx->ac) return; tx->mb->pos = tx->mb->end = STREAM_PRESZ; len = mbuf_get_space(tx->mb); err = tx->ac->ench(tx->enc, mbuf_buf(tx->mb), &len, sampv, sampc); if (err) { warning("audio: %s encode error: %d samples (%m)\n", tx->ac->name, sampc, err); goto out; } tx->mb->pos = STREAM_PRESZ; tx->mb->end = STREAM_PRESZ + len; if (mbuf_get_left(tx->mb)) { err = stream_send(a->strm, tx->marker, -1, tx->ts, tx->mb); if (err) goto out; } /* The RTP clock rate used for generating the RTP timestamp is * independent of the number of channels and the encoding */ frame_size = (tx->is_g722 ? sampc/2 : sampc) / tx->ac->ch; tx->ts += (uint32_t)frame_size; out: tx->marker = false; }
static bool send_handler(int *err, struct sa *dst, struct mbuf *mb, void *arg) { struct menc_st *st = arg; err_status_t e; int len; (void)dst; if (!st->use_srtp || !is_rtp_or_rtcp(mb)) return false; len = (int)mbuf_get_left(mb); if (mbuf_get_space(mb) < ((size_t)len + SRTP_MAX_TRAILER_LEN)) { mbuf_resize(mb, mb->pos + len + SRTP_MAX_TRAILER_LEN); } if (is_rtcp_packet(mb)) { e = srtp_protect_rtcp(st->srtp_tx, mbuf_buf(mb), &len); } else { e = srtp_protect(st->srtp_tx, mbuf_buf(mb), &len); } if (err_status_ok != e) { DEBUG_WARNING("send: failed to protect %s-packet" " with %d bytes (%H)\n", is_rtcp_packet(mb) ? "RTCP" : "RTP", len, errstatus_print, e); *err = EPROTO; return false; } mbuf_set_end(mb, mb->pos + len); return false; /* continue processing */ }
static bool recv_handler(int *err, struct mbuf *mb, bool *estab, void *arg) { struct tls_conn *tc = arg; int r; /* feed SSL data to the BIO */ r = BIO_write(tc->sbio_in, mbuf_buf(mb), (int)mbuf_get_left(mb)); if (r <= 0) { DEBUG_WARNING("recv: BIO_write %d\n", r); *err = ENOMEM; return true; } if (SSL_state(tc->ssl) != SSL_ST_OK) { if (tc->up) { *err = EPROTO; return true; } if (tc->active) { *err = tls_connect(tc); } else { *err = tls_accept(tc); } DEBUG_INFO("state=0x%04x\n", SSL_state(tc->ssl)); /* TLS connection is established */ if (SSL_state(tc->ssl) != SSL_ST_OK) return true; *estab = true; tc->up = true; } mbuf_set_pos(mb, 0); for (;;) { int n; if (mbuf_get_space(mb) < 4096) { *err = mbuf_resize(mb, mb->size + 8192); if (*err) return true; } n = SSL_read(tc->ssl, mbuf_buf(mb), (int)mbuf_get_space(mb)); if (n < 0) { const int ssl_err = SSL_get_error(tc->ssl, n); switch (ssl_err) { case SSL_ERROR_WANT_READ: break; default: *err = EPROTO; return true; } break; } else if (n == 0) break; mb->pos += n; } mbuf_set_end(mb, mb->pos); mbuf_set_pos(mb, 0); return false; }
static bool recv_handler(struct sa *src, struct mbuf *mb, void *arg) { struct tls_sock *ts = arg; struct tls_conn *tc; int r; tc = tls_udp_conn(ts, src); if (!tc) { /* No connection found, assuming Server role */ tc = conn_alloc(ts, src); if (!tc) return true; SSL_set_verify(tc->ssl, 0, 0); SSL_set_accept_state(tc->ssl); } /* feed SSL data to the BIO */ r = BIO_write(tc->sbio_in, mbuf_buf(mb), (int)mbuf_get_left(mb)); if (r <= 0) return true; check_timer(tc); mbuf_set_pos(mb, 0); for (;;) { int n; if (mbuf_get_space(mb) < 4096) { if (mbuf_resize(mb, mb->size + 8192)) return true; } n = SSL_read(tc->ssl, mbuf_buf(mb), (int)mbuf_get_space(mb)); if (n < 0) { const int ssl_err = SSL_get_error(tc->ssl, n); switch (ssl_err) { case SSL_ERROR_WANT_READ: break; default: return true; } break; } else if (n == 0) break; mb->pos += n; } if (!mb->pos) return true; mbuf_set_end(mb, mb->pos); mbuf_set_pos(mb, 0); return false; }