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); }
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; }
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 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); } }