/* * called when an SDP offer is received (got offer: true) or * when an offer is to be sent (got_offer: false) */ static int offer_handler(struct mbuf **mbp, const struct sip_msg *msg, void *arg) { const bool got_offer = mbuf_get_left(msg->mb); int err; (void)arg; if (got_offer) { err = sdp_decode(sdp, msg->mb, true); if (err) { re_fprintf(stderr, "unable to decode SDP offer: %s\n", strerror(err)); return err; } re_printf("SDP offer received\n"); update_media(); } else { re_printf("sending SDP offer\n"); } return sdp_encode(mbp, sdp, !got_offer); }
static int sipsess_offer_handler(struct mbuf **descp, const struct sip_msg *msg, void *arg) { const bool got_offer = mbuf_get_left(msg->mb); struct call *call = arg; int err; MAGIC_CHECK(call); info("call: got re-INVITE%s\n", got_offer ? " (SDP Offer)" : ""); if (got_offer) { /* Decode SDP Offer */ err = sdp_decode(call->sdp, msg->mb, true); if (err) return err; err = update_media(call); if (err) return err; } /* Encode SDP Answer */ return sdp_encode(descp, call->sdp, !got_offer); }
int call_answer(struct call *call, uint16_t scode) { struct mbuf *desc; int err; if (!call || !call->sess) return EINVAL; if (STATE_INCOMING != call->state) { return 0; } info("answering call from %s with %u\n", call->peer_uri, scode); if (call->got_offer) { err = update_media(call); if (err) return err; } err = sdp_encode(&desc, call->sdp, !call->got_offer); if (err) return err; err = sipsess_answer(call->sess, scode, "Answering", desc, "Allow: %s\r\n", uag_allowed_methods()); mem_deref(desc); return err; }
int sdp_encode_list_to_file (session_desc_t *sptr, const char *filename, int append) { FILE *ofile; sdp_encode_t sdp; int retval; CHECK_RETURN(prepare_sdp_encode(&sdp)); ofile = fopen(filename, append ? "a" : "w"); if (ofile == NULL) { free(sdp.buffer); return (-1); } while (sptr != NULL) { sdp.used = 0; retval = sdp_encode(sptr, &sdp); if (retval != 0) { break; } fputs(sdp.buffer, ofile); sptr = sptr->next; } fclose(ofile); free(sdp.buffer); return (0); }
/* called upon incoming calls */ static void connect_handler(const struct sip_msg *msg, void *arg) { struct mbuf *mb; bool got_offer; int err; (void)arg; if (sess) { /* Already in a call */ (void)sip_treply(NULL, sip, msg, 486, "Busy Here"); return; } got_offer = (mbuf_get_left(msg->mb) > 0); /* Decode SDP offer if incoming INVITE contains SDP */ if (got_offer) { err = sdp_decode(sdp, msg->mb, true); if (err) { re_fprintf(stderr, "unable to decode SDP offer: %s\n", strerror(err)); goto out; } update_media(); } /* Encode SDP */ err = sdp_encode(&mb, sdp, !got_offer); if (err) { re_fprintf(stderr, "unable to encode SDP: %s\n", strerror(err)); goto out; } /* Answer incoming call */ err = sipsess_accept(&sess, sess_sock, msg, 200, "OK", name, "application/sdp", mb, auth_handler, NULL, false, offer_handler, answer_handler, establish_handler, NULL, NULL, close_handler, NULL, NULL); mem_deref(mb); /* free SDP buffer */ if (err) { re_fprintf(stderr, "session accept error: %s\n", strerror(err)); goto out; } out: if (err) { (void)sip_treply(NULL, sip, msg, 500, strerror(err)); } else { re_printf("accepting incoming call from <%r>\n", &msg->from.auri); } }
static int oa_offeranswer(struct oa *oa, const char *offer, const char *answer) { struct mbuf *mbo = NULL, *mba = NULL; int err = 0; /* create and send offer, compare offer */ err = sdp_encode(&mbo, oa->alice, true); if (err) goto out; if (!sdp_cmp(mbo, offer)) { DEBUG_WARNING("offer failed:\n%b", mbo->buf, mbo->end); err = EBADMSG; goto out; } /* bob decodes offer */ err = sdp_decode(oa->bob, mbo, true); if (err) goto out; /* create and send answer, compare answer */ err = sdp_encode(&mba, oa->bob, false); if (err) goto out; if (!sdp_cmp(mba, answer)) { DEBUG_WARNING("answer failed:\n%b", mba->buf, mba->end); err = EBADMSG; goto out; } err = sdp_decode(oa->alice, mba, false); out: oa_reset(oa); mem_deref(mbo); mem_deref(mba); return err; }
int sdp_encode_one_to_memory (session_desc_t *sptr, char **mem) { sdp_encode_t sdp; int retval; *mem = NULL; CHECK_RETURN(prepare_sdp_encode(&sdp)); retval = sdp_encode(sptr, &sdp); if (retval != 0) { free(sdp.buffer); return (retval); } *mem = sdp.buffer; return (0); }
int sdp_encode_one_to_file (session_desc_t *sptr, const char *filename, int append) { FILE *ofile; sdp_encode_t sdp; CHECK_RETURN(prepare_sdp_encode(&sdp)); CHECK_RETURN(sdp_encode(sptr, &sdp)); ofile = fopen(filename, append ? "a" : "w"); if (ofile == NULL) { sdp_debug(LOG_CRIT, "Cannot open file %s", filename); free(sdp.buffer); return (-1); } fputs(sdp.buffer, ofile); fclose(ofile); free(sdp.buffer); return (0); }
int sdp_encode_list_to_memory (session_desc_t *sptr, char **mem, int *count) { sdp_encode_t sdp; int retval; int cnt; *mem = NULL; CHECK_RETURN(prepare_sdp_encode(&sdp)); cnt = 0; retval = 0; while (sptr != NULL && retval == 0) { retval = sdp_encode(sptr, &sdp); if (retval == 0) cnt++; sptr = sptr->next; } *mem = sdp.buffer; if (count != NULL) *count = cnt; return (retval); }
int call_sdp_get(const struct call *call, struct mbuf **descp, bool offer) { return sdp_encode(descp, call->sdp, offer); }
int main(int argc, char *argv[]) { struct sa nsv[16]; struct dnsc *dnsc = NULL; struct sa laddr; uint32_t nsc; int err; /* errno return values */ /* enable coredumps to aid debugging */ (void)sys_coredump_set(true); /* initialize libre state */ err = libre_init(); if (err) { re_fprintf(stderr, "re init failed: %s\n", strerror(err)); goto out; } nsc = ARRAY_SIZE(nsv); /* fetch list of DNS server IP addresses */ err = dns_srv_get(NULL, 0, nsv, &nsc); if (err) { re_fprintf(stderr, "unable to get dns servers: %s\n", strerror(err)); goto out; } /* create DNS client */ err = dnsc_alloc(&dnsc, NULL, nsv, nsc); if (err) { re_fprintf(stderr, "unable to create dns client: %s\n", strerror(err)); goto out; } /* create SIP stack instance */ err = sip_alloc(&sip, dnsc, 32, 32, 32, "ua demo v" VERSION " (" ARCH "/" OS ")", exit_handler, NULL); if (err) { re_fprintf(stderr, "sip error: %s\n", strerror(err)); goto out; } /* fetch local IP address */ err = net_default_source_addr_get(AF_INET, &laddr); if (err) { re_fprintf(stderr, "local address error: %s\n", strerror(err)); goto out; } /* listen on random port */ sa_set_port(&laddr, 0); /* add supported SIP transports */ err |= sip_transp_add(sip, SIP_TRANSP_UDP, &laddr); err |= sip_transp_add(sip, SIP_TRANSP_TCP, &laddr); if (err) { re_fprintf(stderr, "transport error: %s\n", strerror(err)); goto out; } /* create SIP session socket */ err = sipsess_listen(&sess_sock, sip, 32, connect_handler, NULL); if (err) { re_fprintf(stderr, "session listen error: %s\n", strerror(err)); goto out; } /* create the RTP/RTCP socket */ err = rtp_listen(&rtp, IPPROTO_UDP, &laddr, 10000, 30000, true, rtp_handler, rtcp_handler, NULL); if (err) { re_fprintf(stderr, "rtp listen error: %m\n", err); goto out; } re_printf("local RTP port is %u\n", sa_port(rtp_local(rtp))); /* create SDP session */ err = sdp_session_alloc(&sdp, &laddr); if (err) { re_fprintf(stderr, "sdp session error: %s\n", strerror(err)); goto out; } /* add audio sdp media, using port from RTP socket */ err = sdp_media_add(&sdp_media, sdp, "audio", sa_port(rtp_local(rtp)), "RTP/AVP"); if (err) { re_fprintf(stderr, "sdp media error: %s\n", strerror(err)); goto out; } /* add G.711 sdp media format */ err = sdp_format_add(NULL, sdp_media, false, "0", "PCMU", 8000, 1, NULL, NULL, NULL, false, NULL); if (err) { re_fprintf(stderr, "sdp format error: %s\n", strerror(err)); goto out; } /* invite provided URI */ if (argc > 1) { struct mbuf *mb; /* create SDP offer */ err = sdp_encode(&mb, sdp, true); if (err) { re_fprintf(stderr, "sdp encode error: %s\n", strerror(err)); goto out; } err = sipsess_connect(&sess, sess_sock, argv[1], name, uri, name, NULL, 0, "application/sdp", mb, auth_handler, NULL, false, offer_handler, answer_handler, progress_handler, establish_handler, NULL, NULL, close_handler, NULL, NULL); mem_deref(mb); /* free SDP buffer */ if (err) { re_fprintf(stderr, "session connect error: %s\n", strerror(err)); goto out; } re_printf("inviting <%s>...\n", argv[1]); } else { err = sipreg_register(®, sip, registrar, uri, uri, 60, name, NULL, 0, 0, auth_handler, NULL, false, register_handler, NULL, NULL, NULL); if (err) { re_fprintf(stderr, "register error: %s\n", strerror(err)); goto out; } re_printf("registering <%s>...\n", uri); } /* main loop */ err = re_main(signal_handler); out: /* clean up/free all state */ mem_deref(sdp); /* will also free sdp_media */ mem_deref(rtp); mem_deref(sess_sock); mem_deref(sip); mem_deref(dnsc); /* free librar state */ libre_close(); /* check for memory leaks */ tmr_debug(); mem_debug(); 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; }
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; }