From ecef413e81f53f3ad08d38df86e763699634266a Mon Sep 17 00:00:00 2001 From: Maximilian Fridrich Date: Mon, 22 Jul 2024 14:47:34 +0200 Subject: [PATCH] transp.c: add sip_transp_add_sock to add SIP transport protocol without opening a listening socket and adapt sip_transp_send accordingly to make UDP work. --- include/re_sip.h | 2 + src/sip/transp.c | 136 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 116 insertions(+), 22 deletions(-) diff --git a/include/re_sip.h b/include/re_sip.h index c4c013c1d..1b7ad009a 100644 --- a/include/re_sip.h +++ b/include/re_sip.h @@ -311,6 +311,8 @@ void sip_set_trace_handler(struct sip *sip, sip_trace_h *traceh); /* transport */ int sip_transp_add(struct sip *sip, enum sip_transp tp, const struct sa *laddr, ...); +int sip_transp_add_sock(struct sip *sip, enum sip_transp tp, + bool listen, const struct sa *laddr, ...); int sip_transp_add_websock(struct sip *sip, enum sip_transp tp, const struct sa *laddr, bool server, const char *cert, struct tls *tls); diff --git a/src/sip/transp.c b/src/sip/transp.c index ea9e9d43c..758a2d6d6 100644 --- a/src/sip/transp.c +++ b/src/sip/transp.c @@ -1195,17 +1195,17 @@ static void http_req_handler(struct http_conn *hc, const struct http_msg *msg, * * @param sip SIP stack instance * @param tp SIP Transport + * @param listen True to open listening socket * @param laddr Local network address - * @param ... Optional transport parameters such as TLS context + * @param ap Optional transport parameters such as TLS context * * @return 0 if success, otherwise errorcode */ -int sip_transp_add(struct sip *sip, enum sip_transp tp, - const struct sa *laddr, ...) +static int add_transp(struct sip *sip, enum sip_transp tp, + bool listen, const struct sa *laddr, va_list ap) { struct sip_transport *transp; struct tls *tls; - va_list ap; int err = 0; if (!sip || !laddr || !sa_isset(laddr, SA_ADDR)) @@ -1221,13 +1221,25 @@ int sip_transp_add(struct sip *sip, enum sip_transp tp, mem_deref(transp); return err; } + + tls = va_arg(ap, struct tls *); + if (!tls) { + err = EINVAL; + goto out; + } + + transp->tls = mem_ref(tls); } list_append(&sip->transpl, &transp->le, transp); transp->sip = sip; transp->tp = tp; - va_start(ap, laddr); + if (!listen) { + transp->laddr = *laddr; + sa_set_port(&transp->laddr, 0); + return err; + } switch (tp) { @@ -1241,16 +1253,6 @@ int sip_transp_add(struct sip *sip, enum sip_transp tp, break; case SIP_TRANSP_TLS: - tls = va_arg(ap, struct tls *); - if (!tls) { - err = EINVAL; - break; - } - - transp->tls = mem_ref(tls); - - /*@fallthrough@*/ - case SIP_TRANSP_TCP: err = tcp_listen((struct tcp_sock **)&transp->sock, laddr, tcp_connect_handler, transp); @@ -1265,8 +1267,7 @@ int sip_transp_add(struct sip *sip, enum sip_transp tp, break; } - va_end(ap); - +out: if (err) mem_deref(transp); @@ -1274,6 +1275,55 @@ int sip_transp_add(struct sip *sip, enum sip_transp tp, } +/** + * Add a SIP transport + * + * @param sip SIP stack instance + * @param tp SIP Transport + * @param laddr Local network address + * @param ... Optional transport parameters such as TLS context + * + * @return 0 if success, otherwise errorcode + */ +int sip_transp_add(struct sip *sip, enum sip_transp tp, + const struct sa *laddr, ...) +{ + int err; + va_list ap; + + va_start(ap, laddr); + err = add_transp(sip, tp, true, laddr, ap); + va_end(ap); + + return err; +} + + +/** + * Add a SIP transport and open listening socket if requested + * + * @param sip SIP stack instance + * @param tp SIP Transport + * @param listen True to open listening socket + * @param laddr Local network address + * @param ... Optional transport parameters such as TLS context + * + * @return 0 if success, otherwise errorcode + */ +int sip_transp_add_sock(struct sip *sip, enum sip_transp tp, + bool listen, const struct sa *laddr, ...) +{ + int err; + va_list ap; + + va_start(ap, laddr); + err = add_transp(sip, tp, listen, laddr, ap); + va_end(ap); + + return err; +} + + /** * Add a SIP websocket transport * @@ -1435,7 +1485,7 @@ int sip_transp_send(struct sip_connqent **qentp, struct sip *sip, void *sock, struct mbuf *mb, sip_conn_h *connh, sip_transp_h *transph, void *arg) { - const struct sip_transport *transp; + struct sip_transport *transp; struct sip_conn *conn; bool secure = false; struct sa dsttmp; @@ -1459,17 +1509,35 @@ int sip_transp_send(struct sip_connqent **qentp, struct sip *sip, void *sock, if (err) return err; - if (connh) - connh(&laddr, dst, mb, arg); - if (!sock) { - transp = transp_find(sip, tp, sa_af(&dsttmp), &dsttmp); + transp = (struct sip_transport *) + transp_find(sip, tp, sa_af(&dsttmp), &dsttmp); if (!transp) return EPROTONOSUPPORT; + if (!transp->sock) { + err = udp_listen((struct udp_sock **) + &transp->sock, &transp->laddr, + udp_recv_handler, transp); + if (err) + break; + + err = udp_local_get(transp->sock, + &transp->laddr); + if (err) { + transp->sock = mem_deref(transp->sock); + break; + } + + laddr = transp->laddr; + } + sock = transp->sock; } + if (connh) + connh(&laddr, dst, mb, arg); + trace_send(sip, tp, sock, &dsttmp, mb); err = udp_send(sock, &dsttmp, mb); @@ -1768,11 +1836,32 @@ int sip_settos(struct sip *sip, uint8_t tos) } +static void sip_transports_print(struct re_printf *pf, const struct sip* sip) +{ + uint8_t i; + struct le *le; + uint32_t mask = 0; + + for (le = sip->transpl.head; le; le = le->next) { + const struct sip_transport *transp = le->data; + mask |= (1 << transp->tp); + } + + for (i = 0; i < SIP_TRANSPC; ++i) { + if (mask==0 || (0 != (mask & (1u << i)))) + (void)re_hprintf(pf, " %s\n", sip_transp_name(i)); + } +} + + static bool debug_handler(struct le *le, void *arg) { const struct sip_transport *transp = le->data; struct re_printf *pf = arg; + if (sa_port(&transp->laddr) == 0) + return false; + (void)re_hprintf(pf, " %J (%s)\n", &transp->laddr, sip_transp_name(transp->tp)); @@ -1813,6 +1902,9 @@ int sip_transp_debug(struct re_printf *pf, const struct sip *sip) int err; err = re_hprintf(pf, "transports:\n"); + sip_transports_print(pf, sip); + + err |= re_hprintf(pf, "transport sockets:\n"); list_apply(&sip->transpl, true, debug_handler, pf); err |= re_hprintf(pf, "connections:\n");