예제 #1
0
파일: transp.c 프로젝트: Issic47/libre
static void udp_recv_handler(const struct sa *src, struct mbuf *mb, void *arg)
{
	struct sip_transport *transp = arg;
	struct stun_unknown_attr ua;
	struct stun_msg *stun_msg;
	struct sip_msg *msg;
	int err;

	if (mb->end <= 4)
		return;

	if (!stun_msg_decode(&stun_msg, mb, &ua)) {

		if (stun_msg_method(stun_msg) == STUN_METHOD_BINDING) {

			switch (stun_msg_class(stun_msg)) {

			case STUN_CLASS_REQUEST:
				(void)stun_reply(IPPROTO_UDP, transp->sock,
						 src, 0, stun_msg,
						 NULL, 0, false, 2,
						 STUN_ATTR_XOR_MAPPED_ADDR,
						 src,
						 STUN_ATTR_SOFTWARE,
						 transp->sip->software);
				break;

			default:
				(void)stun_ctrans_recv(transp->sip->stun,
						       stun_msg, &ua);
				break;
			}
		}

		mem_deref(stun_msg);

		return;
	}

	err = sip_msg_decode(&msg, mb);
	if (err) {
		(void)re_fprintf(stderr, "sip: msg decode err: %m\n", err);
		return;
	}

	msg->sock = mem_ref(transp->sock);
	msg->src = *src;
	msg->dst = transp->laddr;
	msg->tp = SIP_TRANSP_UDP;

	sip_recv(transp->sip, msg);

	mem_deref(msg);
}
예제 #2
0
static int request_copy(struct mbuf **mbp, struct sip_ctrans *ct,
			const char *met, const struct sip_msg *resp)
{
	struct mbuf *mb;
	int err;

	if (!ct->req) {
		err = sip_msg_decode(&ct->req, ct->mb);
		if (err)
			return err;
	}

	mb = mbuf_alloc(1024);
	if (!mb)
		return ENOMEM;

	err  = mbuf_printf(mb, "%s %r SIP/2.0\r\n", met, &ct->req->ruri);
	err |= mbuf_printf(mb, "Via: %r\r\n", &ct->req->via.val);
	err |= mbuf_write_str(mb, "Max-Forwards: 70\r\n");
	err |= sip_msg_hdr_apply(ct->req, true, SIP_HDR_ROUTE,
				 route_handler, mb) ? ENOMEM : 0;
	err |= mbuf_printf(mb, "To: %r\r\n",
			   resp ? &resp->to.val : &ct->req->to.val);
	err |= mbuf_printf(mb, "From: %r\r\n", &ct->req->from.val);
	err |= mbuf_printf(mb, "Call-ID: %r\r\n", &ct->req->callid);
	err |= mbuf_printf(mb, "CSeq: %u %s\r\n", ct->req->cseq.num, met);
	if (ct->sip->software)
		err |= mbuf_printf(mb, "User-Agent: %s\r\n",ct->sip->software);
	err |= mbuf_write_str(mb, "Content-Length: 0\r\n\r\n");

	mb->pos = 0;

	if (err)
		mem_deref(mb);
	else
		*mbp = mb;

	return err;
}
예제 #3
0
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();
}
예제 #4
0
파일: transp.c 프로젝트: Issic47/libre
static void tcp_recv_handler(struct mbuf *mb, void *arg)
{
	struct sip_conn *conn = arg;
	size_t pos;
	int err = 0;

	if (conn->mb) {
		pos = conn->mb->pos;

		conn->mb->pos = conn->mb->end;

		err = mbuf_write_mem(conn->mb, mbuf_buf(mb),mbuf_get_left(mb));
		if (err)
			goto out;

		conn->mb->pos = pos;

		if (mbuf_get_left(conn->mb) > TCP_BUFSIZE_MAX) {
			err = EOVERFLOW;
			goto out;
		}
	}
	else {
		conn->mb = mem_ref(mb);
	}

	for (;;) {
		struct sip_msg *msg;
		uint32_t clen;
		size_t end;

		if (mbuf_get_left(conn->mb) < 2)
			break;

		if (!memcmp(mbuf_buf(conn->mb), "\r\n", 2)) {

			tmr_start(&conn->tmr, TCP_IDLE_TIMEOUT * 1000,
				  conn_tmr_handler, conn);

			conn->mb->pos += 2;

			if (mbuf_get_left(conn->mb) >= 2 &&
			    !memcmp(mbuf_buf(conn->mb), "\r\n", 2)) {

				struct mbuf mbr;

				conn->mb->pos += 2;

				mbr.buf  = crlfcrlf;
				mbr.size = sizeof(crlfcrlf);
				mbr.pos  = 0;
				mbr.end  = 2;

				err = tcp_send(conn->tc, &mbr);
				if (err)
					break;
			}

			if (mbuf_get_left(conn->mb))
				continue;

			conn->mb = mem_deref(conn->mb);
			break;
		}

		pos = conn->mb->pos;

		err = sip_msg_decode(&msg, conn->mb);
		if (err) {
			if (err == ENODATA)
				err = 0;
			break;
		}

		if (!msg->clen.p) {
			mem_deref(msg);
			err = EBADMSG;
			break;
		}

		clen = pl_u32(&msg->clen);

		if (mbuf_get_left(conn->mb) < clen) {
			conn->mb->pos = pos;
			mem_deref(msg);
			break;
		}

		tmr_start(&conn->tmr, TCP_IDLE_TIMEOUT * 1000,
			  conn_tmr_handler, conn);

		end = conn->mb->end;

		msg->mb->end = msg->mb->pos + clen;
		msg->sock = mem_ref(conn);
		msg->src = conn->paddr;
		msg->dst = conn->laddr;
		msg->tp = conn->sc ? SIP_TRANSP_TLS : SIP_TRANSP_TCP;

		sip_recv(conn->sip, msg);
		mem_deref(msg);

		if (end <= conn->mb->end) {
			conn->mb = mem_deref(conn->mb);
			break;
		}

		mb = mbuf_alloc(end - conn->mb->end);
		if (!mb) {
			err = ENOMEM;
			goto out;
		}

		(void)mbuf_write_mem(mb, &conn->mb->buf[conn->mb->end],
				     end - conn->mb->end);

		mb->pos = 0;

		mem_deref(conn->mb);
		conn->mb = mb;
	}

 out:
	if (err) {
		conn_close(conn, err);
		mem_deref(conn);
	}
}