aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2024-11-18 20:36:59 -0800
committerGarrett D'Amore <garrett@damore.org>2024-11-18 20:38:27 -0800
commit6499dd847ca8889ea0aa4a2fe934bcfff9466e60 (patch)
treec803365ce80f0174e6c85a6c8ae12a284d73de6a /src
parent600f81148be4d08b6b1c308165b3eff1c30ac216 (diff)
downloadnng-6499dd847ca8889ea0aa4a2fe934bcfff9466e60.tar.gz
nng-6499dd847ca8889ea0aa4a2fe934bcfff9466e60.tar.bz2
nng-6499dd847ca8889ea0aa4a2fe934bcfff9466e60.zip
Add new nni_url_parse_inline, and add more test cases for coverage.
The inline parsing will be used internally to avoid some allocations.
Diffstat (limited to 'src')
-rw-r--r--src/core/url.c61
-rw-r--r--src/core/url.h1
-rw-r--r--src/core/url_test.c27
3 files changed, 57 insertions, 32 deletions
diff --git a/src/core/url.c b/src/core/url.c
index 74346437..af6be581 100644
--- a/src/core/url.c
+++ b/src/core/url.c
@@ -1,5 +1,5 @@
//
-// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2024 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
@@ -326,23 +326,17 @@ nni_url_default_port(const char *scheme)
// scheme with a leading //, such as http:// or tcp://. So our parser
// is a bit more restricted, but sufficient for our needs.
int
-nng_url_parse(nng_url **urlp, const char *raw)
+nni_url_parse_inline(nng_url *url, const char *raw)
{
- nng_url *url;
size_t len;
const char *s;
char *p;
char c;
int rv;
- if ((url = NNI_ALLOC_STRUCT(url)) == NULL) {
- return (NNG_ENOMEM);
- }
-
// TODO: remove this when NNG_OPT_URL is gone
if ((url->u_rawurl = nni_strdup(raw)) == NULL) {
- rv = NNG_ENOMEM;
- goto error;
+ return (NNG_ENOMEM);
}
// Grab the scheme.
@@ -353,8 +347,7 @@ nng_url_parse(nng_url **urlp, const char *raw)
}
}
if (strncmp(s + len, "://", 3) != 0) {
- rv = NNG_EINVAL;
- goto error;
+ return (NNG_EINVAL);
}
for (int i = 0; nni_schemes[i] != NULL; i++) {
@@ -364,8 +357,7 @@ nng_url_parse(nng_url **urlp, const char *raw)
}
}
if (url->u_scheme == NULL) {
- rv = NNG_ENOTSUP;
- goto error;
+ return (NNG_ENOTSUP);
}
s += len;
@@ -400,7 +392,6 @@ nng_url_parse(nng_url **urlp, const char *raw)
(strcmp(url->u_scheme, "abstract") == 0) ||
(strcmp(url->u_scheme, "inproc") == 0)) {
url->u_path = p;
- *urlp = url;
return (0);
}
@@ -434,8 +425,7 @@ nng_url_parse(nng_url **urlp, const char *raw)
// make sure only one '@' appears in the host (only one user
// info is allowed)
if (strchr(url->u_hostname, '@') != NULL) {
- rv = NNG_EINVAL;
- goto error;
+ return (NNG_EINVAL);
}
}
@@ -446,7 +436,7 @@ nng_url_parse(nng_url **urlp, const char *raw)
}
if ((rv = url_canonify_uri(p)) != 0) {
- goto error;
+ return (rv);
}
while ((c = *p) != '\0') {
@@ -481,14 +471,12 @@ nng_url_parse(nng_url **urlp, const char *raw)
p++;
while (*p != ']') {
if (*p++ == '\0') {
- rv = NNG_EINVAL;
- goto error;
+ return (NNG_EINVAL);
}
}
*p++ = '\0';
if ((*p != ':') && (*p != '\0')) {
- rv = NNG_EINVAL;
- goto error;
+ return (NNG_EINVAL);
}
} else {
while (*p != ':' && *p != '\0') {
@@ -500,31 +488,40 @@ nng_url_parse(nng_url **urlp, const char *raw)
}
// hostname length check
if (strlen(url->u_hostname) >= 256) {
- rv = NNG_EINVAL;
- goto error;
+ return (NNG_EINVAL);
}
if (c == ':') {
// If a colon was present, but no port value present, then
// that is an error.
if (*p == '\0') {
- rv = NNG_EINVAL;
- goto error;
+ return (NNG_EINVAL);
}
- rv = nni_get_port_by_name(p, &url->u_port);
- if (rv != 0) {
- goto error;
+ if (nni_get_port_by_name(p, &url->u_port) != 0) {
+ return (NNG_EINVAL);
}
} else {
url->u_port = nni_url_default_port(url->u_scheme);
}
- *urlp = url;
return (0);
+}
-error:
- nng_url_free(url);
- return (rv);
+int
+nng_url_parse(nng_url **urlp, const char *raw)
+{
+ nng_url *url;
+ int rv;
+
+ if ((url = NNI_ALLOC_STRUCT(url)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+ if ((rv = nni_url_parse_inline(url, raw)) != 0) {
+ nng_url_free(url);
+ return (rv);
+ }
+ *urlp = url;
+ return (0);
}
void
diff --git a/src/core/url.h b/src/core/url.h
index f8a141ac..c0ca32a0 100644
--- a/src/core/url.h
+++ b/src/core/url.h
@@ -33,5 +33,6 @@ extern int nni_url_asprintf(char **, const nng_url *);
extern int nni_url_asprintf_port(char **, const nng_url *, int);
extern size_t nni_url_decode(uint8_t *, const char *, size_t);
extern int nni_url_to_address(nng_sockaddr *, const nng_url *);
+extern int nni_url_parse_inline(nng_url *, const char *);
#endif // CORE_URL_H
diff --git a/src/core/url_test.c b/src/core/url_test.c
index 4de9d4c2..0e30c29e 100644
--- a/src/core/url_test.c
+++ b/src/core/url_test.c
@@ -385,6 +385,30 @@ test_url_good_utf8(void)
}
void
+test_url_missing_port(void)
+{
+ nng_url *url = NULL;
+ NUTS_FAIL(
+ nng_url_parse(&url, "http://www.x.com:/something"), NNG_EINVAL);
+}
+
+void
+test_url_unknown_service(void)
+{
+ nng_url *url = NULL;
+ NUTS_FAIL(
+ nng_url_parse(&url, "http://www.x.com:nosuchservice"), NNG_EINVAL);
+}
+
+void
+test_url_duplicate_userinfo(void)
+{
+ nng_url *url = NULL;
+ NUTS_FAIL(
+ nng_url_parse(&url, "http://user@@user@www.x.com"), NNG_EINVAL);
+}
+
+void
test_url_decode(void)
{
uint8_t out[16];
@@ -463,6 +487,9 @@ NUTS_TESTS = {
{ "url canonify", test_url_canonify },
{ "url path resolve", test_url_path_resolve },
{ "url query info pass", test_url_query_info_pass },
+ { "url missing port", test_url_missing_port },
+ { "url unknown service", test_url_unknown_service },
+ { "url duplicate userinfo", test_url_duplicate_userinfo },
{ "url bad utf8", test_url_bad_utf8 },
{ "url good utf8", test_url_good_utf8 },
{ "url decode", test_url_decode },