Skip to content

Commit

Permalink
Proxy: Update Proxy support for Proxy-Uri: CoAP option
Browse files Browse the repository at this point in the history
Add code to better support the Proxy-Uri: and Proxy-Scheme: CoAP Options.

examples/client.c:

Make sure that the Proxy-Uri: option is added (if set) when clearing down an
observation (fixes obgm#112).
Check that Proxy-Uri: option has a maximum data length of 1034 bytes.
Handle user defined Proxy-Scheme: option correctly.
Update -P option to include scheme to be used when connecting to the proxy.

examples/coap-server.c:

Add in hnd_proxy_uri() handler function. This has support for a direct or ongoing
proxy connection for the coap* protocols. The ongoing connection is set up as a
different CoAP session and is assocated with the incoming session for relaying
requests / responses.

Internal functions taken from client.c are used where appropriate.

Proxy support code has a SERVER_CAN_PROXY wrapper, so footprint can easily be
reduced if required.

New -P and -u options added to support ongoing connections.

include/coap2/net.h:

Add in tracking the proxy uri handler into coap_context_t.

include/coap2/resource.h:

Track whether a resource definition is for Proxy-Uri:/Proxy-Scheme:.
Define the coap_resource_proxy_uri_init() function for handling the Proxy-Uri:
option or Proxy-Scheme: option in an incoming request.

include/coap2/uri.h:

Add in COAP_URI_SCHEME_HTTP and COAP_URI_SCHEME_HTTPS as valid Proxy-Uri:
schemes.
Define the coap_split_proxy_uri() function (similar to coap_split_uri() but
supports the proxy extras.  Both now use a common sub function internally.

libcoap-2.map:
libcoap-2.sym:

Expose the new coap_resource_proxy_uri_init() and coap_split_proxy_uri()
functions.

man/Makefile.am:

Handle coap_resource_get_userdata(3) now being over the 10 definition limit
in man/coap_resource.txt.in.

man/coap-client.txt.in:

Update documentation for the -P option.

man/coap-server.txt.in:

Document the new -P proxy option.
Document the new -u user option.

man/coap_resource.txt.in:

Include documentation for coap_resource_proxy_uri_init().

src/coap_debug.c:

Output the Proxy-Scheme: Option as text.

src/net.c:

Sanity check and handle COAP_OPTION_PROXY_URI and COAP_OPTION_PROXY_SCHEME
in handle_request().

src/resource.c:

Add in coap_resource_proxy_uri_init() function.
Handle the addition of a proxy uri handler in coap_add_resource().

src/uri.c:

Rename coap_split_uri() to coap_split_uri_sub() and add in extra proxy
handling support based on input parameters.

Create new coap_split_uri() and coap_split_proxy_uri() which call
coap_split_uri_sub() appropriately.

TODO:

Remove reference to Proxy support required
  • Loading branch information
mrdeep1 committed Oct 18, 2020
1 parent 4ca959c commit 28c35ae
Show file tree
Hide file tree
Showing 16 changed files with 1,267 additions and 77 deletions.
2 changes: 0 additions & 2 deletions TODO
Expand Up @@ -11,8 +11,6 @@ Classification of issues:
=================
* CRITICAL ISSUES
=================
-> Proxy functionality
-> A coap-server should be able to act as proxy server

================
* SERIOUS ISSUES
Expand Down
158 changes: 128 additions & 30 deletions examples/client.c
Expand Up @@ -58,6 +58,9 @@ static coap_optlist_t *optlist = NULL;
static coap_uri_t uri;
static coap_string_t proxy = { 0, NULL };
static uint16_t proxy_port = COAP_DEFAULT_PORT;
static coap_uri_scheme_t proxy_scheme = COAP_URI_SCHEME_COAP;
static int proxy_scheme_option = 0;
static int uri_host_option = 0;
static unsigned int ping_seconds = 0;

/* reading is done when this flag is set */
Expand Down Expand Up @@ -197,7 +200,7 @@ coap_new_request(coap_context_t *ctx,
else {
unsigned char buf[4];
coap_add_option(pdu,
COAP_OPTION_SIZE1,
COAP_OPTION_SIZE1, /* 60 */
coap_encode_var_safe8(buf, sizeof(buf), length),
buf);

Expand Down Expand Up @@ -232,17 +235,21 @@ clear_obs(coap_context_t *ctx, coap_session_t *session) {
}

for (option = optlist; option; option = option->next ) {
if (option->number == COAP_OPTION_URI_HOST) {
switch (option->number) {
case COAP_OPTION_URI_HOST : /* 3 */
if (!coap_add_option(pdu, option->number, option->length,
option->data)) {
goto error;
}
break;
default:
;
}
}

/* Observe option comes after Uri-Host, but before the others */
if (!coap_add_option(pdu,
COAP_OPTION_OBSERVE,
COAP_OPTION_OBSERVE, /* 6 */
coap_encode_var_safe(buf, sizeof(buf), COAP_OBSERVE_CANCEL),
buf)) {
coap_log(LOG_CRIT, "cannot add option Observe: %u\n", COAP_OBSERVE_CANCEL);
Expand All @@ -269,10 +276,23 @@ clear_obs(coap_context_t *ctx, coap_session_t *session) {
block.num = 0;
block.m = 0;
coap_add_option(pdu,
COAP_OPTION_BLOCK2,
COAP_OPTION_BLOCK2, /* 23 */
coap_encode_var_safe(buf, sizeof(buf), (block.num << 4 | block.m << 3 | block.szx)),
buf);
}
for (option = optlist; option; option = option->next ) {
switch (option->number) {
case COAP_OPTION_PROXY_URI : /* 35 */
case COAP_OPTION_PROXY_SCHEME : /* 39 */
if (!coap_add_option(pdu, option->number, option->length,
option->data)) {
goto error;
}
break;
default:
;
}
}

if (coap_get_log_level() < LOG_DEBUG)
coap_show_pdu(LOG_INFO, pdu);
Expand Down Expand Up @@ -377,7 +397,7 @@ nack_handler(coap_context_t *context UNUSED_PARAM,
break;
case COAP_NACK_ICMP_ISSUE:
default:
break;
;
}
return;
}
Expand Down Expand Up @@ -475,11 +495,22 @@ message_handler(struct coap_context_t *ctx,
coap_log(LOG_DEBUG, "query block %d\n",
(coap_opt_block_num(block_opt) + 1));
coap_add_option(pdu,
blktype,
blktype, /* 23 or 27 */
coap_encode_var_safe(buf, sizeof(buf),
((coap_opt_block_num(block_opt) + 1) << 4) |
COAP_OPT_BLOCK_SZX(block_opt)), buf);

for (option = optlist; option; option = option->next ) {
switch (option->number) {
case COAP_OPTION_PROXY_URI : /* 35 */
case COAP_OPTION_PROXY_SCHEME : /* 39 */
coap_add_option(pdu, option->number, option->length,
option->data);
break;
default:
; /* skip other options */
}
}
tid = coap_send(session, pdu);

if (tid == COAP_INVALID_TID) {
Expand Down Expand Up @@ -562,7 +593,7 @@ message_handler(struct coap_context_t *ctx,
option->data);
break;
default:
; /* skip other options */
; /* skip other options */
}
}

Expand All @@ -573,12 +604,24 @@ message_handler(struct coap_context_t *ctx,

coap_log(LOG_DEBUG, "send block %d\n", block.num);
coap_add_option(pdu,
COAP_OPTION_BLOCK1,
COAP_OPTION_BLOCK1, /* 27 */
coap_encode_var_safe(buf, sizeof(buf),
(block.num << 4) | (block.m << 3) | block.szx), buf);

for (option = optlist; option; option = option->next ) {
switch (option->number) {
case COAP_OPTION_PROXY_URI : /* 35 */
case COAP_OPTION_PROXY_SCHEME : /* 39 */
coap_add_option(pdu, option->number, option->length,
option->data);
break;
default:
; /* skip other options */
}
}

coap_add_option(pdu,
COAP_OPTION_SIZE1,
COAP_OPTION_SIZE1, /* 60 */
coap_encode_var_safe8(buf, sizeof(buf), payload.length),
buf);

Expand Down Expand Up @@ -645,7 +688,7 @@ usage( const char *program, const char *version) {
"Usage: %s [-a addr] [-b [num,]size] [-e text] [-f file] [-l loss]\n"
"\t\t[-m method] [-o file] [-p port] [-r] [-s duration] [-t type]\n"
"\t\t[-v num] [-A type] [-B seconds] [-H hoplimit] [-K interval] [-N]\n"
"\t\t[-O num,text] [-P addr[:port]] [-T token] [-U]\n"
"\t\t[-O num,text] [-P scheme://address[:port]] [-T token] [-U]\n"
"\t\t[[-h match_hint_file] [-k key] [-u user]]\n"
"\t\t[[-c certfile] [-j keyfile] [-C cafile] [-J pkcs11_pin]\n"
"\t\t[-R root_cafile] [-S match_pki_sni_file]] URI\n"
Expand Down Expand Up @@ -680,13 +723,15 @@ usage( const char *program, const char *version) {
"\t-H hoplimit\tSet the Hop Limit count to hoplimit for proxies. Must\n"
"\t \t\thave a value between 1 and 255 inclusive.\n"
"\t \t\tDefault is '16'\n"
"\t-K interval\tsend a ping after interval seconds of inactivity\n"
"\t-K interval\tSend a ping after interval seconds of inactivity\n"
"\t-N \t\tSend NON-confirmable message\n"
"\t-O num,text\tAdd option num with contents text to request. If the\n"
"\t \t\ttext begins with 0x, then the hex text is converted to\n"
"\t \t\tbinary data\n"
"\t-P addr[:port]\tUse proxy (automatically adds Proxy-Uri option to\n"
"\t \t\trequest)\n"
"\t-P scheme://address[:port]\tScheme, address and optional port to\n"
"\t \t\tdefine how to connect to a CoAP proxy (automatically adds\n"
"\t \t\tProxy-Uri option to request) to forward the request to.\n"
"\t \t\tScheme is one of coap, coaps, coap+tcp and coaps+tcp\n"
"\t-T token\tInclude specified token\n"
"\t-U \t\tNever include Uri-Host or Uri-Port options\n"
,program, version, coap_string_tls_version(buffer, sizeof(buffer))
Expand Down Expand Up @@ -836,16 +881,11 @@ cmdline_uri(char *arg, int create_uri_opts) {
size_t buflen;
int res;

if (proxy.length) { /* create Proxy-Uri from argument */
if (!proxy_scheme_option && proxy.length) { /* create Proxy-Uri from argument */
size_t len = strlen(arg);
while (len > 270) {
coap_insert_optlist(&optlist,
coap_new_optlist(COAP_OPTION_PROXY_URI,
270,
(unsigned char *)arg));

len -= 270;
arg += 270;
if (len > 1034) {
coap_log(LOG_ERR, "Absolute URI length must be <= 1034 bytes for a proxy\n");
return -1;
}

coap_insert_optlist(&optlist,
Expand Down Expand Up @@ -978,7 +1018,35 @@ cmdline_subscribe(char *arg) {

static int
cmdline_proxy(char *arg) {
char *proxy_port_str = strrchr((const char *)arg, ':'); /* explicit port ? */
char *proxy_port_str;

if (strncmp(arg, "coap", 4) == 0) {
if (strncmp(arg, "coaps+tcp://", 12) == 0) {
proxy_scheme = COAP_URI_SCHEME_COAPS_TCP;
proxy_port = COAPS_DEFAULT_PORT;
arg += 12;
}
else if (strncmp(arg, "coap+tcp://", 11) == 0) {
proxy_scheme = COAP_URI_SCHEME_COAP_TCP;
proxy_port = COAP_DEFAULT_PORT;
arg += 11;
}
else if (strncmp(arg, "coaps://", 8) == 0) {
proxy_scheme = COAP_URI_SCHEME_COAPS;
proxy_port = COAPS_DEFAULT_PORT;
arg += 8;
}
else if (strncmp(arg, "coap://", 7) == 0) {
proxy_scheme = COAP_URI_SCHEME_COAP;
proxy_port = COAP_DEFAULT_PORT;
arg += 7;
}
else {
coap_log(LOG_WARNING, "Invalid proxy protocol prefix '%s'\n", arg);
return 0;
}
}
proxy_port_str = strrchr((const char *)arg, ':'); /* explicit port ? */
if (proxy_port_str) {
char *ipv6_delimiter = strrchr((const char *)arg, ']');
if (!ipv6_delimiter) {
Expand Down Expand Up @@ -1084,6 +1152,31 @@ cmdline_option(char *arg) {
coap_insert_optlist(&optlist,
coap_new_optlist(num, strlen(arg), (unsigned char *)arg));
}
if (num == COAP_OPTION_PROXY_SCHEME) {
proxy_scheme_option = 1;
if (strcmp(arg, "coaps+tcp") == 0) {
proxy_scheme = COAP_URI_SCHEME_COAPS_TCP;
proxy_port = COAPS_DEFAULT_PORT;
}
else if (strcmp(arg, "coap+tcp") == 0) {
proxy_scheme = COAP_URI_SCHEME_COAP_TCP;
proxy_port = COAP_DEFAULT_PORT;
}
else if (strcmp(arg, "coaps") == 0) {
proxy_scheme = COAP_URI_SCHEME_COAPS;
proxy_port = COAPS_DEFAULT_PORT;
}
else if (strcmp(arg, "coap") == 0) {
proxy_scheme = COAP_URI_SCHEME_COAP;
proxy_port = COAP_DEFAULT_PORT;
}
else {
coap_log(LOG_WARNING, "%s is not a supported CoAP Proxy-Scheme\n", arg);
}
}
if (num == COAP_OPTION_URI_HOST) {
uri_host_option = 1;
}
}

/**
Expand Down Expand Up @@ -1559,6 +1652,7 @@ main(int argc, char **argv) {
ssize_t user_length = -1, key_length = 0;
int create_uri_opts = 1;
size_t i;
coap_uri_scheme_t scheme;
#ifndef _WIN32
struct sigaction sa;
#endif
Expand Down Expand Up @@ -1705,9 +1799,11 @@ main(int argc, char **argv) {
server.length = proxy.length;
server.s = proxy.s;
port = proxy_port;
scheme = proxy_scheme;
} else {
server = uri.host;
port = uri.port;
port = proxy_scheme_option ? proxy_port : uri.port;
scheme = proxy_scheme_option ? proxy_scheme : uri.scheme;
}

/* resolve destination address where server should be sent */
Expand All @@ -1732,11 +1828,11 @@ main(int argc, char **argv) {
session = get_session(
ctx,
node_str[0] ? node_str : NULL, port_str,
uri.scheme==COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP :
uri.scheme==COAP_URI_SCHEME_COAPS_TCP ? COAP_PROTO_TLS :
scheme==COAP_URI_SCHEME_COAP_TCP ? COAP_PROTO_TCP :
scheme==COAP_URI_SCHEME_COAPS_TCP ? COAP_PROTO_TLS :
(reliable ?
uri.scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_TLS : COAP_PROTO_TCP
: uri.scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_UDP),
scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_TLS : COAP_PROTO_TCP
: scheme==COAP_URI_SCHEME_COAPS ? COAP_PROTO_DTLS : COAP_PROTO_UDP),
&dst,
user_length >= 0 ? user : NULL,
user_length >= 0 ? user_length : 0,
Expand Down Expand Up @@ -1770,11 +1866,11 @@ main(int argc, char **argv) {

/* construct CoAP message */

if (!proxy.length && addrptr
if (!uri_host_option && (!proxy.length && addrptr
&& (inet_ntop(dst.addr.sa.sa_family, addrptr, addr, sizeof(addr)) != 0)
&& (strlen(addr) != uri.host.length
|| memcmp(addr, uri.host.s, uri.host.length) != 0)
&& create_uri_opts) {
&& create_uri_opts)) {
/* add Uri-Host */

coap_insert_optlist(&optlist,
Expand Down Expand Up @@ -1857,6 +1953,8 @@ main(int argc, char **argv) {
}
if (valid_ihs.count)
free(valid_ihs.ih_list);
if (proxy.s)
coap_free(proxy.s);
coap_delete_optlist(optlist);
if (payload.s) coap_free(payload.s);
coap_session_release( session );
Expand Down

0 comments on commit 28c35ae

Please sign in to comment.