1c87c5fbaSopenharmony_ci/* coap_session.c -- Session management for libcoap 2c87c5fbaSopenharmony_ci * 3c87c5fbaSopenharmony_ci * Copyright (C) 2017 Jean-Claue Michelou <jcm@spinetix.com> 4c87c5fbaSopenharmony_ci * Copyright (C) 2022-2023 Jon Shallow <supjps-libcoap@jpshallow.com> 5c87c5fbaSopenharmony_ci * 6c87c5fbaSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 7c87c5fbaSopenharmony_ci * 8c87c5fbaSopenharmony_ci * This file is part of the CoAP library libcoap. Please see 9c87c5fbaSopenharmony_ci * README for terms of use. 10c87c5fbaSopenharmony_ci */ 11c87c5fbaSopenharmony_ci 12c87c5fbaSopenharmony_ci/** 13c87c5fbaSopenharmony_ci * @file coap_session.c 14c87c5fbaSopenharmony_ci * @brief Session handling functions 15c87c5fbaSopenharmony_ci */ 16c87c5fbaSopenharmony_ci 17c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h" 18c87c5fbaSopenharmony_ci 19c87c5fbaSopenharmony_ci#ifndef COAP_SESSION_C_ 20c87c5fbaSopenharmony_ci#define COAP_SESSION_C_ 21c87c5fbaSopenharmony_ci 22c87c5fbaSopenharmony_ci#include <stdio.h> 23c87c5fbaSopenharmony_ci 24c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 25c87c5fbaSopenharmony_ci#include <sys/epoll.h> 26c87c5fbaSopenharmony_ci#include <sys/timerfd.h> 27c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 28c87c5fbaSopenharmony_ci 29c87c5fbaSopenharmony_ci#ifndef _WIN32 30c87c5fbaSopenharmony_ci#include <unistd.h> 31c87c5fbaSopenharmony_ci#include <sys/ioctl.h> 32c87c5fbaSopenharmony_ci#include <net/if.h> 33c87c5fbaSopenharmony_ci#include <arpa/inet.h> 34c87c5fbaSopenharmony_ci#else 35c87c5fbaSopenharmony_ci#include <Iphlpapi.h> 36c87c5fbaSopenharmony_ci#endif /* !(_WIN32) */ 37c87c5fbaSopenharmony_ci 38c87c5fbaSopenharmony_ci#ifdef COAP_SUPPORT_SOCKET_BROADCAST 39c87c5fbaSopenharmony_ci#ifndef _WIN32 40c87c5fbaSopenharmony_ci 41c87c5fbaSopenharmony_cistatic int32_t loopback_packet_check(const char *src_buf) { 42c87c5fbaSopenharmony_ci const char addr_perface[] = "::ffff:"; 43c87c5fbaSopenharmony_ci char tmp_buf[INET6_ADDRSTRLEN] = {0}; 44c87c5fbaSopenharmony_ci int ret; 45c87c5fbaSopenharmony_ci void *tmp_addr_ptr = NULL; 46c87c5fbaSopenharmony_ci struct ifreq buf[COAP_INTERFACE_MAX]; 47c87c5fbaSopenharmony_ci struct ifconf ifc = {0}; 48c87c5fbaSopenharmony_ci 49c87c5fbaSopenharmony_ci int fd = socket(AF_INET, SOCK_DGRAM, 0); 50c87c5fbaSopenharmony_ci if (fd < 0) { 51c87c5fbaSopenharmony_ci coap_log_debug("socket fail\n"); 52c87c5fbaSopenharmony_ci return 1; 53c87c5fbaSopenharmony_ci } 54c87c5fbaSopenharmony_ci ifc.ifc_len = sizeof(buf); 55c87c5fbaSopenharmony_ci ifc.ifc_buf = (char *)buf; 56c87c5fbaSopenharmony_ci if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) { 57c87c5fbaSopenharmony_ci coap_log_debug("ioctl fail, errno = %d\n", errno); 58c87c5fbaSopenharmony_ci goto L_IS_LOOPBACK; 59c87c5fbaSopenharmony_ci } 60c87c5fbaSopenharmony_ci int interface_num = ifc.ifc_len / sizeof(struct ifreq); 61c87c5fbaSopenharmony_ci for (int i = 0; i < interface_num && i < COAP_INTERFACE_MAX; i++) { 62c87c5fbaSopenharmony_ci coap_log_debug("interface name: %s\n", buf[i].ifr_name); 63c87c5fbaSopenharmony_ci if (ioctl(fd, SIOCGIFADDR, (char *)&buf[i]) < 0) { 64c87c5fbaSopenharmony_ci coap_log_debug("ioctl fail, errno = %d\n", errno); 65c87c5fbaSopenharmony_ci goto L_IS_LOOPBACK; 66c87c5fbaSopenharmony_ci } 67c87c5fbaSopenharmony_ci tmp_addr_ptr = &((struct sockaddr_in *)&(buf[i].ifr_addr))->sin_addr; 68c87c5fbaSopenharmony_ci inet_ntop(AF_INET, tmp_addr_ptr, tmp_buf, INET_ADDRSTRLEN); 69c87c5fbaSopenharmony_ci if (memcmp(src_buf, addr_perface, strlen(addr_perface)) == 0 && 70c87c5fbaSopenharmony_ci strlen(src_buf) == strlen(tmp_buf) + strlen(addr_perface)) { 71c87c5fbaSopenharmony_ci ret = memcmp(src_buf + strlen(addr_perface), tmp_buf, strlen(src_buf) - strlen(addr_perface)); 72c87c5fbaSopenharmony_ci } else { 73c87c5fbaSopenharmony_ci if (strlen(src_buf) == strlen(tmp_buf)) { 74c87c5fbaSopenharmony_ci ret = memcmp(src_buf, tmp_buf, strlen(src_buf)); 75c87c5fbaSopenharmony_ci } else { 76c87c5fbaSopenharmony_ci ret = 1; 77c87c5fbaSopenharmony_ci } 78c87c5fbaSopenharmony_ci } 79c87c5fbaSopenharmony_ci if (ret == 0) { 80c87c5fbaSopenharmony_ci goto L_IS_LOOPBACK; 81c87c5fbaSopenharmony_ci } 82c87c5fbaSopenharmony_ci } 83c87c5fbaSopenharmony_ci close(fd); 84c87c5fbaSopenharmony_ci return 0; 85c87c5fbaSopenharmony_ciL_IS_LOOPBACK: 86c87c5fbaSopenharmony_ci close(fd); 87c87c5fbaSopenharmony_ci return 1; 88c87c5fbaSopenharmony_ci} 89c87c5fbaSopenharmony_ci#else 90c87c5fbaSopenharmony_cistatic int loopback_packet_compare_ip(const char *src_buf, const char *addr_perface, const char *tmp_buf) { 91c87c5fbaSopenharmony_ci int ret; 92c87c5fbaSopenharmony_ci if (memcmp(src_buf, addr_perface, strlen(addr_perface)) == 0 && 93c87c5fbaSopenharmony_ci strlen(src_buf) == strlen(tmp_buf) + strlen(addr_perface)) { 94c87c5fbaSopenharmony_ci ret = memcmp(src_buf + strlen(addr_perface), tmp_buf, strlen(src_buf) - strlen(addr_perface)); 95c87c5fbaSopenharmony_ci } else { 96c87c5fbaSopenharmony_ci if (strlen(src_buf) == strlen(tmp_buf)) { 97c87c5fbaSopenharmony_ci ret = memcmp(src_buf, tmp_buf, strlen(src_buf)); 98c87c5fbaSopenharmony_ci } else { 99c87c5fbaSopenharmony_ci ret = 1; 100c87c5fbaSopenharmony_ci } 101c87c5fbaSopenharmony_ci } 102c87c5fbaSopenharmony_ci return ret; 103c87c5fbaSopenharmony_ci} 104c87c5fbaSopenharmony_ci 105c87c5fbaSopenharmony_cistatic int32_t loopback_packet_check(const char *src_buf) { 106c87c5fbaSopenharmony_ci const char addr_perface[] = "::ffff:"; 107c87c5fbaSopenharmony_ci char tmp_buf[INET6_ADDRSTRLEN] = { 0 }; 108c87c5fbaSopenharmony_ci int ret; 109c87c5fbaSopenharmony_ci IP_ADAPTER_INFO *adapter_info = NULL; 110c87c5fbaSopenharmony_ci IP_ADAPTER_INFO *adapter = NULL; 111c87c5fbaSopenharmony_ci ULONG adapter_info_len = sizeof(IP_ADAPTER_INFO); 112c87c5fbaSopenharmony_ci adapter_info = (IP_ADAPTER_INFO *)malloc(adapter_info_len); 113c87c5fbaSopenharmony_ci if (adapter_info == NULL) { 114c87c5fbaSopenharmony_ci coap_log_err("adapter_info malloc failed\n"); 115c87c5fbaSopenharmony_ci return 1; 116c87c5fbaSopenharmony_ci } 117c87c5fbaSopenharmony_ci if (GetAdaptersInfo(adapter_info, &adapter_info_len) == ERROR_BUFFER_OVERFLOW) { 118c87c5fbaSopenharmony_ci free(adapter_info); 119c87c5fbaSopenharmony_ci adapter_info = (IP_ADAPTER_INFO *)malloc(adapter_info_len); 120c87c5fbaSopenharmony_ci if (adapter_info == NULL) { 121c87c5fbaSopenharmony_ci coap_log_err("adapter_info malloc failed\n"); 122c87c5fbaSopenharmony_ci return 1; 123c87c5fbaSopenharmony_ci } 124c87c5fbaSopenharmony_ci } 125c87c5fbaSopenharmony_ci int32_t err = GetAdaptersInfo(adapter_info, &adapter_info_len); 126c87c5fbaSopenharmony_ci if (err != NO_ERROR) { 127c87c5fbaSopenharmony_ci coap_log_err("GetAdaptersInfo failed with error: %d\n", err); 128c87c5fbaSopenharmony_ci goto L_IS_LOOPBACK; 129c87c5fbaSopenharmony_ci } 130c87c5fbaSopenharmony_ci adapter = adapter_info; 131c87c5fbaSopenharmony_ci while (adapter != NULL) { 132c87c5fbaSopenharmony_ci PIP_ADDR_STRING pip_addr = &adapter->IpAddressList; 133c87c5fbaSopenharmony_ci while (pip_addr != NULL) { 134c87c5fbaSopenharmony_ci if (strcpy_s(tmp_buf, INET6_ADDRSTRLEN, pip_addr->IpAddress.String) != 0) { 135c87c5fbaSopenharmony_ci goto L_IS_LOOPBACK; 136c87c5fbaSopenharmony_ci } 137c87c5fbaSopenharmony_ci ret = loopback_packet_compare_ip(src_buf, addr_perface, tmp_buf); 138c87c5fbaSopenharmony_ci if (ret == 0) { 139c87c5fbaSopenharmony_ci goto L_IS_LOOPBACK; 140c87c5fbaSopenharmony_ci } 141c87c5fbaSopenharmony_ci pip_addr = pip_addr->Next; 142c87c5fbaSopenharmony_ci } 143c87c5fbaSopenharmony_ci adapter = adapter->Next; 144c87c5fbaSopenharmony_ci } 145c87c5fbaSopenharmony_ci free(adapter_info); 146c87c5fbaSopenharmony_ci return 0; 147c87c5fbaSopenharmony_ciL_IS_LOOPBACK: 148c87c5fbaSopenharmony_ci free(adapter_info); 149c87c5fbaSopenharmony_ci return 1; 150c87c5fbaSopenharmony_ci} 151c87c5fbaSopenharmony_ci#endif /* END OF _WIN32 */ 152c87c5fbaSopenharmony_ci 153c87c5fbaSopenharmony_cistatic int32_t is_loopback_packet(const coap_packet_t *packet) { 154c87c5fbaSopenharmony_ci char src_buf[INET6_ADDRSTRLEN] = {0}; 155c87c5fbaSopenharmony_ci coap_address_ntop(&(packet->addr_info.remote), src_buf, INET6_ADDRSTRLEN); 156c87c5fbaSopenharmony_ci return loopback_packet_check(src_buf); 157c87c5fbaSopenharmony_ci} 158c87c5fbaSopenharmony_ci#endif /* END OF COAP_SUPPORT_SOCKET_BROADCAST */ 159c87c5fbaSopenharmony_ci 160c87c5fbaSopenharmony_cicoap_fixed_point_t 161c87c5fbaSopenharmony_cicoap_multi_fixed_fixed(coap_fixed_point_t fp1, coap_fixed_point_t fp2) { 162c87c5fbaSopenharmony_ci coap_fixed_point_t res; 163c87c5fbaSopenharmony_ci uint32_t fr = fp1.fractional_part * fp2.fractional_part; 164c87c5fbaSopenharmony_ci 165c87c5fbaSopenharmony_ci res.integer_part = fp1.integer_part * fp2.integer_part + fr/1000; 166c87c5fbaSopenharmony_ci res.fractional_part = fr % 1000; 167c87c5fbaSopenharmony_ci return res; 168c87c5fbaSopenharmony_ci} 169c87c5fbaSopenharmony_ci 170c87c5fbaSopenharmony_cicoap_fixed_point_t 171c87c5fbaSopenharmony_cicoap_multi_fixed_uint(coap_fixed_point_t fp1, uint32_t u2) { 172c87c5fbaSopenharmony_ci coap_fixed_point_t res; 173c87c5fbaSopenharmony_ci uint32_t fr = fp1.fractional_part * u2; 174c87c5fbaSopenharmony_ci 175c87c5fbaSopenharmony_ci res.integer_part = fp1.integer_part * u2 + fr/1000; 176c87c5fbaSopenharmony_ci res.fractional_part = fr % 1000; 177c87c5fbaSopenharmony_ci return res; 178c87c5fbaSopenharmony_ci} 179c87c5fbaSopenharmony_ci 180c87c5fbaSopenharmony_cicoap_fixed_point_t 181c87c5fbaSopenharmony_cicoap_add_fixed_fixed(coap_fixed_point_t fp1, coap_fixed_point_t fp2) { 182c87c5fbaSopenharmony_ci coap_fixed_point_t res; 183c87c5fbaSopenharmony_ci uint32_t fr = fp1.fractional_part + fp2.fractional_part; 184c87c5fbaSopenharmony_ci 185c87c5fbaSopenharmony_ci res.integer_part = fp1.integer_part + fp2.integer_part + fr/1000; 186c87c5fbaSopenharmony_ci res.fractional_part = fr % 1000; 187c87c5fbaSopenharmony_ci return res; 188c87c5fbaSopenharmony_ci} 189c87c5fbaSopenharmony_ci 190c87c5fbaSopenharmony_cicoap_fixed_point_t 191c87c5fbaSopenharmony_cicoap_add_fixed_uint(coap_fixed_point_t fp1, uint32_t u2) { 192c87c5fbaSopenharmony_ci coap_fixed_point_t res = fp1; 193c87c5fbaSopenharmony_ci 194c87c5fbaSopenharmony_ci res.integer_part += u2; 195c87c5fbaSopenharmony_ci return res; 196c87c5fbaSopenharmony_ci} 197c87c5fbaSopenharmony_ci 198c87c5fbaSopenharmony_cicoap_fixed_point_t 199c87c5fbaSopenharmony_cicoap_sub_fixed_uint(coap_fixed_point_t fp1, uint32_t u2) { 200c87c5fbaSopenharmony_ci coap_fixed_point_t res = fp1; 201c87c5fbaSopenharmony_ci 202c87c5fbaSopenharmony_ci res.integer_part -= u2; 203c87c5fbaSopenharmony_ci return res; 204c87c5fbaSopenharmony_ci} 205c87c5fbaSopenharmony_ci 206c87c5fbaSopenharmony_cicoap_fixed_point_t 207c87c5fbaSopenharmony_cicoap_div_fixed_uint(coap_fixed_point_t fp1, uint32_t u2) { 208c87c5fbaSopenharmony_ci coap_fixed_point_t res; 209c87c5fbaSopenharmony_ci uint32_t num = (fp1.integer_part * 1000 + fp1.fractional_part) / u2; 210c87c5fbaSopenharmony_ci 211c87c5fbaSopenharmony_ci res.integer_part = num / 1000; 212c87c5fbaSopenharmony_ci res.fractional_part = num % 1000; 213c87c5fbaSopenharmony_ci return res; 214c87c5fbaSopenharmony_ci} 215c87c5fbaSopenharmony_ci 216c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 217c87c5fbaSopenharmony_cicoap_fixed_point_t 218c87c5fbaSopenharmony_cicoap_get_non_timeout_random(coap_session_t *session) { 219c87c5fbaSopenharmony_ci coap_fixed_point_t res; 220c87c5fbaSopenharmony_ci uint8_t ran; 221c87c5fbaSopenharmony_ci 222c87c5fbaSopenharmony_ci coap_prng(&ran, sizeof(ran)); 223c87c5fbaSopenharmony_ci res = coap_sub_fixed_uint(COAP_ACK_RANDOM_FACTOR(session), 1); 224c87c5fbaSopenharmony_ci res = coap_multi_fixed_uint(res, ran); 225c87c5fbaSopenharmony_ci res = coap_div_fixed_uint(res, 0xff); 226c87c5fbaSopenharmony_ci res = coap_add_fixed_fixed(COAP_NON_TIMEOUT(session), res); 227c87c5fbaSopenharmony_ci return res; 228c87c5fbaSopenharmony_ci} 229c87c5fbaSopenharmony_ci 230c87c5fbaSopenharmony_cicoap_tick_t 231c87c5fbaSopenharmony_cicoap_get_non_timeout_random_ticks(coap_session_t *session) { 232c87c5fbaSopenharmony_ci coap_fixed_point_t res = coap_get_non_timeout_random(session); 233c87c5fbaSopenharmony_ci coap_tick_t ticks = (res.integer_part * COAP_TICKS_PER_SECOND + 234c87c5fbaSopenharmony_ci res.fractional_part * COAP_TICKS_PER_SECOND / 1000); 235c87c5fbaSopenharmony_ci 236c87c5fbaSopenharmony_ci return ticks; 237c87c5fbaSopenharmony_ci} 238c87c5fbaSopenharmony_ci 239c87c5fbaSopenharmony_ci/* 240c87c5fbaSopenharmony_ci * Save away derived Congestion Control parameters for speed of access. 241c87c5fbaSopenharmony_ci * They will get updated whenever a component variable is updated. 242c87c5fbaSopenharmony_ci */ 243c87c5fbaSopenharmony_ci 244c87c5fbaSopenharmony_ci/* 245c87c5fbaSopenharmony_ci * NON_PROBING_WAIT = NON_TIMEOUT * ((2 ** NON_MAX_RETRANSMIT) - 1) * 246c87c5fbaSopenharmony_ci * ACK_RANDOM_FACTOR + (2 * MAX_LATENCY) + NON_TIMEOUT_RANDOM 247c87c5fbaSopenharmony_ci * 248c87c5fbaSopenharmony_ci * Do not include NON_TIMEOUT_RANDOM as that changes 249c87c5fbaSopenharmony_ci */ 250c87c5fbaSopenharmony_cistatic void 251c87c5fbaSopenharmony_cicoap_session_fix_non_probing_wait_base(coap_session_t *s) { 252c87c5fbaSopenharmony_ci coap_fixed_point_t res; 253c87c5fbaSopenharmony_ci 254c87c5fbaSopenharmony_ci res = coap_multi_fixed_uint(COAP_NON_TIMEOUT(s), 255c87c5fbaSopenharmony_ci ((1 << (COAP_NON_MAX_RETRANSMIT(s) + 1)) -1)); 256c87c5fbaSopenharmony_ci res = coap_multi_fixed_fixed(res, COAP_ACK_RANDOM_FACTOR(s)); 257c87c5fbaSopenharmony_ci res = coap_add_fixed_uint(res, 2 * COAP_DEFAULT_MAX_LATENCY); 258c87c5fbaSopenharmony_ci COAP_NON_PROBING_WAIT_BASE(s) = res; 259c87c5fbaSopenharmony_ci} 260c87c5fbaSopenharmony_ci 261c87c5fbaSopenharmony_ci/* 262c87c5fbaSopenharmony_ci * NON_PARTIAL_TIMEOUT = NON_TIMEOUT * ((2 ** NON_MAX_RETRANSMIT) - 1) * 263c87c5fbaSopenharmony_ci * ACK_RANDOM_FACTOR + (2 * MAX_LATENCY) + NON_TIMEOUT 264c87c5fbaSopenharmony_ci */ 265c87c5fbaSopenharmony_cistatic void 266c87c5fbaSopenharmony_cicoap_session_fix_non_partial_timeout(coap_session_t *s) { 267c87c5fbaSopenharmony_ci coap_fixed_point_t res; 268c87c5fbaSopenharmony_ci 269c87c5fbaSopenharmony_ci res = coap_multi_fixed_uint(COAP_NON_TIMEOUT(s), 270c87c5fbaSopenharmony_ci ((1 << (COAP_NON_MAX_RETRANSMIT(s) + 1)) -1)); 271c87c5fbaSopenharmony_ci res = coap_multi_fixed_fixed(res, COAP_ACK_RANDOM_FACTOR(s)); 272c87c5fbaSopenharmony_ci res = coap_add_fixed_uint(res, 2 * COAP_DEFAULT_MAX_LATENCY); 273c87c5fbaSopenharmony_ci res = coap_add_fixed_fixed(res, COAP_NON_TIMEOUT(s)); 274c87c5fbaSopenharmony_ci COAP_NON_PARTIAL_TIMEOUT(s) = res; 275c87c5fbaSopenharmony_ci} 276c87c5fbaSopenharmony_ci#endif /* COAP_Q_BLOCK_SUPPORT */ 277c87c5fbaSopenharmony_ci 278c87c5fbaSopenharmony_civoid 279c87c5fbaSopenharmony_cicoap_session_set_ack_timeout(coap_session_t *session, coap_fixed_point_t value) { 280c87c5fbaSopenharmony_ci if (value.integer_part > 0 && value.fractional_part < 1000) { 281c87c5fbaSopenharmony_ci session->ack_timeout = value; 282c87c5fbaSopenharmony_ci coap_log_debug("***%s: session ack_timeout set to %u.%03u\n", 283c87c5fbaSopenharmony_ci coap_session_str(session), session->ack_timeout.integer_part, 284c87c5fbaSopenharmony_ci session->ack_timeout.fractional_part); 285c87c5fbaSopenharmony_ci } 286c87c5fbaSopenharmony_ci} 287c87c5fbaSopenharmony_ci 288c87c5fbaSopenharmony_civoid 289c87c5fbaSopenharmony_cicoap_session_set_ack_random_factor(coap_session_t *session, 290c87c5fbaSopenharmony_ci coap_fixed_point_t value) { 291c87c5fbaSopenharmony_ci if (value.integer_part > 0 && value.fractional_part < 1000) { 292c87c5fbaSopenharmony_ci session->ack_random_factor = value; 293c87c5fbaSopenharmony_ci coap_log_debug("***%s: session ack_random_factor set to %u.%03u\n", 294c87c5fbaSopenharmony_ci coap_session_str(session), session->ack_random_factor.integer_part, 295c87c5fbaSopenharmony_ci session->ack_random_factor.fractional_part); 296c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 297c87c5fbaSopenharmony_ci coap_session_fix_non_probing_wait_base(session); 298c87c5fbaSopenharmony_ci coap_session_fix_non_partial_timeout(session); 299c87c5fbaSopenharmony_ci#endif /* COAP_Q_BLOCK_SUPPORT */ 300c87c5fbaSopenharmony_ci } 301c87c5fbaSopenharmony_ci return; 302c87c5fbaSopenharmony_ci} 303c87c5fbaSopenharmony_ci 304c87c5fbaSopenharmony_civoid 305c87c5fbaSopenharmony_cicoap_session_set_max_retransmit(coap_session_t *session, uint16_t value) { 306c87c5fbaSopenharmony_ci if (value > 0) { 307c87c5fbaSopenharmony_ci session->max_retransmit = value; 308c87c5fbaSopenharmony_ci coap_log_debug("***%s: session max_retransmit set to %u\n", 309c87c5fbaSopenharmony_ci coap_session_str(session), session->max_retransmit); 310c87c5fbaSopenharmony_ci } 311c87c5fbaSopenharmony_ci} 312c87c5fbaSopenharmony_ci 313c87c5fbaSopenharmony_civoid 314c87c5fbaSopenharmony_cicoap_session_set_nstart(coap_session_t *session, uint16_t value) { 315c87c5fbaSopenharmony_ci if (value > 0) { 316c87c5fbaSopenharmony_ci session->nstart = value; 317c87c5fbaSopenharmony_ci coap_log_debug("***%s: session nstart set to %u\n", 318c87c5fbaSopenharmony_ci coap_session_str(session), session->nstart); 319c87c5fbaSopenharmony_ci } 320c87c5fbaSopenharmony_ci} 321c87c5fbaSopenharmony_ci 322c87c5fbaSopenharmony_civoid 323c87c5fbaSopenharmony_cicoap_session_set_default_leisure(coap_session_t *session, 324c87c5fbaSopenharmony_ci coap_fixed_point_t value) { 325c87c5fbaSopenharmony_ci if (value.integer_part > 0 && value.fractional_part < 1000) { 326c87c5fbaSopenharmony_ci session->default_leisure = value; 327c87c5fbaSopenharmony_ci coap_log_debug("***%s: session default_leisure set to %u.%03u\n", 328c87c5fbaSopenharmony_ci coap_session_str(session), session->default_leisure.integer_part, 329c87c5fbaSopenharmony_ci session->default_leisure.fractional_part); 330c87c5fbaSopenharmony_ci } 331c87c5fbaSopenharmony_ci} 332c87c5fbaSopenharmony_ci 333c87c5fbaSopenharmony_civoid 334c87c5fbaSopenharmony_cicoap_session_set_probing_rate(coap_session_t *session, uint32_t value) { 335c87c5fbaSopenharmony_ci if (value > 0) { 336c87c5fbaSopenharmony_ci session->probing_rate = value; 337c87c5fbaSopenharmony_ci coap_log_debug("***%s: session probing_rate set to %" PRIu32 "\n", 338c87c5fbaSopenharmony_ci coap_session_str(session), session->probing_rate); 339c87c5fbaSopenharmony_ci } 340c87c5fbaSopenharmony_ci} 341c87c5fbaSopenharmony_ci 342c87c5fbaSopenharmony_civoid 343c87c5fbaSopenharmony_cicoap_session_set_max_payloads(coap_session_t *session, uint16_t value) { 344c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 345c87c5fbaSopenharmony_ci if (value > 0) { 346c87c5fbaSopenharmony_ci session->max_payloads = value; 347c87c5fbaSopenharmony_ci coap_log_debug("***%s: session max_payloads set to %u\n", 348c87c5fbaSopenharmony_ci coap_session_str(session), session->max_payloads); 349c87c5fbaSopenharmony_ci coap_session_fix_non_probing_wait_base(session); 350c87c5fbaSopenharmony_ci coap_session_fix_non_partial_timeout(session); 351c87c5fbaSopenharmony_ci } 352c87c5fbaSopenharmony_ci#else /* ! COAP_Q_BLOCK_SUPPORT */ 353c87c5fbaSopenharmony_ci (void)session; 354c87c5fbaSopenharmony_ci (void)value; 355c87c5fbaSopenharmony_ci#endif /* ! COAP_Q_BLOCK_SUPPORT */ 356c87c5fbaSopenharmony_ci} 357c87c5fbaSopenharmony_ci 358c87c5fbaSopenharmony_civoid 359c87c5fbaSopenharmony_cicoap_session_set_non_max_retransmit(coap_session_t *session, uint16_t value) { 360c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 361c87c5fbaSopenharmony_ci if (value > 0) { 362c87c5fbaSopenharmony_ci session->non_max_retransmit = value; 363c87c5fbaSopenharmony_ci coap_log_debug("***%s: session non_max_retransmit set to %u\n", 364c87c5fbaSopenharmony_ci coap_session_str(session), session->non_max_retransmit); 365c87c5fbaSopenharmony_ci coap_session_fix_non_probing_wait_base(session); 366c87c5fbaSopenharmony_ci coap_session_fix_non_partial_timeout(session); 367c87c5fbaSopenharmony_ci } 368c87c5fbaSopenharmony_ci#else /* ! COAP_Q_BLOCK_SUPPORT */ 369c87c5fbaSopenharmony_ci (void)session; 370c87c5fbaSopenharmony_ci (void)value; 371c87c5fbaSopenharmony_ci#endif /* ! COAP_Q_BLOCK_SUPPORT */ 372c87c5fbaSopenharmony_ci} 373c87c5fbaSopenharmony_ci 374c87c5fbaSopenharmony_civoid 375c87c5fbaSopenharmony_cicoap_session_set_non_timeout(coap_session_t *session, 376c87c5fbaSopenharmony_ci coap_fixed_point_t value) { 377c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 378c87c5fbaSopenharmony_ci if (value.integer_part > 0 && value.fractional_part < 1000) { 379c87c5fbaSopenharmony_ci session->non_timeout = value; 380c87c5fbaSopenharmony_ci coap_log_debug("***%s: session non_timeout set to %u.%03u\n", 381c87c5fbaSopenharmony_ci coap_session_str(session), session->non_timeout.integer_part, 382c87c5fbaSopenharmony_ci session->non_timeout.fractional_part); 383c87c5fbaSopenharmony_ci coap_session_fix_non_probing_wait_base(session); 384c87c5fbaSopenharmony_ci coap_session_fix_non_partial_timeout(session); 385c87c5fbaSopenharmony_ci } 386c87c5fbaSopenharmony_ci#else /* ! COAP_Q_BLOCK_SUPPORT */ 387c87c5fbaSopenharmony_ci (void)session; 388c87c5fbaSopenharmony_ci (void)value; 389c87c5fbaSopenharmony_ci#endif /* ! COAP_Q_BLOCK_SUPPORT */ 390c87c5fbaSopenharmony_ci} 391c87c5fbaSopenharmony_ci 392c87c5fbaSopenharmony_civoid 393c87c5fbaSopenharmony_cicoap_session_set_non_receive_timeout(coap_session_t *session, 394c87c5fbaSopenharmony_ci coap_fixed_point_t value) { 395c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 396c87c5fbaSopenharmony_ci if (value.integer_part > 0 && value.fractional_part < 1000) 397c87c5fbaSopenharmony_ci session->non_receive_timeout = value; 398c87c5fbaSopenharmony_ci coap_log_debug("***%s: session non_receive_timeout set to %u.%03u\n", 399c87c5fbaSopenharmony_ci coap_session_str(session), 400c87c5fbaSopenharmony_ci session->non_receive_timeout.integer_part, 401c87c5fbaSopenharmony_ci session->non_receive_timeout.fractional_part); 402c87c5fbaSopenharmony_ci#else /* ! COAP_Q_BLOCK_SUPPORT */ 403c87c5fbaSopenharmony_ci (void)session; 404c87c5fbaSopenharmony_ci (void)value; 405c87c5fbaSopenharmony_ci#endif /* ! COAP_Q_BLOCK_SUPPORT */ 406c87c5fbaSopenharmony_ci} 407c87c5fbaSopenharmony_ci 408c87c5fbaSopenharmony_cicoap_fixed_point_t 409c87c5fbaSopenharmony_cicoap_session_get_ack_timeout(const coap_session_t *session) { 410c87c5fbaSopenharmony_ci return session->ack_timeout; 411c87c5fbaSopenharmony_ci} 412c87c5fbaSopenharmony_ci 413c87c5fbaSopenharmony_cicoap_fixed_point_t 414c87c5fbaSopenharmony_cicoap_session_get_ack_random_factor(const coap_session_t *session) { 415c87c5fbaSopenharmony_ci return session->ack_random_factor; 416c87c5fbaSopenharmony_ci} 417c87c5fbaSopenharmony_ci 418c87c5fbaSopenharmony_ciuint16_t 419c87c5fbaSopenharmony_cicoap_session_get_max_retransmit(const coap_session_t *session) { 420c87c5fbaSopenharmony_ci return session->max_retransmit; 421c87c5fbaSopenharmony_ci} 422c87c5fbaSopenharmony_ci 423c87c5fbaSopenharmony_ciuint16_t 424c87c5fbaSopenharmony_cicoap_session_get_nstart(const coap_session_t *session) { 425c87c5fbaSopenharmony_ci return session->nstart; 426c87c5fbaSopenharmony_ci} 427c87c5fbaSopenharmony_ci 428c87c5fbaSopenharmony_cicoap_fixed_point_t 429c87c5fbaSopenharmony_cicoap_session_get_default_leisure(const coap_session_t *session) { 430c87c5fbaSopenharmony_ci return session->default_leisure; 431c87c5fbaSopenharmony_ci} 432c87c5fbaSopenharmony_ci 433c87c5fbaSopenharmony_ciuint32_t 434c87c5fbaSopenharmony_cicoap_session_get_probing_rate(const coap_session_t *session) { 435c87c5fbaSopenharmony_ci return session->probing_rate; 436c87c5fbaSopenharmony_ci} 437c87c5fbaSopenharmony_ci 438c87c5fbaSopenharmony_ciuint16_t 439c87c5fbaSopenharmony_cicoap_session_get_max_payloads(const coap_session_t *session) { 440c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 441c87c5fbaSopenharmony_ci return session->max_payloads; 442c87c5fbaSopenharmony_ci#else /* ! COAP_Q_BLOCK_SUPPORT */ 443c87c5fbaSopenharmony_ci (void)session; 444c87c5fbaSopenharmony_ci return COAP_DEFAULT_MAX_PAYLOADS; 445c87c5fbaSopenharmony_ci#endif /* ! COAP_Q_BLOCK_SUPPORT */ 446c87c5fbaSopenharmony_ci} 447c87c5fbaSopenharmony_ci 448c87c5fbaSopenharmony_ciuint16_t 449c87c5fbaSopenharmony_cicoap_session_get_non_max_retransmit(const coap_session_t *session) { 450c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 451c87c5fbaSopenharmony_ci return session->non_max_retransmit; 452c87c5fbaSopenharmony_ci#else /* ! COAP_Q_BLOCK_SUPPORT */ 453c87c5fbaSopenharmony_ci (void)session; 454c87c5fbaSopenharmony_ci return COAP_DEFAULT_NON_MAX_RETRANSMIT; 455c87c5fbaSopenharmony_ci#endif /* ! COAP_Q_BLOCK_SUPPORT */ 456c87c5fbaSopenharmony_ci} 457c87c5fbaSopenharmony_ci 458c87c5fbaSopenharmony_cicoap_fixed_point_t 459c87c5fbaSopenharmony_cicoap_session_get_non_timeout(const coap_session_t *session) { 460c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 461c87c5fbaSopenharmony_ci return session->non_timeout; 462c87c5fbaSopenharmony_ci#else /* ! COAP_Q_BLOCK_SUPPORT */ 463c87c5fbaSopenharmony_ci (void)session; 464c87c5fbaSopenharmony_ci return COAP_DEFAULT_NON_TIMEOUT; 465c87c5fbaSopenharmony_ci#endif /* ! COAP_Q_BLOCK_SUPPORT */ 466c87c5fbaSopenharmony_ci} 467c87c5fbaSopenharmony_ci 468c87c5fbaSopenharmony_cicoap_fixed_point_t 469c87c5fbaSopenharmony_cicoap_session_get_non_receive_timeout(const coap_session_t *session) { 470c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 471c87c5fbaSopenharmony_ci return session->non_receive_timeout; 472c87c5fbaSopenharmony_ci#else /* ! COAP_Q_BLOCK_SUPPORT */ 473c87c5fbaSopenharmony_ci (void)session; 474c87c5fbaSopenharmony_ci return COAP_DEFAULT_NON_RECEIVE_TIMEOUT; 475c87c5fbaSopenharmony_ci#endif /* ! COAP_Q_BLOCK_SUPPORT */ 476c87c5fbaSopenharmony_ci} 477c87c5fbaSopenharmony_ci 478c87c5fbaSopenharmony_cicoap_session_t * 479c87c5fbaSopenharmony_cicoap_session_reference(coap_session_t *session) { 480c87c5fbaSopenharmony_ci ++session->ref; 481c87c5fbaSopenharmony_ci return session; 482c87c5fbaSopenharmony_ci} 483c87c5fbaSopenharmony_ci 484c87c5fbaSopenharmony_civoid 485c87c5fbaSopenharmony_cicoap_session_release(coap_session_t *session) { 486c87c5fbaSopenharmony_ci if (session) { 487c87c5fbaSopenharmony_ci#ifndef __COVERITY__ 488c87c5fbaSopenharmony_ci assert(session->ref > 0); 489c87c5fbaSopenharmony_ci if (session->ref > 0) 490c87c5fbaSopenharmony_ci --session->ref; 491c87c5fbaSopenharmony_ci if (session->ref == 0 && session->type == COAP_SESSION_TYPE_CLIENT) 492c87c5fbaSopenharmony_ci coap_session_free(session); 493c87c5fbaSopenharmony_ci#else /* __COVERITY__ */ 494c87c5fbaSopenharmony_ci /* Coverity scan is fooled by the reference counter leading to 495c87c5fbaSopenharmony_ci * false positives for USE_AFTER_FREE. */ 496c87c5fbaSopenharmony_ci --session->ref; 497c87c5fbaSopenharmony_ci __coverity_negative_sink__(session->ref); 498c87c5fbaSopenharmony_ci /* Indicate that resources are released properly. */ 499c87c5fbaSopenharmony_ci if (session->ref == 0 && session->type == COAP_SESSION_TYPE_CLIENT) { 500c87c5fbaSopenharmony_ci __coverity_free__(session); 501c87c5fbaSopenharmony_ci } 502c87c5fbaSopenharmony_ci#endif /* __COVERITY__ */ 503c87c5fbaSopenharmony_ci } 504c87c5fbaSopenharmony_ci} 505c87c5fbaSopenharmony_ci 506c87c5fbaSopenharmony_civoid 507c87c5fbaSopenharmony_cicoap_session_set_app_data(coap_session_t *session, void *app_data) { 508c87c5fbaSopenharmony_ci assert(session); 509c87c5fbaSopenharmony_ci session->app = app_data; 510c87c5fbaSopenharmony_ci} 511c87c5fbaSopenharmony_ci 512c87c5fbaSopenharmony_civoid * 513c87c5fbaSopenharmony_cicoap_session_get_app_data(const coap_session_t *session) { 514c87c5fbaSopenharmony_ci assert(session); 515c87c5fbaSopenharmony_ci return session->app; 516c87c5fbaSopenharmony_ci} 517c87c5fbaSopenharmony_ci 518c87c5fbaSopenharmony_cistatic coap_session_t * 519c87c5fbaSopenharmony_cicoap_make_session(coap_proto_t proto, coap_session_type_t type, 520c87c5fbaSopenharmony_ci const coap_addr_hash_t *addr_hash, 521c87c5fbaSopenharmony_ci const coap_address_t *local_addr, 522c87c5fbaSopenharmony_ci const coap_address_t *remote_addr, int ifindex, 523c87c5fbaSopenharmony_ci coap_context_t *context, coap_endpoint_t *endpoint) { 524c87c5fbaSopenharmony_ci coap_session_t *session = (coap_session_t *)coap_malloc_type(COAP_SESSION, 525c87c5fbaSopenharmony_ci sizeof(coap_session_t)); 526c87c5fbaSopenharmony_ci#if ! COAP_SERVER_SUPPORT 527c87c5fbaSopenharmony_ci (void)endpoint; 528c87c5fbaSopenharmony_ci#endif /* ! COAP_SERVER_SUPPORT */ 529c87c5fbaSopenharmony_ci if (!session) 530c87c5fbaSopenharmony_ci return NULL; 531c87c5fbaSopenharmony_ci memset(session, 0, sizeof(*session)); 532c87c5fbaSopenharmony_ci session->proto = proto; 533c87c5fbaSopenharmony_ci session->type = type; 534c87c5fbaSopenharmony_ci if (addr_hash) 535c87c5fbaSopenharmony_ci memcpy(&session->addr_hash, addr_hash, sizeof(session->addr_hash)); 536c87c5fbaSopenharmony_ci else 537c87c5fbaSopenharmony_ci memset(&session->addr_hash, 0, sizeof(session->addr_hash)); 538c87c5fbaSopenharmony_ci if (local_addr) 539c87c5fbaSopenharmony_ci coap_address_copy(&session->addr_info.local, local_addr); 540c87c5fbaSopenharmony_ci else 541c87c5fbaSopenharmony_ci coap_address_init(&session->addr_info.local); 542c87c5fbaSopenharmony_ci if (remote_addr) 543c87c5fbaSopenharmony_ci coap_address_copy(&session->addr_info.remote, remote_addr); 544c87c5fbaSopenharmony_ci else 545c87c5fbaSopenharmony_ci coap_address_init(&session->addr_info.remote); 546c87c5fbaSopenharmony_ci session->ifindex = ifindex; 547c87c5fbaSopenharmony_ci session->context = context; 548c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 549c87c5fbaSopenharmony_ci session->endpoint = endpoint; 550c87c5fbaSopenharmony_ci if (endpoint) 551c87c5fbaSopenharmony_ci session->mtu = endpoint->default_mtu; 552c87c5fbaSopenharmony_ci else 553c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 554c87c5fbaSopenharmony_ci session->mtu = COAP_DEFAULT_MTU; 555c87c5fbaSopenharmony_ci session->block_mode = context->block_mode; 556c87c5fbaSopenharmony_ci if (proto == COAP_PROTO_DTLS) { 557c87c5fbaSopenharmony_ci session->tls_overhead = 29; 558c87c5fbaSopenharmony_ci if (session->tls_overhead >= session->mtu) { 559c87c5fbaSopenharmony_ci session->tls_overhead = session->mtu; 560c87c5fbaSopenharmony_ci coap_log_err("DTLS overhead exceeds MTU\n"); 561c87c5fbaSopenharmony_ci } 562c87c5fbaSopenharmony_ci } 563c87c5fbaSopenharmony_ci session->ack_timeout = COAP_DEFAULT_ACK_TIMEOUT; 564c87c5fbaSopenharmony_ci session->ack_random_factor = COAP_DEFAULT_ACK_RANDOM_FACTOR; 565c87c5fbaSopenharmony_ci session->max_retransmit = COAP_DEFAULT_MAX_RETRANSMIT; 566c87c5fbaSopenharmony_ci session->nstart = COAP_DEFAULT_NSTART; 567c87c5fbaSopenharmony_ci session->default_leisure = COAP_DEFAULT_DEFAULT_LEISURE; 568c87c5fbaSopenharmony_ci session->probing_rate = COAP_DEFAULT_PROBING_RATE; 569c87c5fbaSopenharmony_ci#if COAP_Q_BLOCK_SUPPORT 570c87c5fbaSopenharmony_ci session->max_payloads = COAP_DEFAULT_MAX_PAYLOADS; 571c87c5fbaSopenharmony_ci session->non_max_retransmit = COAP_DEFAULT_NON_MAX_RETRANSMIT; 572c87c5fbaSopenharmony_ci session->non_timeout = COAP_DEFAULT_NON_TIMEOUT; 573c87c5fbaSopenharmony_ci session->non_receive_timeout = COAP_DEFAULT_NON_RECEIVE_TIMEOUT; 574c87c5fbaSopenharmony_ci coap_session_fix_non_probing_wait_base(session); 575c87c5fbaSopenharmony_ci coap_session_fix_non_partial_timeout(session); 576c87c5fbaSopenharmony_ci#endif /* COAP_Q_BLOCK_SUPPORT */ 577c87c5fbaSopenharmony_ci session->dtls_event = -1; 578c87c5fbaSopenharmony_ci session->last_ping_mid = COAP_INVALID_MID; 579c87c5fbaSopenharmony_ci session->last_ack_mid = COAP_INVALID_MID; 580c87c5fbaSopenharmony_ci session->last_con_mid = COAP_INVALID_MID; 581c87c5fbaSopenharmony_ci session->max_token_size = context->max_token_size; /* RFC8974 */ 582c87c5fbaSopenharmony_ci if (session->type != COAP_SESSION_TYPE_CLIENT) 583c87c5fbaSopenharmony_ci session->max_token_checked = COAP_EXT_T_CHECKED; 584c87c5fbaSopenharmony_ci 585c87c5fbaSopenharmony_ci /* Randomly initialize */ 586c87c5fbaSopenharmony_ci /* TCP/TLS have no notion of mid */ 587c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(session->proto)) 588c87c5fbaSopenharmony_ci coap_prng((unsigned char *)&session->tx_mid, sizeof(session->tx_mid)); 589c87c5fbaSopenharmony_ci coap_prng((unsigned char *)&session->tx_rtag, sizeof(session->tx_rtag)); 590c87c5fbaSopenharmony_ci 591c87c5fbaSopenharmony_ci return session; 592c87c5fbaSopenharmony_ci} 593c87c5fbaSopenharmony_ci 594c87c5fbaSopenharmony_civoid 595c87c5fbaSopenharmony_cicoap_session_mfree(coap_session_t *session) { 596c87c5fbaSopenharmony_ci coap_queue_t *q, *tmp; 597c87c5fbaSopenharmony_ci coap_lg_xmit_t *lq, *ltmp; 598c87c5fbaSopenharmony_ci 599c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 600c87c5fbaSopenharmony_ci coap_lg_crcv_t *lg_crcv, *etmp; 601c87c5fbaSopenharmony_ci 602c87c5fbaSopenharmony_ci /* Need to do this before (D)TLS and socket is closed down */ 603c87c5fbaSopenharmony_ci LL_FOREACH_SAFE(session->lg_crcv, lg_crcv, etmp) { 604c87c5fbaSopenharmony_ci if (lg_crcv->observe_set && session->no_observe_cancel == 0) { 605c87c5fbaSopenharmony_ci /* Need to close down observe */ 606c87c5fbaSopenharmony_ci if (coap_cancel_observe(session, lg_crcv->app_token, COAP_MESSAGE_NON)) { 607c87c5fbaSopenharmony_ci /* Need to delete node we set up for NON */ 608c87c5fbaSopenharmony_ci coap_queue_t *queue = session->context->sendqueue; 609c87c5fbaSopenharmony_ci 610c87c5fbaSopenharmony_ci while (queue) { 611c87c5fbaSopenharmony_ci if (queue->session == session) { 612c87c5fbaSopenharmony_ci coap_delete_node(queue); 613c87c5fbaSopenharmony_ci break; 614c87c5fbaSopenharmony_ci } 615c87c5fbaSopenharmony_ci queue = queue->next; 616c87c5fbaSopenharmony_ci } 617c87c5fbaSopenharmony_ci } 618c87c5fbaSopenharmony_ci } 619c87c5fbaSopenharmony_ci LL_DELETE(session->lg_crcv, lg_crcv); 620c87c5fbaSopenharmony_ci coap_block_delete_lg_crcv(session, lg_crcv); 621c87c5fbaSopenharmony_ci } 622c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 623c87c5fbaSopenharmony_ci 624c87c5fbaSopenharmony_ci if (session->partial_pdu) 625c87c5fbaSopenharmony_ci coap_delete_pdu(session->partial_pdu); 626c87c5fbaSopenharmony_ci session->sock.lfunc[COAP_LAYER_SESSION].l_close(session); 627c87c5fbaSopenharmony_ci if (session->psk_identity) 628c87c5fbaSopenharmony_ci coap_delete_bin_const(session->psk_identity); 629c87c5fbaSopenharmony_ci if (session->psk_key) 630c87c5fbaSopenharmony_ci coap_delete_bin_const(session->psk_key); 631c87c5fbaSopenharmony_ci if (session->psk_hint) 632c87c5fbaSopenharmony_ci coap_delete_bin_const(session->psk_hint); 633c87c5fbaSopenharmony_ci 634c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 635c87c5fbaSopenharmony_ci coap_cache_entry_t *cp, *ctmp; 636c87c5fbaSopenharmony_ci HASH_ITER(hh, session->context->cache, cp, ctmp) { 637c87c5fbaSopenharmony_ci /* cp->session is NULL if not session based */ 638c87c5fbaSopenharmony_ci if (cp->session == session) { 639c87c5fbaSopenharmony_ci coap_delete_cache_entry(session->context, cp); 640c87c5fbaSopenharmony_ci } 641c87c5fbaSopenharmony_ci } 642c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 643c87c5fbaSopenharmony_ci LL_FOREACH_SAFE(session->delayqueue, q, tmp) { 644c87c5fbaSopenharmony_ci if (q->pdu->type==COAP_MESSAGE_CON && session->context && 645c87c5fbaSopenharmony_ci session->context->nack_handler) { 646c87c5fbaSopenharmony_ci coap_check_update_token(session, q->pdu); 647c87c5fbaSopenharmony_ci session->context->nack_handler(session, q->pdu, 648c87c5fbaSopenharmony_ci session->proto == COAP_PROTO_DTLS ? 649c87c5fbaSopenharmony_ci COAP_NACK_TLS_FAILED : COAP_NACK_NOT_DELIVERABLE, 650c87c5fbaSopenharmony_ci q->id); 651c87c5fbaSopenharmony_ci } 652c87c5fbaSopenharmony_ci coap_delete_node(q); 653c87c5fbaSopenharmony_ci } 654c87c5fbaSopenharmony_ci LL_FOREACH_SAFE(session->lg_xmit, lq, ltmp) { 655c87c5fbaSopenharmony_ci LL_DELETE(session->lg_xmit, lq); 656c87c5fbaSopenharmony_ci coap_block_delete_lg_xmit(session, lq); 657c87c5fbaSopenharmony_ci } 658c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 659c87c5fbaSopenharmony_ci coap_lg_srcv_t *sq, *stmp; 660c87c5fbaSopenharmony_ci 661c87c5fbaSopenharmony_ci LL_FOREACH_SAFE(session->lg_srcv, sq, stmp) { 662c87c5fbaSopenharmony_ci LL_DELETE(session->lg_srcv, sq); 663c87c5fbaSopenharmony_ci coap_block_delete_lg_srcv(session, sq); 664c87c5fbaSopenharmony_ci } 665c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 666c87c5fbaSopenharmony_ci#if COAP_OSCORE_SUPPORT 667c87c5fbaSopenharmony_ci coap_delete_oscore_associations(session); 668c87c5fbaSopenharmony_ci#endif /* COAP_OSCORE_SUPPORT */ 669c87c5fbaSopenharmony_ci#if COAP_WS_SUPPORT 670c87c5fbaSopenharmony_ci coap_free_type(COAP_STRING, session->ws); 671c87c5fbaSopenharmony_ci coap_delete_str_const(session->ws_host); 672c87c5fbaSopenharmony_ci#endif /* COAP_WS_SUPPORT */ 673c87c5fbaSopenharmony_ci} 674c87c5fbaSopenharmony_ci 675c87c5fbaSopenharmony_civoid 676c87c5fbaSopenharmony_cicoap_session_free(coap_session_t *session) { 677c87c5fbaSopenharmony_ci if (!session) 678c87c5fbaSopenharmony_ci return; 679c87c5fbaSopenharmony_ci assert(session->ref == 0); 680c87c5fbaSopenharmony_ci if (session->ref) 681c87c5fbaSopenharmony_ci return; 682c87c5fbaSopenharmony_ci /* Make sure nothing gets deleted under our feet */ 683c87c5fbaSopenharmony_ci coap_session_reference(session); 684c87c5fbaSopenharmony_ci coap_session_mfree(session); 685c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 686c87c5fbaSopenharmony_ci if (session->endpoint) { 687c87c5fbaSopenharmony_ci if (session->endpoint->sessions) 688c87c5fbaSopenharmony_ci SESSIONS_DELETE(session->endpoint->sessions, session); 689c87c5fbaSopenharmony_ci } else 690c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 691c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 692c87c5fbaSopenharmony_ci if (session->context) { 693c87c5fbaSopenharmony_ci if (session->context->sessions) 694c87c5fbaSopenharmony_ci SESSIONS_DELETE(session->context->sessions, session); 695c87c5fbaSopenharmony_ci } 696c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 697c87c5fbaSopenharmony_ci coap_delete_bin_const(session->last_token); 698c87c5fbaSopenharmony_ci coap_log_debug("***%s: session %p: closed\n", coap_session_str(session), 699c87c5fbaSopenharmony_ci (void *)session); 700c87c5fbaSopenharmony_ci 701c87c5fbaSopenharmony_ci assert(session->ref == 1); 702c87c5fbaSopenharmony_ci coap_free_type(COAP_SESSION, session); 703c87c5fbaSopenharmony_ci} 704c87c5fbaSopenharmony_ci 705c87c5fbaSopenharmony_cistatic size_t 706c87c5fbaSopenharmony_cicoap_session_max_pdu_size_internal(const coap_session_t *session, 707c87c5fbaSopenharmony_ci size_t max_with_header) { 708c87c5fbaSopenharmony_ci#if COAP_DISABLE_TCP 709c87c5fbaSopenharmony_ci (void)session; 710c87c5fbaSopenharmony_ci return max_with_header > 4 ? max_with_header - 4 : 0; 711c87c5fbaSopenharmony_ci#else /* !COAP_DISABLE_TCP */ 712c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(session->proto)) 713c87c5fbaSopenharmony_ci return max_with_header > 4 ? max_with_header - 4 : 0; 714c87c5fbaSopenharmony_ci /* we must assume there is no token to be on the safe side */ 715c87c5fbaSopenharmony_ci if (max_with_header <= 2) 716c87c5fbaSopenharmony_ci return 0; 717c87c5fbaSopenharmony_ci else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP0 + 2) 718c87c5fbaSopenharmony_ci return max_with_header - 2; 719c87c5fbaSopenharmony_ci else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP8 + 3) 720c87c5fbaSopenharmony_ci return max_with_header - 3; 721c87c5fbaSopenharmony_ci else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP16 + 4) 722c87c5fbaSopenharmony_ci return max_with_header - 4; 723c87c5fbaSopenharmony_ci else 724c87c5fbaSopenharmony_ci return max_with_header - 6; 725c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 726c87c5fbaSopenharmony_ci} 727c87c5fbaSopenharmony_ci 728c87c5fbaSopenharmony_cisize_t 729c87c5fbaSopenharmony_cicoap_session_max_pdu_rcv_size(const coap_session_t *session) { 730c87c5fbaSopenharmony_ci if (session->csm_rcv_mtu) 731c87c5fbaSopenharmony_ci return coap_session_max_pdu_size_internal(session, 732c87c5fbaSopenharmony_ci (size_t)(session->csm_rcv_mtu)); 733c87c5fbaSopenharmony_ci 734c87c5fbaSopenharmony_ci return coap_session_max_pdu_size_internal(session, 735c87c5fbaSopenharmony_ci (size_t)(session->mtu - session->tls_overhead)); 736c87c5fbaSopenharmony_ci} 737c87c5fbaSopenharmony_ci 738c87c5fbaSopenharmony_cisize_t 739c87c5fbaSopenharmony_cicoap_session_max_pdu_size(const coap_session_t *session) { 740c87c5fbaSopenharmony_ci size_t max_with_header; 741c87c5fbaSopenharmony_ci 742c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 743c87c5fbaSopenharmony_ci /* 744c87c5fbaSopenharmony_ci * Delay if session->doing_first is set. 745c87c5fbaSopenharmony_ci * E.g. Reliable and CSM not in yet for checking block support 746c87c5fbaSopenharmony_ci */ 747c87c5fbaSopenharmony_ci coap_session_t *session_rw; 748c87c5fbaSopenharmony_ci 749c87c5fbaSopenharmony_ci /* 750c87c5fbaSopenharmony_ci * Need to do this to not get a compiler warning about const parameters 751c87c5fbaSopenharmony_ci * but need to maintain source code backward compatibility 752c87c5fbaSopenharmony_ci */ 753c87c5fbaSopenharmony_ci memcpy(&session_rw, &session, sizeof(session_rw)); 754c87c5fbaSopenharmony_ci if (coap_client_delay_first(session_rw) == 0) { 755c87c5fbaSopenharmony_ci coap_log_debug("coap_client_delay_first: timeout\n"); 756c87c5fbaSopenharmony_ci /* Have to go with the defaults */ 757c87c5fbaSopenharmony_ci } 758c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 759c87c5fbaSopenharmony_ci 760c87c5fbaSopenharmony_ci max_with_header = (size_t)(session->mtu - session->tls_overhead); 761c87c5fbaSopenharmony_ci 762c87c5fbaSopenharmony_ci return coap_session_max_pdu_size_internal(session, max_with_header); 763c87c5fbaSopenharmony_ci} 764c87c5fbaSopenharmony_ci 765c87c5fbaSopenharmony_civoid 766c87c5fbaSopenharmony_cicoap_session_set_mtu(coap_session_t *session, unsigned mtu) { 767c87c5fbaSopenharmony_ci#if defined(WITH_CONTIKI) || defined(WITH_LWIP) 768c87c5fbaSopenharmony_ci if (mtu > COAP_DEFAULT_MAX_PDU_RX_SIZE) 769c87c5fbaSopenharmony_ci mtu = COAP_DEFAULT_MAX_PDU_RX_SIZE; 770c87c5fbaSopenharmony_ci#endif 771c87c5fbaSopenharmony_ci if (mtu < 64) 772c87c5fbaSopenharmony_ci mtu = 64; 773c87c5fbaSopenharmony_ci session->mtu = mtu; 774c87c5fbaSopenharmony_ci if (session->tls_overhead >= session->mtu) { 775c87c5fbaSopenharmony_ci session->tls_overhead = session->mtu; 776c87c5fbaSopenharmony_ci coap_log_err("DTLS overhead exceeds MTU\n"); 777c87c5fbaSopenharmony_ci } 778c87c5fbaSopenharmony_ci} 779c87c5fbaSopenharmony_ci 780c87c5fbaSopenharmony_cissize_t 781c87c5fbaSopenharmony_cicoap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, 782c87c5fbaSopenharmony_ci coap_queue_t *node) { 783c87c5fbaSopenharmony_ci if (node) { 784c87c5fbaSopenharmony_ci coap_queue_t *removed = NULL; 785c87c5fbaSopenharmony_ci coap_remove_from_queue(&session->context->sendqueue, session, node->id, &removed); 786c87c5fbaSopenharmony_ci assert(removed == node); 787c87c5fbaSopenharmony_ci coap_session_release(node->session); 788c87c5fbaSopenharmony_ci node->session = NULL; 789c87c5fbaSopenharmony_ci node->t = 0; 790c87c5fbaSopenharmony_ci } else { 791c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(session->proto)) { 792c87c5fbaSopenharmony_ci coap_queue_t *q = NULL; 793c87c5fbaSopenharmony_ci /* Check same mid is not getting re-used in violation of RFC7252 */ 794c87c5fbaSopenharmony_ci LL_FOREACH(session->delayqueue, q) { 795c87c5fbaSopenharmony_ci if (q->id == pdu->mid) { 796c87c5fbaSopenharmony_ci coap_log_err("** %s: mid=0x%04x: already in-use - dropped\n", 797c87c5fbaSopenharmony_ci coap_session_str(session), pdu->mid); 798c87c5fbaSopenharmony_ci return COAP_INVALID_MID; 799c87c5fbaSopenharmony_ci } 800c87c5fbaSopenharmony_ci } 801c87c5fbaSopenharmony_ci } 802c87c5fbaSopenharmony_ci node = coap_new_node(); 803c87c5fbaSopenharmony_ci if (node == NULL) 804c87c5fbaSopenharmony_ci return COAP_INVALID_MID; 805c87c5fbaSopenharmony_ci node->id = pdu->mid; 806c87c5fbaSopenharmony_ci node->pdu = pdu; 807c87c5fbaSopenharmony_ci if (pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) { 808c87c5fbaSopenharmony_ci uint8_t r; 809c87c5fbaSopenharmony_ci coap_prng(&r, sizeof(r)); 810c87c5fbaSopenharmony_ci /* add timeout in range [ACK_TIMEOUT...ACK_TIMEOUT * ACK_RANDOM_FACTOR] */ 811c87c5fbaSopenharmony_ci node->timeout = coap_calc_timeout(session, r); 812c87c5fbaSopenharmony_ci } 813c87c5fbaSopenharmony_ci } 814c87c5fbaSopenharmony_ci LL_APPEND(session->delayqueue, node); 815c87c5fbaSopenharmony_ci coap_log_debug("** %s: mid=0x%04x: delayed\n", 816c87c5fbaSopenharmony_ci coap_session_str(session), node->id); 817c87c5fbaSopenharmony_ci return COAP_PDU_DELAYED; 818c87c5fbaSopenharmony_ci} 819c87c5fbaSopenharmony_ci 820c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 821c87c5fbaSopenharmony_civoid 822c87c5fbaSopenharmony_cicoap_session_send_csm(coap_session_t *session) { 823c87c5fbaSopenharmony_ci coap_pdu_t *pdu; 824c87c5fbaSopenharmony_ci uint8_t buf[4]; 825c87c5fbaSopenharmony_ci assert(COAP_PROTO_RELIABLE(session->proto)); 826c87c5fbaSopenharmony_ci coap_log_debug("***%s: sending CSM\n", coap_session_str(session)); 827c87c5fbaSopenharmony_ci session->state = COAP_SESSION_STATE_CSM; 828c87c5fbaSopenharmony_ci session->partial_write = 0; 829c87c5fbaSopenharmony_ci if (session->mtu == 0) 830c87c5fbaSopenharmony_ci session->mtu = COAP_DEFAULT_MTU; /* base value */ 831c87c5fbaSopenharmony_ci pdu = coap_pdu_init(COAP_MESSAGE_CON, COAP_SIGNALING_CODE_CSM, 0, 20); 832c87c5fbaSopenharmony_ci if (pdu == NULL 833c87c5fbaSopenharmony_ci || coap_add_option_internal(pdu, COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE, 834c87c5fbaSopenharmony_ci coap_encode_var_safe(buf, sizeof(buf), 835c87c5fbaSopenharmony_ci session->context->csm_max_message_size), buf) == 0 836c87c5fbaSopenharmony_ci || coap_add_option_internal(pdu, COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER, 837c87c5fbaSopenharmony_ci coap_encode_var_safe(buf, sizeof(buf), 838c87c5fbaSopenharmony_ci 0), buf) == 0 839c87c5fbaSopenharmony_ci || (session->max_token_size > COAP_TOKEN_DEFAULT_MAX && 840c87c5fbaSopenharmony_ci coap_add_option_internal(pdu, 841c87c5fbaSopenharmony_ci COAP_SIGNALING_OPTION_EXTENDED_TOKEN_LENGTH, 842c87c5fbaSopenharmony_ci coap_encode_var_safe(buf, sizeof(buf), 843c87c5fbaSopenharmony_ci session->max_token_size), 844c87c5fbaSopenharmony_ci buf) == 0) 845c87c5fbaSopenharmony_ci || coap_pdu_encode_header(pdu, session->proto) == 0 846c87c5fbaSopenharmony_ci ) { 847c87c5fbaSopenharmony_ci coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); 848c87c5fbaSopenharmony_ci } else { 849c87c5fbaSopenharmony_ci ssize_t bytes_written; 850c87c5fbaSopenharmony_ci 851c87c5fbaSopenharmony_ci pdu->session = session; 852c87c5fbaSopenharmony_ci bytes_written = coap_session_send_pdu(session, pdu); 853c87c5fbaSopenharmony_ci if (bytes_written != (ssize_t)pdu->used_size + pdu->hdr_size) { 854c87c5fbaSopenharmony_ci coap_session_disconnected(session, COAP_NACK_NOT_DELIVERABLE); 855c87c5fbaSopenharmony_ci } else { 856c87c5fbaSopenharmony_ci session->csm_rcv_mtu = session->context->csm_max_message_size; 857c87c5fbaSopenharmony_ci if (session->csm_rcv_mtu > COAP_BERT_BASE) 858c87c5fbaSopenharmony_ci session->csm_bert_loc_support = 1; 859c87c5fbaSopenharmony_ci else 860c87c5fbaSopenharmony_ci session->csm_bert_loc_support = 0; 861c87c5fbaSopenharmony_ci } 862c87c5fbaSopenharmony_ci } 863c87c5fbaSopenharmony_ci if (pdu) 864c87c5fbaSopenharmony_ci coap_delete_pdu(pdu); 865c87c5fbaSopenharmony_ci} 866c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 867c87c5fbaSopenharmony_ci 868c87c5fbaSopenharmony_cicoap_mid_t 869c87c5fbaSopenharmony_cicoap_session_send_ping(coap_session_t *session) { 870c87c5fbaSopenharmony_ci coap_pdu_t *ping = NULL; 871c87c5fbaSopenharmony_ci 872c87c5fbaSopenharmony_ci if (session->state != COAP_SESSION_STATE_ESTABLISHED || 873c87c5fbaSopenharmony_ci session->con_active) 874c87c5fbaSopenharmony_ci return COAP_INVALID_MID; 875c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(session->proto)) { 876c87c5fbaSopenharmony_ci uint16_t mid = coap_new_message_id(session); 877c87c5fbaSopenharmony_ci ping = coap_pdu_init(COAP_MESSAGE_CON, 0, mid, 0); 878c87c5fbaSopenharmony_ci } 879c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 880c87c5fbaSopenharmony_ci else { 881c87c5fbaSopenharmony_ci ping = coap_pdu_init(COAP_MESSAGE_CON, COAP_SIGNALING_CODE_PING, 0, 1); 882c87c5fbaSopenharmony_ci } 883c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 884c87c5fbaSopenharmony_ci if (!ping) 885c87c5fbaSopenharmony_ci return COAP_INVALID_MID; 886c87c5fbaSopenharmony_ci return coap_send_internal(session, ping); 887c87c5fbaSopenharmony_ci} 888c87c5fbaSopenharmony_ci 889c87c5fbaSopenharmony_civoid 890c87c5fbaSopenharmony_cicoap_session_connected(coap_session_t *session) { 891c87c5fbaSopenharmony_ci if (session->state != COAP_SESSION_STATE_ESTABLISHED) { 892c87c5fbaSopenharmony_ci coap_log_debug("***%s: session connected\n", 893c87c5fbaSopenharmony_ci coap_session_str(session)); 894c87c5fbaSopenharmony_ci if (session->state == COAP_SESSION_STATE_CSM) { 895c87c5fbaSopenharmony_ci coap_handle_event(session->context, COAP_EVENT_SESSION_CONNECTED, session); 896c87c5fbaSopenharmony_ci if (session->doing_first) 897c87c5fbaSopenharmony_ci session->doing_first = 0; 898c87c5fbaSopenharmony_ci } 899c87c5fbaSopenharmony_ci } 900c87c5fbaSopenharmony_ci 901c87c5fbaSopenharmony_ci session->state = COAP_SESSION_STATE_ESTABLISHED; 902c87c5fbaSopenharmony_ci session->partial_write = 0; 903c87c5fbaSopenharmony_ci 904c87c5fbaSopenharmony_ci if (session->proto==COAP_PROTO_DTLS) { 905c87c5fbaSopenharmony_ci session->tls_overhead = coap_dtls_get_overhead(session); 906c87c5fbaSopenharmony_ci if (session->tls_overhead >= session->mtu) { 907c87c5fbaSopenharmony_ci session->tls_overhead = session->mtu; 908c87c5fbaSopenharmony_ci coap_log_err("DTLS overhead exceeds MTU\n"); 909c87c5fbaSopenharmony_ci } 910c87c5fbaSopenharmony_ci } 911c87c5fbaSopenharmony_ci 912c87c5fbaSopenharmony_ci while (session->delayqueue && session->state == COAP_SESSION_STATE_ESTABLISHED) { 913c87c5fbaSopenharmony_ci ssize_t bytes_written; 914c87c5fbaSopenharmony_ci coap_queue_t *q = session->delayqueue; 915c87c5fbaSopenharmony_ci if (q->pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) { 916c87c5fbaSopenharmony_ci if (session->con_active >= COAP_NSTART(session)) 917c87c5fbaSopenharmony_ci break; 918c87c5fbaSopenharmony_ci session->con_active++; 919c87c5fbaSopenharmony_ci } 920c87c5fbaSopenharmony_ci /* Take entry off the queue */ 921c87c5fbaSopenharmony_ci session->delayqueue = q->next; 922c87c5fbaSopenharmony_ci q->next = NULL; 923c87c5fbaSopenharmony_ci 924c87c5fbaSopenharmony_ci coap_log_debug("** %s: mid=0x%04x: transmitted after delay\n", 925c87c5fbaSopenharmony_ci coap_session_str(session), (int)q->pdu->mid); 926c87c5fbaSopenharmony_ci bytes_written = coap_session_send_pdu(session, q->pdu); 927c87c5fbaSopenharmony_ci if (q->pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) { 928c87c5fbaSopenharmony_ci if (coap_wait_ack(session->context, session, q) >= 0) 929c87c5fbaSopenharmony_ci q = NULL; 930c87c5fbaSopenharmony_ci } 931c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(session->proto)) { 932c87c5fbaSopenharmony_ci if (q) 933c87c5fbaSopenharmony_ci coap_delete_node(q); 934c87c5fbaSopenharmony_ci if (bytes_written < 0) 935c87c5fbaSopenharmony_ci break; 936c87c5fbaSopenharmony_ci } else { 937c87c5fbaSopenharmony_ci if (bytes_written <= 0 || (size_t)bytes_written < q->pdu->used_size + q->pdu->hdr_size) { 938c87c5fbaSopenharmony_ci q->next = session->delayqueue; 939c87c5fbaSopenharmony_ci session->delayqueue = q; 940c87c5fbaSopenharmony_ci if (bytes_written > 0) 941c87c5fbaSopenharmony_ci session->partial_write = (size_t)bytes_written; 942c87c5fbaSopenharmony_ci break; 943c87c5fbaSopenharmony_ci } else { 944c87c5fbaSopenharmony_ci coap_delete_node(q); 945c87c5fbaSopenharmony_ci } 946c87c5fbaSopenharmony_ci } 947c87c5fbaSopenharmony_ci } 948c87c5fbaSopenharmony_ci} 949c87c5fbaSopenharmony_ci 950c87c5fbaSopenharmony_ci#if COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_DEBUG 951c87c5fbaSopenharmony_cistatic const char * 952c87c5fbaSopenharmony_cicoap_nack_name(coap_nack_reason_t reason) { 953c87c5fbaSopenharmony_ci switch (reason) { 954c87c5fbaSopenharmony_ci case COAP_NACK_TOO_MANY_RETRIES: 955c87c5fbaSopenharmony_ci return "COAP_NACK_TOO_MANY_RETRIES"; 956c87c5fbaSopenharmony_ci case COAP_NACK_NOT_DELIVERABLE: 957c87c5fbaSopenharmony_ci return "COAP_NACK_NOT_DELIVERABLE"; 958c87c5fbaSopenharmony_ci case COAP_NACK_RST: 959c87c5fbaSopenharmony_ci return "COAP_NACK_RST"; 960c87c5fbaSopenharmony_ci case COAP_NACK_TLS_FAILED: 961c87c5fbaSopenharmony_ci return "COAP_NACK_TLS_FAILED"; 962c87c5fbaSopenharmony_ci case COAP_NACK_ICMP_ISSUE: 963c87c5fbaSopenharmony_ci return "COAP_NACK_ICMP_ISSUE"; 964c87c5fbaSopenharmony_ci case COAP_NACK_BAD_RESPONSE: 965c87c5fbaSopenharmony_ci return "COAP_NACK_BAD_RESPONSE"; 966c87c5fbaSopenharmony_ci case COAP_NACK_TLS_LAYER_FAILED: 967c87c5fbaSopenharmony_ci return "COAP_NACK_TLS_LAYER_FAILED"; 968c87c5fbaSopenharmony_ci case COAP_NACK_WS_LAYER_FAILED: 969c87c5fbaSopenharmony_ci return "COAP_NACK_WS_LAYER_FAILED"; 970c87c5fbaSopenharmony_ci case COAP_NACK_WS_FAILED: 971c87c5fbaSopenharmony_ci return "COAP_NACK_WS_FAILED"; 972c87c5fbaSopenharmony_ci default: 973c87c5fbaSopenharmony_ci return "???"; 974c87c5fbaSopenharmony_ci } 975c87c5fbaSopenharmony_ci} 976c87c5fbaSopenharmony_ci#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_DEBUG */ 977c87c5fbaSopenharmony_ci 978c87c5fbaSopenharmony_civoid 979c87c5fbaSopenharmony_cicoap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason) { 980c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 981c87c5fbaSopenharmony_ci coap_session_state_t state = session->state; 982c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 983c87c5fbaSopenharmony_ci coap_lg_xmit_t *lq, *ltmp; 984c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 985c87c5fbaSopenharmony_ci coap_lg_srcv_t *sq, *stmp; 986c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 987c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 988c87c5fbaSopenharmony_ci coap_lg_crcv_t *cq, *etmp; 989c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 990c87c5fbaSopenharmony_ci 991c87c5fbaSopenharmony_ci if (reason == COAP_NACK_ICMP_ISSUE) { 992c87c5fbaSopenharmony_ci if (session->context->nack_handler) { 993c87c5fbaSopenharmony_ci int sent_nack = 0; 994c87c5fbaSopenharmony_ci coap_queue_t *q = session->context->sendqueue; 995c87c5fbaSopenharmony_ci while (q) { 996c87c5fbaSopenharmony_ci if (q->session == session) { 997c87c5fbaSopenharmony_ci /* Take the first one */ 998c87c5fbaSopenharmony_ci coap_bin_const_t token = q->pdu->actual_token; 999c87c5fbaSopenharmony_ci 1000c87c5fbaSopenharmony_ci coap_check_update_token(session, q->pdu); 1001c87c5fbaSopenharmony_ci session->context->nack_handler(session, q->pdu, reason, q->id); 1002c87c5fbaSopenharmony_ci coap_update_token(q->pdu, token.length, token.s); 1003c87c5fbaSopenharmony_ci sent_nack = 1; 1004c87c5fbaSopenharmony_ci break; 1005c87c5fbaSopenharmony_ci } 1006c87c5fbaSopenharmony_ci q = q->next; 1007c87c5fbaSopenharmony_ci } 1008c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1009c87c5fbaSopenharmony_ci if (!sent_nack && session->lg_crcv) { 1010c87c5fbaSopenharmony_ci /* Take the first one */ 1011c87c5fbaSopenharmony_ci session->context->nack_handler(session, &session->lg_crcv->pdu, reason, 1012c87c5fbaSopenharmony_ci session->lg_crcv->pdu.mid); 1013c87c5fbaSopenharmony_ci sent_nack = 1; 1014c87c5fbaSopenharmony_ci } 1015c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 1016c87c5fbaSopenharmony_ci if (!sent_nack) { 1017c87c5fbaSopenharmony_ci /* Unable to determine which request ICMP issue was for */ 1018c87c5fbaSopenharmony_ci session->context->nack_handler(session, NULL, reason, 0); 1019c87c5fbaSopenharmony_ci } 1020c87c5fbaSopenharmony_ci } 1021c87c5fbaSopenharmony_ci coap_log_debug("***%s: session issue (%s)\n", 1022c87c5fbaSopenharmony_ci coap_session_str(session), coap_nack_name(reason)); 1023c87c5fbaSopenharmony_ci return; 1024c87c5fbaSopenharmony_ci } 1025c87c5fbaSopenharmony_ci coap_log_debug("***%s: session disconnected (%s)\n", 1026c87c5fbaSopenharmony_ci coap_session_str(session), coap_nack_name(reason)); 1027c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1028c87c5fbaSopenharmony_ci coap_delete_observers(session->context, session); 1029c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1030c87c5fbaSopenharmony_ci 1031c87c5fbaSopenharmony_ci if (session->proto == COAP_PROTO_UDP) 1032c87c5fbaSopenharmony_ci session->state = COAP_SESSION_STATE_ESTABLISHED; 1033c87c5fbaSopenharmony_ci else 1034c87c5fbaSopenharmony_ci session->state = COAP_SESSION_STATE_NONE; 1035c87c5fbaSopenharmony_ci 1036c87c5fbaSopenharmony_ci session->con_active = 0; 1037c87c5fbaSopenharmony_ci 1038c87c5fbaSopenharmony_ci if (session->partial_pdu) { 1039c87c5fbaSopenharmony_ci coap_delete_pdu(session->partial_pdu); 1040c87c5fbaSopenharmony_ci session->partial_pdu = NULL; 1041c87c5fbaSopenharmony_ci } 1042c87c5fbaSopenharmony_ci session->partial_read = 0; 1043c87c5fbaSopenharmony_ci 1044c87c5fbaSopenharmony_ci while (session->delayqueue) { 1045c87c5fbaSopenharmony_ci coap_queue_t *q = session->delayqueue; 1046c87c5fbaSopenharmony_ci session->delayqueue = q->next; 1047c87c5fbaSopenharmony_ci q->next = NULL; 1048c87c5fbaSopenharmony_ci coap_log_debug("** %s: mid=0x%04x: not transmitted after disconnect\n", 1049c87c5fbaSopenharmony_ci coap_session_str(session), q->id); 1050c87c5fbaSopenharmony_ci if (q && q->pdu->type == COAP_MESSAGE_CON 1051c87c5fbaSopenharmony_ci && session->context->nack_handler) { 1052c87c5fbaSopenharmony_ci coap_check_update_token(session, q->pdu); 1053c87c5fbaSopenharmony_ci session->context->nack_handler(session, q->pdu, reason, q->id); 1054c87c5fbaSopenharmony_ci } 1055c87c5fbaSopenharmony_ci if (q) 1056c87c5fbaSopenharmony_ci coap_delete_node(q); 1057c87c5fbaSopenharmony_ci } 1058c87c5fbaSopenharmony_ci 1059c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1060c87c5fbaSopenharmony_ci /* Need to do this before (D)TLS and socket is closed down */ 1061c87c5fbaSopenharmony_ci LL_FOREACH_SAFE(session->lg_crcv, cq, etmp) { 1062c87c5fbaSopenharmony_ci LL_DELETE(session->lg_crcv, cq); 1063c87c5fbaSopenharmony_ci coap_block_delete_lg_crcv(session, cq); 1064c87c5fbaSopenharmony_ci } 1065c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 1066c87c5fbaSopenharmony_ci LL_FOREACH_SAFE(session->lg_xmit, lq, ltmp) { 1067c87c5fbaSopenharmony_ci LL_DELETE(session->lg_xmit, lq); 1068c87c5fbaSopenharmony_ci coap_block_delete_lg_xmit(session, lq); 1069c87c5fbaSopenharmony_ci } 1070c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1071c87c5fbaSopenharmony_ci LL_FOREACH_SAFE(session->lg_srcv, sq, stmp) { 1072c87c5fbaSopenharmony_ci LL_DELETE(session->lg_srcv, sq); 1073c87c5fbaSopenharmony_ci coap_block_delete_lg_srcv(session, sq); 1074c87c5fbaSopenharmony_ci } 1075c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1076c87c5fbaSopenharmony_ci coap_cancel_session_messages(session->context, session, reason); 1077c87c5fbaSopenharmony_ci 1078c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1079c87c5fbaSopenharmony_ci if (COAP_PROTO_RELIABLE(session->proto)) { 1080c87c5fbaSopenharmony_ci if (coap_netif_available(session)) { 1081c87c5fbaSopenharmony_ci coap_handle_event(session->context, 1082c87c5fbaSopenharmony_ci state == COAP_SESSION_STATE_CONNECTING ? 1083c87c5fbaSopenharmony_ci COAP_EVENT_TCP_FAILED : COAP_EVENT_TCP_CLOSED, session); 1084c87c5fbaSopenharmony_ci } 1085c87c5fbaSopenharmony_ci if (state != COAP_SESSION_STATE_NONE) { 1086c87c5fbaSopenharmony_ci coap_handle_event(session->context, 1087c87c5fbaSopenharmony_ci state == COAP_SESSION_STATE_ESTABLISHED ? 1088c87c5fbaSopenharmony_ci COAP_EVENT_SESSION_CLOSED : COAP_EVENT_SESSION_FAILED, session); 1089c87c5fbaSopenharmony_ci } 1090c87c5fbaSopenharmony_ci if (session->doing_first) 1091c87c5fbaSopenharmony_ci session->doing_first = 0; 1092c87c5fbaSopenharmony_ci } 1093c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1094c87c5fbaSopenharmony_ci session->sock.lfunc[COAP_LAYER_SESSION].l_close(session); 1095c87c5fbaSopenharmony_ci} 1096c87c5fbaSopenharmony_ci 1097c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1098c87c5fbaSopenharmony_cistatic void 1099c87c5fbaSopenharmony_cicoap_make_addr_hash(coap_addr_hash_t *addr_hash, coap_proto_t proto, 1100c87c5fbaSopenharmony_ci const coap_addr_tuple_t *addr_info) { 1101c87c5fbaSopenharmony_ci memset(addr_hash, 0, sizeof(coap_addr_hash_t)); 1102c87c5fbaSopenharmony_ci coap_address_copy(&addr_hash->remote, &addr_info->remote); 1103c87c5fbaSopenharmony_ci addr_hash->lport = coap_address_get_port(&addr_info->local); 1104c87c5fbaSopenharmony_ci addr_hash->proto = proto; 1105c87c5fbaSopenharmony_ci} 1106c87c5fbaSopenharmony_ci 1107c87c5fbaSopenharmony_cicoap_session_t * 1108c87c5fbaSopenharmony_cicoap_endpoint_get_session(coap_endpoint_t *endpoint, 1109c87c5fbaSopenharmony_ci const coap_packet_t *packet, coap_tick_t now) { 1110c87c5fbaSopenharmony_ci coap_session_t *session; 1111c87c5fbaSopenharmony_ci coap_session_t *rtmp; 1112c87c5fbaSopenharmony_ci unsigned int num_idle = 0; 1113c87c5fbaSopenharmony_ci unsigned int num_hs = 0; 1114c87c5fbaSopenharmony_ci coap_session_t *oldest = NULL; 1115c87c5fbaSopenharmony_ci coap_session_t *oldest_hs = NULL; 1116c87c5fbaSopenharmony_ci coap_addr_hash_t addr_hash; 1117c87c5fbaSopenharmony_ci#ifdef COAP_SUPPORT_SOCKET_BROADCAST 1118c87c5fbaSopenharmony_ci if (is_loopback_packet(packet) == 1) { 1119c87c5fbaSopenharmony_ci coap_log_debug("coap_endpoint_get_session: drop loopback packet"); 1120c87c5fbaSopenharmony_ci return NULL; 1121c87c5fbaSopenharmony_ci } 1122c87c5fbaSopenharmony_ci#endif 1123c87c5fbaSopenharmony_ci coap_make_addr_hash(&addr_hash, endpoint->proto, &packet->addr_info); 1124c87c5fbaSopenharmony_ci SESSIONS_FIND(endpoint->sessions, addr_hash, session); 1125c87c5fbaSopenharmony_ci if (session) { 1126c87c5fbaSopenharmony_ci /* Maybe mcast or unicast IP address which is not in the hash */ 1127c87c5fbaSopenharmony_ci coap_address_copy(&session->addr_info.local, &packet->addr_info.local); 1128c87c5fbaSopenharmony_ci session->ifindex = packet->ifindex; 1129c87c5fbaSopenharmony_ci session->last_rx_tx = now; 1130c87c5fbaSopenharmony_ci return session; 1131c87c5fbaSopenharmony_ci } 1132c87c5fbaSopenharmony_ci 1133c87c5fbaSopenharmony_ci SESSIONS_ITER(endpoint->sessions, session, rtmp) { 1134c87c5fbaSopenharmony_ci if (session->ref == 0 && session->delayqueue == NULL) { 1135c87c5fbaSopenharmony_ci if (session->type == COAP_SESSION_TYPE_SERVER) { 1136c87c5fbaSopenharmony_ci ++num_idle; 1137c87c5fbaSopenharmony_ci if (oldest==NULL || session->last_rx_tx < oldest->last_rx_tx) 1138c87c5fbaSopenharmony_ci oldest = session; 1139c87c5fbaSopenharmony_ci 1140c87c5fbaSopenharmony_ci if (session->state == COAP_SESSION_STATE_HANDSHAKE) { 1141c87c5fbaSopenharmony_ci ++num_hs; 1142c87c5fbaSopenharmony_ci /* See if this is a partial (D)TLS session set up 1143c87c5fbaSopenharmony_ci which needs to be cleared down to prevent DOS */ 1144c87c5fbaSopenharmony_ci if ((session->last_rx_tx + COAP_PARTIAL_SESSION_TIMEOUT_TICKS) < now) { 1145c87c5fbaSopenharmony_ci if (oldest_hs == NULL || 1146c87c5fbaSopenharmony_ci session->last_rx_tx < oldest_hs->last_rx_tx) 1147c87c5fbaSopenharmony_ci oldest_hs = session; 1148c87c5fbaSopenharmony_ci } 1149c87c5fbaSopenharmony_ci } 1150c87c5fbaSopenharmony_ci } else if (session->type == COAP_SESSION_TYPE_HELLO) { 1151c87c5fbaSopenharmony_ci ++num_hs; 1152c87c5fbaSopenharmony_ci /* See if this is a partial (D)TLS session set up for Client Hello 1153c87c5fbaSopenharmony_ci which needs to be cleared down to prevent DOS */ 1154c87c5fbaSopenharmony_ci if ((session->last_rx_tx + COAP_PARTIAL_SESSION_TIMEOUT_TICKS) < now) { 1155c87c5fbaSopenharmony_ci if (oldest_hs == NULL || 1156c87c5fbaSopenharmony_ci session->last_rx_tx < oldest_hs->last_rx_tx) 1157c87c5fbaSopenharmony_ci oldest_hs = session; 1158c87c5fbaSopenharmony_ci } 1159c87c5fbaSopenharmony_ci } 1160c87c5fbaSopenharmony_ci } 1161c87c5fbaSopenharmony_ci } 1162c87c5fbaSopenharmony_ci 1163c87c5fbaSopenharmony_ci if (endpoint->context->max_idle_sessions > 0 && 1164c87c5fbaSopenharmony_ci num_idle >= endpoint->context->max_idle_sessions) { 1165c87c5fbaSopenharmony_ci coap_handle_event(oldest->context, COAP_EVENT_SERVER_SESSION_DEL, oldest); 1166c87c5fbaSopenharmony_ci coap_session_free(oldest); 1167c87c5fbaSopenharmony_ci } else if (oldest_hs) { 1168c87c5fbaSopenharmony_ci coap_log_warn("***%s: Incomplete session timed out\n", 1169c87c5fbaSopenharmony_ci coap_session_str(oldest_hs)); 1170c87c5fbaSopenharmony_ci coap_handle_event(oldest_hs->context, COAP_EVENT_SERVER_SESSION_DEL, oldest_hs); 1171c87c5fbaSopenharmony_ci coap_session_free(oldest_hs); 1172c87c5fbaSopenharmony_ci } 1173c87c5fbaSopenharmony_ci 1174c87c5fbaSopenharmony_ci if (num_hs > (endpoint->context->max_handshake_sessions ? 1175c87c5fbaSopenharmony_ci endpoint->context->max_handshake_sessions : 1176c87c5fbaSopenharmony_ci COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS)) { 1177c87c5fbaSopenharmony_ci /* Maxed out on number of sessions in (D)TLS negotiation state */ 1178c87c5fbaSopenharmony_ci coap_log_debug("Oustanding sessions in COAP_SESSION_STATE_HANDSHAKE too " 1179c87c5fbaSopenharmony_ci "large. New request ignored\n"); 1180c87c5fbaSopenharmony_ci return NULL; 1181c87c5fbaSopenharmony_ci } 1182c87c5fbaSopenharmony_ci 1183c87c5fbaSopenharmony_ci if (endpoint->proto == COAP_PROTO_DTLS) { 1184c87c5fbaSopenharmony_ci /* 1185c87c5fbaSopenharmony_ci * Need to check that this actually is a Client Hello before wasting 1186c87c5fbaSopenharmony_ci * time allocating and then freeing off session. 1187c87c5fbaSopenharmony_ci */ 1188c87c5fbaSopenharmony_ci 1189c87c5fbaSopenharmony_ci /* 1190c87c5fbaSopenharmony_ci * Generic header structure of the DTLS record layer. 1191c87c5fbaSopenharmony_ci * typedef struct __attribute__((__packed__)) { 1192c87c5fbaSopenharmony_ci * uint8_t content_type; content type of the included message 1193c87c5fbaSopenharmony_ci * uint16_t version; Protocol version 1194c87c5fbaSopenharmony_ci * uint16_t epoch; counter for cipher state changes 1195c87c5fbaSopenharmony_ci * uint8_t sequence_number[6]; sequence number 1196c87c5fbaSopenharmony_ci * uint16_t length; length of the following fragment 1197c87c5fbaSopenharmony_ci * uint8_t handshake; If content_type == DTLS_CT_HANDSHAKE 1198c87c5fbaSopenharmony_ci * } dtls_record_handshake_t; 1199c87c5fbaSopenharmony_ci */ 1200c87c5fbaSopenharmony_ci#define OFF_CONTENT_TYPE 0 /* offset of content_type in dtls_record_handshake_t */ 1201c87c5fbaSopenharmony_ci#define DTLS_CT_ALERT 21 /* Content Type Alert */ 1202c87c5fbaSopenharmony_ci#define DTLS_CT_HANDSHAKE 22 /* Content Type Handshake */ 1203c87c5fbaSopenharmony_ci#define OFF_HANDSHAKE_TYPE 13 /* offset of handshake in dtls_record_handshake_t */ 1204c87c5fbaSopenharmony_ci#define DTLS_HT_CLIENT_HELLO 1 /* Client Hello handshake type */ 1205c87c5fbaSopenharmony_ci 1206c87c5fbaSopenharmony_ci const uint8_t *payload = (const uint8_t *)packet->payload; 1207c87c5fbaSopenharmony_ci size_t length = packet->length; 1208c87c5fbaSopenharmony_ci if (length < (OFF_HANDSHAKE_TYPE + 1)) { 1209c87c5fbaSopenharmony_ci coap_log_debug("coap_dtls_hello: ContentType %d Short Packet (%zu < %d) dropped\n", 1210c87c5fbaSopenharmony_ci payload[OFF_CONTENT_TYPE], length, 1211c87c5fbaSopenharmony_ci OFF_HANDSHAKE_TYPE + 1); 1212c87c5fbaSopenharmony_ci return NULL; 1213c87c5fbaSopenharmony_ci } 1214c87c5fbaSopenharmony_ci if (payload[OFF_CONTENT_TYPE] != DTLS_CT_HANDSHAKE || 1215c87c5fbaSopenharmony_ci payload[OFF_HANDSHAKE_TYPE] != DTLS_HT_CLIENT_HELLO) { 1216c87c5fbaSopenharmony_ci /* only log if not a late alert */ 1217c87c5fbaSopenharmony_ci if (payload[OFF_CONTENT_TYPE] != DTLS_CT_ALERT) 1218c87c5fbaSopenharmony_ci coap_log_debug("coap_dtls_hello: ContentType %d Handshake %d dropped\n", 1219c87c5fbaSopenharmony_ci payload[OFF_CONTENT_TYPE], payload[OFF_HANDSHAKE_TYPE]); 1220c87c5fbaSopenharmony_ci return NULL; 1221c87c5fbaSopenharmony_ci } 1222c87c5fbaSopenharmony_ci } 1223c87c5fbaSopenharmony_ci 1224c87c5fbaSopenharmony_ci session = coap_make_session(endpoint->proto, COAP_SESSION_TYPE_SERVER, 1225c87c5fbaSopenharmony_ci &addr_hash, &packet->addr_info.local, 1226c87c5fbaSopenharmony_ci &packet->addr_info.remote, 1227c87c5fbaSopenharmony_ci packet->ifindex, endpoint->context, endpoint); 1228c87c5fbaSopenharmony_ci if (session) { 1229c87c5fbaSopenharmony_ci session->last_rx_tx = now; 1230c87c5fbaSopenharmony_ci memcpy(session->sock.lfunc, endpoint->sock.lfunc, 1231c87c5fbaSopenharmony_ci sizeof(session->sock.lfunc)); 1232c87c5fbaSopenharmony_ci if (endpoint->proto == COAP_PROTO_UDP) 1233c87c5fbaSopenharmony_ci session->state = COAP_SESSION_STATE_ESTABLISHED; 1234c87c5fbaSopenharmony_ci else if (endpoint->proto == COAP_PROTO_DTLS) { 1235c87c5fbaSopenharmony_ci session->type = COAP_SESSION_TYPE_HELLO; 1236c87c5fbaSopenharmony_ci } 1237c87c5fbaSopenharmony_ci SESSIONS_ADD(endpoint->sessions, session); 1238c87c5fbaSopenharmony_ci coap_log_debug("***%s: session %p: new incoming session\n", 1239c87c5fbaSopenharmony_ci coap_session_str(session), (void *)session); 1240c87c5fbaSopenharmony_ci coap_handle_event(session->context, COAP_EVENT_SERVER_SESSION_NEW, session); 1241c87c5fbaSopenharmony_ci } 1242c87c5fbaSopenharmony_ci return session; 1243c87c5fbaSopenharmony_ci} 1244c87c5fbaSopenharmony_ci 1245c87c5fbaSopenharmony_cicoap_session_t * 1246c87c5fbaSopenharmony_cicoap_session_new_dtls_session(coap_session_t *session, 1247c87c5fbaSopenharmony_ci coap_tick_t now) { 1248c87c5fbaSopenharmony_ci if (session) { 1249c87c5fbaSopenharmony_ci session->last_rx_tx = now; 1250c87c5fbaSopenharmony_ci session->type = COAP_SESSION_TYPE_SERVER; 1251c87c5fbaSopenharmony_ci coap_dtls_establish(session); 1252c87c5fbaSopenharmony_ci } 1253c87c5fbaSopenharmony_ci return session; 1254c87c5fbaSopenharmony_ci} 1255c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1256c87c5fbaSopenharmony_ci 1257c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1258c87c5fbaSopenharmony_cistatic coap_session_t * 1259c87c5fbaSopenharmony_cicoap_session_create_client(coap_context_t *ctx, 1260c87c5fbaSopenharmony_ci const coap_address_t *local_if, 1261c87c5fbaSopenharmony_ci const coap_address_t *server, 1262c87c5fbaSopenharmony_ci coap_proto_t proto) { 1263c87c5fbaSopenharmony_ci coap_session_t *session = NULL; 1264c87c5fbaSopenharmony_ci int default_port = COAP_DEFAULT_PORT; 1265c87c5fbaSopenharmony_ci 1266c87c5fbaSopenharmony_ci assert(server); 1267c87c5fbaSopenharmony_ci 1268c87c5fbaSopenharmony_ci switch (proto) { 1269c87c5fbaSopenharmony_ci case COAP_PROTO_UDP: 1270c87c5fbaSopenharmony_ci default_port = COAP_DEFAULT_PORT; 1271c87c5fbaSopenharmony_ci break; 1272c87c5fbaSopenharmony_ci case COAP_PROTO_DTLS: 1273c87c5fbaSopenharmony_ci if (!coap_dtls_is_supported()) { 1274c87c5fbaSopenharmony_ci coap_log_crit("coap_new_client_session*: DTLS not supported\n"); 1275c87c5fbaSopenharmony_ci return NULL; 1276c87c5fbaSopenharmony_ci } 1277c87c5fbaSopenharmony_ci default_port = COAPS_DEFAULT_PORT; 1278c87c5fbaSopenharmony_ci break; 1279c87c5fbaSopenharmony_ci case COAP_PROTO_TCP: 1280c87c5fbaSopenharmony_ci if (!coap_tcp_is_supported()) { 1281c87c5fbaSopenharmony_ci coap_log_crit("coap_new_client_session*: TCP not supported\n"); 1282c87c5fbaSopenharmony_ci return NULL; 1283c87c5fbaSopenharmony_ci } 1284c87c5fbaSopenharmony_ci default_port = COAP_DEFAULT_PORT; 1285c87c5fbaSopenharmony_ci break; 1286c87c5fbaSopenharmony_ci case COAP_PROTO_TLS: 1287c87c5fbaSopenharmony_ci if (!coap_tls_is_supported()) { 1288c87c5fbaSopenharmony_ci coap_log_crit("coap_new_client_session*: TLS not supported\n"); 1289c87c5fbaSopenharmony_ci return NULL; 1290c87c5fbaSopenharmony_ci } 1291c87c5fbaSopenharmony_ci default_port = COAPS_DEFAULT_PORT; 1292c87c5fbaSopenharmony_ci break; 1293c87c5fbaSopenharmony_ci case COAP_PROTO_WS: 1294c87c5fbaSopenharmony_ci if (!coap_ws_is_supported()) { 1295c87c5fbaSopenharmony_ci coap_log_crit("coap_new_client_session*: WS not supported\n"); 1296c87c5fbaSopenharmony_ci return NULL; 1297c87c5fbaSopenharmony_ci } 1298c87c5fbaSopenharmony_ci default_port = 80; 1299c87c5fbaSopenharmony_ci break; 1300c87c5fbaSopenharmony_ci case COAP_PROTO_WSS: 1301c87c5fbaSopenharmony_ci if (!coap_wss_is_supported()) { 1302c87c5fbaSopenharmony_ci coap_log_crit("coap_new_client_session*: WSS not supported\n"); 1303c87c5fbaSopenharmony_ci return NULL; 1304c87c5fbaSopenharmony_ci } 1305c87c5fbaSopenharmony_ci default_port = 443; 1306c87c5fbaSopenharmony_ci break; 1307c87c5fbaSopenharmony_ci case COAP_PROTO_NONE: 1308c87c5fbaSopenharmony_ci case COAP_PROTO_LAST: 1309c87c5fbaSopenharmony_ci default: 1310c87c5fbaSopenharmony_ci assert(0); 1311c87c5fbaSopenharmony_ci return NULL; 1312c87c5fbaSopenharmony_ci } 1313c87c5fbaSopenharmony_ci session = coap_make_session(proto, COAP_SESSION_TYPE_CLIENT, NULL, 1314c87c5fbaSopenharmony_ci local_if, server, 0, ctx, NULL); 1315c87c5fbaSopenharmony_ci if (!session) 1316c87c5fbaSopenharmony_ci goto error; 1317c87c5fbaSopenharmony_ci 1318c87c5fbaSopenharmony_ci coap_session_reference(session); 1319c87c5fbaSopenharmony_ci session->sock.session = session; 1320c87c5fbaSopenharmony_ci memcpy(&session->sock.lfunc, coap_layers_coap[proto], 1321c87c5fbaSopenharmony_ci sizeof(session->sock.lfunc)); 1322c87c5fbaSopenharmony_ci 1323c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(proto)) { 1324c87c5fbaSopenharmony_ci coap_session_t *s, *rtmp; 1325c87c5fbaSopenharmony_ci if (!coap_netif_dgrm_connect(session, local_if, server, default_port)) { 1326c87c5fbaSopenharmony_ci goto error; 1327c87c5fbaSopenharmony_ci } 1328c87c5fbaSopenharmony_ci /* Check that this is not a duplicate 4-tuple */ 1329c87c5fbaSopenharmony_ci SESSIONS_ITER_SAFE(ctx->sessions, s, rtmp) { 1330c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(s->proto) && 1331c87c5fbaSopenharmony_ci coap_address_equals(&session->addr_info.local, 1332c87c5fbaSopenharmony_ci &s->addr_info.local) && 1333c87c5fbaSopenharmony_ci coap_address_equals(&session->addr_info.remote, 1334c87c5fbaSopenharmony_ci &s->addr_info.remote)) { 1335c87c5fbaSopenharmony_ci coap_log_warn("***%s: session %p: duplicate - already exists\n", 1336c87c5fbaSopenharmony_ci coap_session_str(session), (void *)session); 1337c87c5fbaSopenharmony_ci goto error; 1338c87c5fbaSopenharmony_ci } 1339c87c5fbaSopenharmony_ci } 1340c87c5fbaSopenharmony_ci#ifdef WITH_CONTIKI 1341c87c5fbaSopenharmony_ci session->sock.context = ctx; 1342c87c5fbaSopenharmony_ci#endif /* WITH_CONTIKI */ 1343c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1344c87c5fbaSopenharmony_ci } else if (COAP_PROTO_RELIABLE(proto)) { 1345c87c5fbaSopenharmony_ci if (!coap_netif_strm_connect1(session, local_if, server, default_port)) { 1346c87c5fbaSopenharmony_ci goto error; 1347c87c5fbaSopenharmony_ci } 1348c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1349c87c5fbaSopenharmony_ci } 1350c87c5fbaSopenharmony_ci 1351c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 1352c87c5fbaSopenharmony_ci session->sock.session = session; 1353c87c5fbaSopenharmony_ci coap_epoll_ctl_add(&session->sock, 1354c87c5fbaSopenharmony_ci EPOLLIN | 1355c87c5fbaSopenharmony_ci ((session->sock.flags & COAP_SOCKET_WANT_CONNECT) ? 1356c87c5fbaSopenharmony_ci EPOLLOUT : 0), 1357c87c5fbaSopenharmony_ci __func__); 1358c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 1359c87c5fbaSopenharmony_ci 1360c87c5fbaSopenharmony_ci session->sock.flags |= COAP_SOCKET_NOT_EMPTY | COAP_SOCKET_WANT_READ; 1361c87c5fbaSopenharmony_ci if (local_if) 1362c87c5fbaSopenharmony_ci session->sock.flags |= COAP_SOCKET_BOUND; 1363c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1364c87c5fbaSopenharmony_ci if (ctx->proxy_uri_resource) 1365c87c5fbaSopenharmony_ci session->proxy_session = 1; 1366c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1367c87c5fbaSopenharmony_ci SESSIONS_ADD(ctx->sessions, session); 1368c87c5fbaSopenharmony_ci return session; 1369c87c5fbaSopenharmony_ci 1370c87c5fbaSopenharmony_cierror: 1371c87c5fbaSopenharmony_ci /* 1372c87c5fbaSopenharmony_ci * Need to add in the session as coap_session_release() 1373c87c5fbaSopenharmony_ci * will call SESSIONS_DELETE in coap_session_free(). 1374c87c5fbaSopenharmony_ci */ 1375c87c5fbaSopenharmony_ci if (session) 1376c87c5fbaSopenharmony_ci SESSIONS_ADD(ctx->sessions, session); 1377c87c5fbaSopenharmony_ci coap_session_release(session); 1378c87c5fbaSopenharmony_ci return NULL; 1379c87c5fbaSopenharmony_ci} 1380c87c5fbaSopenharmony_ci 1381c87c5fbaSopenharmony_cistatic void 1382c87c5fbaSopenharmony_cicoap_session_check_connect(coap_session_t *session) { 1383c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(session->proto)) { 1384c87c5fbaSopenharmony_ci session->sock.lfunc[COAP_LAYER_SESSION].l_establish(session); 1385c87c5fbaSopenharmony_ci } 1386c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1387c87c5fbaSopenharmony_ci if (COAP_PROTO_RELIABLE(session->proto)) { 1388c87c5fbaSopenharmony_ci if (session->sock.flags & COAP_SOCKET_WANT_CONNECT) { 1389c87c5fbaSopenharmony_ci session->state = COAP_SESSION_STATE_CONNECTING; 1390c87c5fbaSopenharmony_ci if (session->state != COAP_SESSION_STATE_ESTABLISHED && 1391c87c5fbaSopenharmony_ci session->state != COAP_SESSION_STATE_NONE && 1392c87c5fbaSopenharmony_ci session->type == COAP_SESSION_TYPE_CLIENT) { 1393c87c5fbaSopenharmony_ci session->doing_first = 1; 1394c87c5fbaSopenharmony_ci } 1395c87c5fbaSopenharmony_ci } else { 1396c87c5fbaSopenharmony_ci /* Initial connect worked immediately */ 1397c87c5fbaSopenharmony_ci session->sock.lfunc[COAP_LAYER_SESSION].l_establish(session); 1398c87c5fbaSopenharmony_ci } 1399c87c5fbaSopenharmony_ci } 1400c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1401c87c5fbaSopenharmony_ci coap_ticks(&session->last_rx_tx); 1402c87c5fbaSopenharmony_ci} 1403c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 1404c87c5fbaSopenharmony_ci 1405c87c5fbaSopenharmony_civoid 1406c87c5fbaSopenharmony_cicoap_session_establish(coap_session_t *session) { 1407c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(session->proto)) 1408c87c5fbaSopenharmony_ci coap_session_connected(session); 1409c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1410c87c5fbaSopenharmony_ci if (COAP_PROTO_RELIABLE(session->proto)) 1411c87c5fbaSopenharmony_ci coap_session_send_csm(session); 1412c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1413c87c5fbaSopenharmony_ci} 1414c87c5fbaSopenharmony_ci 1415c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1416c87c5fbaSopenharmony_cicoap_session_t * 1417c87c5fbaSopenharmony_cicoap_new_client_session(coap_context_t *ctx, 1418c87c5fbaSopenharmony_ci const coap_address_t *local_if, 1419c87c5fbaSopenharmony_ci const coap_address_t *server, 1420c87c5fbaSopenharmony_ci coap_proto_t proto) { 1421c87c5fbaSopenharmony_ci coap_session_t *session = coap_session_create_client(ctx, local_if, server, 1422c87c5fbaSopenharmony_ci proto); 1423c87c5fbaSopenharmony_ci if (session) { 1424c87c5fbaSopenharmony_ci coap_log_debug("***%s: session %p: created outgoing session\n", 1425c87c5fbaSopenharmony_ci coap_session_str(session), (void *)session); 1426c87c5fbaSopenharmony_ci coap_session_check_connect(session); 1427c87c5fbaSopenharmony_ci } 1428c87c5fbaSopenharmony_ci return session; 1429c87c5fbaSopenharmony_ci} 1430c87c5fbaSopenharmony_ci 1431c87c5fbaSopenharmony_cicoap_session_t * 1432c87c5fbaSopenharmony_cicoap_new_client_session_psk(coap_context_t *ctx, 1433c87c5fbaSopenharmony_ci const coap_address_t *local_if, 1434c87c5fbaSopenharmony_ci const coap_address_t *server, 1435c87c5fbaSopenharmony_ci coap_proto_t proto, const char *identity, 1436c87c5fbaSopenharmony_ci const uint8_t *key, unsigned key_len) { 1437c87c5fbaSopenharmony_ci coap_dtls_cpsk_t setup_data; 1438c87c5fbaSopenharmony_ci 1439c87c5fbaSopenharmony_ci memset(&setup_data, 0, sizeof(setup_data)); 1440c87c5fbaSopenharmony_ci setup_data.version = COAP_DTLS_CPSK_SETUP_VERSION; 1441c87c5fbaSopenharmony_ci 1442c87c5fbaSopenharmony_ci if (identity) { 1443c87c5fbaSopenharmony_ci setup_data.psk_info.identity.s = (const uint8_t *)identity; 1444c87c5fbaSopenharmony_ci setup_data.psk_info.identity.length = strlen(identity); 1445c87c5fbaSopenharmony_ci } 1446c87c5fbaSopenharmony_ci 1447c87c5fbaSopenharmony_ci if (key && key_len > 0) { 1448c87c5fbaSopenharmony_ci setup_data.psk_info.key.s = key; 1449c87c5fbaSopenharmony_ci setup_data.psk_info.key.length = key_len; 1450c87c5fbaSopenharmony_ci } 1451c87c5fbaSopenharmony_ci 1452c87c5fbaSopenharmony_ci return coap_new_client_session_psk2(ctx, local_if, server, 1453c87c5fbaSopenharmony_ci proto, &setup_data); 1454c87c5fbaSopenharmony_ci} 1455c87c5fbaSopenharmony_ci 1456c87c5fbaSopenharmony_cicoap_session_t * 1457c87c5fbaSopenharmony_cicoap_new_client_session_psk2(coap_context_t *ctx, 1458c87c5fbaSopenharmony_ci const coap_address_t *local_if, 1459c87c5fbaSopenharmony_ci const coap_address_t *server, 1460c87c5fbaSopenharmony_ci coap_proto_t proto, 1461c87c5fbaSopenharmony_ci coap_dtls_cpsk_t *setup_data) { 1462c87c5fbaSopenharmony_ci coap_session_t *session = coap_session_create_client(ctx, local_if, 1463c87c5fbaSopenharmony_ci server, proto); 1464c87c5fbaSopenharmony_ci 1465c87c5fbaSopenharmony_ci if (!session) 1466c87c5fbaSopenharmony_ci return NULL; 1467c87c5fbaSopenharmony_ci 1468c87c5fbaSopenharmony_ci session->cpsk_setup_data = *setup_data; 1469c87c5fbaSopenharmony_ci if (setup_data->psk_info.identity.s) { 1470c87c5fbaSopenharmony_ci session->psk_identity = 1471c87c5fbaSopenharmony_ci coap_new_bin_const(setup_data->psk_info.identity.s, 1472c87c5fbaSopenharmony_ci setup_data->psk_info.identity.length); 1473c87c5fbaSopenharmony_ci if (!session->psk_identity) { 1474c87c5fbaSopenharmony_ci coap_log_warn("Cannot store session Identity (PSK)\n"); 1475c87c5fbaSopenharmony_ci coap_session_release(session); 1476c87c5fbaSopenharmony_ci return NULL; 1477c87c5fbaSopenharmony_ci } 1478c87c5fbaSopenharmony_ci } else if (coap_dtls_is_supported() || coap_tls_is_supported()) { 1479c87c5fbaSopenharmony_ci coap_log_warn("Identity (PSK) not defined\n"); 1480c87c5fbaSopenharmony_ci coap_session_release(session); 1481c87c5fbaSopenharmony_ci return NULL; 1482c87c5fbaSopenharmony_ci } 1483c87c5fbaSopenharmony_ci 1484c87c5fbaSopenharmony_ci if (setup_data->psk_info.key.s && setup_data->psk_info.key.length > 0) { 1485c87c5fbaSopenharmony_ci session->psk_key = coap_new_bin_const(setup_data->psk_info.key.s, 1486c87c5fbaSopenharmony_ci setup_data->psk_info.key.length); 1487c87c5fbaSopenharmony_ci if (!session->psk_key) { 1488c87c5fbaSopenharmony_ci coap_log_warn("Cannot store session pre-shared key (PSK)\n"); 1489c87c5fbaSopenharmony_ci coap_session_release(session); 1490c87c5fbaSopenharmony_ci return NULL; 1491c87c5fbaSopenharmony_ci } 1492c87c5fbaSopenharmony_ci } else if (coap_dtls_is_supported() || coap_tls_is_supported()) { 1493c87c5fbaSopenharmony_ci coap_log_warn("Pre-shared key (PSK) not defined\n"); 1494c87c5fbaSopenharmony_ci coap_session_release(session); 1495c87c5fbaSopenharmony_ci return NULL; 1496c87c5fbaSopenharmony_ci } 1497c87c5fbaSopenharmony_ci 1498c87c5fbaSopenharmony_ci if (coap_dtls_is_supported() || coap_tls_is_supported()) { 1499c87c5fbaSopenharmony_ci if (!coap_dtls_context_set_cpsk(ctx, setup_data)) { 1500c87c5fbaSopenharmony_ci coap_session_release(session); 1501c87c5fbaSopenharmony_ci return NULL; 1502c87c5fbaSopenharmony_ci } 1503c87c5fbaSopenharmony_ci } 1504c87c5fbaSopenharmony_ci coap_log_debug("***%s: new outgoing session\n", 1505c87c5fbaSopenharmony_ci coap_session_str(session)); 1506c87c5fbaSopenharmony_ci coap_session_check_connect(session); 1507c87c5fbaSopenharmony_ci return session; 1508c87c5fbaSopenharmony_ci} 1509c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 1510c87c5fbaSopenharmony_ci 1511c87c5fbaSopenharmony_ciint 1512c87c5fbaSopenharmony_cicoap_session_refresh_psk_hint(coap_session_t *session, 1513c87c5fbaSopenharmony_ci const coap_bin_const_t *psk_hint 1514c87c5fbaSopenharmony_ci ) { 1515c87c5fbaSopenharmony_ci /* We may be refreshing the hint with the same hint */ 1516c87c5fbaSopenharmony_ci coap_bin_const_t *old_psk_hint = session->psk_hint; 1517c87c5fbaSopenharmony_ci 1518c87c5fbaSopenharmony_ci if (psk_hint && psk_hint->s) { 1519c87c5fbaSopenharmony_ci if (session->psk_hint) { 1520c87c5fbaSopenharmony_ci if (coap_binary_equal(session->psk_hint, psk_hint)) 1521c87c5fbaSopenharmony_ci return 1; 1522c87c5fbaSopenharmony_ci } 1523c87c5fbaSopenharmony_ci session->psk_hint = coap_new_bin_const(psk_hint->s, 1524c87c5fbaSopenharmony_ci psk_hint->length); 1525c87c5fbaSopenharmony_ci if (!session->psk_hint) { 1526c87c5fbaSopenharmony_ci coap_log_err("No memory to store identity hint (PSK)\n"); 1527c87c5fbaSopenharmony_ci if (old_psk_hint) 1528c87c5fbaSopenharmony_ci coap_delete_bin_const(old_psk_hint); 1529c87c5fbaSopenharmony_ci return 0; 1530c87c5fbaSopenharmony_ci } 1531c87c5fbaSopenharmony_ci } else { 1532c87c5fbaSopenharmony_ci session->psk_hint = NULL; 1533c87c5fbaSopenharmony_ci } 1534c87c5fbaSopenharmony_ci if (old_psk_hint) 1535c87c5fbaSopenharmony_ci coap_delete_bin_const(old_psk_hint); 1536c87c5fbaSopenharmony_ci 1537c87c5fbaSopenharmony_ci return 1; 1538c87c5fbaSopenharmony_ci} 1539c87c5fbaSopenharmony_ci 1540c87c5fbaSopenharmony_ciint 1541c87c5fbaSopenharmony_cicoap_session_refresh_psk_key(coap_session_t *session, 1542c87c5fbaSopenharmony_ci const coap_bin_const_t *psk_key 1543c87c5fbaSopenharmony_ci ) { 1544c87c5fbaSopenharmony_ci /* We may be refreshing the key with the same key */ 1545c87c5fbaSopenharmony_ci coap_bin_const_t *old_psk_key = session->psk_key; 1546c87c5fbaSopenharmony_ci 1547c87c5fbaSopenharmony_ci if (psk_key && psk_key->s) { 1548c87c5fbaSopenharmony_ci if (session->psk_key) { 1549c87c5fbaSopenharmony_ci if (coap_binary_equal(session->psk_key, psk_key)) 1550c87c5fbaSopenharmony_ci return 1; 1551c87c5fbaSopenharmony_ci } 1552c87c5fbaSopenharmony_ci session->psk_key = coap_new_bin_const(psk_key->s, psk_key->length); 1553c87c5fbaSopenharmony_ci if (!session->psk_key) { 1554c87c5fbaSopenharmony_ci coap_log_err("No memory to store pre-shared key (PSK)\n"); 1555c87c5fbaSopenharmony_ci if (old_psk_key) 1556c87c5fbaSopenharmony_ci coap_delete_bin_const(old_psk_key); 1557c87c5fbaSopenharmony_ci return 0; 1558c87c5fbaSopenharmony_ci } 1559c87c5fbaSopenharmony_ci } else { 1560c87c5fbaSopenharmony_ci session->psk_key = NULL; 1561c87c5fbaSopenharmony_ci } 1562c87c5fbaSopenharmony_ci if (old_psk_key) 1563c87c5fbaSopenharmony_ci coap_delete_bin_const(old_psk_key); 1564c87c5fbaSopenharmony_ci 1565c87c5fbaSopenharmony_ci return 1; 1566c87c5fbaSopenharmony_ci} 1567c87c5fbaSopenharmony_ci 1568c87c5fbaSopenharmony_ciint 1569c87c5fbaSopenharmony_cicoap_session_refresh_psk_identity(coap_session_t *session, 1570c87c5fbaSopenharmony_ci const coap_bin_const_t *psk_identity 1571c87c5fbaSopenharmony_ci ) { 1572c87c5fbaSopenharmony_ci /* We may be refreshing the identity with the same identity */ 1573c87c5fbaSopenharmony_ci coap_bin_const_t *old_psk_identity = session->psk_identity; 1574c87c5fbaSopenharmony_ci 1575c87c5fbaSopenharmony_ci if (psk_identity && psk_identity->s) { 1576c87c5fbaSopenharmony_ci if (session->psk_identity) { 1577c87c5fbaSopenharmony_ci if (coap_binary_equal(session->psk_identity, psk_identity)) 1578c87c5fbaSopenharmony_ci return 1; 1579c87c5fbaSopenharmony_ci } 1580c87c5fbaSopenharmony_ci session->psk_identity = coap_new_bin_const(psk_identity->s, 1581c87c5fbaSopenharmony_ci psk_identity->length); 1582c87c5fbaSopenharmony_ci if (!session->psk_identity) { 1583c87c5fbaSopenharmony_ci coap_log_err("No memory to store pre-shared key identity (PSK)\n"); 1584c87c5fbaSopenharmony_ci if (old_psk_identity) 1585c87c5fbaSopenharmony_ci coap_delete_bin_const(old_psk_identity); 1586c87c5fbaSopenharmony_ci return 0; 1587c87c5fbaSopenharmony_ci } 1588c87c5fbaSopenharmony_ci } else { 1589c87c5fbaSopenharmony_ci session->psk_identity = NULL; 1590c87c5fbaSopenharmony_ci } 1591c87c5fbaSopenharmony_ci if (old_psk_identity) 1592c87c5fbaSopenharmony_ci coap_delete_bin_const(old_psk_identity); 1593c87c5fbaSopenharmony_ci 1594c87c5fbaSopenharmony_ci return 1; 1595c87c5fbaSopenharmony_ci} 1596c87c5fbaSopenharmony_ci 1597c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1598c87c5fbaSopenharmony_ciconst coap_bin_const_t * 1599c87c5fbaSopenharmony_cicoap_session_get_psk_hint(const coap_session_t *session) { 1600c87c5fbaSopenharmony_ci if (session) 1601c87c5fbaSopenharmony_ci return session->psk_hint; 1602c87c5fbaSopenharmony_ci return NULL; 1603c87c5fbaSopenharmony_ci} 1604c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1605c87c5fbaSopenharmony_ci 1606c87c5fbaSopenharmony_ciconst coap_bin_const_t * 1607c87c5fbaSopenharmony_cicoap_session_get_psk_identity(const coap_session_t *session) { 1608c87c5fbaSopenharmony_ci const coap_bin_const_t *psk_identity = NULL; 1609c87c5fbaSopenharmony_ci if (session) { 1610c87c5fbaSopenharmony_ci psk_identity = session->psk_identity; 1611c87c5fbaSopenharmony_ci if (psk_identity == NULL) { 1612c87c5fbaSopenharmony_ci psk_identity = &session->cpsk_setup_data.psk_info.identity; 1613c87c5fbaSopenharmony_ci } 1614c87c5fbaSopenharmony_ci } 1615c87c5fbaSopenharmony_ci return psk_identity; 1616c87c5fbaSopenharmony_ci} 1617c87c5fbaSopenharmony_ci 1618c87c5fbaSopenharmony_ciconst coap_bin_const_t * 1619c87c5fbaSopenharmony_cicoap_session_get_psk_key(const coap_session_t *session) { 1620c87c5fbaSopenharmony_ci if (session) 1621c87c5fbaSopenharmony_ci return session->psk_key; 1622c87c5fbaSopenharmony_ci return NULL; 1623c87c5fbaSopenharmony_ci} 1624c87c5fbaSopenharmony_ci 1625c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1626c87c5fbaSopenharmony_cicoap_session_t * 1627c87c5fbaSopenharmony_cicoap_new_client_session_pki(coap_context_t *ctx, 1628c87c5fbaSopenharmony_ci const coap_address_t *local_if, 1629c87c5fbaSopenharmony_ci const coap_address_t *server, 1630c87c5fbaSopenharmony_ci coap_proto_t proto, 1631c87c5fbaSopenharmony_ci coap_dtls_pki_t *setup_data) { 1632c87c5fbaSopenharmony_ci coap_session_t *session; 1633c87c5fbaSopenharmony_ci 1634c87c5fbaSopenharmony_ci if (coap_dtls_is_supported() || coap_tls_is_supported()) { 1635c87c5fbaSopenharmony_ci if (!setup_data) { 1636c87c5fbaSopenharmony_ci return NULL; 1637c87c5fbaSopenharmony_ci } else { 1638c87c5fbaSopenharmony_ci if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION) { 1639c87c5fbaSopenharmony_ci coap_log_err("coap_new_client_session_pki: Wrong version of setup_data\n"); 1640c87c5fbaSopenharmony_ci return NULL; 1641c87c5fbaSopenharmony_ci } 1642c87c5fbaSopenharmony_ci } 1643c87c5fbaSopenharmony_ci 1644c87c5fbaSopenharmony_ci } 1645c87c5fbaSopenharmony_ci session = coap_session_create_client(ctx, local_if, server, proto); 1646c87c5fbaSopenharmony_ci 1647c87c5fbaSopenharmony_ci if (!session) { 1648c87c5fbaSopenharmony_ci return NULL; 1649c87c5fbaSopenharmony_ci } 1650c87c5fbaSopenharmony_ci 1651c87c5fbaSopenharmony_ci if (coap_dtls_is_supported() || coap_tls_is_supported()) { 1652c87c5fbaSopenharmony_ci /* we know that setup_data is not NULL */ 1653c87c5fbaSopenharmony_ci if (!coap_dtls_context_set_pki(ctx, setup_data, COAP_DTLS_ROLE_CLIENT)) { 1654c87c5fbaSopenharmony_ci coap_session_release(session); 1655c87c5fbaSopenharmony_ci return NULL; 1656c87c5fbaSopenharmony_ci } 1657c87c5fbaSopenharmony_ci } 1658c87c5fbaSopenharmony_ci coap_log_debug("***%s: new outgoing session\n", 1659c87c5fbaSopenharmony_ci coap_session_str(session)); 1660c87c5fbaSopenharmony_ci coap_session_check_connect(session); 1661c87c5fbaSopenharmony_ci return session; 1662c87c5fbaSopenharmony_ci} 1663c87c5fbaSopenharmony_ci#endif /* ! COAP_CLIENT_SUPPORT */ 1664c87c5fbaSopenharmony_ci 1665c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1666c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1667c87c5fbaSopenharmony_cicoap_session_t * 1668c87c5fbaSopenharmony_cicoap_new_server_session(coap_context_t *ctx, coap_endpoint_t *ep) { 1669c87c5fbaSopenharmony_ci coap_session_t *session; 1670c87c5fbaSopenharmony_ci session = coap_make_session(ep->proto, COAP_SESSION_TYPE_SERVER, 1671c87c5fbaSopenharmony_ci NULL, NULL, NULL, 0, ctx, ep); 1672c87c5fbaSopenharmony_ci if (!session) 1673c87c5fbaSopenharmony_ci goto error; 1674c87c5fbaSopenharmony_ci 1675c87c5fbaSopenharmony_ci memcpy(session->sock.lfunc, ep->sock.lfunc, sizeof(session->sock.lfunc)); 1676c87c5fbaSopenharmony_ci if (!coap_netif_strm_accept(ep, session)) 1677c87c5fbaSopenharmony_ci goto error; 1678c87c5fbaSopenharmony_ci 1679c87c5fbaSopenharmony_ci coap_make_addr_hash(&session->addr_hash, session->proto, &session->addr_info); 1680c87c5fbaSopenharmony_ci 1681c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 1682c87c5fbaSopenharmony_ci session->sock.session = session; 1683c87c5fbaSopenharmony_ci coap_epoll_ctl_add(&session->sock, 1684c87c5fbaSopenharmony_ci EPOLLIN, 1685c87c5fbaSopenharmony_ci __func__); 1686c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 1687c87c5fbaSopenharmony_ci SESSIONS_ADD(ep->sessions, session); 1688c87c5fbaSopenharmony_ci if (session) { 1689c87c5fbaSopenharmony_ci coap_log_debug("***%s: session %p: new incoming session\n", 1690c87c5fbaSopenharmony_ci coap_session_str(session), (void *)session); 1691c87c5fbaSopenharmony_ci coap_handle_event(session->context, COAP_EVENT_TCP_CONNECTED, session); 1692c87c5fbaSopenharmony_ci coap_handle_event(session->context, COAP_EVENT_SERVER_SESSION_NEW, session); 1693c87c5fbaSopenharmony_ci session->state = COAP_SESSION_STATE_CONNECTING; 1694c87c5fbaSopenharmony_ci session->sock.lfunc[COAP_LAYER_SESSION].l_establish(session); 1695c87c5fbaSopenharmony_ci } 1696c87c5fbaSopenharmony_ci return session; 1697c87c5fbaSopenharmony_ci 1698c87c5fbaSopenharmony_cierror: 1699c87c5fbaSopenharmony_ci /* 1700c87c5fbaSopenharmony_ci * Need to add in the session as coap_session_release() 1701c87c5fbaSopenharmony_ci * will call SESSIONS_DELETE in coap_session_free(). 1702c87c5fbaSopenharmony_ci */ 1703c87c5fbaSopenharmony_ci if (session) { 1704c87c5fbaSopenharmony_ci SESSIONS_ADD(ep->sessions, session); 1705c87c5fbaSopenharmony_ci coap_session_free(session); 1706c87c5fbaSopenharmony_ci } 1707c87c5fbaSopenharmony_ci return NULL; 1708c87c5fbaSopenharmony_ci} 1709c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1710c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1711c87c5fbaSopenharmony_ci 1712c87c5fbaSopenharmony_civoid 1713c87c5fbaSopenharmony_cicoap_session_init_token(coap_session_t *session, size_t len, 1714c87c5fbaSopenharmony_ci const uint8_t *data) { 1715c87c5fbaSopenharmony_ci session->tx_token = coap_decode_var_bytes8(data, len); 1716c87c5fbaSopenharmony_ci} 1717c87c5fbaSopenharmony_ci 1718c87c5fbaSopenharmony_civoid 1719c87c5fbaSopenharmony_cicoap_session_new_token(coap_session_t *session, size_t *len, 1720c87c5fbaSopenharmony_ci uint8_t *data) { 1721c87c5fbaSopenharmony_ci *len = coap_encode_var_safe8(data, 1722c87c5fbaSopenharmony_ci sizeof(session->tx_token), ++session->tx_token); 1723c87c5fbaSopenharmony_ci} 1724c87c5fbaSopenharmony_ci 1725c87c5fbaSopenharmony_ciuint16_t 1726c87c5fbaSopenharmony_cicoap_new_message_id(coap_session_t *session) { 1727c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(session->proto)) 1728c87c5fbaSopenharmony_ci return ++session->tx_mid; 1729c87c5fbaSopenharmony_ci /* TCP/TLS have no notion of mid */ 1730c87c5fbaSopenharmony_ci return 0; 1731c87c5fbaSopenharmony_ci} 1732c87c5fbaSopenharmony_ci 1733c87c5fbaSopenharmony_ciconst coap_address_t * 1734c87c5fbaSopenharmony_cicoap_session_get_addr_remote(const coap_session_t *session) { 1735c87c5fbaSopenharmony_ci if (session) 1736c87c5fbaSopenharmony_ci return &session->addr_info.remote; 1737c87c5fbaSopenharmony_ci return NULL; 1738c87c5fbaSopenharmony_ci} 1739c87c5fbaSopenharmony_ci 1740c87c5fbaSopenharmony_ciconst coap_address_t * 1741c87c5fbaSopenharmony_cicoap_session_get_addr_local(const coap_session_t *session) { 1742c87c5fbaSopenharmony_ci if (session) 1743c87c5fbaSopenharmony_ci return &session->addr_info.local; 1744c87c5fbaSopenharmony_ci return NULL; 1745c87c5fbaSopenharmony_ci} 1746c87c5fbaSopenharmony_ci 1747c87c5fbaSopenharmony_ciconst coap_address_t * 1748c87c5fbaSopenharmony_cicoap_session_get_addr_mcast(const coap_session_t *session) { 1749c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1750c87c5fbaSopenharmony_ci if (session && session->type == COAP_SESSION_TYPE_CLIENT && 1751c87c5fbaSopenharmony_ci session->sock.flags & COAP_SOCKET_MULTICAST) 1752c87c5fbaSopenharmony_ci return &session->sock.mcast_addr; 1753c87c5fbaSopenharmony_ci#else /* ! COAP_CLIENT_SUPPORT */ 1754c87c5fbaSopenharmony_ci (void)session; 1755c87c5fbaSopenharmony_ci#endif /* ! COAP_CLIENT_SUPPORT */ 1756c87c5fbaSopenharmony_ci return NULL; 1757c87c5fbaSopenharmony_ci} 1758c87c5fbaSopenharmony_ci 1759c87c5fbaSopenharmony_cicoap_context_t * 1760c87c5fbaSopenharmony_cicoap_session_get_context(const coap_session_t *session) { 1761c87c5fbaSopenharmony_ci if (session) 1762c87c5fbaSopenharmony_ci return session->context; 1763c87c5fbaSopenharmony_ci return NULL; 1764c87c5fbaSopenharmony_ci} 1765c87c5fbaSopenharmony_ci 1766c87c5fbaSopenharmony_cicoap_proto_t 1767c87c5fbaSopenharmony_cicoap_session_get_proto(const coap_session_t *session) { 1768c87c5fbaSopenharmony_ci if (session) 1769c87c5fbaSopenharmony_ci return session->proto; 1770c87c5fbaSopenharmony_ci return 0; 1771c87c5fbaSopenharmony_ci} 1772c87c5fbaSopenharmony_ci 1773c87c5fbaSopenharmony_cicoap_session_type_t 1774c87c5fbaSopenharmony_cicoap_session_get_type(const coap_session_t *session) { 1775c87c5fbaSopenharmony_ci if (session) 1776c87c5fbaSopenharmony_ci return session->type; 1777c87c5fbaSopenharmony_ci return 0; 1778c87c5fbaSopenharmony_ci} 1779c87c5fbaSopenharmony_ci 1780c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1781c87c5fbaSopenharmony_ciint 1782c87c5fbaSopenharmony_cicoap_session_set_type_client(coap_session_t *session) { 1783c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1784c87c5fbaSopenharmony_ci if (session && session->type == COAP_SESSION_TYPE_SERVER) { 1785c87c5fbaSopenharmony_ci coap_session_reference(session); 1786c87c5fbaSopenharmony_ci session->type = COAP_SESSION_TYPE_CLIENT; 1787c87c5fbaSopenharmony_ci return 1; 1788c87c5fbaSopenharmony_ci } 1789c87c5fbaSopenharmony_ci#else /* ! COAP_SERVER_SUPPORT */ 1790c87c5fbaSopenharmony_ci (void)session; 1791c87c5fbaSopenharmony_ci#endif /* ! COAP_SERVER_SUPPORT */ 1792c87c5fbaSopenharmony_ci return 0; 1793c87c5fbaSopenharmony_ci} 1794c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 1795c87c5fbaSopenharmony_ci 1796c87c5fbaSopenharmony_cicoap_session_state_t 1797c87c5fbaSopenharmony_cicoap_session_get_state(const coap_session_t *session) { 1798c87c5fbaSopenharmony_ci if (session) 1799c87c5fbaSopenharmony_ci return session->state; 1800c87c5fbaSopenharmony_ci return 0; 1801c87c5fbaSopenharmony_ci} 1802c87c5fbaSopenharmony_ci 1803c87c5fbaSopenharmony_ciint 1804c87c5fbaSopenharmony_cicoap_session_get_ifindex(const coap_session_t *session) { 1805c87c5fbaSopenharmony_ci if (session) 1806c87c5fbaSopenharmony_ci return session->ifindex; 1807c87c5fbaSopenharmony_ci return -1; 1808c87c5fbaSopenharmony_ci} 1809c87c5fbaSopenharmony_ci 1810c87c5fbaSopenharmony_civoid * 1811c87c5fbaSopenharmony_cicoap_session_get_tls(const coap_session_t *session, 1812c87c5fbaSopenharmony_ci coap_tls_library_t *tls_lib) { 1813c87c5fbaSopenharmony_ci if (session) 1814c87c5fbaSopenharmony_ci return coap_dtls_get_tls(session, tls_lib); 1815c87c5fbaSopenharmony_ci return NULL; 1816c87c5fbaSopenharmony_ci} 1817c87c5fbaSopenharmony_ci 1818c87c5fbaSopenharmony_cistatic const char * 1819c87c5fbaSopenharmony_cicoap_proto_name(coap_proto_t proto) { 1820c87c5fbaSopenharmony_ci switch (proto) { 1821c87c5fbaSopenharmony_ci case COAP_PROTO_UDP: 1822c87c5fbaSopenharmony_ci return "UDP "; 1823c87c5fbaSopenharmony_ci case COAP_PROTO_DTLS: 1824c87c5fbaSopenharmony_ci return "DTLS"; 1825c87c5fbaSopenharmony_ci case COAP_PROTO_TCP: 1826c87c5fbaSopenharmony_ci return "TCP "; 1827c87c5fbaSopenharmony_ci case COAP_PROTO_TLS: 1828c87c5fbaSopenharmony_ci return "TLS "; 1829c87c5fbaSopenharmony_ci case COAP_PROTO_WS: 1830c87c5fbaSopenharmony_ci return "WS "; 1831c87c5fbaSopenharmony_ci case COAP_PROTO_WSS: 1832c87c5fbaSopenharmony_ci return "WSS "; 1833c87c5fbaSopenharmony_ci case COAP_PROTO_NONE: 1834c87c5fbaSopenharmony_ci case COAP_PROTO_LAST: 1835c87c5fbaSopenharmony_ci default: 1836c87c5fbaSopenharmony_ci return "????" ; 1837c87c5fbaSopenharmony_ci break; 1838c87c5fbaSopenharmony_ci } 1839c87c5fbaSopenharmony_ci return NULL; 1840c87c5fbaSopenharmony_ci} 1841c87c5fbaSopenharmony_ci 1842c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 1843c87c5fbaSopenharmony_cicoap_endpoint_t * 1844c87c5fbaSopenharmony_cicoap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto) { 1845c87c5fbaSopenharmony_ci coap_endpoint_t *ep = NULL; 1846c87c5fbaSopenharmony_ci 1847c87c5fbaSopenharmony_ci assert(context); 1848c87c5fbaSopenharmony_ci assert(listen_addr); 1849c87c5fbaSopenharmony_ci assert(proto != COAP_PROTO_NONE); 1850c87c5fbaSopenharmony_ci 1851c87c5fbaSopenharmony_ci if (proto == COAP_PROTO_DTLS && !coap_dtls_is_supported()) { 1852c87c5fbaSopenharmony_ci coap_log_crit("coap_new_endpoint: DTLS not supported\n"); 1853c87c5fbaSopenharmony_ci goto error; 1854c87c5fbaSopenharmony_ci } 1855c87c5fbaSopenharmony_ci 1856c87c5fbaSopenharmony_ci if (proto == COAP_PROTO_TLS && !coap_tls_is_supported()) { 1857c87c5fbaSopenharmony_ci coap_log_crit("coap_new_endpoint: TLS not supported\n"); 1858c87c5fbaSopenharmony_ci goto error; 1859c87c5fbaSopenharmony_ci } 1860c87c5fbaSopenharmony_ci 1861c87c5fbaSopenharmony_ci if (proto == COAP_PROTO_TCP && !coap_tcp_is_supported()) { 1862c87c5fbaSopenharmony_ci coap_log_crit("coap_new_endpoint: TCP not supported\n"); 1863c87c5fbaSopenharmony_ci goto error; 1864c87c5fbaSopenharmony_ci } 1865c87c5fbaSopenharmony_ci 1866c87c5fbaSopenharmony_ci if (proto == COAP_PROTO_WS && !coap_ws_is_supported()) { 1867c87c5fbaSopenharmony_ci coap_log_crit("coap_new_endpoint: WS not supported\n"); 1868c87c5fbaSopenharmony_ci goto error; 1869c87c5fbaSopenharmony_ci } 1870c87c5fbaSopenharmony_ci 1871c87c5fbaSopenharmony_ci if (proto == COAP_PROTO_WSS && !coap_wss_is_supported()) { 1872c87c5fbaSopenharmony_ci coap_log_crit("coap_new_endpoint: WSS not supported\n"); 1873c87c5fbaSopenharmony_ci goto error; 1874c87c5fbaSopenharmony_ci } 1875c87c5fbaSopenharmony_ci 1876c87c5fbaSopenharmony_ci if (proto == COAP_PROTO_DTLS || proto == COAP_PROTO_TLS || 1877c87c5fbaSopenharmony_ci proto == COAP_PROTO_WSS) { 1878c87c5fbaSopenharmony_ci if (!coap_dtls_context_check_keys_enabled(context)) { 1879c87c5fbaSopenharmony_ci coap_log_info("coap_new_endpoint: one of coap_context_set_psk() or " 1880c87c5fbaSopenharmony_ci "coap_context_set_pki() not called\n"); 1881c87c5fbaSopenharmony_ci goto error; 1882c87c5fbaSopenharmony_ci } 1883c87c5fbaSopenharmony_ci } 1884c87c5fbaSopenharmony_ci 1885c87c5fbaSopenharmony_ci ep = coap_malloc_endpoint(); 1886c87c5fbaSopenharmony_ci if (!ep) { 1887c87c5fbaSopenharmony_ci coap_log_warn("coap_new_endpoint: malloc"); 1888c87c5fbaSopenharmony_ci goto error; 1889c87c5fbaSopenharmony_ci } 1890c87c5fbaSopenharmony_ci 1891c87c5fbaSopenharmony_ci memset(ep, 0, sizeof(coap_endpoint_t)); 1892c87c5fbaSopenharmony_ci ep->context = context; 1893c87c5fbaSopenharmony_ci ep->proto = proto; 1894c87c5fbaSopenharmony_ci ep->sock.endpoint = ep; 1895c87c5fbaSopenharmony_ci assert(proto < COAP_PROTO_LAST); 1896c87c5fbaSopenharmony_ci memcpy(&ep->sock.lfunc, coap_layers_coap[proto], sizeof(ep->sock.lfunc)); 1897c87c5fbaSopenharmony_ci 1898c87c5fbaSopenharmony_ci if (COAP_PROTO_NOT_RELIABLE(proto)) { 1899c87c5fbaSopenharmony_ci if (!coap_netif_dgrm_listen(ep, listen_addr)) 1900c87c5fbaSopenharmony_ci goto error; 1901c87c5fbaSopenharmony_ci#ifdef WITH_CONTIKI 1902c87c5fbaSopenharmony_ci ep->sock.context = context; 1903c87c5fbaSopenharmony_ci#endif /* WITH_CONTIKI */ 1904c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP 1905c87c5fbaSopenharmony_ci } else if (COAP_PROTO_RELIABLE(proto)) { 1906c87c5fbaSopenharmony_ci if (!coap_netif_strm_listen(ep, listen_addr)) 1907c87c5fbaSopenharmony_ci goto error; 1908c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */ 1909c87c5fbaSopenharmony_ci } else { 1910c87c5fbaSopenharmony_ci coap_log_crit("coap_new_endpoint: protocol not supported\n"); 1911c87c5fbaSopenharmony_ci goto error; 1912c87c5fbaSopenharmony_ci } 1913c87c5fbaSopenharmony_ci 1914c87c5fbaSopenharmony_ci if (COAP_LOG_DEBUG <= coap_get_log_level()) { 1915c87c5fbaSopenharmony_ci#ifndef INET6_ADDRSTRLEN 1916c87c5fbaSopenharmony_ci#define INET6_ADDRSTRLEN 40 1917c87c5fbaSopenharmony_ci#endif 1918c87c5fbaSopenharmony_ci unsigned char addr_str[INET6_ADDRSTRLEN + 8]; 1919c87c5fbaSopenharmony_ci 1920c87c5fbaSopenharmony_ci if (coap_print_addr(&ep->bind_addr, addr_str, INET6_ADDRSTRLEN + 8)) { 1921c87c5fbaSopenharmony_ci coap_log_debug("created %s endpoint %s\n", coap_proto_name(ep->proto), 1922c87c5fbaSopenharmony_ci addr_str); 1923c87c5fbaSopenharmony_ci } 1924c87c5fbaSopenharmony_ci } 1925c87c5fbaSopenharmony_ci 1926c87c5fbaSopenharmony_ci ep->default_mtu = COAP_DEFAULT_MTU; 1927c87c5fbaSopenharmony_ci 1928c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 1929c87c5fbaSopenharmony_ci ep->sock.endpoint = ep; 1930c87c5fbaSopenharmony_ci coap_epoll_ctl_add(&ep->sock, 1931c87c5fbaSopenharmony_ci EPOLLIN, 1932c87c5fbaSopenharmony_ci __func__); 1933c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 1934c87c5fbaSopenharmony_ci 1935c87c5fbaSopenharmony_ci LL_PREPEND(context->endpoint, ep); 1936c87c5fbaSopenharmony_ci return ep; 1937c87c5fbaSopenharmony_ci 1938c87c5fbaSopenharmony_cierror: 1939c87c5fbaSopenharmony_ci coap_free_endpoint(ep); 1940c87c5fbaSopenharmony_ci return NULL; 1941c87c5fbaSopenharmony_ci} 1942c87c5fbaSopenharmony_ci 1943c87c5fbaSopenharmony_civoid 1944c87c5fbaSopenharmony_cicoap_endpoint_set_default_mtu(coap_endpoint_t *ep, unsigned mtu) { 1945c87c5fbaSopenharmony_ci ep->default_mtu = (uint16_t)mtu; 1946c87c5fbaSopenharmony_ci} 1947c87c5fbaSopenharmony_ci 1948c87c5fbaSopenharmony_civoid 1949c87c5fbaSopenharmony_cicoap_free_endpoint(coap_endpoint_t *ep) { 1950c87c5fbaSopenharmony_ci if (ep) { 1951c87c5fbaSopenharmony_ci coap_session_t *session, *rtmp; 1952c87c5fbaSopenharmony_ci 1953c87c5fbaSopenharmony_ci SESSIONS_ITER_SAFE(ep->sessions, session, rtmp) { 1954c87c5fbaSopenharmony_ci assert(session->ref == 0); 1955c87c5fbaSopenharmony_ci if (session->ref == 0) { 1956c87c5fbaSopenharmony_ci coap_session_free(session); 1957c87c5fbaSopenharmony_ci } 1958c87c5fbaSopenharmony_ci } 1959c87c5fbaSopenharmony_ci if (coap_netif_available_ep(ep)) { 1960c87c5fbaSopenharmony_ci /* 1961c87c5fbaSopenharmony_ci * ep->sock.endpoint is set in coap_new_endpoint(). 1962c87c5fbaSopenharmony_ci * ep->sock.session is never set. 1963c87c5fbaSopenharmony_ci * 1964c87c5fbaSopenharmony_ci * session->sock.session is set for both clients and servers (when a 1965c87c5fbaSopenharmony_ci * new session is accepted), but does not affect the endpoint. 1966c87c5fbaSopenharmony_ci * 1967c87c5fbaSopenharmony_ci * So, it is safe to call coap_netif_close_ep() after all the sessions 1968c87c5fbaSopenharmony_ci * have been freed above as we are only working with the endpoint sock. 1969c87c5fbaSopenharmony_ci */ 1970c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT 1971c87c5fbaSopenharmony_ci assert(ep->sock.session == NULL); 1972c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */ 1973c87c5fbaSopenharmony_ci coap_netif_close_ep(ep); 1974c87c5fbaSopenharmony_ci } 1975c87c5fbaSopenharmony_ci 1976c87c5fbaSopenharmony_ci if (ep->context && ep->context->endpoint) { 1977c87c5fbaSopenharmony_ci LL_DELETE(ep->context->endpoint, ep); 1978c87c5fbaSopenharmony_ci } 1979c87c5fbaSopenharmony_ci coap_mfree_endpoint(ep); 1980c87c5fbaSopenharmony_ci } 1981c87c5fbaSopenharmony_ci} 1982c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 1983c87c5fbaSopenharmony_ci 1984c87c5fbaSopenharmony_cicoap_session_t * 1985c87c5fbaSopenharmony_cicoap_session_get_by_peer(const coap_context_t *ctx, 1986c87c5fbaSopenharmony_ci const coap_address_t *remote_addr, 1987c87c5fbaSopenharmony_ci int ifindex) { 1988c87c5fbaSopenharmony_ci coap_session_t *s, *rtmp; 1989c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 1990c87c5fbaSopenharmony_ci SESSIONS_ITER(ctx->sessions, s, rtmp) { 1991c87c5fbaSopenharmony_ci if (s->ifindex == ifindex) { 1992c87c5fbaSopenharmony_ci if (s->sock.flags & COAP_SOCKET_MULTICAST) { 1993c87c5fbaSopenharmony_ci if (coap_address_equals(&s->sock.mcast_addr, remote_addr)) 1994c87c5fbaSopenharmony_ci return s; 1995c87c5fbaSopenharmony_ci } else if (coap_address_equals(&s->addr_info.remote, remote_addr)) 1996c87c5fbaSopenharmony_ci return s; 1997c87c5fbaSopenharmony_ci } 1998c87c5fbaSopenharmony_ci } 1999c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 2000c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 2001c87c5fbaSopenharmony_ci coap_endpoint_t *ep; 2002c87c5fbaSopenharmony_ci 2003c87c5fbaSopenharmony_ci LL_FOREACH(ctx->endpoint, ep) { 2004c87c5fbaSopenharmony_ci SESSIONS_ITER(ep->sessions, s, rtmp) { 2005c87c5fbaSopenharmony_ci if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote, 2006c87c5fbaSopenharmony_ci remote_addr)) 2007c87c5fbaSopenharmony_ci return s; 2008c87c5fbaSopenharmony_ci } 2009c87c5fbaSopenharmony_ci } 2010c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 2011c87c5fbaSopenharmony_ci return NULL; 2012c87c5fbaSopenharmony_ci} 2013c87c5fbaSopenharmony_ci 2014c87c5fbaSopenharmony_ci#ifndef INET6_ADDRSTRLEN 2015c87c5fbaSopenharmony_ci#define INET6_ADDRSTRLEN 46 2016c87c5fbaSopenharmony_ci#endif 2017c87c5fbaSopenharmony_ciconst char * 2018c87c5fbaSopenharmony_cicoap_session_str(const coap_session_t *session) { 2019c87c5fbaSopenharmony_ci static char szSession[2 * (INET6_ADDRSTRLEN + 8) + 24]; 2020c87c5fbaSopenharmony_ci char *p = szSession, *end = szSession + sizeof(szSession); 2021c87c5fbaSopenharmony_ci if (coap_print_addr(&session->addr_info.local, 2022c87c5fbaSopenharmony_ci (unsigned char *)p, end - p) > 0) 2023c87c5fbaSopenharmony_ci p += strlen(p); 2024c87c5fbaSopenharmony_ci if (p + 6 < end) { 2025c87c5fbaSopenharmony_ci strcpy(p, " <-> "); 2026c87c5fbaSopenharmony_ci p += 5; 2027c87c5fbaSopenharmony_ci } 2028c87c5fbaSopenharmony_ci if (p + 1 < end) { 2029c87c5fbaSopenharmony_ci if (coap_print_addr(&session->addr_info.remote, 2030c87c5fbaSopenharmony_ci (unsigned char *)p, end - p) > 0) 2031c87c5fbaSopenharmony_ci p += strlen(p); 2032c87c5fbaSopenharmony_ci } 2033c87c5fbaSopenharmony_ci if (session->ifindex > 0 && p + 1 < end) 2034c87c5fbaSopenharmony_ci p += snprintf(p, end - p, " (if%d)", session->ifindex); 2035c87c5fbaSopenharmony_ci if (p + 6 < end) { 2036c87c5fbaSopenharmony_ci strcpy(p, " "); 2037c87c5fbaSopenharmony_ci p++; 2038c87c5fbaSopenharmony_ci strcpy(p, coap_proto_name(session->proto)); 2039c87c5fbaSopenharmony_ci } 2040c87c5fbaSopenharmony_ci 2041c87c5fbaSopenharmony_ci return szSession; 2042c87c5fbaSopenharmony_ci} 2043c87c5fbaSopenharmony_ci 2044c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT 2045c87c5fbaSopenharmony_ciconst char * 2046c87c5fbaSopenharmony_cicoap_endpoint_str(const coap_endpoint_t *endpoint) { 2047c87c5fbaSopenharmony_ci static char szEndpoint[128]; 2048c87c5fbaSopenharmony_ci char *p = szEndpoint, *end = szEndpoint + sizeof(szEndpoint); 2049c87c5fbaSopenharmony_ci if (coap_print_addr(&endpoint->bind_addr, (unsigned char *)p, end - p) > 0) 2050c87c5fbaSopenharmony_ci p += strlen(p); 2051c87c5fbaSopenharmony_ci if (p + 6 < end) { 2052c87c5fbaSopenharmony_ci if (endpoint->proto == COAP_PROTO_UDP) { 2053c87c5fbaSopenharmony_ci strcpy(p, " UDP"); 2054c87c5fbaSopenharmony_ci p += 4; 2055c87c5fbaSopenharmony_ci } else if (endpoint->proto == COAP_PROTO_DTLS) { 2056c87c5fbaSopenharmony_ci strcpy(p, " DTLS"); 2057c87c5fbaSopenharmony_ci p += 5; 2058c87c5fbaSopenharmony_ci } else { 2059c87c5fbaSopenharmony_ci strcpy(p, " NONE"); 2060c87c5fbaSopenharmony_ci p += 5; 2061c87c5fbaSopenharmony_ci } 2062c87c5fbaSopenharmony_ci } 2063c87c5fbaSopenharmony_ci 2064c87c5fbaSopenharmony_ci return szEndpoint; 2065c87c5fbaSopenharmony_ci} 2066c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */ 2067c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT 2068c87c5fbaSopenharmony_civoid 2069c87c5fbaSopenharmony_cicoap_session_set_no_observe_cancel(coap_session_t *session) { 2070c87c5fbaSopenharmony_ci session->no_observe_cancel = 1; 2071c87c5fbaSopenharmony_ci} 2072c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */ 2073c87c5fbaSopenharmony_ci#endif /* COAP_SESSION_C_ */ 2074