static void sipsub_notify_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct call *call = arg; struct pl scode, reason; uint32_t sc; if (re_regex((char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb), "SIP/2.0 [0-9]+ [^\r\n]+", &scode, &reason)) { (void)sip_reply(sip, msg, 400, "Bad sipfrag"); return; } (void)sip_reply(sip, msg, 200, "OK"); sc = pl_u32(&scode); if (sc >= 300) { warning("call: transfer failed: %u %r\n", sc, &reason); call_event_handler(call, CALL_EVENT_TRANSFER_FAILED, "%u %r", sc, &reason); } else if (sc >= 200) { call_event_handler(call, CALL_EVENT_CLOSED, "Call transfered"); } }
static void bye_handler(struct sipsess_sock *sock, const struct sip_msg *msg) { struct sip *sip = sock->sip; struct sipsess *sess; sess = sipsess_find(sock, msg); if (!sess) { (void)sip_reply(sip, msg, 481, "Call Does Not Exist"); return; } if (!sip_dialog_rseq_valid(sess->dlg, msg)) { (void)sip_reply(sip, msg, 500, "Server Internal Error"); return; } (void)sip_treplyf(NULL, NULL, sip, msg, false, 200, "OK", "%s" "Content-Length: 0\r\n" "\r\n", sess->close_hdrs); sess->peerterm = true; if (sess->terminated) return; if (sess->st) { (void)sip_treply(&sess->st, sess->sip, sess->msg, 487, "Request Terminated"); } sipsess_terminate(sess, ECONNRESET, NULL); }
static void bye_handler(struct sipsess_sock *sock, const struct sip_msg *msg) { struct sip *sip = sock->sip; struct sipsess *sess; sess = sipsess_find(sock, msg); if (!sess) { (void)sip_reply(sip, msg, 481, "Call Does Not Exist"); return; } if (!sip_dialog_rseq_valid(sess->dlg, msg)) { (void)sip_reply(sip, msg, 500, "Server Internal Error"); return; } (void)sip_treply(NULL, sip, msg, 200, "OK"); sess->peerterm = true; if (sess->terminated) return; if (sess->st) { (void)sip_treply(&sess->st, sess->sip, sess->msg, 487, "Request Terminated"); } sipsess_terminate(sess, E_SIP_SESSION_CLOSED_BYE, NULL); }
static void sip_recv(struct sip *sip, const struct sip_msg *msg) { struct le *le = sip->lsnrl.head; while (le) { struct sip_lsnr *lsnr = le->data; le = le->next; if (msg->req != lsnr->req) continue; if (lsnr->msgh(msg, lsnr->arg)) return; } if (msg->req) { (void)re_fprintf(stderr, "unhandeled request from %J: %r %r\n", &msg->src, &msg->met, &msg->ruri); if (!pl_strcmp(&msg->met, "CANCEL")) (void)sip_reply(sip, msg, 481, "Transaction Does Not Exist"); else (void)sip_reply(sip, msg, 501, "Not Implemented"); } else { (void)re_fprintf(stderr, "unhandeled response from %J:" " %u %r (%r)\n", &msg->src, msg->scode, &msg->reason, &msg->cseq.met); } }
static void sipsess_info_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct call *call = arg; if (msg_ctype_cmp(&msg->ctyp, "application", "dtmf-relay")) { struct pl body, sig, dur; int err; pl_set_mbuf(&body, msg->mb); err = re_regex(body.p, body.l, "Signal=[0-9]+", &sig); err |= re_regex(body.p, body.l, "Duration=[0-9]+", &dur); if (err) { (void)sip_reply(sip, msg, 400, "Bad Request"); } else { char s = pl_u32(&sig); uint32_t duration = pl_u32(&dur); if (s == 10) s = '*'; else if (s == 11) s = '#'; else s += '0'; info("received DTMF: '%c' (duration=%r)\n", s, &dur); (void)sip_reply(sip, msg, 200, "OK"); if (call->dtmfh) { tmr_start(&call->tmr_dtmf, duration, dtmfend_handler, call); call->dtmfh(call, s, call->arg); } } } #ifdef USE_VIDEO else if (msg_ctype_cmp(&msg->ctyp, "application", "media_control+xml")) { call_handle_info_req(call, msg); (void)sip_reply(sip, msg, 200, "OK"); } #endif else { (void)sip_reply(sip, msg, 488, "Not Acceptable Here"); } }
static void sipsess_refer_handler(struct sip *sip, const struct sip_msg *msg, void *arg) { struct call *call = arg; const struct sip_hdr *hdr; int err; /* get the transfer target */ hdr = sip_msg_hdr(msg, SIP_HDR_REFER_TO); if (!hdr) { warning("call: bad REFER request from %r\n", &msg->from.auri); (void)sip_reply(sip, msg, 400, "Missing Refer-To header"); return; } /* The REFER creates an implicit subscription. * Reply 202 to the REFER request */ call->not = mem_deref(call->not); err = sipevent_accept(&call->not, uag_sipevent_sock(), msg, sipsess_dialog(call->sess), NULL, 202, "Accepted", 60, 60, 60, ua_cuser(call->ua), "message/sipfrag", auth_handler, call->acc, true, sipnot_close_handler, call, "Allow: %s\r\n", uag_allowed_methods()); if (err) { warning("call: refer: sipevent_accept failed: %m\n", err); return; } (void)call_notify_sipfrag(call, 100, "Trying"); call_event_handler(call, CALL_EVENT_TRANSFER, "%r", &hdr->val); }
static void bye_handler(struct sipsess_sock *sock, const struct sip_msg *msg) { struct sip *sip = sock->sip; struct sipsess *sess; // char tmp[256]; sess = sipsess_find(sock, msg); if (!sess) { (void)sip_reply(sip, msg, 481, "Call Does Not Exist"); return; } if (!sip_dialog_rseq_valid(sess->dlg, msg)) { (void)sip_reply(sip, msg, 500, "Server Internal Error"); return; } /* QXIP */ if (sess->xrtpstats && !sess->xrtpstats[0] == '\0') { /* Inject X-RTP-Stat header */ (void)sip_treplyf(NULL, NULL, sip, msg, false, 200, "OK", "X-RTP-Stat: %s\r\nContent-Length: 0\r\n\r\n", sess->xrtpstats); } else { /* Vanilla 200 OK */ (void)sip_treply(NULL, sip, msg, 200, "OK"); } sess->peerterm = true; if (sess->terminated) return; if (sess->st) { (void)sip_treply(&sess->st, sess->sip, sess->msg, 487, "Request Terminated"); } sipsess_terminate(sess, ECONNRESET, NULL); }
static void reinvite_handler(struct sipsess_sock *sock, const struct sip_msg *msg) { struct sip *sip = sock->sip; struct sipsess *sess; struct mbuf *desc; char m[256]; int err; sess = sipsess_find(sock, msg); if (!sess || sess->terminated) { (void)sip_treply(NULL, sip, msg, 481, "Call Does Not Exist"); return; } if (!sip_dialog_rseq_valid(sess->dlg, msg)) { (void)sip_treply(NULL, sip, msg, 500, "Server Internal Error"); return; } if (sess->st || sess->awaiting_answer) { (void)sip_treplyf(NULL, NULL, sip, msg, false, 500, "Server Internal Error", "Retry-After: 5\r\n" "Content-Length: 0\r\n" "\r\n"); return; } if (sess->req) { (void)sip_treply(NULL, sip, msg, 491, "Request Pending"); return; } err = sess->offerh(&desc, msg, sess->arg); if (err) { (void)sip_reply(sip, msg, 488, str_error(err, m, sizeof(m))); return; } (void)sip_dialog_update(sess->dlg, msg); (void)sipsess_reply_2xx(sess, msg, 200, "OK", desc, NULL, NULL); /* pending modifications considered outdated; sdp may have changed in above exchange */ sess->desc = mem_deref(sess->desc); sess->modify_pending = false; tmr_cancel(&sess->tmr); mem_deref(desc); }
static void udp_recv(const struct sa *src, struct mbuf *mb, void *arg) { struct sip_server *srv = arg; struct sip_msg *msg; int err; #if 0 re_printf("sip: %zu bytes from %J\n", mbuf_get_left(mb), src); re_printf("%b\n", mb->buf, mb->end); #endif err = sip_msg_decode(&msg, mb); if (err) { warning("selftest: sip_msg_decode: %m\n", err); return; } if (0 == pl_strcmp(&msg->met, "REGISTER")) srv->got_register_req = true; msg->sock = mem_ref(srv->us); msg->src = *src; msg->dst = srv->laddr; msg->tp = SIP_TRANSP_UDP; if (srv->terminate) err = sip_reply(srv->sip, msg, 503, "Server Error"); else err = sip_reply(srv->sip, msg, 200, "OK"); if (err) { warning("selftest: could not reply: %m\n", err); } mem_deref(msg); if (srv->terminate) re_cancel(); }
static void refer_handler(struct sipsess_sock *sock, const struct sip_msg *msg) { struct sip *sip = sock->sip; struct sipsess *sess; sess = sipsess_find(sock, msg); if (!sess || sess->terminated) { (void)sip_reply(sip, msg, 481, "Call Does Not Exist"); return; } if (!sip_dialog_rseq_valid(sess->dlg, msg)) { (void)sip_reply(sip, msg, 500, "Server Internal Error"); return; } if (!sess->referh) { (void)sip_reply(sip, msg, 501, "Not Implemented"); return; } sess->referh(sip, msg, sess->arg); }
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); } }