diff --git a/include/coap3/coap_net.h b/include/coap3/coap_net.h
index ce292ec3de..ebb650aa8e 100644
--- a/include/coap3/coap_net.h
+++ b/include/coap3/coap_net.h
@@ -37,7 +37,6 @@
#include "coap_pdu.h"
#include "coap_session.h"
#include "coap_debug.h"
-#include "coap_resource.h"
/**
* @ingroup application_api
@@ -608,28 +607,6 @@ void coap_context_set_app_data(coap_context_t *context, void *data);
*/
void *coap_context_get_app_data(const coap_context_t *context);
-/**
- * Definition of get .well-known/core string callback function
- */
-typedef coap_print_status_t (*coap_print_wellknown_t)(coap_context_t *context,
- coap_session_t *session,
- const coap_pdu_t *request,
- unsigned char *buf,
- size_t *buflen,
- size_t offset,
- const coap_string_t *query_filter);
-
-/**
- * Defines the callback that is called when the .well-known/core resource is requested.
- *
- * @param context The context to associate the print_wellknown callback with
- * @param callback The callback to invoke when the .well-known/core resource is requested
- * or NULL to unregister a previously registered callback.
- *
- */
-void coap_register_print_wellknown_callback(coap_context_t *context,
- coap_print_wellknown_t callback);
-
/**@}*/
/**
diff --git a/include/coap3/coap_net_internal.h b/include/coap3/coap_net_internal.h
index 6646ce95f3..0c0b28547f 100644
--- a/include/coap3/coap_net_internal.h
+++ b/include/coap3/coap_net_internal.h
@@ -59,8 +59,6 @@ struct coap_context_t {
coap_resource_release_userdata_handler_t release_userdata;
/**< function to release user_data
when resource is deleted */
- coap_print_wellknown_t print_wellknown_userdata; /**< custom response for
- well-known/core resource */
#endif /* COAP_SERVER_SUPPORT */
#if COAP_ASYNC_SUPPORT
diff --git a/include/coap3/coap_resource.h b/include/coap3/coap_resource.h
index 30d463c560..b4661dcaa4 100644
--- a/include/coap3/coap_resource.h
+++ b/include/coap3/coap_resource.h
@@ -150,6 +150,13 @@ typedef void (*coap_method_handler_t)(coap_resource_t *resource,
*/
#define COAP_RESOURCE_FLAGS_OSCORE_ONLY 0x400
+/**
+ * Define this when invoking *coap_resource_unknown_init2*() if .well-known/core
+ * is to be passed to the unknown URI handler rather than processed locally.
+ * Used for easily passing on a request as a reverse-proxy request.
+ */
+#define COAP_RESOURCE_HANDLE_WELLKNOWN_CORE 0x800
+
/**
* Creates a new resource object and initializes the link field to the string
* @p uri_path. This function returns the new coap_resource_t object.
@@ -497,8 +504,9 @@ coap_print_status_t coap_print_link(const coap_resource_t *resource,
/**
* Prints the names of all known resources for @p context to @p buf. This function
* sets @p buflen to the number of bytes actually written and returns
- * @c 1 on success. On error, the value in @p buflen is undefined and
- * the return value will be @c 0.
+ * @c COAP_PRINT_STATUS_ERROR on error. On error, the value in @p buflen is undefined.
+ * Otherwise, the lower 28 bits are set to the number of bytes that have actually
+ * been written. COAP_PRINT_STATUS_TRUNC is set when the output has been truncated.
*
* @param context The context with the resource map.
* @param buf The buffer to write the result.
diff --git a/include/coap3/coap_resource_internal.h b/include/coap3/coap_resource_internal.h
index 6bb5a49eb3..923e7cbc34 100644
--- a/include/coap3/coap_resource_internal.h
+++ b/include/coap3/coap_resource_internal.h
@@ -185,8 +185,11 @@ void coap_delete_attr(coap_attr_t *attr);
/**
* Prints the names of all known resources for @p context to @p buf. This function
* sets @p buflen to the number of bytes actually written and returns
- * @c 1 on success. On error, the value in @p buflen is undefined and
- * the return value will be @c 0.
+ * @c COAP_PRINT_STATUS_ERROR on error. On error, the value in @p buflen is undefined.
+ * Otherwise, the lower 28 bits are set to the number of bytes that have actually
+ * been written. COAP_PRINT_STATUS_TRUNC is set when the output has been truncated.
+ *
+ * Note: This function must be called in the locked state.
*
* @param context The context with the resource map.
* @param buf The buffer to write the result.
diff --git a/libcoap-3.map b/libcoap-3.map
index 502cc2e3b4..6bb004e117 100644
--- a/libcoap-3.map
+++ b/libcoap-3.map
@@ -202,7 +202,6 @@ global:
coap_register_option;
coap_register_ping_handler;
coap_register_pong_handler;
- coap_register_print_wellknown_callback;
coap_register_request_handler;
coap_register_response_handler;
coap_resize_binary;
diff --git a/libcoap-3.sym b/libcoap-3.sym
index efee3edd0d..71df243876 100644
--- a/libcoap-3.sym
+++ b/libcoap-3.sym
@@ -200,7 +200,6 @@ coap_register_nack_handler
coap_register_option
coap_register_ping_handler
coap_register_pong_handler
-coap_register_print_wellknown_callback
coap_register_request_handler
coap_register_response_handler
coap_resize_binary
diff --git a/man/coap_handler.txt.in b/man/coap_handler.txt.in
index 0dd73b9e4d..59e95da016 100644
--- a/man/coap_handler.txt.in
+++ b/man/coap_handler.txt.in
@@ -16,8 +16,7 @@ coap_register_response_handler,
coap_register_nack_handler,
coap_register_ping_handler,
coap_register_pong_handler,
-coap_register_event_handler,
-coap_register_print_wellknown_callback
+coap_register_event_handler
- Work with CoAP handlers
SYNOPSIS
@@ -42,9 +41,6 @@ coap_pong_handler_t _handler_)*;
*void coap_register_event_handler(coap_context_t *_context_,
coap_event_handler_t _handler_)*;
-*void coap_register_print_wellknown_callback(coap_context_t *context,
-coap_print_wellknown_t callback);*
-
For specific (D)TLS library support, link with
*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls*,
@@ -392,39 +388,6 @@ typedef enum {
} coap_event_t;
----
-*Function: coap_register_print_wellknown_callback()*
-
-The *coap_register_print_wellknown_callback*() function registers a
-callback function that is called instead of the default *coap_print_wellknown*()
-function when the implicit .well-known/core resource is requested.
-
-The callback function prototype is defined as:
-[source, c]
-----
-/**
- * @param context The context with the resource map.
- * @param session The CoAP session.
- * @param buf The buffer to write the result.
- * @param buflen Must be initialized to the maximum length of buf and will be
- * set to the length of the well-known response on return.
- * @param offset The offset in bytes where the output shall start and is shifted
- * accordingly with the characters that have been processed. This
- * parameter is used to support the block option.
- * @param query_filter A filter query according to Link Format
- *
- * @return COAP_PRINT_STATUS_ERROR on error. Otherwise, the lower 28 bits are
- * set to the number of bytes that have actually been written to
- * @p buf. COAP_PRINT_STATUS_TRUNC is set when the output has been
- * truncated.
- */
-typedef coap_print_status_t (*coap_print_wellknown_t)(coap_context_t *context,
- coap_session_t *session,
- unsigned char *buf,
- size_t *buflen,
- size_t offset,
- const coap_string_t *query_filter);
-----
-
EXAMPLES
--------
*GET Resource Callback Handler*
diff --git a/man/coap_resource.txt.in b/man/coap_resource.txt.in
index 41adeba102..057119ab83 100644
--- a/man/coap_resource.txt.in
+++ b/man/coap_resource.txt.in
@@ -155,13 +155,22 @@ to the request handler.
*COAP_RESOURCE_FLAGS_OSCORE_ONLY*::
Define this resource as an OSCORE enabled access only.
+*COAP_RESOURCE_HANDLE_WELLKNOWN_CORE*::
+Define this when invoking *coap_resource_unknown_init2*() if .well-known/core
+is to be passed to the unknown URI handler rather than processed locally.
+Used for easily passing on a request as a reverse-proxy request.
+
*NOTE:* The following flags are only tested against if
*coap_mcast_per_resource*() has been called. If *coap_mcast_per_resource*()
has not been called, then all resources have multicast support, libcoap adds
in random delays to the responses, and 4.xx / 5.xx responses are dropped.
*NOTE:* The pseudo resource for ".well-known/core" always has multicast
-support enabled and is not configurable.
+support enabled and is not configurable. It is possible for a server to
+create a resource for ".well-known/core" that can then control the
+multicast support and the provided GET request handler can call
+*coap_print_wellknown*() to produce the same information as the pseudo
+resource.
[horizontal]
*COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT*::
@@ -173,7 +182,7 @@ sending the response back to the client. It is then the responsibility of
the app to delay the responses for multicast requests. See
"https://rfc-editor.org/rfc/rfc7252#section-8.2[RFC7252 8.2. Request/Response
Layer]".
- However, the pseudo resource for ".well-known/core" always has multicast
+However, the pseudo resource for ".well-known/core" always has multicast
support enabled.
*COAP_RESOURCE_FLAGS_LIB_ENA_MCAST_SUPPRESS_2_05*::
@@ -302,6 +311,9 @@ identified by the unique string _uri_path_ associated with _context_.
The *coap_print_wellknown*() function prints the names of all known resources
of the given _context_ into _buf_ which has a maximum size of _buflen_. The
first _offset_ bytes are skipped from the output to handle block transfers.
+Setting _offset_ to 0 means the entire (matching) information is output.
+Setting _offset_ to UINT_MAX skips, but calculates the size of, the (matching)
+output.
The _query_filter_ is usually defined by the CoAP Uri-Query options as a query.
RETURN VALUES
diff --git a/src/coap_net.c b/src/coap_net.c
index 7df2e21bee..f5c958a910 100644
--- a/src/coap_net.c
+++ b/src/coap_net.c
@@ -2713,40 +2713,6 @@ coap_new_error_response(const coap_pdu_t *request, coap_pdu_code_t code,
}
#if COAP_SERVER_SUPPORT
-/**
- * Quick hack to determine the size of the resource description for
- * .well-known/core.
- */
-COAP_STATIC_INLINE ssize_t
-get_wkc_len(coap_context_t *context,
- coap_session_t *session,
- const coap_pdu_t *request,
- const coap_string_t *query_filter) {
- unsigned char buf[1];
- size_t len = 0;
- int result = 0;
-
- if (context->print_wellknown_userdata) {
- result = context->print_wellknown_userdata(context,
- session,
- request,
- buf,
- &len,
- UINT_MAX,
- query_filter);
- } else {
- coap_lock_lock(session->context, return COAP_PRINT_STATUS_ERROR);
- result = coap_print_wellknown_lkd(context, buf, &len, UINT_MAX, query_filter);
- coap_lock_unlock(session->context);
- }
- if (result & COAP_PRINT_STATUS_ERROR) {
- coap_log_warn("cannot determine length of /.well-known/core\n");
- return -1L;
- }
-
- return len;
-}
-
#define SZX_TO_BYTES(SZX) ((size_t)(1 << ((SZX) + 4)))
static void
@@ -2755,40 +2721,38 @@ free_wellknown_response(coap_session_t *session COAP_UNUSED, void *app_ptr) {
}
/*
- * Caution - this handler is being treated as if in app space.
+ * Caution: As this handler is in libcoap space, it is called with
+ * context locked.
*/
static void
-hnd_get_wellknown(coap_resource_t *resource,
- coap_session_t *session,
- const coap_pdu_t *request,
- const coap_string_t *query,
- coap_pdu_t *response) {
+hnd_get_wellknown_lkd(coap_resource_t *resource,
+ coap_session_t *session,
+ const coap_pdu_t *request,
+ const coap_string_t *query,
+ coap_pdu_t *response) {
size_t len = 0;
coap_string_t *data_string = NULL;
- int result = 0;
- ssize_t wkc_len = get_wkc_len(session->context, session, request, query);
+ coap_print_status_t result = 0;
+ size_t wkc_len = 0;
+ uint8_t buf[4];
- if (wkc_len) {
- if (wkc_len < 0)
- goto error;
+ /*
+ * Quick hack to determine the size of the resource descriptions for
+ * .well-known/core.
+ */
+ result = coap_print_wellknown_lkd(session->context, buf, &wkc_len, UINT_MAX, query);
+ if (result & COAP_PRINT_STATUS_ERROR) {
+ coap_log_warn("cannot determine length of /.well-known/core\n");
+ goto error;
+ }
+
+ if (wkc_len > 0) {
data_string = coap_new_string(wkc_len);
if (!data_string)
goto error;
len = wkc_len;
- if (session->context->print_wellknown_userdata) {
- result = session->context->print_wellknown_userdata(session->context,
- session,
- request,
- data_string->s,
- &len,
- 0,
- query);
- } else {
- coap_lock_lock(session->context, goto error);
- result = coap_print_wellknown_lkd(session->context, data_string->s, &len, 0, query);
- coap_lock_unlock(session->context);
- }
+ result = coap_print_wellknown_lkd(session->context, data_string->s, &len, 0, query);
if ((result & COAP_PRINT_STATUS_ERROR) != 0) {
coap_log_debug("coap_print_wellknown failed\n");
goto error;
@@ -2797,8 +2761,6 @@ hnd_get_wellknown(coap_resource_t *resource,
data_string->length = len;
if (!(session->block_mode & COAP_BLOCK_USE_LIBCOAP)) {
- uint8_t buf[4];
-
if (!coap_insert_option(response, COAP_OPTION_CONTENT_FORMAT,
coap_encode_var_safe(buf, sizeof(buf),
COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf)) {
@@ -2826,6 +2788,12 @@ hnd_get_wellknown(coap_resource_t *resource,
data_string)) {
goto error_released;
}
+ } else {
+ if (!coap_insert_option(response, COAP_OPTION_CONTENT_FORMAT,
+ coap_encode_var_safe(buf, sizeof(buf),
+ COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf)) {
+ goto error;
+ }
}
response->code = COAP_RESPONSE_CODE(205);
return;
@@ -3215,20 +3183,31 @@ handle_request(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu
* if configured, for the unknown handler.
*
* if a PROXY URI/Scheme request and proxy URI handler defined, call the
- * proxy URI handler
+ * proxy URI handler.
*
- * else if well-known URI generate a default response
+ * else if unknown URI handler defined and COAP_RESOURCE_HANDLE_WELLKNOWN_CORE
+ * set, call the unknown URI handler with any unknown URI (including
+ * .well-known/core) if the appropriate method is defined.
+ *
+ * else if well-known URI generate a default response.
*
* else if unknown URI handler defined, call the unknown
* URI handler (to allow for potential generation of resource
* [RFC7272 5.8.3]) if the appropriate method is defined.
*
- * else if DELETE return 2.02 (RFC7252: 5.8.4. DELETE)
+ * else if DELETE return 2.02 (RFC7252: 5.8.4. DELETE).
*
- * else return 4.04 */
+ * else return 4.04.
+ */
if (is_proxy_uri || is_proxy_scheme) {
resource = context->proxy_uri_resource;
+ } else if (context->unknown_resource != NULL &&
+ context->unknown_resource->flags & COAP_RESOURCE_HANDLE_WELLKNOWN_CORE &&
+ ((size_t)pdu->code - 1 <
+ (sizeof(resource->handler) / sizeof(coap_method_handler_t))) &&
+ (context->unknown_resource->handler[pdu->code - 1])) {
+ resource = context->unknown_resource;
} else if (coap_string_equal(uri_path, &coap_default_uri_wellknown)) {
/* request for .well-known/core */
resource = &resource_uri_wellknown;
@@ -3446,13 +3425,21 @@ handle_request(coap_context_t *context, coap_session_t *session, coap_pdu_t *pdu
/*
* Call the request handler with everything set up
*/
- coap_log_debug("call custom handler for resource '%*.*s' (3)\n",
- (int)resource->uri_path->length, (int)resource->uri_path->length,
- resource->uri_path->s);
- coap_lock_callback_release(context,
- h(resource, session, pdu, query, response),
- /* context is being freed off */
- goto finish);
+ if (resource == &resource_uri_wellknown) {
+ /* Leave context locked */
+ coap_log_debug("call handler for pseudo resource '%*.*s' (3)\n",
+ (int)resource->uri_path->length, (int)resource->uri_path->length,
+ resource->uri_path->s);
+ h(resource, session, pdu, query, response);
+ } else {
+ coap_log_debug("call custom handler for resource '%*.*s' (3)\n",
+ (int)resource->uri_path->length, (int)resource->uri_path->length,
+ resource->uri_path->s);
+ coap_lock_callback_release(context,
+ h(resource, session, pdu, query, response),
+ /* context is being freed off */
+ goto finish);
+ }
/* Check validity of response code */
if (!coap_check_code_class(session, response)) {
@@ -4411,7 +4398,7 @@ coap_startup(void) {
(const uint8_t *)".well-known/core"
};
memset(&resource_uri_wellknown, 0, sizeof(resource_uri_wellknown));
- resource_uri_wellknown.handler[COAP_REQUEST_GET-1] = hnd_get_wellknown;
+ resource_uri_wellknown.handler[COAP_REQUEST_GET-1] = hnd_get_wellknown_lkd;
resource_uri_wellknown.flags = COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT;
resource_uri_wellknown.uri_path = &well_known;
#endif /* COAP_SERVER_SUPPORT */
@@ -4731,12 +4718,6 @@ coap_mcast_per_resource(coap_context_t *context) {
context->mcast_per_resource = 1;
}
-void
-coap_register_print_wellknown_callback(coap_context_t *context,
- coap_print_wellknown_t hnd) {
- context->print_wellknown_userdata = hnd;
-}
-
#endif /* ! COAP_SERVER_SUPPORT */
#if COAP_CLIENT_SUPPORT
diff --git a/src/coap_resource.c b/src/coap_resource.c
index 8f48c83e34..589e9d3e8d 100644
--- a/src/coap_resource.c
+++ b/src/coap_resource.c
@@ -101,29 +101,7 @@ match(const coap_str_const_t *text, const coap_str_const_t *pattern,
memcmp(text->s, pattern->s, pattern->length) == 0;
}
-/**
- * Prints the names of all known resources for @p context to @p buf. This function
- * sets @p buflen to the number of bytes actually written and returns
- * @c 1 on succes. On error, the value in @p buflen is undefined and
- * the return value will be @c 0.
- *
- * @param context The context with the resource map.
- * @param session The CoAP session.
- * @param buf The buffer to write the result.
- * @param buflen Must be initialized to the maximum length of @p buf and will be
- * set to the length of the well-known response on return.
- * @param offset The offset in bytes where the output shall start and is
- * shifted accordingly with the characters that have been
- * processed. This parameter is used to support the block
- * option.
- * @param query_filter A filter query according to Link Format
- *
- * @return COAP_PRINT_STATUS_ERROR on error. Otherwise, the lower 28 bits are
- * set to the number of bytes that have actually been written to
- * @p buf. COAP_PRINT_STATUS_TRUNC is set when the output has been
- * truncated.
- */
-coap_print_status_t
+COAP_API coap_print_status_t
coap_print_wellknown(coap_context_t *context, unsigned char *buf,
size_t *buflen, size_t offset,
const coap_string_t *query_filter) {
@@ -134,6 +112,11 @@ coap_print_wellknown(coap_context_t *context, unsigned char *buf,
return result;
}
+static coap_str_const_t coap_default_uri_wellknown = {
+ sizeof(COAP_DEFAULT_URI_WELLKNOWN)-1,
+ (const uint8_t *)COAP_DEFAULT_URI_WELLKNOWN
+};
+
coap_print_status_t
coap_print_wellknown_lkd(coap_context_t *context, unsigned char *buf,
size_t *buflen, size_t offset,
@@ -161,6 +144,7 @@ coap_print_wellknown_lkd(coap_context_t *context, unsigned char *buf,
};
#endif /* WITHOUT_QUERY_FILTER */
+ coap_lock_check_locked(context);
#ifndef WITHOUT_QUERY_FILTER
/* split query filter, if any */
if (query_filter) {
@@ -207,6 +191,10 @@ coap_print_wellknown_lkd(coap_context_t *context, unsigned char *buf,
RESOURCES_ITER(context->resources, r) {
+ if (coap_string_equal(r->uri_path, &coap_default_uri_wellknown)) {
+ /* server app has defined a resource for .well-known/core - ignore */
+ continue;
+ }
#ifndef WITHOUT_QUERY_FILTER
if (resource_param.length) { /* there is a query filter */
@@ -314,7 +302,7 @@ coap_resource_unknown_init2(coap_method_handler_t put_handler, int flags) {
r->is_unknown = 1;
/* Something unlikely to be used, but it shows up in the logs */
r->uri_path = coap_new_str_const(coap_unknown_resource_uri, sizeof(coap_unknown_resource_uri)-1);
- r->flags = flags & COAP_RESOURCE_FLAGS_MCAST_LIST;
+ 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");
@@ -372,7 +360,7 @@ coap_resource_proxy_uri_init2(coap_method_handler_t handler,
r->proxy_name_count = i;
}
}
- r->flags = flags & COAP_RESOURCE_FLAGS_MCAST_LIST;
+ r->flags = flags & ~COAP_RESOURCE_FLAGS_RELEASE_URI;
} else {
coap_log_debug("coap_resource_proxy_uri_init2: no memory left\n");
}