static int request(struct sip_req *sr) { info("baresip.sipreq.request()\n"); return sip_drequestf(&sr->req, uag_sip(), true, sr->method, sr->dlg, 0, sr->auth, NULL, resp_handler, sr, sr->fmt ? "%s" : NULL, sr->fmt); }
/* Handle incoming calls */ static void sipsess_conn_handler(const struct sip_msg *msg, void *arg) { const struct sip_hdr *hdr; struct ua *ua; struct call *call = NULL; char to_uri[256]; int err; (void)arg; ua = uag_find(&msg->uri.user); if (!ua) { warning("ua: %r: UA not found: %r\n", &msg->from.auri, &msg->uri.user); (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found"); return; } /* handle multiple calls */ if (list_count(&ua->calls) + 1 > MAX_CALLS) { info("ua: rejected call from %r (maximum %d calls)\n", &msg->from.auri, MAX_CALLS); (void)sip_treply(NULL, uag.sip, msg, 486, "Busy Here"); return; } /* Handle Require: header, check for any required extensions */ hdr = sip_msg_hdr_apply(msg, true, SIP_HDR_REQUIRE, require_handler, ua); if (hdr) { info("ua: call from %r rejected with 420" " -- option-tag '%r' not supported\n", &msg->from.auri, &hdr->val); (void)sip_treplyf(NULL, NULL, uag.sip, msg, false, 420, "Bad Extension", "Unsupported: %r\r\n" "Content-Length: 0\r\n\r\n", &hdr->val); return; } (void)pl_strcpy(&msg->to.auri, to_uri, sizeof(to_uri)); err = ua_call_alloc(&call, ua, VIDMODE_ON, msg, NULL, to_uri); if (err) { warning("ua: call_alloc: %m\n", err); goto error; } err = call_accept(call, uag.sock, msg); if (err) goto error; return; error: mem_deref(call); (void)sip_treply(NULL, uag.sip, msg, 500, "Call Error"); }
static bool request_handler(const struct sip_msg *msg, void *arg) { struct message *message = arg; struct ua *ua; struct le *le = message->lsnrl.head; bool hdld = false; if (pl_strcmp(&msg->met, "MESSAGE")) return false; ua = uag_find(&msg->uri.user); if (!ua) { (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found"); return true; } while (le) { struct message_lsnr *lsnr = le->data; le = le->next; handle_message(lsnr, ua, msg); hdld = true; } return hdld; }
/** * Listen to incoming SIP MESSAGE messages * * @param message Messaging subsystem * @param recvh Message receive handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int message_listen(struct message *message, message_recv_h *recvh, void *arg) { struct message_lsnr *lsnr; int err = 0; if (!message || !recvh) return EINVAL; /* create the SIP listener if it does not exist */ if (!message->sip_lsnr) { err = sip_listen(&message->sip_lsnr, uag_sip(), true, request_handler, message); if (err) goto out; } lsnr = mem_zalloc(sizeof(*lsnr), listener_destructor); if (!lsnr) return ENOMEM; lsnr->recvh = recvh; lsnr->arg = arg; list_append(&message->lsnrl, &lsnr->le, lsnr); out: return err; }
static void handle_message(struct ua *ua, const struct sip_msg *msg) { static const char ctype_text[] = "text/plain"; struct pl ctype_pl = {ctype_text, sizeof(ctype_text)-1}; (void)ua; if (msg_ctype_cmp(&msg->ctyp, "text", "plain") && recvh) { recvh(&msg->from.auri, &ctype_pl, msg->mb, recvarg); (void)sip_reply(uag_sip(), msg, 200, "OK"); } else { (void)sip_replyf(uag_sip(), msg, 415, "Unsupported Media Type", "Accept: %s\r\n" "Content-Length: 0\r\n" "\r\n", ctype_text); } }
static bool sub_handler(const struct sip_msg *msg, void *arg) { struct ua *ua; (void)arg; ua = uag_find(&msg->uri.user); if (!ua) { warning("presence: no UA found for %r\n", &msg->uri.user); (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found"); return true; } if (notifier_add(evsock, msg, ua)) (void)sip_treply(NULL, uag_sip(), msg, 400, "Bad Presence"); return true; }
int notifier_init(void) { int err; err = sipevent_listen(&evsock, uag_sip(), 32, 32, sub_handler, NULL); if (err) return err; return cmd_register(cmdv, ARRAY_SIZE(cmdv)); }
int message_init(message_recv_h *h, void *arg) { int err; err = sip_listen(&lsnr, uag_sip(), true, request_handler, NULL); if (err) return err; recvh = h; recvarg = arg; return 0; }
static bool request_handler(const struct sip_msg *msg, void *arg) { struct ua *ua; (void)arg; if (pl_strcmp(&msg->met, "MESSAGE")) return false; ua = uag_find(&msg->uri.user); if (!ua) { (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found"); return true; } handle_message(ua, msg); return true; }
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 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; 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) { err = sdp_decode(call->sdp, msg->mb, true); if (err) return err; call->got_offer = true; /* 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; }