From e111de999e22ed5d968ac50844e92f3f21dc0c2e Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 30 Mar 2021 11:06:02 +0200 Subject: [PATCH] core: dset - helper function to encode/decode uri alias values --- src/core/dset.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ src/core/dset.h | 2 + 2 files changed, 121 insertions(+) diff --git a/src/core/dset.c b/src/core/dset.c index 16e1cdc12ec..12521350438 100644 --- a/src/core/dset.c +++ b/src/core/dset.c @@ -1113,6 +1113,125 @@ int uri_trim_rcv_alias(str *uri, str *nuri) return 1; } +/** + * encode sip uri to uri alias parameter format + * - param: iuri - input sip uri + * - param: ualias - output uri alias value in format: address~port~proto + * * ualias->s must point to a buffer of size ualias->len, at least iuri->len + * * ualias->len is adjusted to the output value length + * - return 0 on success, negative on error + */ +int ksr_uri_alias_encode(str *iuri, str *ualias) +{ + sip_uri_t puri; + char *p; + + if (parse_uri (iuri->s, iuri->len, &puri) < 0) { + LM_ERR("failed to parse uri [%.*s]\n", iuri->len, iuri->s); + return -1; + } + + /*host~port~proto*/ + if(puri.host.len + 16 >= ualias->len) { + LM_ERR("not enough space to build uri alias - buf size: %d\n", + ualias->len); + return -1; + } + p = ualias->s; + memcpy(p, puri.host.s, puri.host.len); + p += puri.host.len; + *p++ = '~'; + if(puri.port.len>0) { + memcpy(p, puri.port.s, puri.port.len); + p += puri.port.len; + } else { + if(puri.proto==PROTO_TLS || puri.proto==PROTO_WSS) { + memcpy(p, "5061", 4); + } else { + memcpy(p, "5060", 4); + } + p += 4; + } + *p++ = '~'; + *p++ = puri.proto + '0'; + ualias->len = p - ualias->s; + ualias->s[ualias->len] = '\0'; + + LM_DBG("encoded <%.*s> => [%.*s]\n", + iuri->len, iuri->s, ualias->len, ualias->s); + + return 0; +} + +/** + * decode uri alias parameter to a sip uri + * - param: ualias - uri alias value in format: address~port~proto + * - param: ouri - output uri - ouri->s must point to a buffer of size ouri->len + * * ouri->len is adjusted to the output value length + * - return 0 on success, negative on error + */ +int ksr_uri_alias_decode(str *ualias, str *ouri) +{ + int n; + char *p; + int nproto; + str sproto; + + /* 24 => sip:...;transport=sctp */ + if(ualias->len + 24 >= ouri->len) { + LM_ERR("received uri alias is too long: %d\n", ualias->len); + return -1; + } + + /* received=ip~port~proto */ + memcpy(ouri->s, "sip:", 4); + memcpy(ouri->s + 4, ualias->s, ualias->len); + ouri->s[4 + ualias->len] = '\0'; + p = ouri->s + 4; + n = 0; + while(*p!='\0') { + if(*p=='~') { + n++; + if(n==1) { + /* port */ + *p = ':'; + } else if(n==2) { + /* proto */ + *p = ';'; + p++; + if(*p=='\0') { + LM_ERR("invalid received format\n"); + goto error; + } + nproto = *p - '0'; + if (nproto != PROTO_UDP) { + proto_type_to_str(nproto, &sproto); + if (sproto.len == 0) { + LM_ERR("unknown proto in received param\n"); + goto error; + } + memcpy(p, "transport=", 10); + p += 10; + memcpy(p, sproto.s, sproto.len); + p += sproto.len; + *p = '\0'; + ouri->len = (int)(p - ouri->s); + ouri->s[ouri->len] = '\0'; + break; + } + } else { + LM_ERR("invalid number of separators (%d)\n", n); + goto error; + } + } + p++; + } + return 0; + +error: + return -1; +} + /* address of record (aor) management */ /* address of record considered case sensitive diff --git a/src/core/dset.h b/src/core/dset.h index 981f1a5d6a6..cf19fdfe1b2 100644 --- a/src/core/dset.h +++ b/src/core/dset.h @@ -285,6 +285,8 @@ int setbflagsval(unsigned int branch, flag_t val); int uri_add_rcv_alias(sip_msg_t *msg, str *uri, str *nuri); int uri_restore_rcv_alias(str *uri, str *nuri, str *suri); int uri_trim_rcv_alias(str *uri, str *nuri); +int ksr_uri_alias_encode(str *iuri, str *ualias); +int ksr_uri_alias_decode(str *ualias, str *ouri); int init_dst_set(void);