예제 #1
0
파일: listen.c 프로젝트: soramimi/qSIP
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);
}
예제 #2
0
파일: ua.c 프로젝트: pasichnichenko/baresip
/* 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");
}
예제 #3
0
파일: sip_ua.c 프로젝트: chk-jxcn/redemo
/* 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);
	}
}
예제 #4
0
파일: listen.c 프로젝트: lmangani/libre
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);
}
예제 #5
0
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);
}
예제 #6
0
파일: message.c 프로젝트: alfredh/baresip
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;
}
예제 #7
0
파일: notifier.c 프로젝트: FOSSRIT/baresip
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;
}
예제 #8
0
static void notify_handler(struct sip *sip, const struct sip_msg *msg,
			   void *arg)
{
	enum presence_status status = PRESENCE_CLOSED;
	struct presence *pres = arg;
	const struct sip_hdr *hdr;
	struct pl pl;

	pres->failc = 0;

	hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_TYPE);
	if (!hdr || 0 != pl_strcasecmp(&hdr->val, "application/pidf+xml")) {

		if (hdr)
			(void)re_printf("presence: unsupported"
					" content-type: '%r'\n",
					&hdr->val);

		sip_treplyf(NULL, NULL, sip, msg, false,
			    415, "Unsupported Media Type",
			    "Accept: application/pidf+xml\r\n"
			    "Content-Length: 0\r\n"
			    "\r\n");
		return;
	}

	if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb),
		      "<status>[^<]*<basic>[^<]*</basic>[^<]*</status>",
		      NULL, &pl, NULL)) {

		if (!pl_strcasecmp(&pl, "open"))
			status = PRESENCE_OPEN;
	}

	if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb),
		      "<rpid:away/>")) {

		status = PRESENCE_CLOSED;
	}
	else if (!re_regex((const char *)mbuf_buf(msg->mb),
			   mbuf_get_left(msg->mb),
			   "<rpid:busy/>")) {

		status = PRESENCE_BUSY;
	}
	else if (!re_regex((const char *)mbuf_buf(msg->mb),
			   mbuf_get_left(msg->mb),
			   "<rpid:on-the-phone/>")) {

		status = PRESENCE_BUSY;
	}

	(void)sip_treply(NULL, sip, msg, 200, "OK");

	contact_set_presence(pres->contact, status);
}
예제 #9
0
파일: mwi.c 프로젝트: qwertos/baresip
static void notify_handler(struct sip *sip, const struct sip_msg *msg,
                           void *arg)
{
    struct mwi *mwi = arg;

    if (mbuf_get_left(msg->mb)) {
        re_printf("----- MWI for %s -----\n", ua_aor(mwi->ua));
        re_printf("%b\n", mbuf_buf(msg->mb), mbuf_get_left(msg->mb));
    }

    (void)sip_treply(NULL, sip, msg, 200, "OK");
}
예제 #10
0
파일: listen.c 프로젝트: lmangani/libre
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);
}
예제 #11
0
static void cancel_handler(void *arg)
{
	struct sipsess *sess = arg;

	(void)sip_treply(&sess->st, sess->sip, sess->msg,
			 487, "Request Terminated");

	sess->peerterm = true;

	if (sess->terminated)
		return;

	sipsess_terminate(sess, ECONNRESET, NULL);
}
예제 #12
0
static void notify_handler(struct sip *sip, const struct sip_msg *msg,
			   void *arg)
{
	struct mwi *mwi = arg;

	if (mbuf_get_left(msg->mb)) {
		ui_output("----- MWI for %s -----\n", ua_aor(mwi->ua));
		ui_output("%b\n", mbuf_buf(msg->mb), mbuf_get_left(msg->mb));
	}

	(void)sip_treply(NULL, sip, msg, 200, "OK");

	if (mwi->shutdown)
		mem_deref(mwi);
}
예제 #13
0
파일: message.c 프로젝트: AmesianX/baresip
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;
}
예제 #14
0
파일: ua.c 프로젝트: pasichnichenko/baresip
static void handle_options(struct ua *ua, const struct sip_msg *msg)
{
	struct sip_contact contact;
	struct call *call = NULL;
	struct mbuf *desc = NULL;
	int err;

	err = ua_call_alloc(&call, ua, VIDMODE_ON, NULL, NULL, NULL);
	if (err) {
		(void)sip_treply(NULL, uag.sip, msg, 500, "Call Error");
		return;
	}

	err = call_sdp_get(call, &desc, true);
	if (err)
		goto out;

	sip_contact_set(&contact, ua_cuser(ua), &msg->dst, msg->tp);

	err = sip_treplyf(NULL, NULL, uag.sip,
			  msg, true, 200, "OK",
			  "Allow: %s\r\n"
			  "%H"
			  "%H"
			  "Content-Type: application/sdp\r\n"
			  "Content-Length: %zu\r\n"
			  "\r\n"
			  "%b",
			  uag_allowed_methods(),
			  ua_print_supported, ua,
			  sip_contact_print, &contact,
			  mbuf_get_left(desc),
			  mbuf_buf(desc),
			  mbuf_get_left(desc));
	if (err) {
		warning("ua: options: sip_treplyf: %m\n", err);
	}

 out:
	mem_deref(desc);
	mem_deref(call);
}
예제 #15
0
파일: listen.c 프로젝트: lmangani/libre
static void internal_connect_handler(const struct sip_msg *msg, void *arg)
{
	struct sipsess_sock *sock = arg;

	(void)sip_treply(NULL, sock->sip, msg, 486, "Busy Here");
}
예제 #16
0
파일: subscriber.c 프로젝트: QXIP/baresip
static void notify_handler(struct sip *sip, const struct sip_msg *msg,
			   void *arg)
{
	enum presence_status status = PRESENCE_CLOSED;
	struct presence *pres = arg;
	const struct sip_hdr *type_hdr, *length_hdr;
	struct pl pl;

	pres->failc = 0;

	type_hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_TYPE);

	if (!type_hdr) {

		length_hdr = sip_msg_hdr(msg, SIP_HDR_CONTENT_LENGTH);
		if (0 == pl_strcmp(&length_hdr->val, "0")) {

			status = PRESENCE_UNKNOWN;
			goto done;
		}
	}

	if (!type_hdr ||
	    0 != pl_strcasecmp(&type_hdr->val, "application/pidf+xml")) {

		if (type_hdr)
			warning("presence: unsupported content-type: '%r'\n",
				&type_hdr->val);

		sip_treplyf(NULL, NULL, sip, msg, false,
			    415, "Unsupported Media Type",
			    "Accept: application/pidf+xml\r\n"
			    "Content-Length: 0\r\n"
			    "\r\n");
		return;
	}

	if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb),
		      "<basic>[^<]+</basic>", &pl)) {
		if (!pl_strcasecmp(&pl, "open"))
			status = PRESENCE_OPEN;
	}

	if (!re_regex((const char *)mbuf_buf(msg->mb), mbuf_get_left(msg->mb),
		      "<rpid:away/>")) {

		status = PRESENCE_CLOSED;
	}
	else if (!re_regex((const char *)mbuf_buf(msg->mb),
			   mbuf_get_left(msg->mb),
			   "<rpid:busy/>")) {

		status = PRESENCE_BUSY;
	}
	else if (!re_regex((const char *)mbuf_buf(msg->mb),
			   mbuf_get_left(msg->mb),
			   "<rpid:on-the-phone/>")) {

		status = PRESENCE_BUSY;
	}

done:
	(void)sip_treply(NULL, sip, msg, 200, "OK");

	contact_set_presence(pres->contact, status);
}
예제 #17
0
파일: call.c 프로젝트: aKlausKranz/baresip
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;
}
예제 #18
0
파일: call.c 프로젝트: sealaunch/baresip
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;
}