static bool sdp_attr_handler(const char *name, const char *value, void *arg) { struct menc_st *st = arg; struct crypto c; (void)name; if (sdes_decode_crypto(&c, value)) return false; if (0 != pl_strcmp(&c.key_method, "inline")) return false; if (!cryptosuite_issupported(&c.suite)) return false; st->crypto_suite = mem_deref(st->crypto_suite); pl_strdup(&st->crypto_suite, &c.suite); if (start_crypto(st, &c.key_info)) return false; sdp_enc(st, st->sdpm, c.tag, st->crypto_suite); return true; }
static int 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_st *st; const char *rattr = NULL; int layer = 10; /* above zero */ int err = 0; bool mux = (rtpsock == rtcpsock); (void)sess; (void)rtp; if (!stp || !sdpm) return EINVAL; if (proto != IPPROTO_UDP) return EPROTONOSUPPORT; st = (struct menc_st *)*stp; if (!st) { st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->sdpm = mem_ref(sdpm); err = sdp_media_set_alt_protos(st->sdpm, 4, "RTP/AVP", "RTP/AVPF", "RTP/SAVP", "RTP/SAVPF"); if (err) goto out; if (rtpsock) { st->rtpsock = mem_ref(rtpsock); err |= udp_register_helper(&st->uh_rtp, rtpsock, layer, send_handler, recv_handler, st); } if (rtcpsock && !mux) { st->rtcpsock = mem_ref(rtcpsock); err |= udp_register_helper(&st->uh_rtcp, rtcpsock, layer, send_handler, recv_handler, st); } if (err) goto out; /* set our preferred crypto-suite */ err |= str_dup(&st->crypto_suite, aes_cm_128_hmac_sha1_80); if (err) goto out; err = setup_srtp(st); if (err) goto out; } /* SDP handling */ if (sdp_media_rattr(st->sdpm, "crypto")) { rattr = sdp_media_rattr_apply(st->sdpm, "crypto", sdp_attr_handler, st); if (!rattr) { DEBUG_WARNING("no valid a=crypto attribute from" " remote peer\n"); } } if (!rattr) err = sdp_enc(st, sdpm, 0, st->crypto_suite); out: if (err) mem_deref(st); else *stp = (struct menc_media *)st; return err; }
static int media_alloc(struct menc_media **stp, struct menc_sess *sess, struct rtp_sock *rtp, struct udp_sock *rtpsock, struct udp_sock *rtcpsock, const struct sa *raddr_rtp, const struct sa *raddr_rtcp, struct sdp_media *sdpm) { struct menc_st *st; const char *rattr = NULL; int layer = 10; /* above zero */ int err = 0; bool mux = (rtpsock == rtcpsock); (void)sess; (void)rtp; (void)raddr_rtp; (void)raddr_rtcp; if (!stp || !sdpm || !sess) return EINVAL; st = (struct menc_st *)*stp; if (!st) { st = mem_zalloc(sizeof(*st), destructor); if (!st) return ENOMEM; st->sess = sess; st->sdpm = mem_ref(sdpm); if (0 == str_cmp(sdp_media_proto(sdpm), "RTP/AVP")) { err = sdp_media_set_alt_protos(st->sdpm, 4, "RTP/AVP", "RTP/AVPF", "RTP/SAVP", "RTP/SAVPF"); if (err) goto out; } if (rtpsock) { st->rtpsock = mem_ref(rtpsock); err |= udp_register_helper(&st->uh_rtp, rtpsock, layer, send_handler, recv_handler, st); } if (rtcpsock && !mux) { st->rtcpsock = mem_ref(rtcpsock); err |= udp_register_helper(&st->uh_rtcp, rtcpsock, layer, send_handler, recv_handler, st); } if (err) goto out; /* set our preferred crypto-suite */ err |= str_dup(&st->crypto_suite, preferred_suite); if (err) goto out; rand_bytes(st->key_tx, sizeof(st->key_tx)); } /* SDP handling */ if (sdp_media_rport(sdpm)) st->got_sdp = true; if (sdp_media_rattr(st->sdpm, "crypto")) { rattr = sdp_media_rattr_apply(st->sdpm, "crypto", sdp_attr_handler, st); if (!rattr) { warning("srtp: no valid a=crypto attribute from" " remote peer\n"); } } if (!rattr) err = sdp_enc(st, sdpm, 1, st->crypto_suite); out: if (err) mem_deref(st); else *stp = (struct menc_media *)st; return err; }