diff --git a/components/coap/CMakeLists.txt b/components/coap/CMakeLists.txt index 01cd61e..288d4be 100644 --- a/components/coap/CMakeLists.txt +++ b/components/coap/CMakeLists.txt @@ -3,10 +3,13 @@ set(COMPONENT_ADD_INCLUDEDIRS port/include port/include/coap libcoap/include lib set(COMPONENT_SRCS "libcoap/src/address.c" "libcoap/src/async.c" "libcoap/src/block.c" + "libcoap/src/coap_event.c" + "libcoap/src/coap_hashkey.c" + "libcoap/src/coap_io.c" + "libcoap/src/coap_session.c" "libcoap/src/coap_time.c" - "libcoap/src/debug.c" + "libcoap/src/coap_debug.c" "libcoap/src/encode.c" - "libcoap/src/hashkey.c" "libcoap/src/mem.c" "libcoap/src/net.c" "libcoap/src/option.c" @@ -15,7 +18,7 @@ set(COMPONENT_SRCS "libcoap/src/address.c" "libcoap/src/str.c" "libcoap/src/subscribe.c" "libcoap/src/uri.c" - "port/coap_io_socket.c") + "libcoap/src/coap_notls.c") set(COMPONENT_REQUIRES lwip) @@ -26,16 +29,3 @@ register_component() # TODO: find a way to move this to a port header target_compile_definitions(${COMPONENT_TARGET} PUBLIC WITH_POSIX) -set_source_files_properties( - libcoap/src/debug.c - libcoap/src/pdu.c - PROPERTIES COMPILE_FLAGS - -Wno-write-strings) - -if(GCC_NOT_5_2_0) - # Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo - set_source_files_properties( - libcoap/src/option.c - PROPERTIES COMPILE_FLAGS - -Wno-implicit-fallthrough) -endif() \ No newline at end of file diff --git a/components/coap/component.mk b/components/coap/component.mk index bd7b0e0..6067471 100644 --- a/components/coap/component.mk +++ b/components/coap/component.mk @@ -2,17 +2,11 @@ # Component Makefile # -COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap +COMPONENT_ADD_INCLUDEDIRS := port/include port/include/coap libcoap/include libcoap/include/coap2 -COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_time.o libcoap/src/debug.o libcoap/src/encode.o libcoap/src/hashkey.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o port/coap_io_socket.o +COMPONENT_OBJS = libcoap/src/address.o libcoap/src/async.o libcoap/src/block.o libcoap/src/coap_event.o libcoap/src/coap_hashkey.o libcoap/src/coap_io.o libcoap/src/coap_session.o libcoap/src/coap_time.o libcoap/src/coap_debug.o libcoap/src/encode.o libcoap/src/mem.o libcoap/src/net.o libcoap/src/option.o libcoap/src/pdu.o libcoap/src/resource.o libcoap/src/str.o libcoap/src/subscribe.o libcoap/src/uri.o libcoap/src/coap_notls.o COMPONENT_SRCDIRS := libcoap/src libcoap port COMPONENT_SUBMODULES += libcoap -libcoap/src/debug.o: CFLAGS += -Wno-write-strings -libcoap/src/pdu.o: CFLAGS += -Wno-write-strings -ifeq ($(GCC_NOT_5_2_0), 1) -# Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo -libcoap/src/option.o: CFLAGS += -Wno-implicit-fallthrough -endif diff --git a/components/coap/libcoap b/components/coap/libcoap index 6468887..cfec0d0 160000 --- a/components/coap/libcoap +++ b/components/coap/libcoap @@ -1 +1 @@ -Subproject commit 6468887a12666f88b8704d797fc176cd4f40ee4c +Subproject commit cfec0d072c5b99ed3e54828ca50ea2f6b91e1f50 diff --git a/components/coap/port/include/coap/coap.h b/components/coap/port/include/coap/coap.h index cbdc9df..f048ca8 100644 --- a/components/coap/port/include/coap/coap.h +++ b/components/coap/port/include/coap/coap.h @@ -17,19 +17,21 @@ #ifndef _COAP_H_ #define _COAP_H_ -#include "libcoap.h" - #ifdef __cplusplus extern "C" { #endif +#include "libcoap.h" + #include "address.h" #include "async.h" #include "bits.h" #include "block.h" +#include "coap_dtls.h" +#include "coap_event.h" #include "coap_io.h" #include "coap_time.h" -#include "debug.h" +#include "coap_debug.h" #include "encode.h" #include "mem.h" #include "net.h" @@ -40,8 +42,6 @@ extern "C" { #include "str.h" #include "subscribe.h" #include "uri.h" -#include "uthash.h" -#include "utlist.h" #ifdef __cplusplus } diff --git a/components/coap/port/include/coap_config_posix.h b/components/coap/port/include/coap_config_posix.h index a77e97f..1809e68 100644 --- a/components/coap/port/include/coap_config_posix.h +++ b/components/coap/port/include/coap_config_posix.h @@ -25,6 +25,7 @@ #define HAVE_SYS_SOCKET_H #define HAVE_MALLOC #define HAVE_ARPA_INET_H +#define HAVE_TIME_H #define IP_PKTINFO IP_MULTICAST_IF #define IPV6_PKTINFO IPV6_V6ONLY @@ -36,6 +37,61 @@ #define CUSTOM_COAP_NETWORK_SEND #define CUSTOM_COAP_NETWORK_READ -#endif +#ifndef s6_addr32 +#define s6_addr32 un.u32_addr +#endif /* ! s6_addr32 */ +#ifndef IN6_IS_ADDR_V4MAPPED +# define IN6_IS_ADDR_V4MAPPED(a) \ + (__extension__ \ + ({ const struct in6_addr *__a = (const struct in6_addr *) (a); \ + __a->s6_addr32[0] == 0 \ + && __a->s6_addr32[1] == 0 \ + && __a->s6_addr32[2] == htonl (0xffff); })) +#endif /* !IN6_IS_ADDR_V4MAPPED */ + +#ifndef CMSG_FIRSTHDR + +/* RFC 3542, Section 20: Ancillary Data */ +struct cmsghdr { + socklen_t cmsg_len; /* number of bytes, including header */ + int cmsg_level; /* originating protocol */ + int cmsg_type; /* protocol-specific type */ +}; +/* Data section follows header and possible padding, typically referred to as + unsigned char cmsg_data[]; */ + +/* cmsg header/data alignment. NOTE: we align to native word size (double word +size on 16-bit arch) so structures are not placed at an unaligned address. +16-bit arch needs double word to ensure 32-bit alignment because socklen_t +could be 32 bits. If we ever have cmsg data with a 64-bit variable, alignment +will need to increase long long */ +#define ALIGN_H(size) (((size) + sizeof(long) - 1U) & ~(sizeof(long)-1U)) +#define ALIGN_D(size) ALIGN_H(size) + +#define CMSG_FIRSTHDR(mhdr) \ + ((mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \ + (struct cmsghdr *)(mhdr)->msg_control : \ + (struct cmsghdr *)NULL) + +#define CMSG_NXTHDR(mhdr, cmsg) \ + (((cmsg) == NULL) ? CMSG_FIRSTHDR(mhdr) : \ + (((u8_t *)(cmsg) + ALIGN_H((cmsg)->cmsg_len) \ + + ALIGN_D(sizeof(struct cmsghdr)) > \ + (u8_t *)((mhdr)->msg_control) + (mhdr)->msg_controllen) ? \ + (struct cmsghdr *)NULL : \ + (struct cmsghdr *)((void*)((u8_t *)(cmsg) + \ + ALIGN_H((cmsg)->cmsg_len))))) + +#define CMSG_DATA(cmsg) ((void*)((u8_t *)(cmsg) + \ + ALIGN_D(sizeof(struct cmsghdr)))) + +#define CMSG_SPACE(length) (ALIGN_D(sizeof(struct cmsghdr)) + \ + ALIGN_H(length)) + +#define CMSG_LEN(length) (ALIGN_D(sizeof(struct cmsghdr)) + \ + length) +#endif /* !CMSG_FIRSTHDR */ + +#endif /* WITH_POSIX */ #endif /* COAP_CONFIG_POSIX_H_ */ diff --git a/examples/protocols/coap_client/main/coap_client_example_main.c b/examples/protocols/coap_client/main/coap_client_example_main.c index e2d1b96..34eb5c0 100644 --- a/examples/protocols/coap_client/main/coap_client_example_main.c +++ b/examples/protocols/coap_client/main/coap_client_example_main.c @@ -52,17 +52,20 @@ const static int CONNECTED_BIT = BIT0; const static char *TAG = "CoAP_client"; -static void message_handler(struct coap_context_t *ctx, const coap_endpoint_t *local_interface, const coap_address_t *remote, +static int resp_wait = 1; + +static void message_handler(coap_context_t *ctx, coap_session_t *session, coap_pdu_t *sent, coap_pdu_t *received, const coap_tid_t id) { unsigned char* data = NULL; size_t data_len; - if (COAP_RESPONSE_CLASS(received->hdr->code) == 2) { + if (COAP_RESPONSE_CLASS(received->code) == 2) { if (coap_get_data(received, &data_len, &data)) { printf("Received: %s\n", data); } } + resp_wait = 0; } static void coap_example_task(void *p) @@ -70,17 +73,22 @@ static void coap_example_task(void *p) struct hostent *hp; struct ip4_addr *ip4_addr; - coap_context_t* ctx = NULL; coap_address_t dst_addr, src_addr; static coap_uri_t uri; - fd_set readfds; - struct timeval tv; - int flags, result; - coap_pdu_t* request = NULL; const char* server_uri = COAP_DEFAULT_DEMO_URI; - uint8_t get_method = 1; char* phostname = NULL; while (1) { + coap_optlist_t *optlist = NULL; +#define BUFSIZE 40 + unsigned char _buf[BUFSIZE]; + unsigned char *buf; + size_t buflen; + int res; + int wait_ms; + coap_context_t* ctx = NULL; + coap_session_t* session = NULL; + coap_pdu_t* request = NULL; + /* Wait for the callback to set the CONNECTED_BIT in the event group. */ @@ -93,6 +101,12 @@ static void coap_example_task(void *p) break; } + if ((uri.scheme==COAP_URI_SCHEME_COAPS || uri.scheme==COAP_URI_SCHEME_COAPS_TCP) + && !coap_dtls_is_supported()) { + ESP_LOGE(TAG, "CoAP server uri scheme error"); + break; + } + phostname = (char *)calloc(1, uri.host.length + 1); if (phostname == NULL) { @@ -107,6 +121,7 @@ static void coap_example_task(void *p) if (hp == NULL) { ESP_LOGE(TAG, "DNS lookup failed"); vTaskDelay(1000 / portTICK_PERIOD_MS); + free(phostname); continue; } @@ -121,46 +136,87 @@ static void coap_example_task(void *p) src_addr.addr.sin.sin_port = htons(0); src_addr.addr.sin.sin_addr.s_addr = INADDR_ANY; - ctx = coap_new_context(&src_addr); - if (ctx) { - coap_address_init(&dst_addr); - dst_addr.addr.sin.sin_family = AF_INET; - dst_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT); - dst_addr.addr.sin.sin_addr.s_addr = ip4_addr->addr; - - request = coap_new_pdu(); - if (request){ - request->hdr->type = COAP_MESSAGE_CON; - request->hdr->id = coap_new_message_id(ctx); - request->hdr->code = get_method; - coap_add_option(request, COAP_OPTION_URI_PATH, uri.path.length, uri.path.s); - - coap_register_response_handler(ctx, message_handler); - coap_send_confirmed(ctx, ctx->endpoint, &dst_addr, request); - - flags = fcntl(ctx->sockfd, F_GETFL, 0); - fcntl(ctx->sockfd, F_SETFL, flags|O_NONBLOCK); - - tv.tv_usec = COAP_DEFAULT_TIME_USEC; - tv.tv_sec = COAP_DEFAULT_TIME_SEC; - - for(;;) { - FD_ZERO(&readfds); - FD_CLR( ctx->sockfd, &readfds ); - FD_SET( ctx->sockfd, &readfds ); - result = select( ctx->sockfd+1, &readfds, 0, 0, &tv ); - if (result > 0) { - if (FD_ISSET( ctx->sockfd, &readfds )) - coap_read(ctx); - } else if (result < 0) { - break; - } else { - ESP_LOGE(TAG, "select timeout"); - } - } + if (uri.path.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_PATH, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); + } + } + + if (uri.query.length) { + buflen = BUFSIZE; + buf = _buf; + res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen); + + while (res--) { + coap_insert_optlist(&optlist, + coap_new_optlist(COAP_OPTION_URI_QUERY, + coap_opt_length(buf), + coap_opt_value(buf))); + + buf += coap_opt_size(buf); + } + } + + ctx = coap_new_context(NULL); + if (!ctx) { + ESP_LOGE(TAG, "coap_new_context() failed"); + goto clean_up; + } + + coap_address_init(&dst_addr); + dst_addr.addr.sin.sin_family = AF_INET; + dst_addr.addr.sin.sin_port = htons(uri.port); + dst_addr.addr.sin.sin_addr.s_addr = ip4_addr->addr; + + session = coap_new_client_session(ctx, &src_addr, &dst_addr, uri.scheme); + if (!session) { + ESP_LOGE(TAG, "coap_new_client_session() failed"); + goto clean_up; + } + + coap_register_response_handler(ctx, message_handler); + + request = coap_new_pdu(session); + if (!request) { + ESP_LOGE(TAG, "coap_new_pdu() failed"); + goto clean_up; + } + request->type = COAP_MESSAGE_CON; + request->tid = coap_new_message_id(session); + request->code = COAP_REQUEST_GET; + coap_add_optlist_pdu(request, &optlist); + + resp_wait = 1; + coap_send(session, request); + + wait_ms = COAP_DEFAULT_TIME_SEC * 1000; + + while (resp_wait) { + int result = coap_run_once(ctx, wait_ms > 1000 ? 1000 : wait_ms); + if (result >= 0) { + if (result >= wait_ms) { + ESP_LOGE(TAG, "select timeout"); + break; + } + else { + wait_ms -= result; + } } - coap_free_context(ctx); } +clean_up: + if (optlist) coap_delete_optlist(optlist); + if (session) coap_session_release(session); + if (ctx) coap_free_context(ctx); + coap_cleanup(); } vTaskDelete(NULL); diff --git a/examples/protocols/coap_server/main/coap_server_example_main.c b/examples/protocols/coap_server/main/coap_server_example_main.c index 0d2ce0a..119ed62 100644 --- a/examples/protocols/coap_server/main/coap_server_example_main.c +++ b/examples/protocols/coap_server/main/coap_server_example_main.c @@ -43,52 +43,31 @@ const static int CONNECTED_BIT = BIT0; const static char *TAG = "CoAP_server"; -static coap_async_state_t *async = NULL; - -static void -send_async_response(coap_context_t *ctx, const coap_endpoint_t *local_if) -{ - coap_pdu_t *response; - unsigned char buf[3]; - const char* response_data = "Hello World!"; - response = coap_pdu_init(async->flags & COAP_MESSAGE_CON, COAP_RESPONSE_CODE(205), 0, COAP_MAX_PDU_SIZE); - response->hdr->id = coap_new_message_id(ctx); - if (async->tokenlen) - coap_add_token(response, async->tokenlen, async->token); - coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf); - coap_add_data (response, strlen(response_data), (unsigned char *)response_data); - - if (coap_send(ctx, local_if, &async->peer, response) == COAP_INVALID_TID) { - - } - coap_delete_pdu(response); - coap_async_state_t *tmp; - coap_remove_async(ctx, async->id, &tmp); - coap_free_async(async); - async = NULL; -} - /* * The resource handler */ static void -async_handler(coap_context_t *ctx, struct coap_resource_t *resource, - const coap_endpoint_t *local_interface, coap_address_t *peer, - coap_pdu_t *request, str *token, coap_pdu_t *response) +get_handler(coap_context_t *ctx, coap_resource_t *resource, + coap_session_t *session, + coap_pdu_t *request, coap_binary_t *token, + coap_string_t *query, coap_pdu_t *response) { - async = coap_register_async(ctx, peer, request, COAP_ASYNC_SEPARATE | COAP_ASYNC_CONFIRM, (void*)"no data"); + coap_add_data_blocked_response(resource, session, request, response, token, + COAP_MEDIATYPE_TEXT_PLAIN, 0, + strlen("no data"), + (const uint8_t *)"no data"); } static void coap_example_thread(void *p) { - coap_context_t* ctx = NULL; + coap_context_t *ctx = NULL; coap_address_t serv_addr; coap_resource_t* resource = NULL; - fd_set readfds; - struct timeval tv; - int flags = 0; while (1) { + coap_endpoint_t *ep_udp = NULL; + unsigned wait_ms; + /* Wait for the callback to set the CONNECTED_BIT in the event group. */ @@ -101,43 +80,42 @@ static void coap_example_thread(void *p) serv_addr.addr.sin.sin_family = AF_INET; serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY; serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT); - ctx = coap_new_context(&serv_addr); - if (ctx) { - flags = fcntl(ctx->sockfd, F_GETFL, 0); - fcntl(ctx->sockfd, F_SETFL, flags|O_NONBLOCK); - - tv.tv_usec = COAP_DEFAULT_TIME_USEC; - tv.tv_sec = COAP_DEFAULT_TIME_SEC; - /* Initialize the resource */ - resource = coap_resource_init((unsigned char *)"Espressif", 9, 0); - if (resource){ - coap_register_handler(resource, COAP_REQUEST_GET, async_handler); - coap_add_resource(ctx, resource); - /*For incoming connections*/ - for (;;) { - FD_ZERO(&readfds); - FD_CLR( ctx->sockfd, &readfds); - FD_SET( ctx->sockfd, &readfds); - - int result = select( ctx->sockfd+1, &readfds, 0, 0, &tv ); - if (result > 0){ - if (FD_ISSET( ctx->sockfd, &readfds )) - coap_read(ctx); - } else if (result < 0){ - break; - } else { - ESP_LOGE(TAG, "select timeout"); - } - - if (async) { - send_async_response(ctx, ctx->endpoint); - } - } - } - coap_free_context(ctx); + ctx = coap_new_context(&serv_addr); + if (!ctx) { + continue; + } + ep_udp = coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_UDP); + if (!ep_udp) { + goto clean_up; + } + resource = coap_resource_init(coap_make_str_const("Espressif"), 0); + if (!resource) { + goto clean_up; + } + coap_register_handler(resource, COAP_REQUEST_GET, get_handler); + coap_add_resource(ctx, resource); + + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; + + while (1) { + int result = coap_run_once(ctx, wait_ms); + if (result < 0) { + break; + } + else if (result && (unsigned)result < wait_ms) { + /* decrement if there is a result wait time returned */ + wait_ms -= result; + } + if (result) { + /* result must have been >= wait_ms, so reset wait_ms */ + wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; + } } } +clean_up: + coap_free_context(ctx); + coap_cleanup(); vTaskDelete(NULL); }