diff --git a/Xcode/nyoci.xcodeproj/project.pbxproj b/Xcode/nyoci.xcodeproj/project.pbxproj index 9aa599c..ac840ad 100644 --- a/Xcode/nyoci.xcodeproj/project.pbxproj +++ b/Xcode/nyoci.xcodeproj/project.pbxproj @@ -196,9 +196,9 @@ 277A052920AC959F00970354 /* help.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = help.h; sourceTree = ""; }; 277A052A20AC959F00970354 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 277A053620AC959F00970354 /* nyocictl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nyocictl.h; sourceTree = ""; }; - 277A054520AC959F00970354 /* nyoci-plat-net-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "nyoci-plat-net-internal.h"; sourceTree = ""; }; - 277A054620AC959F00970354 /* nyoci-plat-net.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "nyoci-plat-net.c"; sourceTree = ""; }; - 277A054720AC959F00970354 /* nyoci-plat-net.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "nyoci-plat-net.h"; sourceTree = ""; }; + 277A054520AC959F00970354 /* nyoci-plat-net-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "nyoci-plat-net-internal.h"; sourceTree = ""; usesTabs = 0; }; + 277A054620AC959F00970354 /* nyoci-plat-net.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "nyoci-plat-net.c"; sourceTree = ""; usesTabs = 0; }; + 277A054720AC959F00970354 /* nyoci-plat-net.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "nyoci-plat-net.h"; sourceTree = ""; usesTabs = 0; }; 277A055820AC959F00970354 /* nyoci-plat-tls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "nyoci-plat-tls.c"; sourceTree = ""; }; 277A055920AC959F00970354 /* nyoci-plat-tls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "nyoci-plat-tls.h"; sourceTree = ""; }; 277A056220AC959F00970354 /* main-client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "main-client.c"; sourceTree = ""; }; @@ -724,7 +724,7 @@ GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", HAVE_CONFIG_H, - DEBUG, + "DEBUG=1", ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -735,7 +735,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = macOS/; - MACOSX_DEPLOYMENT_TARGET = 10.13; + MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -797,7 +797,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = macOS/; - MACOSX_DEPLOYMENT_TARGET = 10.13; + MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SYSTEM_HEADER_SEARCH_PATHS = ../src; diff --git a/src/libnyoci/assert-macros.h b/src/libnyoci/assert-macros.h index 2f8027e..031689d 100644 --- a/src/libnyoci/assert-macros.h +++ b/src/libnyoci/assert-macros.h @@ -62,6 +62,7 @@ #if !DEBUG || ASSERT_MACROS_SQUELCH #define assert_printf(fmt, ...) do { } while(0) #define check_string(c, s) do { } while(0) + #define check_string_errno(c, s) do { } while(0) #define require_action_string(c, l, a, s) \ do { if(!(c)) { \ a; goto l; \ @@ -79,6 +80,12 @@ PSTR(__FILE__ ":%d: "fmt"\n"), \ __LINE__, \ __VA_ARGS__) + #elif ESP_PLATFORM + #define assert_printf(fmt, ...) \ + ESP_LOGE("nyoci", \ + __FILE__ ":%d: "fmt"\n", \ + __LINE__, \ + __VA_ARGS__) #else #if ASSERT_MACROS_USE_SYSLOG #define assert_printf(fmt, ...) \ @@ -102,6 +109,9 @@ #define check_string(c, s) \ do { if(!(c)) assert_printf("Check Failed (%s)", \ s); } while(0) + #define check_string_errno(c, s) \ + do { if(!(c)) assert_printf("Check Failed (%s), errno=%d", \ + s, errno); } while(0) #define require_action_string(c, l, a, s) \ do { if(!(c)) { \ assert_printf("Requirement Failed (%s)", \ @@ -122,6 +132,7 @@ #endif #define check(c) check_string(c, # c) + #define check_errno(c) check_string_errno(c, # c) #define check_noerr(c) check((c) == 0) #define check_noerr_string(c, s) check_string((c) == 0, s) #define require_quiet(c, l) do { if(!(c)) goto l; } while(0) diff --git a/src/libnyoci/coap.c b/src/libnyoci/coap.c index 1de08f6..ceb7e63 100644 --- a/src/libnyoci/coap.c +++ b/src/libnyoci/coap.c @@ -490,6 +490,8 @@ coap_option_key_to_cstr( case COAP_OPTION_CONTENT_TYPE: ret = "Content-type"; break; case COAP_OPTION_MAX_AGE: ret = "Max-age"; break; case COAP_OPTION_ETAG: ret = "Etag"; break; + case COAP_OPTION_IF_MATCH: ret = "If-Match"; break; + case COAP_OPTION_IF_NONE_MATCH: ret = "If-None-Match"; break; case COAP_OPTION_PROXY_URI: ret = "Proxy-uri"; break; case COAP_OPTION_URI_HOST: ret = "URI-host"; break; case COAP_OPTION_URI_PORT: ret = "URI-port"; break; @@ -657,6 +659,7 @@ http_code_to_cstr(int x) { break; case HTTP_RESULT_CODE_REQUEST_TIMEOUT: return "REQUEST_TIMEOUT"; break; + case HTTP_RESULT_CODE_PRECONDITION_FAILED: return "PRECONDITION_FAILED"; break; case HTTP_RESULT_CODE_BAD_REQUEST: return "BAD_REQUEST"; break; case HTTP_RESULT_CODE_UNAUTHORIZED: return "UNAUTHORIZED"; break; diff --git a/src/libnyoci/coap.h b/src/libnyoci/coap.h index c6ccc5b..43774d9 100644 --- a/src/libnyoci/coap.h +++ b/src/libnyoci/coap.h @@ -133,6 +133,11 @@ enum { COAP_METHOD_POST = 2, COAP_METHOD_PUT = 3, COAP_METHOD_DELETE = 4, + + // RFC 8132 + COAP_METHOD_FETCH = 5, + COAP_METHOD_PATCH = 6, + COAP_METHOD_IPATCH = 7, }; enum { @@ -172,11 +177,16 @@ enum { COAP_RESULT_504_GATEWAY_TIMEOUT = HTTP_TO_COAP_CODE(504), COAP_RESULT_505_PROXYING_NOT_SUPPORTED = HTTP_TO_COAP_CODE(505), - // https://tools.ietf.org/html/draft-ietf-core-block-20#section-2.9 + // RFC 7959, section-2.9 COAP_RESULT_231_CONTINUE = HTTP_TO_COAP_CODE(231), COAP_RESULT_408_REQUEST_ENTITY_INCOMPLETE = HTTP_TO_COAP_CODE(408), COAP_RESULT_413_REQUEST_ENTITY_TOO_LARGE = HTTP_TO_COAP_CODE(413), + // RFC 8132 + COAP_RESULT_409_CONFLICT = HTTP_TO_COAP_CODE(409), + COAP_RESULT_422_UNPROCESSABLE_ENTITY = HTTP_TO_COAP_CODE(422), + + // https://tools.ietf.org/html/draft-bormann-core-coap-sig-01 COAP_CODE_701_CSM = HTTP_TO_COAP_CODE(701), COAP_CODE_702_PING = HTTP_TO_COAP_CODE(702), @@ -205,6 +215,7 @@ enum { HTTP_RESULT_CODE_METHOD_NOT_ALLOWED = 405, HTTP_RESULT_CODE_NOT_ACCEPTABLE = 406, HTTP_RESULT_CODE_REQUEST_TIMEOUT= 408, + HTTP_RESULT_CODE_CONFLICT = 409, HTTP_RESULT_CODE_PRECONDITION_FAILED = 412, HTTP_RESULT_CODE_REQUEST_ENTITY_TOO_LARGE = 413, HTTP_RESULT_CODE_UNSUPPORTED_MEDIA_TYPE = 415, @@ -222,7 +233,6 @@ enum { HTTP_RESULT_CODE_SEE_OTHER = 303, HTTP_RESULT_CODE_TEMPORARY_REDIRECT = 307, HTTP_RESULT_CODE_PARTIAL_CONTENT = 206, - HTTP_RESULT_CODE_CONFLICT = 409, HTTP_RESULT_CODE_GONE = 410, HTTP_RESULT_CODE_REQUESTED_RANGE_NOT_SATISFIABLE = 416, }; @@ -247,13 +257,13 @@ typedef enum { COAP_OPTION_URI_QUERY = 15, COAP_OPTION_ACCEPT = 17, COAP_OPTION_LOCATION_QUERY = 20, - COAP_OPTION_BLOCK2 = 23, /* draft-ietf-core-block-10 */ - COAP_OPTION_BLOCK1 = 27, /* draft-ietf-core-block-10 */ - COAP_OPTION_SIZE = 28, /* draft-ietf-core-block-10 */ + COAP_OPTION_BLOCK2 = 23, /* RFC 7959 */ + COAP_OPTION_BLOCK1 = 27, /* RFC 7959 */ + COAP_OPTION_SIZE = 28, /* RFC 7959 */ COAP_OPTION_PROXY_URI = 35, - COAP_OPTION_SIZE2 = 28, /* draft-ietf-core-block-20 */ - COAP_OPTION_SIZE1 = 60, /* draft-ietf-core-block-20 */ + COAP_OPTION_SIZE2 = 28, /* RFC 7959 */ + COAP_OPTION_SIZE1 = 60, /* RFC 7959 */ ////////////////////////////////////////////////////////////////////// // Experimental after this point. Experimentals start at 65000. @@ -300,6 +310,10 @@ enum { COAP_CONTENT_TYPE_APPLICATION_EXI = 47, COAP_CONTENT_TYPE_APPLICATION_JSON = 50, + //! RFC 8132 + COAP_CONTENT_TYPE_APPLICATION_JSON_PATCH = 51, + COAP_CONTENT_TYPE_APPLICATION_MERGE_PATCH = 52, + //! application/cbor rfc7049 COAP_CONTENT_TYPE_APPLICATION_CBOR = 60, diff --git a/src/libnyoci/libnyoci.h b/src/libnyoci/libnyoci.h index aa47446..c5c0b52 100644 --- a/src/libnyoci/libnyoci.h +++ b/src/libnyoci/libnyoci.h @@ -490,6 +490,12 @@ NYOCI_API_EXTERN nyoci_status_t nyoci_outbound_append_content_formatted(const ch nyoci_outbound_append_content_formatted(fmt,__VA_ARGS__) #endif +//! Returns a pointer to the start of the current outbound CoAP packet. +NYOCI_API_EXTERN const struct coap_header_s* nyoci_outbound_get_packet(void); + +//! Returns the length of the outbound packet. +NYOCI_API_EXTERN coap_size_t nyoci_outbound_get_packet_length(void); + //! Sends the outbound packet. /*! After calling this function, you are done for this callback. You may not ** call any other nyoci_outbound_* functions. You may only send one outbound diff --git a/src/libnyoci/nyoci-internal.h b/src/libnyoci/nyoci-internal.h index a14cc8f..3943c95 100644 --- a/src/libnyoci/nyoci-internal.h +++ b/src/libnyoci/nyoci-internal.h @@ -50,6 +50,10 @@ ((uint32_t)random_rand() ^ \ ((uint32_t)random_rand() << 16)) #define NYOCI_RANDOM_MAX RAND_MAX +#elif ESP_PLATFORM +#include +#define NYOCI_FUNC_RANDOM_UINT32() randombytes_random() +#define NYOCI_RANDOM_MAX (uint32_t)(0xFFFFFFFF) #else #define NYOCI_FUNC_RANDOM_UINT32() \ ((uint32_t)random() ^ \ diff --git a/src/libnyoci/nyoci-logging.h b/src/libnyoci/nyoci-logging.h index b6ad026..dd1562f 100644 --- a/src/libnyoci/nyoci-logging.h +++ b/src/libnyoci/nyoci-logging.h @@ -34,40 +34,46 @@ #if !VERBOSE_DEBUG -#define CSTR(x) (x) + #define CSTR(x) (x) -#ifndef DEBUG_PRINTF -#define DEBUG_PRINTF(...) do { } while(0) -#endif -#define NYOCI_DEBUG_OUT_FILE stdout + #ifndef DEBUG_PRINTF + #define DEBUG_PRINTF(...) do { } while(0) + #endif + #define NYOCI_DEBUG_OUT_FILE stdout #elif defined(__AVR__) -#define NYOCI_DEBUG_OUT_FILE stdout + #define NYOCI_DEBUG_OUT_FILE stdout -#include -#include -#define CSTR(x) PSTR(x) -#define DEBUG_PRINTF(...) \ + #include + #include + #define CSTR(x) PSTR(x) + #define DEBUG_PRINTF(...) \ do { fprintf_P(NYOCI_DEBUG_OUT_FILE, __VA_ARGS__); fputc( \ - '\n', \ - NYOCI_DEBUG_OUT_FILE); } while(0) + '\n', \ + NYOCI_DEBUG_OUT_FILE); } while(0) -#else // __AVR__ -#define NYOCI_DEBUG_OUT_FILE stderr +#elif defined(ESP_PLATFORM) + #include + #define DEBUG_PRINTF(FMT, ...) ESP_LOGI("nyoci", FMT, ##__VA_ARGS__) + #define NYOCI_DEBUG_OUT_FILE stderr + #define CSTR(x) x -#include -#define CSTR(x) (x) -#if ASSERT_MACROS_USES_SYSLOG -#include -#define DEBUG_PRINTF(...) syslog(7, __VA_ARGS__) -#elif ASSERT_MACROS_USE_VANILLA_PRINTF -#define DEBUG_PRINTF(...) \ - do { printf(__VA_ARGS__); printf("\n"); } while(0) #else -#define DEBUG_PRINTF(...) \ - do { fprintf(NYOCI_DEBUG_OUT_FILE, __VA_ARGS__); fputc('\n', \ - NYOCI_DEBUG_OUT_FILE); } while(0) -#endif + #define NYOCI_DEBUG_OUT_FILE stderr + + #include + #define CSTR(x) (x) + #if ASSERT_MACROS_USES_SYSLOG + #include + #define DEBUG_PRINTF(...) syslog(7, __VA_ARGS__) + #elif ASSERT_MACROS_USE_VANILLA_PRINTF + #define DEBUG_PRINTF(...) \ + do { printf(__VA_ARGS__); printf("\n"); } while(0) + #else + #define DEBUG_PRINTF(...) \ + do { fprintf(NYOCI_DEBUG_OUT_FILE, __VA_ARGS__); fputc('\n', \ + NYOCI_DEBUG_OUT_FILE); } while(0) + #endif #endif diff --git a/src/libnyoci/nyoci-outbound.c b/src/libnyoci/nyoci-outbound.c index 9c57dc8..59173e8 100644 --- a/src/libnyoci/nyoci-outbound.c +++ b/src/libnyoci/nyoci-outbound.c @@ -726,6 +726,22 @@ nyoci_outbound_set_var_content_unsigned_long_int(unsigned long int v) } +const struct coap_header_s* +nyoci_outbound_get_packet(void) +{ + nyoci_t const self = nyoci_get_current_instance(); + return self->outbound.packet; +} + +coap_size_t +nyoci_outbound_get_packet_length(void) +{ + nyoci_t const self = nyoci_get_current_instance(); + coap_size_t header_len = (coap_size_t)(nyoci_outbound_get_content_ptr(NULL)-(char*)self->outbound.packet); + return header_len+self->outbound.content_len; +} + + nyoci_status_t nyoci_outbound_quick_response(coap_code_t code, const char* body) { diff --git a/src/nyocictl/cmd_list.c b/src/nyocictl/cmd_list.c index 48a88c2..5307333 100644 --- a/src/nyocictl/cmd_list.c +++ b/src/nyocictl/cmd_list.c @@ -181,7 +181,7 @@ parse_link_format(char* content, coap_size_t content_length, void* context) { type = (coap_content_type_t)strtol(value, NULL, 0); } else if (0 == strcmp(key, "obs")) { - obs = (strtol(value, NULL, 0) != NULL); + obs = (strtol(value, NULL, 0) != 0); } else if (0 == strcmp(key, "sh")) { sh_url = value; diff --git a/src/nyocictl/main.c b/src/nyocictl/main.c index 59e526f..af7e326 100644 --- a/src/nyocictl/main.c +++ b/src/nyocictl/main.c @@ -75,6 +75,12 @@ static arg_list_item_t option_list[] = { void print_commands(void); +static void print_env_help(void) { + printf("Environment:\n" + " NYOCI_CURRENT_PATH CoAP URL to access; defaults to coap://localhost/\n" + " COAP_PROXY_URL Proxy server to use\n"); +} + static int tool_cmd_help( nyoci_t nyoci, int argc, char* argv[] @@ -92,6 +98,7 @@ tool_cmd_help( return exec_command(nyoci, 2, (char**)argv2); } else { print_commands(); + print_env_help(); } return ERRORCODE_HELP; } @@ -766,6 +773,7 @@ main( argv[0], "[options] [args]"); print_commands(); + print_env_help(); gRet = ERRORCODE_HELP; goto bail; } diff --git a/src/plat-net/posix/nyoci-plat-net-internal.h b/src/plat-net/posix/nyoci-plat-net-internal.h index e1cef57..e83e47e 100644 --- a/src/plat-net/posix/nyoci-plat-net-internal.h +++ b/src/plat-net/posix/nyoci-plat-net-internal.h @@ -45,6 +45,12 @@ #define NYOCI_PLAT_NET_POSIX_FAMILY AF_INET6 #endif +#ifndef NYOCI_LWIP + #ifdef ESP_PLATFORM + #define NYOCI_LWIP + #endif +#endif + #if NYOCI_SINGLETON #define nyoci_internal_multicast_joinleave(self,...) nyoci_internal_multicast_joinleave(__VA_ARGS__) #endif @@ -53,6 +59,15 @@ #define NYOCI_ADDR_NTOP(str, len, addr) inet_ntop(NYOCI_PLAT_NET_POSIX_FAMILY, addr , str, len-1) #if NYOCI_PLAT_NET_POSIX_FAMILY == AF_INET6 +#ifndef IN6_IS_ADDR_V4MAPPED + // IN6_IS_ADDR_V4MAPPED is not defined in lwIP. I copied this macro from macOS 10.13's in6.h. --snej + #define IN6_IS_ADDR_V4MAPPED(a) \ + ((*(const __uint32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \ + (*(const __uint32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \ + (*(const __uint32_t *)(const void *)(&(a)->s6_addr[8]) == \ + ntohl(0x0000ffff))) +#endif + #define ___nyoci_len sin6_len #define ___nyoci_family sin6_family #define NYOCI_IS_ADDR_MULTICAST(addrptr) (IN6_IS_ADDR_MULTICAST(addrptr) || (IN6_IS_ADDR_V4MAPPED(addrptr) && ((addrptr)->s6_addr[12] & 0xF0)==0xE0)) @@ -66,6 +81,7 @@ #endif #ifdef IPV6_PKTINFO #define NYOCI_PKTINFO IPV6_PKTINFO +#define nyoci_pktinfo in6_pktinfo #endif #define NYOCI_IPPROTO IPPROTO_IPV6 @@ -77,6 +93,7 @@ #endif #ifdef IP_PKTINFO #define NYOCI_PKTINFO IP_PKTINFO +#define nyoci_pktinfo in_pktinfo #endif #define NYOCI_IPPROTO IPPROTO_IPV4 @@ -90,7 +107,7 @@ #endif // NYOCI_PLAT_NET_POSIX_FAMILY NYOCI_BEGIN_C_DECLS - + struct nyoci_plat_s { int mcfd_v6; //!< For multicast int mcfd_v4; //!< For multicast @@ -109,10 +126,8 @@ struct nyoci_plat_s { nyoci_sockaddr_t sockaddr_remote; nyoci_session_type_t session_type; -#if NYOCI_PLAT_NET_POSIX_FAMILY==AF_INET6 - struct in6_pktinfo pktinfo; -#elif NYOCI_PLAT_NET_POSIX_FAMILY==AF_INET - struct in_pktinfo pktinfo; +#ifdef NYOCI_PKTINFO + struct nyoci_pktinfo pktinfo; #endif char outbound_packet_bytes[NYOCI_MAX_PACKET_LENGTH+1]; diff --git a/src/plat-net/posix/nyoci-plat-net.c b/src/plat-net/posix/nyoci-plat-net.c index d9174a3..c6f3ef5 100644 --- a/src/plat-net/posix/nyoci-plat-net.c +++ b/src/plat-net/posix/nyoci-plat-net.c @@ -47,10 +47,8 @@ #include "nyoci-missing.h" #include -#include #include #include -#include #include #include #include @@ -58,8 +56,34 @@ #include #include #include -#include -#include + +#ifdef NYOCI_LWIP + // Lightweight IP library + #define ipv6_mreq ip6_mreq + #define EAI_AGAIN TRY_AGAIN +#else + #include +#endif + +#ifndef NYOCI_CAN_POLL + #ifdef NYOCI_LWIP + #define NYOCI_CAN_POLL 0 + #else + #define NYOCI_CAN_POLL 1 + #endif +#endif + +#ifndef NYOCI_CAN_SENDMSG + #ifdef NYOCI_LWIP + #define NYOCI_CAN_SENDMSG 0 + #else + #define NYOCI_CAN_SENDMSG 1 + #endif +#endif + +#if NYOCI_CAN_POLL + #include +#endif #ifndef SOCKADDR_HAS_LENGTH_FIELD #if defined(__KAME__) @@ -72,6 +96,35 @@ #endif +#ifdef NYOCI_LWIP +// lwIP does not have a gai_strerror() function +__unused static const char* +gai_strerror(int err) +{ + static const char* kMessages[] = { + "EAI_NONAME", // 200 + "EAI_SERVICE", // 201 + "EAI_FAIL", // 202 + "EAI_MEMORY", // 203 + "EAI_FAMILY", // 204 + NULL, NULL, NULL, NULL, NULL, + "HOST_NOT_FOUND",// 210 + "NO_DATA", // 211 + "NO_RECOVERY", // 212 + "TRY_AGAIN", // 213 + }; + if (err >= EAI_NONAME && err <= TRY_AGAIN) { + const char *msg = kMessages[err - EAI_NONAME]; + if (msg) + return msg; + } + static char buffer[20]; + sprintf(buffer, "netdb#%d", err); + return buffer; +} +#endif + + static struct addrinfo * get_addresses(const char * address, int sockType, int sockFamily) { @@ -111,7 +164,7 @@ static void fill_multicast_group(multicast_group_s * group, const struct sockadd group->family = addr->sa_family; group->group_size = group->family == AF_INET ? sizeof(struct ip_mreq) : sizeof(struct ipv6_mreq); - + if(group->family == AF_INET){ struct ip_mreq * mreq = &group->group.ip4_group; @@ -121,7 +174,11 @@ static void fill_multicast_group(multicast_group_s * group, const struct sockadd else{ struct ipv6_mreq * mreq = &group->group.ip6_group; +#ifdef NYOCI_LWIP + mreq->ipv6mr_interface = in6addr_any;//TODO: enable specify the interface address; +#else mreq->ipv6mr_interface = interfaceIndex; +#endif mreq->ipv6mr_multiaddr = ((struct sockaddr_in6*)addr)->sin6_addr; } @@ -230,7 +287,7 @@ nyoci_plat_init(nyoci_t self) { #if NYOCI_PLAT_NET_POSIX_FAMILY == AF_INET6 if (self->plat.mcfd_v6 == -1) { self->plat.mcfd_v6 = socket(AF_INET6, SOCK_DGRAM, 0); - check(self->plat.mcfd_v6 >= 0); + check_errno(self->plat.mcfd_v6 >= 0); if (self->plat.mcfd_v6 >= 0 ) { int btrue = 1; @@ -247,7 +304,7 @@ nyoci_plat_init(nyoci_t self) { if (self->plat.mcfd_v4 == -1) { self->plat.mcfd_v4 = socket(AF_INET, SOCK_DGRAM, 0); - check(self->plat.mcfd_v4 >= 0); + check_errno(self->plat.mcfd_v4 >= 0); if (self->plat.mcfd_v4 >= 0) { int btrue = 1; @@ -455,6 +512,7 @@ nyoci_plat_bind_to_port( return nyoci_plat_bind_to_sockaddr(self, type, &saddr); } +#if NYOCI_CAN_POLL int nyoci_plat_update_pollfds( nyoci_t self, @@ -495,6 +553,7 @@ nyoci_plat_update_pollfds( bail: return ret; } +#endif //NYOCI_CAN_POLL nyoci_status_t nyoci_plat_update_fdsets( @@ -579,6 +638,7 @@ sendtofrom( ); check(ret>0); } else { +#if NYOCI_CAN_SENDMSG struct iovec iov = { (void *)data, len }; uint8_t cmbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))]; struct cmsghdr *scmsgp; @@ -617,11 +677,14 @@ sendtofrom( pktinfo->ipi_addr = ((struct sockaddr_in*)saddr_from)->sin_addr; pktinfo->ipi_ifindex = 0; } - + ret = sendmsg(fd, &msg, flags); check(ret > 0); check_string(ret >= 0, strerror(errno)); +#else // !NYOCI_CAN_SENDMSG + abort(); //TODO +#endif // NYOCI_CAN_SENDMSG } return ret; @@ -795,8 +858,10 @@ nyoci_plat_wait( ) { NYOCI_SINGLETON_SELF_HOOK; nyoci_status_t ret = NYOCI_STATUS_OK; - struct pollfd polls[4]; int descriptors_ready; + +#if NYOCI_CAN_POLL + struct pollfd polls[4]; int poll_count; poll_count = nyoci_plat_update_pollfds(self, polls, sizeof(polls)/sizeof(*polls)); @@ -815,6 +880,25 @@ nyoci_plat_wait( descriptors_ready = poll(polls, poll_count, cms); +#else // !NYOCI_CAN_POLL + fd_set reads, writes, errors; + int fdCount = 0; + FD_ZERO(&reads); + FD_ZERO(&writes); + FD_ZERO(&errors); + if (cms <= 0) { + cms = 3600 * MSEC_PER_SEC; + } + ret = nyoci_plat_update_fdsets(self, &reads, &writes, &errors, &fdCount, &cms); + if (ret != NYOCI_STATUS_OK) + goto bail; + struct timeval timeout = {cms / 1000, (cms % 1000) * 1000}; + + DEBUG_PRINTF("Calling select for %dms ...", cms); + descriptors_ready = select(fdCount, &reads, &writes, &errors, &timeout); + DEBUG_PRINTF("...select returned (%d events)", descriptors_ready); +#endif // NYOCI_CAN_POLL + // Ensure that poll did not fail with an error. require_action_string(descriptors_ready != -1, bail, @@ -830,6 +914,121 @@ nyoci_plat_wait( return ret; } +// wraps an IPv4 address in its IPv6 equivalent +static struct sockaddr_in6 +wrapIPv4Address(const struct sockaddr_in *addr4) +{ + struct sockaddr_in6 addr6 = { + .sin6_len = sizeof(struct sockaddr_in6), + .sin6_family = AF_INET6, + .sin6_port = addr4->sin_port + }; + addr6.sin6_addr.s6_addr[10] = addr6.sin6_addr.s6_addr[11] = 0xFF; + memcpy(&addr6.sin6_addr.s6_addr[12], &addr4->sin_addr, 4); + return addr6; +} + +static nyoci_status_t +nyoci_plat_process_fd(nyoci_t self, int fd) +{ + nyoci_status_t ret = 0; + char packet[NYOCI_MAX_PACKET_LENGTH+1]; + nyoci_sockaddr_t remote_saddr = {}; + nyoci_sockaddr_t local_saddr = {}; + ssize_t packet_len = 0; + +#if NYOCI_CAN_POLL + char cmbuf[0x100]; + struct iovec iov = { packet, NYOCI_MAX_PACKET_LENGTH }; + struct msghdr msg = { + .msg_name = &remote_saddr, + .msg_namelen = sizeof(remote_saddr), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmbuf, + .msg_controllen = sizeof(cmbuf), + }; + struct cmsghdr *cmsg; + + packet_len = recvmsg(fd, &msg, 0); + + require_action(packet_len > 0, bail, ret = NYOCI_STATUS_ERRNO); + + packet[packet_len] = 0; + + for ( + cmsg = CMSG_FIRSTHDR(&msg); + cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg) + ) { + if (cmsg->cmsg_level != NYOCI_IPPROTO + || cmsg->cmsg_type != NYOCI_PKTINFO + ) { + continue; + } + + // Preinitialize some of the fields. + local_saddr = remote_saddr; + +#if NYOCI_PLAT_NET_POSIX_FAMILY==AF_INET6 + struct in6_pktinfo *pi = (struct in6_pktinfo *)CMSG_DATA(cmsg); + local_saddr.nyoci_addr = pi->ipi6_addr; + local_saddr.sin6_scope_id = pi->ipi6_ifindex; + +#elif NYOCI_PLAT_NET_POSIX_FAMILY==AF_INET + struct in_pktinfo *pi = (struct in_pktinfo *)CMSG_DATA(cmsg); + local_saddr.nyoci_addr = pi->ipi_addr; +#endif + + local_saddr.nyoci_port = htons(get_port_for_fd(fd)); + + self->plat.pktinfo = *pi; + } + +#else // !NYOCI_CAN_POLL + socklen_t addr_len = sizeof(remote_saddr); + packet_len = recvfrom(fd, packet, NYOCI_MAX_PACKET_LENGTH, 0, + (struct sockaddr*)&remote_saddr, &addr_len); + require_action(packet_len > 0, bail, ret = NYOCI_STATUS_ERRNO); + + packet[packet_len] = 0; + + addr_len = sizeof(local_saddr); + getsockname(fd, (struct sockaddr*)&local_saddr, &addr_len); +#endif // NYOCI_CAN_POLL + +#if NYOCI_PLAT_NET_POSIX_FAMILY == AF_INET6 + if (remote_saddr.sin6_family == AF_INET) { + // If the incoming address is an IPv4 address (which happens on lwIP), convert it to a + // v4-mapped IPv6 address since that's the form we're expecting. + remote_saddr = wrapIPv4Address((struct sockaddr_in*)&remote_saddr); + } +#endif + + nyoci_set_current_instance(self); + nyoci_plat_set_remote_sockaddr(&remote_saddr); + nyoci_plat_set_local_sockaddr(&local_saddr); + + if (self->plat.fd_udp == fd) { + nyoci_plat_set_session_type(NYOCI_SESSION_TYPE_UDP); + + ret = nyoci_inbound_packet_process(self, packet, (coap_size_t)packet_len, 0); + require_noerr(ret, bail); + +#if NYOCI_DTLS + } else if (self->plat.fd_dtls == fd) { + nyoci_plat_set_session_type(NYOCI_SESSION_TYPE_DTLS); + nyoci_plat_tls_inbound_packet_process( + self, + packet, + (coap_size_t)packet_len + ); +#endif + } +bail: + return ret; +} + nyoci_status_t nyoci_plat_process( nyoci_t self @@ -837,6 +1036,7 @@ nyoci_plat_process( NYOCI_SINGLETON_SELF_HOOK; nyoci_status_t ret = 0; +#if NYOCI_CAN_POLL int tmp; struct pollfd polls[4]; int poll_count; @@ -861,83 +1061,43 @@ nyoci_plat_process( if(tmp > 0) { for (tmp = 0; tmp < poll_count; tmp++) { - if (!polls[tmp].revents) { - continue; - } else { - char packet[NYOCI_MAX_PACKET_LENGTH+1]; - nyoci_sockaddr_t remote_saddr = {}; - nyoci_sockaddr_t local_saddr = {}; - ssize_t packet_len = 0; - char cmbuf[0x100]; - struct iovec iov = { packet, NYOCI_MAX_PACKET_LENGTH }; - struct msghdr msg = { - .msg_name = &remote_saddr, - .msg_namelen = sizeof(remote_saddr), - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = cmbuf, - .msg_controllen = sizeof(cmbuf), - }; - struct cmsghdr *cmsg; - - packet_len = recvmsg(polls[tmp].fd, &msg, 0); - - require_action(packet_len > 0, bail, ret = NYOCI_STATUS_ERRNO); - - packet[packet_len] = 0; - - for ( - cmsg = CMSG_FIRSTHDR(&msg); - cmsg != NULL; - cmsg = CMSG_NXTHDR(&msg, cmsg) - ) { - if (cmsg->cmsg_level != NYOCI_IPPROTO - || cmsg->cmsg_type != NYOCI_PKTINFO - ) { - continue; - } - - // Preinitialize some of the fields. - local_saddr = remote_saddr; - -#if NYOCI_PLAT_NET_POSIX_FAMILY==AF_INET6 - struct in6_pktinfo *pi = (struct in6_pktinfo *)CMSG_DATA(cmsg); - local_saddr.nyoci_addr = pi->ipi6_addr; - local_saddr.sin6_scope_id = pi->ipi6_ifindex; - -#elif NYOCI_PLAT_NET_POSIX_FAMILY==AF_INET - struct in_pktinfo *pi = (struct in_pktinfo *)CMSG_DATA(cmsg); - local_saddr.nyoci_addr = pi->ipi_addr; -#endif - - local_saddr.nyoci_port = htons(get_port_for_fd(polls[tmp].fd)); - - self->plat.pktinfo = *pi; - } - - nyoci_set_current_instance(self); - nyoci_plat_set_remote_sockaddr(&remote_saddr); - nyoci_plat_set_local_sockaddr(&local_saddr); - - if (self->plat.fd_udp == polls[tmp].fd) { - nyoci_plat_set_session_type(NYOCI_SESSION_TYPE_UDP); + if (polls[tmp].revents) { + ret = nyoci_plat_process_fd(self, polls[tmp].fd); + if (ret != NYOCI_STATUS_OK) + goto bail; + } + } + } - ret = nyoci_inbound_packet_process(self, packet, (coap_size_t)packet_len, 0); - require_noerr(ret, bail); +#else // !NYOCI_CAN_POLL + fd_set reads, writes, errors; + int fdCount = 0; + FD_ZERO(&reads); + FD_ZERO(&writes); + FD_ZERO(&errors); + ret = nyoci_plat_update_fdsets(self, &reads, &writes, &errors, &fdCount, NULL); + if (ret != NYOCI_STATUS_OK) + goto bail; -#if NYOCI_DTLS - } else if (self->plat.fd_dtls == polls[tmp].fd) { - nyoci_plat_set_session_type(NYOCI_SESSION_TYPE_DTLS); - nyoci_plat_tls_inbound_packet_process( - self, - packet, - (coap_size_t)packet_len - ); -#endif - } + struct timeval zero_timeout = {0, 0}; + int descriptors_ready = select(fdCount, &reads, &writes, &errors, &zero_timeout); + require_action_string( + descriptors_ready >= 0, + bail, + ret = NYOCI_STATUS_ERRNO, + strerror(errno) + ); + + if (descriptors_ready > 0) { + for (int fd = 0; fd < fdCount; ++fd) { + if (FD_ISSET(fd, &reads)) { + ret = nyoci_plat_process_fd(self, fd); + if (ret != NYOCI_STATUS_OK) + goto bail; } } } +#endif // NYOCI_CAN_POLL nyoci_handle_timers(self); diff --git a/src/plat-net/posix/nyoci-plat-net.h b/src/plat-net/posix/nyoci-plat-net.h index 7374b81..d48c9c0 100644 --- a/src/plat-net/posix/nyoci-plat-net.h +++ b/src/plat-net/posix/nyoci-plat-net.h @@ -40,7 +40,12 @@ #include #include #include + +#ifdef ESP_PLATFORM +#include +#else #include +#endif #if NYOCI_SINGLETON #define nyoci_plat_update_fdsets(self,...) nyoci_plat_update_fdsets(__VA_ARGS__)