Skip to content

Commit

Permalink
reverse-proxy: Provide dedicated reverse-proxy handler setup function
Browse files Browse the repository at this point in the history
  • Loading branch information
mrdeep1 committed Aug 16, 2024
1 parent 626d463 commit 3d790a5
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 18 deletions.
12 changes: 2 additions & 10 deletions examples/coap-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1122,15 +1122,7 @@ init_resources(coap_context_t *ctx) {
#if COAP_PROXY_SUPPORT
if (reverse_proxy.entry_count) {
/* Create a reverse proxy resource to handle PUTs */
r = coap_resource_unknown_init2(hnd_reverse_proxy_uri,
COAP_RESOURCE_HANDLE_WELLKNOWN_CORE);
/* Add in handling other requests as well */
coap_register_handler(r, COAP_REQUEST_GET, hnd_reverse_proxy_uri);
coap_register_handler(r, COAP_REQUEST_POST, hnd_reverse_proxy_uri);
coap_register_handler(r, COAP_REQUEST_DELETE, hnd_reverse_proxy_uri);
coap_register_handler(r, COAP_REQUEST_FETCH, hnd_reverse_proxy_uri);
coap_register_handler(r, COAP_REQUEST_PATCH, hnd_reverse_proxy_uri);
coap_register_handler(r, COAP_REQUEST_IPATCH, hnd_reverse_proxy_uri);
r = coap_resource_reverse_proxy_init(hnd_reverse_proxy_uri, 0);
coap_add_resource(ctx, r);
coap_register_event_handler(ctx, proxy_event_handler);
coap_register_response_handler(ctx, reverse_response_handler);
Expand Down Expand Up @@ -1840,7 +1832,7 @@ cmdline_proxy(char *arg) {
new_entry = realloc(forward_proxy.entry,
(forward_proxy.entry_count + 1)*sizeof(forward_proxy.entry[0]));
if (!new_entry) {
coap_log_err("CoAP Reverse-Proxy realloc() error\n");
coap_log_err("CoAP Proxy realloc() error\n");
return 0;
}
forward_proxy.entry = new_entry;
Expand Down
23 changes: 21 additions & 2 deletions include/coap3/coap_resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ coap_resource_t *coap_resource_unknown_init(coap_method_handler_t put_handler);
* DELETE handler specified for the resource removal) or by maintaining an
* active resource list.
*
* Note: There can only be one unknown resource handler per context - attaching
* a new one overrides the previous definition.
* Note: There can only be one unknown or reverse-proxy resource handler per
* context - attaching a new one overrides the previous definition.
*
* Note: It is not possible to observe the unknown resource with a GET request
* - a separate resource needs to be created by the PUT (or POST)
Expand Down Expand Up @@ -286,6 +286,25 @@ coap_resource_t *coap_resource_proxy_uri_init2(coap_method_handler_t handler,
const char *host_name_list[],
int flags);

/**
* Creates a new resource object for the reverse-proxy resource handler with
* control over multicast request packets.
*
* Note: There can only be one reverse-proxy or unknown resource handler per
* context - attaching a new one overrides the previous definition.
*
* This function returns the new coap_resource_t object.
*
* @param handler The PUT/POST/GET etc. handler that handles all the reverse-proxy
* requests including .well-known-core.
* @param flags Zero or more COAP_RESOURCE_FLAGS_*MCAST* ored together to
* indicate what to do with multicast packets.
*
* @return A pointer to the new object or @c NULL on error.
*/
coap_resource_t *coap_resource_reverse_proxy_init(coap_method_handler_t handler,
int flags);

/**
* Returns the resource identified by the unique string @p uri_path. If no
* resource was found, this function returns @c NULL.
Expand Down
1 change: 1 addition & 0 deletions libcoap-3.map
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ global:
coap_resource_proxy_uri_init2;
coap_resource_proxy_uri_init;
coap_resource_release_userdata_handler;
coap_resource_reverse_proxy_init;
coap_resource_set_dirty;
coap_resource_set_get_observable;
coap_resource_set_mode;
Expand Down
1 change: 1 addition & 0 deletions libcoap-3.sym
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ coap_resource_notify_observers
coap_resource_proxy_uri_init
coap_resource_proxy_uri_init2
coap_resource_release_userdata_handler
coap_resource_reverse_proxy_init
coap_resource_set_dirty
coap_resource_set_get_observable
coap_resource_set_mode
Expand Down
1 change: 1 addition & 0 deletions man/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ install-man: install-man3 install-man5 install-man7
@echo ".so man3/coap_recovery.3" > coap_session_set_probing_rate.3
@echo ".so man3/coap_recovery.3" > coap_session_get_probing_rate.3
@echo ".so man3/coap_recovery.3" > coap_debug_set_packet_loss.3
@echo ".so man3/coap_resource.3" > coap_delete_resource.3
@echo ".so man3/coap_resource.3" > coap_resource_set_mode.3
@echo ".so man3/coap_resource.3" > coap_resource_set_userdata.3
@echo ".so man3/coap_resource.3" > coap_resource_get_userdata.3
Expand Down
125 changes: 123 additions & 2 deletions man/coap_proxy.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with
DESCRIPTION
-----------

To simplify some of the CoAP proxy requirements, some of the functionaliy
is provided by libcoap.
To simplify some of the CoAP proxy requirements, some of the proxy forwarding
functionality is provided by libcoap.

The resourse handlers to handle forward or reverse proxy requests are defined using
*coap_resource_proxy_uri_init2*(3) or coap_resource_reverse_proxy_init*(3).

FUNCTIONS
---------
Expand Down Expand Up @@ -81,6 +84,124 @@ return 1 on success and 0 on failure.
*coap_proxy_forward_response*() returns one of COAP_RESPONSE_OK or
COAP_RESPONSE_FAIL.

EXAMPLES
--------
*Forward Proxy Set Up*

[source, c]
----
#include <coap@LIBCOAP_API_VERSION@/coap.h>

static size_t proxy_host_name_count = 0;
static const char **proxy_host_name_list = NULL;
static coap_proxy_server_list_t forward_proxy = { NULL, 0, 0, COAP_PROXY_FORWARD, 0, 300};

static void
hnd_forward_proxy_uri(coap_resource_t *resource,
coap_session_t *session,
const coap_pdu_t *request,
const coap_string_t *query COAP_UNUSED,
coap_pdu_t *response) {

if (!coap_proxy_forward_request(session, request, response, resource,
NULL, &forward_proxy)) {
coap_log_debug("hnd_forward_proxy_uri: Failed to forward PDU\n");
/* Non ACK response code set on error detection */
}

/* Leave response code as is */
}

static coap_response_t
proxy_response_handler(coap_session_t *session,
const coap_pdu_t *sent COAP_UNUSED,
const coap_pdu_t *received,
const coap_mid_t id COAP_UNUSED) {
return coap_proxy_forward_response(session, received, NULL);
}

static void
init_resources(coap_context_t *ctx) {

coap_resource_t *r;

/* See coap_resource_proxy_uri_init2(3) */
r = coap_resource_proxy_uri_init2(hnd_forward_proxy_uri, proxy_host_name_count,
proxy_host_name_list, 0);
coap_add_resource(ctx, r);
coap_register_response_handler(ctx, proxy_response_handler);
/* Add in event or nack handlers if required */
}

static void
init_proxy_info(coap_uri_t *proxy_uri, const char *proxy_host_name) {
coap_proxy_server_t *new_entry;

new_entry = realloc(forward_proxy.entry,
(forward_proxy.entry_count + 1)*sizeof(forward_proxy.entry[0]));

if (!new_entry) {
coap_log_err("CoAP Proxy realloc() error\n");
return;
}
/* Can have multiple of these upstream proxy hosts for doing round robin etc. */
forward_proxy.entry = new_entry;
memset(&forward_proxy.entry[forward_proxy.entry_count], 0, sizeof(forward_proxy.entry[0]));
forward_proxy.entry[forward_proxy.entry_count].uri = *proxy_uri;
forward_proxy.entry_count++;

/* The proxy host could be known by multile names - add them all in */
proxy_host_name_count = 0;
proxy_host_name_list = coap_malloc(proxy_host_name_count * sizeof(char *));
proxy_host_name_list[0] = proxy_host_name;
}
----

*Reverse Proxy Set Up*

[source, c]
----
#include <coap@LIBCOAP_API_VERSION@/coap.h>

static coap_proxy_server_list_t reverse_proxy = { NULL, 0, 0, COAP_PROXY_REVERSE_STRIP, 0, 10};

static void
hnd_reverse_proxy_uri(coap_resource_t *resource,
coap_session_t *session,
const coap_pdu_t *request,
const coap_string_t *query COAP_UNUSED,
coap_pdu_t *response) {

if (!coap_proxy_forward_request(session, request, response, resource,
NULL, &reverse_proxy)) {
coap_log_debug("hnd_reverse_proxy: Failed to forward PDU\n");
/* Non ACK response code set on error detection */
}

/* Leave response code as is */
}

static coap_response_t
proxy_response_handler(coap_session_t *session,
const coap_pdu_t *sent COAP_UNUSED,
const coap_pdu_t *received,
const coap_mid_t id COAP_UNUSED) {
return coap_proxy_forward_response(session, received, NULL);
}

static void
init_resources(coap_context_t *ctx) {

coap_resource_t *r;

/* See coap_resource_reverse_proxy_init(3) */
r = coap_resource_reverse_proxy_init(hnd_reverse_proxy_uri, 0);
coap_add_resource(ctx, r);
coap_register_response_handler(ctx, proxy_response_handler);
/* Add in event or nack handlers if required */
}
----

FURTHER INFORMATION
-------------------
See
Expand Down
27 changes: 24 additions & 3 deletions man/coap_resource.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ coap_resource_unknown_init,
coap_resource_unknown_init2,
coap_resource_proxy_uri_init,
coap_resource_proxy_uri_init2,
coap_resource_reverse_proxy_init,
coap_add_resource,
coap_delete_resource,
coap_resource_set_mode,
Expand Down Expand Up @@ -47,6 +48,9 @@ _proxy_handler_, size_t _host_name_count_, const char *_host_name_list_[]);*
_proxy_handler_, size_t _host_name_count_, const char *_host_name_list_[],
int _flags_);*

*coap_resource_t *coap_resource_reverse_proxy_init(coap_method_handler_t
_rev_proxy_handler_, int _flags_);*

*void coap_add_resource(coap_context_t *_context_,
coap_resource_t *_resource_);*

Expand Down Expand Up @@ -224,6 +228,9 @@ _resource_ to handle PUT requests to resources that are unknown. Additional
handlers can be added to this resource if required. _flags_ can be zero or
more of the COAP_RESOURCE_FLAGS MCAST definitions.

*NOTE:* There can only be one reverse-proxy or unknown resource handler per
context - attaching a new one overrides the previous definition.

*Function: coap_resource_proxy_uri_init()*

The *coap_resource_proxy_uri_init*() function returns a newly created
Expand All @@ -248,6 +255,20 @@ _host_name_count_. This is used to check whether the current endpoint is
the proxy target address, or the request has to be passed on to an upstream
server. _flags_ can be zero or more COAP_RESOURCE_FLAGS MCAST definitions.

*NOTE:* There can only be one proxy resource handler per
context - attaching a new one overrides the previous definition.

*Function: coap_resource_reverse_proxy_init()*

The *coap_resource_reverse_proxy_init*() function returns a newly created
_resource_ of type _coap_resource_t_ *. _rev_proxy_handler_ is automatically added
to the _resource_ to handle all the PUT/POST/GET etc. requests including
.well-known/core. There is no need to add explicit request type handlers.
_flags_ can be zero or more COAP_RESOURCE_FLAGS MCAST definitions.

*NOTE:* There can only be one reverse-proxy or unknown resource handler per
context - attaching a new one overrides the previous definition.

*Function: coap_add_resource()*

The *coap_add_resource*() function registers the given _resource_ with the
Expand Down Expand Up @@ -319,9 +340,9 @@ The _query_filter_ is usually defined by the CoAP Uri-Query options as a query.
RETURN VALUES
-------------
*coap_resource_init*(), *coap_resource_unknown_init*(),
*coap_resource_unknown_init2*(), *coap_resource_proxy_uri_init*() and
*coap_resource_proxy_uri_init2*() return a newly created resource
or NULL if there is a malloc failure.
*coap_resource_unknown_init2*(), *coap_resource_proxy_uri_init*(),
*coap_resource_proxy_uri_init2*() and *coap_resource_reverse_proxy_init*()
return a newly created resource or NULL if there is a malloc failure.

*coap_delete_resource*() returns 0 on failure (_resource_ not
found), 1 on success.
Expand Down
32 changes: 31 additions & 1 deletion src/coap_resource.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ coap_resource_unknown_init2(coap_method_handler_t put_handler, int flags) {
r->flags = flags & ~COAP_RESOURCE_FLAGS_RELEASE_URI;
coap_register_handler(r, COAP_REQUEST_PUT, put_handler);
} else {
coap_log_debug("coap_resource_unknown_init: no memory left\n");
coap_log_debug("coap_resource_unknown_init2: no memory left\n");
}

return r;
Expand Down Expand Up @@ -375,6 +375,36 @@ coap_resource_proxy_uri_init(coap_method_handler_t handler,
host_name_list, 0);
}

static const uint8_t coap_rev_proxy_resource_uri[] =
"- Rev Proxy -";

coap_resource_t *
coap_resource_reverse_proxy_init(coap_method_handler_t handler, int flags) {
coap_resource_t *r;

r = (coap_resource_t *)coap_malloc_type(COAP_RESOURCE, sizeof(coap_resource_t));
if (r) {
memset(r, 0, sizeof(coap_resource_t));
r->is_unknown = 1;
/* Something unlikely to be used, but it shows up in the logs */
r->uri_path = coap_new_str_const(coap_rev_proxy_resource_uri,
sizeof(coap_rev_proxy_resource_uri)-1);
r->flags = flags & ~COAP_RESOURCE_FLAGS_RELEASE_URI;
r->flags |= COAP_RESOURCE_HANDLE_WELLKNOWN_CORE;
coap_register_handler(r, COAP_REQUEST_PUT, handler);
coap_register_handler(r, COAP_REQUEST_GET, handler);
coap_register_handler(r, COAP_REQUEST_POST, handler);
coap_register_handler(r, COAP_REQUEST_DELETE, handler);
coap_register_handler(r, COAP_REQUEST_FETCH, handler);
coap_register_handler(r, COAP_REQUEST_PATCH, handler);
coap_register_handler(r, COAP_REQUEST_IPATCH, handler);
} else {
coap_log_debug("coap_resource_rev_proxy_init: no memory left\n");
}

return r;
}

coap_attr_t *
coap_add_attr(coap_resource_t *resource,
coap_str_const_t *name,
Expand Down

0 comments on commit 3d790a5

Please sign in to comment.