From 813de0e39f155e6f0bf31a407dc7533bdd1b7964 Mon Sep 17 00:00:00 2001 From: Jon Shallow Date: Mon, 16 Jan 2023 15:56:26 +0000 Subject: [PATCH] uri.c: Simplify coap_split_uri_sub() Remove complexity from parsing and make it easier to add in new schemes. --- Makefile.am | 1 + include/coap3/coap_internal.h | 2 +- include/coap3/coap_uri_internal.h | 40 +++++++++ include/coap3/uri.h | 2 - src/coap_oscore.c | 4 +- src/uri.c | 132 +++++++++++------------------- win32/libcoap.vcxproj | 1 + win32/libcoap.vcxproj.filters | 3 + 8 files changed, 94 insertions(+), 91 deletions(-) create mode 100644 include/coap3/coap_uri_internal.h diff --git a/Makefile.am b/Makefile.am index aa42ac19..2f8588ee 100644 --- a/Makefile.am +++ b/Makefile.am @@ -82,6 +82,7 @@ EXTRA_DIST = \ include/coap$(LIBCOAP_API_VERSION)/coap_session_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_subscribe_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_tcp_internal.h \ + include/coap$(LIBCOAP_API_VERSION)/coap_uri_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_uthash_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap_utlist_internal.h \ include/coap$(LIBCOAP_API_VERSION)/coap.h.in \ diff --git a/include/coap3/coap_internal.h b/include/coap3/coap_internal.h index 3c246b5d..2a5fb62b 100644 --- a/include/coap3/coap_internal.h +++ b/include/coap3/coap_internal.h @@ -83,11 +83,11 @@ typedef struct oscore_ctx_t oscore_ctx_t; #include "coap_oscore_internal.h" #endif /* HAVE_OSCORE */ #include "coap_pdu_internal.h" -#include "coap_session_internal.h" #include "coap_resource_internal.h" #include "coap_session_internal.h" #include "coap_subscribe_internal.h" #include "coap_tcp_internal.h" +#include "coap_uri_internal.h" #include "coap_utlist_internal.h" #include "coap_uthash_internal.h" diff --git a/include/coap3/coap_uri_internal.h b/include/coap3/coap_uri_internal.h new file mode 100644 index 00000000..309a44bd --- /dev/null +++ b/include/coap3/coap_uri_internal.h @@ -0,0 +1,40 @@ +/* + * coap_uri_internal.h -- URI functions for libcoap + * + * Copyright (C) 2019--2023 Olaf Bergmann and others + * + * SPDX-License-Identifier: BSD-2-Clause + * + * This file is part of the CoAP library libcoap. Please see README for terms + * of use. + */ + +/** + * @file coap_uri_internal.h + * @brief CoAP URI internal information + */ + +#ifndef COAP_URI_INTERNAL_H_ +#define COAP_URI_INTERNAL_H_ + +#include "coap_internal.h" + +/** + * @ingroup internal_api + * @defgroup uri URI Support + * Internal API for handling CoAP URIs + * @{ + */ + +typedef struct { + const char *name; /**< scheme name */ + uint16_t port; /**< default scheme port */ + uint16_t proxy_only; /**< set if proxy support only */ + coap_uri_scheme_t scheme; /**< scheme */ +} coap_uri_info_t; + +extern coap_uri_info_t coap_uri_scheme[COAP_URI_SCHEME_LAST]; + +/** @} */ + +#endif /* COAP_URI_INTERNAL_H_ */ diff --git a/include/coap3/uri.h b/include/coap3/uri.h index abed3bef..b5b814c4 100644 --- a/include/coap3/uri.h +++ b/include/coap3/uri.h @@ -35,8 +35,6 @@ typedef enum coap_uri_scheme_t { COAP_URI_SCHEME_LAST /* 6 Size of scheme */ } coap_uri_scheme_t; -extern const char *coap_uri_scheme[COAP_URI_SCHEME_LAST]; - /** This mask can be used to check if a parsed URI scheme is secure. */ #define COAP_URI_SCHEME_SECURE_MASK 0x01 diff --git a/src/coap_oscore.c b/src/coap_oscore.c index b69956ad..c8528061 100644 --- a/src/coap_oscore.c +++ b/src/coap_oscore.c @@ -228,8 +228,8 @@ coap_rebuild_pdu_for_proxy(coap_pdu_t *pdu) { } if (!coap_insert_option(pdu, COAP_OPTION_PROXY_SCHEME, - strlen(coap_uri_scheme[uri.scheme]), - (const uint8_t *)coap_uri_scheme[uri.scheme])) + strlen(coap_uri_scheme[uri.scheme].name), + (const uint8_t *)coap_uri_scheme[uri.scheme].name)) goto error; coap_free_type(COAP_STRING, keep_proxy_uri); return 1; diff --git a/src/uri.c b/src/uri.c index de7bdc77..5376651a 100644 --- a/src/uri.c +++ b/src/uri.c @@ -43,21 +43,18 @@ strnchr(const uint8_t *s, size_t len, unsigned char c) { return len ? s : NULL; } -#define ISEQUAL_CI(a,b) \ - ((a) == (b) || (islower(b) && ((a) == ((b) - 0x20)))) - typedef enum coap_uri_check_t { COAP_URI_CHECK_URI, COAP_URI_CHECK_PROXY } coap_uri_check_t; -const char *coap_uri_scheme[] = { - "coap", /* COAP_URI_SCHEME_COAP */ - "coaps", /* COAP_URI_SCHEME_COAPS */ - "coap+tcp", /* COAP_URI_SCHEME_COAP_TCP */ - "coaps+tcp", /* COAP_URI_SCHEME_COAPS_TCP */ - "http", /* COAP_URI_SCHEME_HTTP */ - "https" /* COAP_URI_SCHEME_HTTPS */ +coap_uri_info_t coap_uri_scheme[COAP_URI_SCHEME_LAST] = { + { "coap", 5683, 0, COAP_URI_SCHEME_COAP }, + { "coaps", 5684, 0, COAP_URI_SCHEME_COAPS }, + { "coap+tcp", 5683, 0, COAP_URI_SCHEME_COAP_TCP }, + { "coaps+tcp", 5684, 0, COAP_URI_SCHEME_COAPS_TCP }, + { "http", 80, 1, COAP_URI_SCHEME_HTTP }, + { "https", 443, 1, COAP_URI_SCHEME_HTTPS } }; static int @@ -67,8 +64,7 @@ coap_split_uri_sub(const uint8_t *str_var, coap_uri_check_t check_proxy) { const uint8_t *p, *q; int res = 0; - int is_http_proxy_scheme = 0; - size_t keep_len = len; + size_t i; if (!str_var || !uri || len == 0) return -1; @@ -79,85 +75,48 @@ coap_split_uri_sub(const uint8_t *str_var, /* search for scheme */ p = str_var; if (*p == '/') { - if (check_proxy == COAP_URI_CHECK_PROXY) + /* no scheme, host or port */ + if (check_proxy == COAP_URI_CHECK_PROXY) { + /* Must have ongoing host if proxy definition */ return -1; + } q = p; goto path; } - q = (const uint8_t *)COAP_DEFAULT_SCHEME; - while (len && *q && ISEQUAL_CI(*p, *q)) { - ++p; ++q; --len; + /* find scheme terminating :// */ + while (len >= 3 && !(p[0] == ':' && p[1] == '/' && p[2] == '/')) { + ++p; + --len; } - if (*q && check_proxy == COAP_URI_CHECK_PROXY) { - /* Scheme could be something other than coap */ - len = keep_len; - p = str_var; - q = (const uint8_t *)"http"; - while (len && *q && ISEQUAL_CI(*p, *q)) { - ++p; ++q; --len; - } - if (*q == 0) { - if (len && ISEQUAL_CI(*p, 's')) { - /* https:// */ - ++p; --len; - uri->scheme = COAP_URI_SCHEME_HTTPS; - uri->port = 443; - } - else { - /* http:// */ - uri->scheme = COAP_URI_SCHEME_HTTP; - uri->port = 80; - } - } - else { - /* Unknown scheme */ - res = -1; - goto error; - } - is_http_proxy_scheme = 1; - } - - /* If q does not point to the string end marker '\0', the schema - * identifier is wrong. */ - if (*q) { - res = -1; - goto error; - } - - if (is_http_proxy_scheme == 0) { - /* There might be an additional 's', indicating the secure version: */ - if (len && (*p == 's')) { - ++p; --len; - uri->scheme = COAP_URI_SCHEME_COAPS; - uri->port = COAPS_DEFAULT_PORT; - } else { - uri->scheme = COAP_URI_SCHEME_COAP; - } - - /* There might be an addition "+tcp", indicating reliable transport: */ - if (len>=4 && p[0] == '+' && p[1] == 't' && p[2] == 'c' && p[3] == 'p' ) { - p += 4; - len -= 4; - if (uri->scheme == COAP_URI_SCHEME_COAPS) - uri->scheme = COAP_URI_SCHEME_COAPS_TCP; - else - uri->scheme = COAP_URI_SCHEME_COAP_TCP; - } - } - q = (const uint8_t *)"://"; - while (len && *q && *p == *q) { - ++p; ++q; --len; - } - - if (*q) { + if (len < 3) { + /* scheme not defined with a :// terminator */ res = -2; goto error; } + for (i = 0; i < COAP_URI_SCHEME_LAST; i++) { + if ((p - str_var) == (int)strlen(coap_uri_scheme[i].name) && + memcmp(str_var, coap_uri_scheme[i].name, p - str_var) == 0) { + if (check_proxy != COAP_URI_CHECK_PROXY && coap_uri_scheme[i].proxy_only) + return -1; + uri->scheme = coap_uri_scheme[i].scheme; + uri->port = coap_uri_scheme[i].port; + break; + } + } + if (i == COAP_URI_SCHEME_LAST) { + /* scheme unknown */ + res = -1; + goto error; + } + /* skip :// */ + p += 3; + len -= 3; /* p points to beginning of Uri-Host */ q = p; - if (len && *p == '[') { /* IPv6 address reference */ + if (len && *p == '[') { + /* IPv6 address reference */ ++p; while (len && *q != ']') { @@ -171,7 +130,8 @@ coap_split_uri_sub(const uint8_t *str_var, COAP_SET_STR(&uri->host, q - p, p); ++q; --len; - } else { /* IPv4 address or FQDN */ + } else { + /* IPv4 address or FQDN */ while (len && *q != ':' && *q != '/' && *q != '?') { ++q; --len; @@ -199,19 +159,19 @@ coap_split_uri_sub(const uint8_t *str_var, int uri_port = 0; while ((p < q) && (uri_port <= UINT16_MAX)) - uri_port = uri_port * 10 + (*p++ - '0'); + uri_port = uri_port * 10 + (*p++ - '0'); /* check if port number is in allowed range */ if (uri_port > UINT16_MAX) { - res = -4; - goto error; + res = -4; + goto error; } uri->port = (uint16_t)uri_port; } } - path: /* at this point, p must point to an absolute path */ +path: /* at this point, p must point to an absolute path */ if (!len) goto end; @@ -239,10 +199,10 @@ coap_split_uri_sub(const uint8_t *str_var, len = 0; } - end: +end: return len ? -1 : 0; - error: +error: return res; } diff --git a/win32/libcoap.vcxproj b/win32/libcoap.vcxproj index 96c870da..69252cca 100644 --- a/win32/libcoap.vcxproj +++ b/win32/libcoap.vcxproj @@ -109,6 +109,7 @@ + diff --git a/win32/libcoap.vcxproj.filters b/win32/libcoap.vcxproj.filters index 5231afca..ae55b127 100644 --- a/win32/libcoap.vcxproj.filters +++ b/win32/libcoap.vcxproj.filters @@ -218,6 +218,9 @@ Header Files + + Header Files + Header Files