1c87c5fbaSopenharmony_ci/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2c87c5fbaSopenharmony_ci 3c87c5fbaSopenharmony_ci/* oscore-interop-server 4c87c5fbaSopenharmony_ci * 5c87c5fbaSopenharmony_ci * A server for use in the RFC 8613 OSCORE interop testing. 6c87c5fbaSopenharmony_ci * https://core-wg.github.io/oscore/test-spec5.html 7c87c5fbaSopenharmony_ci * 8c87c5fbaSopenharmony_ci * Copyright (C) 2022-2023 Olaf Bergmann <bergmann@tzi.org> and others 9c87c5fbaSopenharmony_ci * 10c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 11c87c5fbaSopenharmony_ci * 12c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see README for terms 13c87c5fbaSopenharmony_ci * of use. 14c87c5fbaSopenharmony_ci */ 15c87c5fbaSopenharmony_ci 16c87c5fbaSopenharmony_ci#include <string.h> 17c87c5fbaSopenharmony_ci#include <stdlib.h> 18c87c5fbaSopenharmony_ci#include <stdio.h> 19c87c5fbaSopenharmony_ci#include <ctype.h> 20c87c5fbaSopenharmony_ci#include <inttypes.h> 21c87c5fbaSopenharmony_ci#include <sys/types.h> 22c87c5fbaSopenharmony_ci#include <sys/stat.h> 23c87c5fbaSopenharmony_ci#include <errno.h> 24c87c5fbaSopenharmony_ci#include <signal.h> 25c87c5fbaSopenharmony_ci#ifdef _WIN32 26c87c5fbaSopenharmony_ci#define strcasecmp _stricmp 27c87c5fbaSopenharmony_ci#define strncasecmp _strnicmp 28c87c5fbaSopenharmony_ci#include "getopt.c" 29c87c5fbaSopenharmony_ci#if !defined(S_ISDIR) 30c87c5fbaSopenharmony_ci#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) 31c87c5fbaSopenharmony_ci#endif 32c87c5fbaSopenharmony_ci#ifndef R_OK 33c87c5fbaSopenharmony_ci#define R_OK 4 34c87c5fbaSopenharmony_ci#endif 35c87c5fbaSopenharmony_cistatic char * 36c87c5fbaSopenharmony_cistrndup(const char *s1, size_t n) { 37c87c5fbaSopenharmony_ci char *copy = (char *)malloc(n + 1); 38c87c5fbaSopenharmony_ci if (copy) { 39c87c5fbaSopenharmony_ci memcpy(copy, s1, n); 40c87c5fbaSopenharmony_ci copy[n] = 0; 41c87c5fbaSopenharmony_ci } 42c87c5fbaSopenharmony_ci return copy; 43c87c5fbaSopenharmony_ci} 44c87c5fbaSopenharmony_ci#include <io.h> 45c87c5fbaSopenharmony_ci#define access _access 46c87c5fbaSopenharmony_ci#define fileno _fileno 47c87c5fbaSopenharmony_ci#else 48c87c5fbaSopenharmony_ci#include <unistd.h> 49c87c5fbaSopenharmony_ci#include <sys/select.h> 50c87c5fbaSopenharmony_ci#include <sys/socket.h> 51c87c5fbaSopenharmony_ci#include <netinet/in.h> 52c87c5fbaSopenharmony_ci#include <arpa/inet.h> 53c87c5fbaSopenharmony_ci#include <netdb.h> 54c87c5fbaSopenharmony_ci#include <dirent.h> 55c87c5fbaSopenharmony_ci#endif 56c87c5fbaSopenharmony_ci 57c87c5fbaSopenharmony_ci#include <coap3/coap.h> 58c87c5fbaSopenharmony_ci 59c87c5fbaSopenharmony_ci#ifndef min 60c87c5fbaSopenharmony_ci#define min(a,b) ((a) < (b) ? (a) : (b)) 61c87c5fbaSopenharmony_ci#endif 62c87c5fbaSopenharmony_ci 63c87c5fbaSopenharmony_cistatic coap_oscore_conf_t *oscore_conf; 64c87c5fbaSopenharmony_cistatic int doing_oscore = 0; 65c87c5fbaSopenharmony_ci 66c87c5fbaSopenharmony_ci/* set to 1 to request clean server shutdown */ 67c87c5fbaSopenharmony_cistatic int quit = 0; 68c87c5fbaSopenharmony_ci 69c87c5fbaSopenharmony_cistatic coap_resource_t *r_observe_1; 70c87c5fbaSopenharmony_cistatic coap_resource_t *r_observe_2; 71c87c5fbaSopenharmony_ci 72c87c5fbaSopenharmony_cistatic int resource_flags = COAP_RESOURCE_FLAGS_NOTIFY_CON; 73c87c5fbaSopenharmony_ci 74c87c5fbaSopenharmony_cistatic uint32_t block_mode = COAP_BLOCK_USE_LIBCOAP; 75c87c5fbaSopenharmony_cistatic uint32_t csm_max_message_size = 0; 76c87c5fbaSopenharmony_ci 77c87c5fbaSopenharmony_ci/* SIGINT handler: set quit to 1 for graceful termination */ 78c87c5fbaSopenharmony_cistatic void 79c87c5fbaSopenharmony_cihandle_sigint(int signum COAP_UNUSED) { 80c87c5fbaSopenharmony_ci quit = 1; 81c87c5fbaSopenharmony_ci} 82c87c5fbaSopenharmony_ci 83c87c5fbaSopenharmony_ci#define INDEX "This is a OSCORE test server made with libcoap " \ 84c87c5fbaSopenharmony_ci "(see https://libcoap.net)\n" \ 85c87c5fbaSopenharmony_ci "Copyright (C) 2023 Olaf Bergmann <bergmann@tzi.org> " \ 86c87c5fbaSopenharmony_ci "and others\n\n" 87c87c5fbaSopenharmony_ci 88c87c5fbaSopenharmony_cistatic void 89c87c5fbaSopenharmony_cihnd_get_index(coap_resource_t *resource, 90c87c5fbaSopenharmony_ci coap_session_t *session, 91c87c5fbaSopenharmony_ci const coap_pdu_t *request, 92c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 93c87c5fbaSopenharmony_ci coap_pdu_t *response) { 94c87c5fbaSopenharmony_ci 95c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 96c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 97c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 98c87c5fbaSopenharmony_ci 0x2ffff, 0, strlen(INDEX), 99c87c5fbaSopenharmony_ci (const uint8_t *)INDEX, NULL, NULL); 100c87c5fbaSopenharmony_ci} 101c87c5fbaSopenharmony_ci 102c87c5fbaSopenharmony_ci#define HELLO_WORLD "Hello World!" 103c87c5fbaSopenharmony_ci 104c87c5fbaSopenharmony_cistatic void 105c87c5fbaSopenharmony_cihnd_get_hello_coap(coap_resource_t *resource, 106c87c5fbaSopenharmony_ci coap_session_t *session, 107c87c5fbaSopenharmony_ci const coap_pdu_t *request, 108c87c5fbaSopenharmony_ci const coap_string_t *query, 109c87c5fbaSopenharmony_ci coap_pdu_t *response) { 110c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 111c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 112c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 113c87c5fbaSopenharmony_ci -1, 0, strlen(HELLO_WORLD), 114c87c5fbaSopenharmony_ci (const uint8_t *)HELLO_WORLD, NULL, NULL); 115c87c5fbaSopenharmony_ci} 116c87c5fbaSopenharmony_ci 117c87c5fbaSopenharmony_cistatic void 118c87c5fbaSopenharmony_cihnd_get_hello_1(coap_resource_t *resource, 119c87c5fbaSopenharmony_ci coap_session_t *session, 120c87c5fbaSopenharmony_ci const coap_pdu_t *request, 121c87c5fbaSopenharmony_ci const coap_string_t *query, 122c87c5fbaSopenharmony_ci coap_pdu_t *response) { 123c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 124c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 125c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 126c87c5fbaSopenharmony_ci -1, 0, strlen(HELLO_WORLD), 127c87c5fbaSopenharmony_ci (const uint8_t *)HELLO_WORLD, NULL, NULL); 128c87c5fbaSopenharmony_ci} 129c87c5fbaSopenharmony_ci 130c87c5fbaSopenharmony_cistatic void 131c87c5fbaSopenharmony_cihnd_get_hello_2(coap_resource_t *resource, 132c87c5fbaSopenharmony_ci coap_session_t *session, 133c87c5fbaSopenharmony_ci const coap_pdu_t *request, 134c87c5fbaSopenharmony_ci const coap_string_t *query, 135c87c5fbaSopenharmony_ci coap_pdu_t *response) { 136c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 137c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 138c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 139c87c5fbaSopenharmony_ci -1, 0x2b, strlen(HELLO_WORLD), 140c87c5fbaSopenharmony_ci (const uint8_t *)HELLO_WORLD, NULL, NULL); 141c87c5fbaSopenharmony_ci} 142c87c5fbaSopenharmony_ci 143c87c5fbaSopenharmony_cistatic void 144c87c5fbaSopenharmony_cihnd_get_hello_3(coap_resource_t *resource, 145c87c5fbaSopenharmony_ci coap_session_t *session, 146c87c5fbaSopenharmony_ci const coap_pdu_t *request, 147c87c5fbaSopenharmony_ci const coap_string_t *query, 148c87c5fbaSopenharmony_ci coap_pdu_t *response) { 149c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 150c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 151c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 152c87c5fbaSopenharmony_ci 5, 0, strlen(HELLO_WORLD), 153c87c5fbaSopenharmony_ci (const uint8_t *)HELLO_WORLD, NULL, NULL); 154c87c5fbaSopenharmony_ci} 155c87c5fbaSopenharmony_ci 156c87c5fbaSopenharmony_cistatic void 157c87c5fbaSopenharmony_cihnd_post_hello_6(coap_resource_t *resource, 158c87c5fbaSopenharmony_ci coap_session_t *session, 159c87c5fbaSopenharmony_ci const coap_pdu_t *request, 160c87c5fbaSopenharmony_ci const coap_string_t *query, 161c87c5fbaSopenharmony_ci coap_pdu_t *response) { 162c87c5fbaSopenharmony_ci size_t size; 163c87c5fbaSopenharmony_ci const uint8_t *data; 164c87c5fbaSopenharmony_ci 165c87c5fbaSopenharmony_ci (void)coap_get_data(request, &size, &data); 166c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); 167c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 168c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 169c87c5fbaSopenharmony_ci -1, 0, size, 170c87c5fbaSopenharmony_ci data, NULL, NULL); 171c87c5fbaSopenharmony_ci} 172c87c5fbaSopenharmony_ci 173c87c5fbaSopenharmony_cistatic void 174c87c5fbaSopenharmony_cihnd_put_hello_7(coap_resource_t *resource, 175c87c5fbaSopenharmony_ci coap_session_t *session, 176c87c5fbaSopenharmony_ci const coap_pdu_t *request, 177c87c5fbaSopenharmony_ci const coap_string_t *query, 178c87c5fbaSopenharmony_ci coap_pdu_t *response) { 179c87c5fbaSopenharmony_ci size_t size; 180c87c5fbaSopenharmony_ci const uint8_t *data; 181c87c5fbaSopenharmony_ci coap_opt_iterator_t opt_iter; 182c87c5fbaSopenharmony_ci coap_opt_t *option; 183c87c5fbaSopenharmony_ci uint64_t etag; 184c87c5fbaSopenharmony_ci 185c87c5fbaSopenharmony_ci 186c87c5fbaSopenharmony_ci if ((option = coap_check_option(request, COAP_OPTION_IF_MATCH, 187c87c5fbaSopenharmony_ci &opt_iter)) != NULL) { 188c87c5fbaSopenharmony_ci etag = coap_decode_var_bytes8(coap_opt_value(option), 189c87c5fbaSopenharmony_ci coap_opt_length(option)); 190c87c5fbaSopenharmony_ci if (etag != 0x7b) { 191c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_PRECONDITION_FAILED); 192c87c5fbaSopenharmony_ci return; 193c87c5fbaSopenharmony_ci } 194c87c5fbaSopenharmony_ci } 195c87c5fbaSopenharmony_ci 196c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CHANGED); 197c87c5fbaSopenharmony_ci (void)coap_get_data(request, &size, &data); 198c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 199c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 200c87c5fbaSopenharmony_ci -1, 0x7b, size, 201c87c5fbaSopenharmony_ci data, NULL, NULL); 202c87c5fbaSopenharmony_ci} 203c87c5fbaSopenharmony_ci 204c87c5fbaSopenharmony_cistatic void 205c87c5fbaSopenharmony_cihnd_get_observe1(coap_resource_t *resource, 206c87c5fbaSopenharmony_ci coap_session_t *session, 207c87c5fbaSopenharmony_ci const coap_pdu_t *request, 208c87c5fbaSopenharmony_ci const coap_string_t *query, 209c87c5fbaSopenharmony_ci coap_pdu_t *response) { 210c87c5fbaSopenharmony_ci static int count = 0; 211c87c5fbaSopenharmony_ci 212c87c5fbaSopenharmony_ci count++; 213c87c5fbaSopenharmony_ci switch (count) { 214c87c5fbaSopenharmony_ci case 1: 215c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 216c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 217c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 218c87c5fbaSopenharmony_ci 1, 0, strlen("one"), 219c87c5fbaSopenharmony_ci (const uint8_t *)"one", NULL, NULL); 220c87c5fbaSopenharmony_ci break; 221c87c5fbaSopenharmony_ci case 2: 222c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 223c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 224c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 225c87c5fbaSopenharmony_ci 1, 0, strlen("two"), 226c87c5fbaSopenharmony_ci (const uint8_t *)"two", NULL, NULL); 227c87c5fbaSopenharmony_ci break; 228c87c5fbaSopenharmony_ci default: 229c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_INTERNAL_ERROR); 230c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 231c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 232c87c5fbaSopenharmony_ci -1, 0, strlen("Terminate Observe"), 233c87c5fbaSopenharmony_ci (const uint8_t *)"Terminate Observe", 234c87c5fbaSopenharmony_ci NULL, NULL); 235c87c5fbaSopenharmony_ci r_observe_1 = NULL; 236c87c5fbaSopenharmony_ci } 237c87c5fbaSopenharmony_ci} 238c87c5fbaSopenharmony_ci 239c87c5fbaSopenharmony_cistatic void 240c87c5fbaSopenharmony_cihnd_get_observe2(coap_resource_t *resource, 241c87c5fbaSopenharmony_ci coap_session_t *session, 242c87c5fbaSopenharmony_ci const coap_pdu_t *request, 243c87c5fbaSopenharmony_ci const coap_string_t *query, 244c87c5fbaSopenharmony_ci coap_pdu_t *response) { 245c87c5fbaSopenharmony_ci static int count = 0; 246c87c5fbaSopenharmony_ci 247c87c5fbaSopenharmony_ci count++; 248c87c5fbaSopenharmony_ci switch (count) { 249c87c5fbaSopenharmony_ci case 1: 250c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 251c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 252c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 253c87c5fbaSopenharmony_ci 1, 0, strlen("one"), 254c87c5fbaSopenharmony_ci (const uint8_t *)"one", NULL, NULL); 255c87c5fbaSopenharmony_ci break; 256c87c5fbaSopenharmony_ci case 2: 257c87c5fbaSopenharmony_ci default: 258c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT); 259c87c5fbaSopenharmony_ci coap_add_data_large_response(resource, session, request, response, 260c87c5fbaSopenharmony_ci query, COAP_MEDIATYPE_TEXT_PLAIN, 261c87c5fbaSopenharmony_ci 1, 0, strlen("two"), 262c87c5fbaSopenharmony_ci (const uint8_t *)"two", NULL, NULL); 263c87c5fbaSopenharmony_ci r_observe_2 = NULL; 264c87c5fbaSopenharmony_ci break; 265c87c5fbaSopenharmony_ci } 266c87c5fbaSopenharmony_ci} 267c87c5fbaSopenharmony_ci 268c87c5fbaSopenharmony_cistatic void 269c87c5fbaSopenharmony_cihnd_del_test(coap_resource_t *resource COAP_UNUSED, 270c87c5fbaSopenharmony_ci coap_session_t *session COAP_UNUSED, 271c87c5fbaSopenharmony_ci const coap_pdu_t *request COAP_UNUSED, 272c87c5fbaSopenharmony_ci const coap_string_t *query COAP_UNUSED, 273c87c5fbaSopenharmony_ci coap_pdu_t *response) { 274c87c5fbaSopenharmony_ci coap_pdu_set_code(response, COAP_RESPONSE_CODE_DELETED); 275c87c5fbaSopenharmony_ci} 276c87c5fbaSopenharmony_ci 277c87c5fbaSopenharmony_cistatic void 278c87c5fbaSopenharmony_ciinit_resources(coap_context_t *ctx) { 279c87c5fbaSopenharmony_ci coap_resource_t *r; 280c87c5fbaSopenharmony_ci 281c87c5fbaSopenharmony_ci r = coap_resource_init(NULL, COAP_RESOURCE_FLAGS_HAS_MCAST_SUPPORT); 282c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_index); 283c87c5fbaSopenharmony_ci 284c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("ct"), coap_make_str_const("0"), 0); 285c87c5fbaSopenharmony_ci coap_add_attr(r, coap_make_str_const("title"), 286c87c5fbaSopenharmony_ci coap_make_str_const("\"General Info\""), 0); 287c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 288c87c5fbaSopenharmony_ci 289c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/hello/coap"), 290c87c5fbaSopenharmony_ci resource_flags); 291c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_hello_coap); 292c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 293c87c5fbaSopenharmony_ci 294c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/hello/1"), 295c87c5fbaSopenharmony_ci resource_flags | COAP_RESOURCE_FLAGS_OSCORE_ONLY); 296c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_hello_1); 297c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 298c87c5fbaSopenharmony_ci 299c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/hello/2"), 300c87c5fbaSopenharmony_ci resource_flags | COAP_RESOURCE_FLAGS_OSCORE_ONLY); 301c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_hello_2); 302c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 303c87c5fbaSopenharmony_ci 304c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/hello/3"), 305c87c5fbaSopenharmony_ci resource_flags | COAP_RESOURCE_FLAGS_OSCORE_ONLY); 306c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_hello_3); 307c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 308c87c5fbaSopenharmony_ci 309c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/hello/6"), 310c87c5fbaSopenharmony_ci resource_flags | COAP_RESOURCE_FLAGS_OSCORE_ONLY); 311c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_POST, hnd_post_hello_6); 312c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 313c87c5fbaSopenharmony_ci 314c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/hello/7"), 315c87c5fbaSopenharmony_ci resource_flags | COAP_RESOURCE_FLAGS_OSCORE_ONLY); 316c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_PUT, hnd_put_hello_7); 317c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 318c87c5fbaSopenharmony_ci 319c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/observe1"), 320c87c5fbaSopenharmony_ci resource_flags | COAP_RESOURCE_FLAGS_OSCORE_ONLY); 321c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_observe1); 322c87c5fbaSopenharmony_ci coap_resource_set_get_observable(r, 1); 323c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 324c87c5fbaSopenharmony_ci r_observe_1 = r; 325c87c5fbaSopenharmony_ci 326c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/observe2"), 327c87c5fbaSopenharmony_ci resource_flags | COAP_RESOURCE_FLAGS_OSCORE_ONLY); 328c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_GET, hnd_get_observe2); 329c87c5fbaSopenharmony_ci coap_resource_set_get_observable(r, 1); 330c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 331c87c5fbaSopenharmony_ci r_observe_2 = r; 332c87c5fbaSopenharmony_ci 333c87c5fbaSopenharmony_ci r = coap_resource_init(coap_make_str_const("oscore/test"), 334c87c5fbaSopenharmony_ci resource_flags | COAP_RESOURCE_FLAGS_OSCORE_ONLY); 335c87c5fbaSopenharmony_ci coap_register_request_handler(r, COAP_REQUEST_DELETE, hnd_del_test); 336c87c5fbaSopenharmony_ci coap_add_resource(ctx, r); 337c87c5fbaSopenharmony_ci} 338c87c5fbaSopenharmony_ci 339c87c5fbaSopenharmony_cistatic uint8_t * 340c87c5fbaSopenharmony_ciread_file_mem(const char *file, size_t *length) { 341c87c5fbaSopenharmony_ci FILE *f; 342c87c5fbaSopenharmony_ci uint8_t *buf; 343c87c5fbaSopenharmony_ci struct stat statbuf; 344c87c5fbaSopenharmony_ci 345c87c5fbaSopenharmony_ci *length = 0; 346c87c5fbaSopenharmony_ci if (!file || !(f = fopen(file, "r"))) 347c87c5fbaSopenharmony_ci return NULL; 348c87c5fbaSopenharmony_ci 349c87c5fbaSopenharmony_ci if (fstat(fileno(f), &statbuf) == -1) { 350c87c5fbaSopenharmony_ci fclose(f); 351c87c5fbaSopenharmony_ci return NULL; 352c87c5fbaSopenharmony_ci } 353c87c5fbaSopenharmony_ci 354c87c5fbaSopenharmony_ci buf = coap_malloc(statbuf.st_size+1); 355c87c5fbaSopenharmony_ci if (!buf) { 356c87c5fbaSopenharmony_ci fclose(f); 357c87c5fbaSopenharmony_ci return NULL; 358c87c5fbaSopenharmony_ci } 359c87c5fbaSopenharmony_ci 360c87c5fbaSopenharmony_ci if (fread(buf, 1, statbuf.st_size, f) != (size_t)statbuf.st_size) { 361c87c5fbaSopenharmony_ci fclose(f); 362c87c5fbaSopenharmony_ci coap_free(buf); 363c87c5fbaSopenharmony_ci return NULL; 364c87c5fbaSopenharmony_ci } 365c87c5fbaSopenharmony_ci buf[statbuf.st_size] = '\000'; 366c87c5fbaSopenharmony_ci *length = (size_t)(statbuf.st_size + 1); 367c87c5fbaSopenharmony_ci fclose(f); 368c87c5fbaSopenharmony_ci return buf; 369c87c5fbaSopenharmony_ci} 370c87c5fbaSopenharmony_ci 371c87c5fbaSopenharmony_cistatic void 372c87c5fbaSopenharmony_ciusage(const char *program, const char *version) { 373c87c5fbaSopenharmony_ci const char *p; 374c87c5fbaSopenharmony_ci char buffer[120]; 375c87c5fbaSopenharmony_ci const char *lib_build = coap_package_build(); 376c87c5fbaSopenharmony_ci 377c87c5fbaSopenharmony_ci p = strrchr(program, '/'); 378c87c5fbaSopenharmony_ci if (p) 379c87c5fbaSopenharmony_ci program = ++p; 380c87c5fbaSopenharmony_ci 381c87c5fbaSopenharmony_ci fprintf(stderr, "%s v%s -- OSCORE interop implementation\n" 382c87c5fbaSopenharmony_ci "(c) 2023 Olaf Bergmann <bergmann@tzi.org> and others\n\n" 383c87c5fbaSopenharmony_ci "Build: %s\n" 384c87c5fbaSopenharmony_ci "%s\n" 385c87c5fbaSopenharmony_ci , program, version, lib_build, 386c87c5fbaSopenharmony_ci coap_string_tls_version(buffer, sizeof(buffer))); 387c87c5fbaSopenharmony_ci fprintf(stderr, "%s\n", coap_string_tls_support(buffer, sizeof(buffer))); 388c87c5fbaSopenharmony_ci fprintf(stderr, "\n" 389c87c5fbaSopenharmony_ci "Usage: %s [-d max] [-g group] [-l loss] [-p port] [-r] [-v num]\n" 390c87c5fbaSopenharmony_ci "\t\t[-A address] [-E oscore_conf_file[,seq_file]] [-G group_if]\n" 391c87c5fbaSopenharmony_ci "\t\t[-L value] [-N] [-P scheme://address[:port],[name1[,name2..]]]\n" 392c87c5fbaSopenharmony_ci "\t\t[-X size]\n" 393c87c5fbaSopenharmony_ci "General Options\n" 394c87c5fbaSopenharmony_ci "\t-d max \t\tAllow dynamic creation of up to a total of max\n" 395c87c5fbaSopenharmony_ci "\t \t\tresources. If max is reached, a 4.06 code is returned\n" 396c87c5fbaSopenharmony_ci "\t \t\tuntil one of the dynamic resources has been deleted\n" 397c87c5fbaSopenharmony_ci "\t-g group\tJoin the given multicast group\n" 398c87c5fbaSopenharmony_ci "\t \t\tNote: DTLS over multicast is not currently supported\n" 399c87c5fbaSopenharmony_ci "\t-l list\t\tFail to send some datagrams specified by a comma\n" 400c87c5fbaSopenharmony_ci "\t \t\tseparated list of numbers or number ranges\n" 401c87c5fbaSopenharmony_ci "\t \t\t(for debugging only)\n" 402c87c5fbaSopenharmony_ci "\t-l loss%%\tRandomly fail to send datagrams with the specified\n" 403c87c5fbaSopenharmony_ci "\t \t\tprobability - 100%% all datagrams, 0%% no datagrams\n" 404c87c5fbaSopenharmony_ci "\t \t\t(for debugging only)\n" 405c87c5fbaSopenharmony_ci "\t-p port\t\tListen on specified port for UDP and TCP. If (D)TLS is\n" 406c87c5fbaSopenharmony_ci "\t \t\tenabled, then the coap-server will also listen on\n" 407c87c5fbaSopenharmony_ci "\t \t\t 'port'+1 for DTLS and TLS. The default port is 5683\n" 408c87c5fbaSopenharmony_ci "\t-r \t\tEnable multicast per resource support. If enabled,\n" 409c87c5fbaSopenharmony_ci "\t \t\tonly '/', '/async' and '/.well-known/core' are enabled\n" 410c87c5fbaSopenharmony_ci "\t \t\tfor multicast requests support, otherwise all\n" 411c87c5fbaSopenharmony_ci "\t \t\tresources are enabled\n" 412c87c5fbaSopenharmony_ci "\t-v num \t\tVerbosity level (default 3, maximum is 9). Above 7,\n" 413c87c5fbaSopenharmony_ci "\t \t\tthere is increased verbosity in GnuTLS and OpenSSL\n" 414c87c5fbaSopenharmony_ci "\t \t\tlogging\n" 415c87c5fbaSopenharmony_ci "\t-A address\tInterface address to bind to\n" 416c87c5fbaSopenharmony_ci "\t-E oscore_conf_file[,seq_file]\n" 417c87c5fbaSopenharmony_ci "\t \t\toscore_conf_file contains OSCORE configuration. See\n" 418c87c5fbaSopenharmony_ci "\t \t\tcoap-oscore-conf(5) for definitions.\n" 419c87c5fbaSopenharmony_ci "\t \t\tOptional seq_file is used to save the current transmit\n" 420c87c5fbaSopenharmony_ci "\t \t\tsequence number, so on restart sequence numbers continue\n" 421c87c5fbaSopenharmony_ci "\t-G group_if\tUse this interface for listening for the multicast\n" 422c87c5fbaSopenharmony_ci "\t \t\tgroup. This can be different from the implied interface\n" 423c87c5fbaSopenharmony_ci "\t \t\tif the -A option is used\n" 424c87c5fbaSopenharmony_ci "\t-L value\tSum of one or more COAP_BLOCK_* flag valuess for block\n" 425c87c5fbaSopenharmony_ci "\t \t\thandling methods. Default is 1 (COAP_BLOCK_USE_LIBCOAP)\n" 426c87c5fbaSopenharmony_ci "\t \t\t(Sum of one or more of 1,2 and 4)\n" 427c87c5fbaSopenharmony_ci "\t-N \t\tMake \"observe\" responses NON-confirmable. Even if set\n" 428c87c5fbaSopenharmony_ci "\t \t\tevery fifth response will still be sent as a confirmable\n" 429c87c5fbaSopenharmony_ci "\t \t\tresponse (RFC 7641 requirement)\n" 430c87c5fbaSopenharmony_ci , program); 431c87c5fbaSopenharmony_ci} 432c87c5fbaSopenharmony_ci 433c87c5fbaSopenharmony_cistatic coap_context_t * 434c87c5fbaSopenharmony_ciget_context(const char *node, const char *port) { 435c87c5fbaSopenharmony_ci coap_context_t *ctx = NULL; 436c87c5fbaSopenharmony_ci int s; 437c87c5fbaSopenharmony_ci struct addrinfo hints; 438c87c5fbaSopenharmony_ci struct addrinfo *result, *rp; 439c87c5fbaSopenharmony_ci 440c87c5fbaSopenharmony_ci ctx = coap_new_context(NULL); 441c87c5fbaSopenharmony_ci if (!ctx) { 442c87c5fbaSopenharmony_ci return NULL; 443c87c5fbaSopenharmony_ci } 444c87c5fbaSopenharmony_ci 445c87c5fbaSopenharmony_ci memset(&hints, 0, sizeof(struct addrinfo)); 446c87c5fbaSopenharmony_ci hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 447c87c5fbaSopenharmony_ci hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */ 448c87c5fbaSopenharmony_ci hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 449c87c5fbaSopenharmony_ci 450c87c5fbaSopenharmony_ci s = getaddrinfo(node, port, &hints, &result); 451c87c5fbaSopenharmony_ci if (s != 0) { 452c87c5fbaSopenharmony_ci fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); 453c87c5fbaSopenharmony_ci coap_free_context(ctx); 454c87c5fbaSopenharmony_ci return NULL; 455c87c5fbaSopenharmony_ci } 456c87c5fbaSopenharmony_ci 457c87c5fbaSopenharmony_ci /* iterate through results until success */ 458c87c5fbaSopenharmony_ci for (rp = result; rp != NULL; rp = rp->ai_next) { 459c87c5fbaSopenharmony_ci coap_address_t addr; 460c87c5fbaSopenharmony_ci coap_endpoint_t *ep_udp = NULL; 461c87c5fbaSopenharmony_ci 462c87c5fbaSopenharmony_ci if (rp->ai_addrlen <= (socklen_t)sizeof(addr.addr)) { 463c87c5fbaSopenharmony_ci coap_address_init(&addr); 464c87c5fbaSopenharmony_ci addr.size = (socklen_t)rp->ai_addrlen; 465c87c5fbaSopenharmony_ci memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen); 466c87c5fbaSopenharmony_ci 467c87c5fbaSopenharmony_ci ep_udp = coap_new_endpoint(ctx, &addr, COAP_PROTO_UDP); 468c87c5fbaSopenharmony_ci if (!ep_udp) { 469c87c5fbaSopenharmony_ci coap_log_crit("cannot create UDP endpoint\n"); 470c87c5fbaSopenharmony_ci continue; 471c87c5fbaSopenharmony_ci } 472c87c5fbaSopenharmony_ci if (coap_tcp_is_supported()) { 473c87c5fbaSopenharmony_ci coap_endpoint_t *ep_tcp; 474c87c5fbaSopenharmony_ci ep_tcp = coap_new_endpoint(ctx, &addr, COAP_PROTO_TCP); 475c87c5fbaSopenharmony_ci if (!ep_tcp) { 476c87c5fbaSopenharmony_ci coap_log_crit("cannot create TCP endpoint\n"); 477c87c5fbaSopenharmony_ci } 478c87c5fbaSopenharmony_ci } 479c87c5fbaSopenharmony_ci if (ep_udp) 480c87c5fbaSopenharmony_ci goto finish; 481c87c5fbaSopenharmony_ci } 482c87c5fbaSopenharmony_ci } 483c87c5fbaSopenharmony_ci 484c87c5fbaSopenharmony_ci fprintf(stderr, "no context available for interface '%s'\n", node); 485c87c5fbaSopenharmony_ci coap_free_context(ctx); 486c87c5fbaSopenharmony_ci ctx = NULL; 487c87c5fbaSopenharmony_ci 488c87c5fbaSopenharmony_cifinish: 489c87c5fbaSopenharmony_ci freeaddrinfo(result); 490c87c5fbaSopenharmony_ci return ctx; 491c87c5fbaSopenharmony_ci} 492c87c5fbaSopenharmony_ci 493c87c5fbaSopenharmony_cistatic FILE *oscore_seq_num_fp = NULL; 494c87c5fbaSopenharmony_cistatic const char *oscore_conf_file = NULL; 495c87c5fbaSopenharmony_cistatic const char *oscore_seq_save_file = NULL; 496c87c5fbaSopenharmony_ci 497c87c5fbaSopenharmony_cistatic int 498c87c5fbaSopenharmony_cioscore_save_seq_num(uint64_t sender_seq_num, void *param COAP_UNUSED) { 499c87c5fbaSopenharmony_ci if (oscore_seq_num_fp) { 500c87c5fbaSopenharmony_ci rewind(oscore_seq_num_fp); 501c87c5fbaSopenharmony_ci fprintf(oscore_seq_num_fp, "%" PRIu64 "\n", sender_seq_num); 502c87c5fbaSopenharmony_ci fflush(oscore_seq_num_fp); 503c87c5fbaSopenharmony_ci } 504c87c5fbaSopenharmony_ci return 1; 505c87c5fbaSopenharmony_ci} 506c87c5fbaSopenharmony_ci 507c87c5fbaSopenharmony_cistatic coap_oscore_conf_t * 508c87c5fbaSopenharmony_ciget_oscore_conf(coap_context_t *context) { 509c87c5fbaSopenharmony_ci uint8_t *buf; 510c87c5fbaSopenharmony_ci size_t length; 511c87c5fbaSopenharmony_ci coap_str_const_t file_mem; 512c87c5fbaSopenharmony_ci uint64_t start_seq_num = 0; 513c87c5fbaSopenharmony_ci 514c87c5fbaSopenharmony_ci buf = read_file_mem(oscore_conf_file, &length); 515c87c5fbaSopenharmony_ci if (buf == NULL) { 516c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE configuration file error: %s\n", oscore_conf_file); 517c87c5fbaSopenharmony_ci return NULL; 518c87c5fbaSopenharmony_ci } 519c87c5fbaSopenharmony_ci file_mem.s = buf; 520c87c5fbaSopenharmony_ci file_mem.length = length; 521c87c5fbaSopenharmony_ci if (oscore_seq_save_file) { 522c87c5fbaSopenharmony_ci oscore_seq_num_fp = fopen(oscore_seq_save_file, "r+"); 523c87c5fbaSopenharmony_ci if (oscore_seq_num_fp == NULL) { 524c87c5fbaSopenharmony_ci /* Try creating it */ 525c87c5fbaSopenharmony_ci oscore_seq_num_fp = fopen(oscore_seq_save_file, "w+"); 526c87c5fbaSopenharmony_ci if (oscore_seq_num_fp == NULL) { 527c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE save restart info file error: %s\n", 528c87c5fbaSopenharmony_ci oscore_seq_save_file); 529c87c5fbaSopenharmony_ci return NULL; 530c87c5fbaSopenharmony_ci } 531c87c5fbaSopenharmony_ci } 532c87c5fbaSopenharmony_ci if (fscanf(oscore_seq_num_fp, "%" PRIu64, &start_seq_num) != 1) { 533c87c5fbaSopenharmony_ci /* Must be empty */ 534c87c5fbaSopenharmony_ci start_seq_num = 0; 535c87c5fbaSopenharmony_ci } 536c87c5fbaSopenharmony_ci } 537c87c5fbaSopenharmony_ci oscore_conf = coap_new_oscore_conf(file_mem, 538c87c5fbaSopenharmony_ci oscore_save_seq_num, 539c87c5fbaSopenharmony_ci NULL, start_seq_num); 540c87c5fbaSopenharmony_ci coap_free(buf); 541c87c5fbaSopenharmony_ci if (oscore_conf == NULL) { 542c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE configuration file error: %s\n", oscore_conf_file); 543c87c5fbaSopenharmony_ci return NULL; 544c87c5fbaSopenharmony_ci } 545c87c5fbaSopenharmony_ci coap_context_oscore_server(context, oscore_conf); 546c87c5fbaSopenharmony_ci return oscore_conf; 547c87c5fbaSopenharmony_ci} 548c87c5fbaSopenharmony_ci 549c87c5fbaSopenharmony_cistatic int 550c87c5fbaSopenharmony_cicmdline_oscore(char *arg) { 551c87c5fbaSopenharmony_ci if (coap_oscore_is_supported()) { 552c87c5fbaSopenharmony_ci char *sep = strchr(arg, ','); 553c87c5fbaSopenharmony_ci 554c87c5fbaSopenharmony_ci if (sep) 555c87c5fbaSopenharmony_ci *sep = '\000'; 556c87c5fbaSopenharmony_ci oscore_conf_file = arg; 557c87c5fbaSopenharmony_ci 558c87c5fbaSopenharmony_ci if (sep) { 559c87c5fbaSopenharmony_ci sep++; 560c87c5fbaSopenharmony_ci oscore_seq_save_file = sep; 561c87c5fbaSopenharmony_ci } 562c87c5fbaSopenharmony_ci doing_oscore = 1; 563c87c5fbaSopenharmony_ci return 1; 564c87c5fbaSopenharmony_ci } 565c87c5fbaSopenharmony_ci fprintf(stderr, "OSCORE support not enabled\n"); 566c87c5fbaSopenharmony_ci return 0; 567c87c5fbaSopenharmony_ci} 568c87c5fbaSopenharmony_ci 569c87c5fbaSopenharmony_ciint 570c87c5fbaSopenharmony_cimain(int argc, char **argv) { 571c87c5fbaSopenharmony_ci coap_context_t *ctx; 572c87c5fbaSopenharmony_ci char *group = NULL; 573c87c5fbaSopenharmony_ci char *group_if = NULL; 574c87c5fbaSopenharmony_ci coap_tick_t now; 575c87c5fbaSopenharmony_ci char addr_str[NI_MAXHOST] = "::"; 576c87c5fbaSopenharmony_ci char port_str[NI_MAXSERV] = "5683"; 577c87c5fbaSopenharmony_ci int opt; 578c87c5fbaSopenharmony_ci int mcast_per_resource = 0; 579c87c5fbaSopenharmony_ci coap_log_t log_level = COAP_LOG_WARN; 580c87c5fbaSopenharmony_ci unsigned wait_ms; 581c87c5fbaSopenharmony_ci coap_time_t t_last = 0; 582c87c5fbaSopenharmony_ci int coap_fd; 583c87c5fbaSopenharmony_ci fd_set m_readfds; 584c87c5fbaSopenharmony_ci int nfds = 0; 585c87c5fbaSopenharmony_ci uint16_t cache_ignore_options[] = { COAP_OPTION_BLOCK1, 586c87c5fbaSopenharmony_ci COAP_OPTION_BLOCK2, 587c87c5fbaSopenharmony_ci /* See https://rfc-editor.org/rfc/rfc7959#section-2.10 */ 588c87c5fbaSopenharmony_ci COAP_OPTION_MAXAGE, 589c87c5fbaSopenharmony_ci /* See https://rfc-editor.org/rfc/rfc7959#section-2.10 */ 590c87c5fbaSopenharmony_ci COAP_OPTION_IF_NONE_MATCH 591c87c5fbaSopenharmony_ci }; 592c87c5fbaSopenharmony_ci#ifndef _WIN32 593c87c5fbaSopenharmony_ci struct sigaction sa; 594c87c5fbaSopenharmony_ci#endif 595c87c5fbaSopenharmony_ci 596c87c5fbaSopenharmony_ci /* Initialize libcoap library */ 597c87c5fbaSopenharmony_ci coap_startup(); 598c87c5fbaSopenharmony_ci 599c87c5fbaSopenharmony_ci while ((opt = getopt(argc, argv, "g:G:l:p:rv:A:E:L:NX:")) != -1) { 600c87c5fbaSopenharmony_ci switch (opt) { 601c87c5fbaSopenharmony_ci case 'A' : 602c87c5fbaSopenharmony_ci strncpy(addr_str, optarg, NI_MAXHOST-1); 603c87c5fbaSopenharmony_ci addr_str[NI_MAXHOST - 1] = '\0'; 604c87c5fbaSopenharmony_ci break; 605c87c5fbaSopenharmony_ci case 'E': 606c87c5fbaSopenharmony_ci if (!cmdline_oscore(optarg)) { 607c87c5fbaSopenharmony_ci exit(1); 608c87c5fbaSopenharmony_ci } 609c87c5fbaSopenharmony_ci break; 610c87c5fbaSopenharmony_ci case 'g' : 611c87c5fbaSopenharmony_ci group = optarg; 612c87c5fbaSopenharmony_ci break; 613c87c5fbaSopenharmony_ci case 'G' : 614c87c5fbaSopenharmony_ci group_if = optarg; 615c87c5fbaSopenharmony_ci break; 616c87c5fbaSopenharmony_ci case 'l': 617c87c5fbaSopenharmony_ci if (!coap_debug_set_packet_loss(optarg)) { 618c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 619c87c5fbaSopenharmony_ci exit(1); 620c87c5fbaSopenharmony_ci } 621c87c5fbaSopenharmony_ci break; 622c87c5fbaSopenharmony_ci case 'L': 623c87c5fbaSopenharmony_ci block_mode = strtoul(optarg, NULL, 0); 624c87c5fbaSopenharmony_ci if (!(block_mode & COAP_BLOCK_USE_LIBCOAP)) { 625c87c5fbaSopenharmony_ci fprintf(stderr, "Block mode must include COAP_BLOCK_USE_LIBCOAP (1)\n"); 626c87c5fbaSopenharmony_ci exit(-1); 627c87c5fbaSopenharmony_ci } 628c87c5fbaSopenharmony_ci break; 629c87c5fbaSopenharmony_ci case 'N': 630c87c5fbaSopenharmony_ci resource_flags = COAP_RESOURCE_FLAGS_NOTIFY_NON; 631c87c5fbaSopenharmony_ci break; 632c87c5fbaSopenharmony_ci case 'p' : 633c87c5fbaSopenharmony_ci strncpy(port_str, optarg, NI_MAXSERV-1); 634c87c5fbaSopenharmony_ci port_str[NI_MAXSERV - 1] = '\0'; 635c87c5fbaSopenharmony_ci break; 636c87c5fbaSopenharmony_ci case 'r' : 637c87c5fbaSopenharmony_ci mcast_per_resource = 1; 638c87c5fbaSopenharmony_ci break; 639c87c5fbaSopenharmony_ci case 'v' : 640c87c5fbaSopenharmony_ci log_level = strtol(optarg, NULL, 10); 641c87c5fbaSopenharmony_ci break; 642c87c5fbaSopenharmony_ci case 'X': 643c87c5fbaSopenharmony_ci csm_max_message_size = strtol(optarg, NULL, 10); 644c87c5fbaSopenharmony_ci break; 645c87c5fbaSopenharmony_ci default: 646c87c5fbaSopenharmony_ci usage(argv[0], LIBCOAP_PACKAGE_VERSION); 647c87c5fbaSopenharmony_ci exit(1); 648c87c5fbaSopenharmony_ci } 649c87c5fbaSopenharmony_ci } 650c87c5fbaSopenharmony_ci 651c87c5fbaSopenharmony_ci#ifdef _WIN32 652c87c5fbaSopenharmony_ci signal(SIGINT, handle_sigint); 653c87c5fbaSopenharmony_ci#else 654c87c5fbaSopenharmony_ci memset(&sa, 0, sizeof(sa)); 655c87c5fbaSopenharmony_ci sigemptyset(&sa.sa_mask); 656c87c5fbaSopenharmony_ci sa.sa_handler = handle_sigint; 657c87c5fbaSopenharmony_ci sa.sa_flags = 0; 658c87c5fbaSopenharmony_ci sigaction(SIGINT, &sa, NULL); 659c87c5fbaSopenharmony_ci sigaction(SIGTERM, &sa, NULL); 660c87c5fbaSopenharmony_ci /* So we do not exit on a SIGPIPE */ 661c87c5fbaSopenharmony_ci sa.sa_handler = SIG_IGN; 662c87c5fbaSopenharmony_ci sigaction(SIGPIPE, &sa, NULL); 663c87c5fbaSopenharmony_ci#endif 664c87c5fbaSopenharmony_ci 665c87c5fbaSopenharmony_ci coap_dtls_set_log_level(log_level); 666c87c5fbaSopenharmony_ci coap_set_log_level(log_level); 667c87c5fbaSopenharmony_ci 668c87c5fbaSopenharmony_ci ctx = get_context(addr_str, port_str); 669c87c5fbaSopenharmony_ci if (!ctx) 670c87c5fbaSopenharmony_ci return -1; 671c87c5fbaSopenharmony_ci 672c87c5fbaSopenharmony_ci init_resources(ctx); 673c87c5fbaSopenharmony_ci if (mcast_per_resource) 674c87c5fbaSopenharmony_ci coap_mcast_per_resource(ctx); 675c87c5fbaSopenharmony_ci coap_context_set_block_mode(ctx, block_mode); 676c87c5fbaSopenharmony_ci if (csm_max_message_size) 677c87c5fbaSopenharmony_ci coap_context_set_csm_max_message_size(ctx, csm_max_message_size); 678c87c5fbaSopenharmony_ci if (doing_oscore) { 679c87c5fbaSopenharmony_ci if (get_oscore_conf(ctx) == NULL) 680c87c5fbaSopenharmony_ci goto finish; 681c87c5fbaSopenharmony_ci } 682c87c5fbaSopenharmony_ci 683c87c5fbaSopenharmony_ci /* Define the options to ignore when setting up cache-keys */ 684c87c5fbaSopenharmony_ci coap_cache_ignore_options(ctx, cache_ignore_options, 685c87c5fbaSopenharmony_ci sizeof(cache_ignore_options)/sizeof(cache_ignore_options[0])); 686c87c5fbaSopenharmony_ci /* join multicast group if requested at command line */ 687c87c5fbaSopenharmony_ci if (group) 688c87c5fbaSopenharmony_ci coap_join_mcast_group_intf(ctx, group, group_if); 689c87c5fbaSopenharmony_ci 690c87c5fbaSopenharmony_ci coap_fd = coap_context_get_coap_fd(ctx); 691c87c5fbaSopenharmony_ci if (coap_fd != -1) { 692c87c5fbaSopenharmony_ci /* if coap_fd is -1, then epoll is not supported within libcoap */ 693c87c5fbaSopenharmony_ci FD_ZERO(&m_readfds); 694c87c5fbaSopenharmony_ci FD_SET(coap_fd, &m_readfds); 695c87c5fbaSopenharmony_ci nfds = coap_fd + 1; 696c87c5fbaSopenharmony_ci } 697c87c5fbaSopenharmony_ci 698c87c5fbaSopenharmony_ci wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; 699c87c5fbaSopenharmony_ci 700c87c5fbaSopenharmony_ci while (!quit) { 701c87c5fbaSopenharmony_ci int result; 702c87c5fbaSopenharmony_ci 703c87c5fbaSopenharmony_ci if (coap_fd != -1) { 704c87c5fbaSopenharmony_ci /* 705c87c5fbaSopenharmony_ci * Using epoll. It is more usual to call coap_io_process() with wait_ms 706c87c5fbaSopenharmony_ci * (as in the non-epoll branch), but doing it this way gives the 707c87c5fbaSopenharmony_ci * flexibility of potentially working with other file descriptors that 708c87c5fbaSopenharmony_ci * are not a part of libcoap. 709c87c5fbaSopenharmony_ci */ 710c87c5fbaSopenharmony_ci fd_set readfds = m_readfds; 711c87c5fbaSopenharmony_ci struct timeval tv; 712c87c5fbaSopenharmony_ci coap_tick_t begin, end; 713c87c5fbaSopenharmony_ci 714c87c5fbaSopenharmony_ci coap_ticks(&begin); 715c87c5fbaSopenharmony_ci 716c87c5fbaSopenharmony_ci tv.tv_sec = wait_ms / 1000; 717c87c5fbaSopenharmony_ci tv.tv_usec = (wait_ms % 1000) * 1000; 718c87c5fbaSopenharmony_ci /* Wait until any i/o takes place or timeout */ 719c87c5fbaSopenharmony_ci result = select(nfds, &readfds, NULL, NULL, &tv); 720c87c5fbaSopenharmony_ci if (result == -1) { 721c87c5fbaSopenharmony_ci if (errno != EAGAIN) { 722c87c5fbaSopenharmony_ci coap_log_debug("select: %s (%d)\n", coap_socket_strerror(), 723c87c5fbaSopenharmony_ci errno); 724c87c5fbaSopenharmony_ci break; 725c87c5fbaSopenharmony_ci } 726c87c5fbaSopenharmony_ci } 727c87c5fbaSopenharmony_ci if (result > 0) { 728c87c5fbaSopenharmony_ci if (FD_ISSET(coap_fd, &readfds)) { 729c87c5fbaSopenharmony_ci result = coap_io_process(ctx, COAP_IO_NO_WAIT); 730c87c5fbaSopenharmony_ci } 731c87c5fbaSopenharmony_ci } 732c87c5fbaSopenharmony_ci if (result >= 0) { 733c87c5fbaSopenharmony_ci coap_ticks(&end); 734c87c5fbaSopenharmony_ci /* Track the overall time spent in select() and coap_io_process() */ 735c87c5fbaSopenharmony_ci result = (int)(end - begin); 736c87c5fbaSopenharmony_ci } 737c87c5fbaSopenharmony_ci } else { 738c87c5fbaSopenharmony_ci /* 739c87c5fbaSopenharmony_ci * epoll is not supported within libcoap 740c87c5fbaSopenharmony_ci * 741c87c5fbaSopenharmony_ci * result is time spent in coap_io_process() 742c87c5fbaSopenharmony_ci */ 743c87c5fbaSopenharmony_ci result = coap_io_process(ctx, wait_ms); 744c87c5fbaSopenharmony_ci } 745c87c5fbaSopenharmony_ci if (result < 0) { 746c87c5fbaSopenharmony_ci break; 747c87c5fbaSopenharmony_ci } else if (result && (unsigned)result < wait_ms) { 748c87c5fbaSopenharmony_ci /* decrement if there is a result wait time returned */ 749c87c5fbaSopenharmony_ci wait_ms -= result; 750c87c5fbaSopenharmony_ci } else { 751c87c5fbaSopenharmony_ci /* 752c87c5fbaSopenharmony_ci * result == 0, or result >= wait_ms 753c87c5fbaSopenharmony_ci * (wait_ms could have decremented to a small value, below 754c87c5fbaSopenharmony_ci * the granularity of the timer in coap_io_process() and hence 755c87c5fbaSopenharmony_ci * result == 0) 756c87c5fbaSopenharmony_ci */ 757c87c5fbaSopenharmony_ci wait_ms = COAP_RESOURCE_CHECK_TIME * 1000; 758c87c5fbaSopenharmony_ci } 759c87c5fbaSopenharmony_ci if (r_observe_1 || r_observe_2) { 760c87c5fbaSopenharmony_ci coap_time_t t_now; 761c87c5fbaSopenharmony_ci unsigned int next_sec_ms; 762c87c5fbaSopenharmony_ci 763c87c5fbaSopenharmony_ci coap_ticks(&now); 764c87c5fbaSopenharmony_ci t_now = coap_ticks_to_rt(now); 765c87c5fbaSopenharmony_ci if (t_last != t_now) { 766c87c5fbaSopenharmony_ci /* Happens once per second */ 767c87c5fbaSopenharmony_ci t_last = t_now; 768c87c5fbaSopenharmony_ci if (r_observe_1) 769c87c5fbaSopenharmony_ci coap_resource_notify_observers(r_observe_1, NULL); 770c87c5fbaSopenharmony_ci if (r_observe_2) 771c87c5fbaSopenharmony_ci coap_resource_notify_observers(r_observe_2, NULL); 772c87c5fbaSopenharmony_ci } 773c87c5fbaSopenharmony_ci /* need to wait until next second starts if wait_ms is too large */ 774c87c5fbaSopenharmony_ci next_sec_ms = 1000 - (now % COAP_TICKS_PER_SECOND) * 775c87c5fbaSopenharmony_ci 1000 / COAP_TICKS_PER_SECOND; 776c87c5fbaSopenharmony_ci if (next_sec_ms && next_sec_ms < wait_ms) 777c87c5fbaSopenharmony_ci wait_ms = next_sec_ms; 778c87c5fbaSopenharmony_ci } 779c87c5fbaSopenharmony_ci } 780c87c5fbaSopenharmony_ci 781c87c5fbaSopenharmony_cifinish: 782c87c5fbaSopenharmony_ci 783c87c5fbaSopenharmony_ci if (oscore_seq_num_fp) 784c87c5fbaSopenharmony_ci fclose(oscore_seq_num_fp); 785c87c5fbaSopenharmony_ci 786c87c5fbaSopenharmony_ci coap_free_context(ctx); 787c87c5fbaSopenharmony_ci coap_cleanup(); 788c87c5fbaSopenharmony_ci 789c87c5fbaSopenharmony_ci return 0; 790c87c5fbaSopenharmony_ci} 791