libcoap  4.3.0rc2
coap_session.c
Go to the documentation of this file.
1 /* session.c -- Session management for libcoap
2 *
3 * Copyright (C) 2017 Jean-Claue Michelou <jcm@spinetix.com>
4 *
5 * This file is part of the CoAP library libcoap. Please see
6 * README for terms of use.
7 */
8 
9 #include "coap3/coap_internal.h"
10 
11 #ifndef COAP_SESSION_C_
12 #define COAP_SESSION_C_
13 
14 #include <stdio.h>
15 
16 #ifdef COAP_EPOLL_SUPPORT
17 #include <sys/epoll.h>
18 #include <sys/timerfd.h>
19 #endif /* COAP_EPOLL_SUPPORT */
20 #include <errno.h>
21 
22 void
23 coap_session_set_max_retransmit (coap_session_t *session, unsigned int value) {
24  if (value > 0)
25  session->max_retransmit = value;
26  coap_log(LOG_DEBUG, "***%s: session max_retransmit set to %d\n",
27  coap_session_str(session), session->max_retransmit);
28  return;
29 }
30 
31 void
33  if (value.integer_part > 0 && value.fractional_part < 1000)
34  session->ack_timeout = value;
35  coap_log(LOG_DEBUG, "***%s: session ack_timeout set to %d.%03d\n",
36  coap_session_str(session), session->ack_timeout.integer_part,
37  session->ack_timeout.fractional_part);
38  return;
39 }
40 
41 void
43  coap_fixed_point_t value) {
44  if (value.integer_part > 0 && value.fractional_part < 1000)
45  session->ack_random_factor = value;
46  coap_log(LOG_DEBUG, "***%s: session ack_random_factor set to %d.%03d\n",
49  return;
50 }
51 
52 unsigned int
54  return session->max_retransmit;
55 }
56 
59  return session->ack_timeout;
60 }
61 
64  return session->ack_random_factor;
65 }
66 
69  ++session->ref;
70  return session;
71 }
72 
73 void
75  if (session) {
76 #ifndef __COVERITY__
77  assert(session->ref > 0);
78  if (session->ref > 0)
79  --session->ref;
80  if (session->ref == 0 && session->type == COAP_SESSION_TYPE_CLIENT)
81  coap_session_free(session);
82 #else /* __COVERITY__ */
83  /* Coverity scan is fooled by the reference counter leading to
84  * false positives for USE_AFTER_FREE. */
85  --session->ref;
86  __coverity_negative_sink__(session->ref);
87  /* Indicate that resources are released properly. */
88  if (session->ref == 0 && session->type == COAP_SESSION_TYPE_CLIENT) {
89  __coverity_free__(session);
90  }
91 #endif /* __COVERITY__ */
92  }
93 }
94 
95 void
96 coap_session_set_app_data(coap_session_t *session, void *app_data) {
97  assert(session);
98  session->app = app_data;
99 }
100 
101 void *
103  assert(session);
104  return session->app;
105 }
106 
107 static coap_session_t *
109  const coap_addr_hash_t *addr_hash, const coap_address_t *local_addr,
110  const coap_address_t *remote_addr, int ifindex, coap_context_t *context,
111  coap_endpoint_t *endpoint) {
113  if (!session)
114  return NULL;
115  memset(session, 0, sizeof(*session));
116  session->proto = proto;
117  session->type = type;
118  if (addr_hash)
119  memcpy(&session->addr_hash, addr_hash, sizeof(session->addr_hash));
120  else
121  memset(&session->addr_hash, 0, sizeof(session->addr_hash));
122  if (local_addr)
123  coap_address_copy(&session->addr_info.local, local_addr);
124  else
125  coap_address_init(&session->addr_info.local);
126  if (remote_addr)
127  coap_address_copy(&session->addr_info.remote, remote_addr);
128  else
130  session->ifindex = ifindex;
131  session->context = context;
132  session->endpoint = endpoint;
133  session->block_mode = context->block_mode;
134  if (endpoint)
135  session->mtu = endpoint->default_mtu;
136  else
137  session->mtu = COAP_DEFAULT_MTU;
138  if (proto == COAP_PROTO_DTLS) {
139  session->tls_overhead = 29;
140  if (session->tls_overhead >= session->mtu) {
141  session->tls_overhead = session->mtu;
142  coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n");
143  }
144  }
148  session->dtls_event = -1;
149  session->last_ping_mid = COAP_INVALID_MID;
150 
151  /* initialize message id */
152  coap_prng((unsigned char *)&session->tx_mid, sizeof(session->tx_mid));
153 
154  return session;
155 }
156 
158  coap_queue_t *q, *tmp;
159  coap_cache_entry_t *cp, *ctmp;
160  coap_lg_xmit_t *lq, *ltmp;
161  coap_lg_crcv_t *cq, *etmp;
162  coap_lg_srcv_t *sq, *stmp;
163 
164  /* Need to do this before (D)TLS and socket is closed down */
165  LL_FOREACH_SAFE(session->lg_crcv, cq, etmp) {
166  if (cq->observe_set) {
167  /* Need to close down observe */
168  if (coap_cancel_observe(session, cq->app_token, COAP_MESSAGE_NON)) {
169  /* Need to delete node we set up for NON */
170  coap_queue_t *queue = session->context->sendqueue;
171 
172  while (queue) {
173  if (queue->session == session) {
174  coap_delete_node(queue);
175  break;
176  }
177  queue = queue->next;
178  }
179  }
180  }
181  LL_DELETE(session->lg_crcv, cq);
182  coap_block_delete_lg_crcv(session, cq);
183  }
184 
185  if (session->partial_pdu)
186  coap_delete_pdu(session->partial_pdu);
187  if (session->proto == COAP_PROTO_DTLS)
188  coap_dtls_free_session(session);
189 #if !COAP_DISABLE_TCP
190  else if (session->proto == COAP_PROTO_TLS)
191  coap_tls_free_session(session);
192 #endif /* !COAP_DISABLE_TCP */
193  if (session->sock.flags != COAP_SOCKET_EMPTY)
194  coap_socket_close(&session->sock);
195  if (session->psk_identity)
196  coap_free(session->psk_identity);
197  if (session->psk_key)
198  coap_free(session->psk_key);
199  if (session->psk_hint)
200  coap_free(session->psk_hint);
201 
202  HASH_ITER(hh, session->context->cache, cp, ctmp) {
203  /* cp->session is NULL if not session based */
204  if (cp->session == session) {
205  coap_delete_cache_entry(session->context, cp);
206  }
207  }
208  LL_FOREACH_SAFE(session->delayqueue, q, tmp) {
209  if (q->pdu->type==COAP_MESSAGE_CON && session->context && session->context->nack_handler)
210  session->context->nack_handler(session->context, session, q->pdu, session->proto == COAP_PROTO_DTLS ? COAP_NACK_TLS_FAILED : COAP_NACK_NOT_DELIVERABLE, q->id);
211  coap_delete_node(q);
212  }
213  LL_FOREACH_SAFE(session->lg_xmit, lq, ltmp) {
214  LL_DELETE(session->lg_xmit, lq);
215  coap_block_delete_lg_xmit(session, lq);
216  }
217  LL_FOREACH_SAFE(session->lg_srcv, sq, stmp) {
218  LL_DELETE(session->lg_srcv, sq);
219  coap_block_delete_lg_srcv(session, sq);
220  }
221 }
222 
224  if (!session)
225  return;
226  assert(session->ref == 0);
227  if (session->ref)
228  return;
229  coap_session_mfree(session);
230  if (session->endpoint) {
231  if (session->endpoint->sessions)
232  SESSIONS_DELETE(session->endpoint->sessions, session);
233  } else if (session->context) {
234  if (session->context->sessions)
235  SESSIONS_DELETE(session->context->sessions, session);
236  }
237  coap_log(LOG_DEBUG, "***%s: session closed\n", coap_session_str(session));
238 
239  coap_free_type(COAP_SESSION, session);
240 }
241 
243  size_t max_with_header = (size_t)(session->mtu - session->tls_overhead);
244 #if COAP_DISABLE_TCP
245  return max_with_header > 4 ? max_with_header - 4 : 0;
246 #else /* !COAP_DISABLE_TCP */
247  if (COAP_PROTO_NOT_RELIABLE(session->proto))
248  return max_with_header > 4 ? max_with_header - 4 : 0;
249  /* we must assume there is no token to be on the safe side */
250  if (max_with_header <= 2)
251  return 0;
252  else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP0 + 2)
253  return max_with_header - 2;
254  else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP8 + 3)
255  return max_with_header - 3;
256  else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP16 + 4)
257  return max_with_header - 4;
258  else
259  return max_with_header - 6;
260 #endif /* !COAP_DISABLE_TCP */
261 }
262 
263 void coap_session_set_mtu(coap_session_t *session, unsigned mtu) {
264 #if defined(WITH_CONTIKI) || defined(WITH_LWIP)
265  if (mtu > COAP_MAX_MESSAGE_SIZE_TCP16 + 4)
266  mtu = COAP_MAX_MESSAGE_SIZE_TCP16 + 4;
267 #endif
268  session->mtu = mtu;
269  if (session->tls_overhead >= session->mtu) {
270  session->tls_overhead = session->mtu;
271  coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n");
272  }
273 }
274 
275 ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen) {
276  ssize_t bytes_written;
277 
278  coap_socket_t *sock = &session->sock;
279  if (sock->flags == COAP_SOCKET_EMPTY) {
280  assert(session->endpoint != NULL);
281  sock = &session->endpoint->sock;
282  }
283 
284  bytes_written = coap_socket_send(sock, session, data, datalen);
285  if (bytes_written == (ssize_t)datalen) {
286  coap_ticks(&session->last_rx_tx);
287  coap_log(LOG_DEBUG, "* %s: sent %zd bytes\n",
288  coap_session_str(session), datalen);
289  } else {
290  coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes\n",
291  coap_session_str(session), datalen);
292  }
293  return bytes_written;
294 }
295 
296 ssize_t coap_session_write(coap_session_t *session, const uint8_t *data, size_t datalen) {
297  ssize_t bytes_written = coap_socket_write(&session->sock, data, datalen);
298  if (bytes_written > 0) {
299  coap_ticks(&session->last_rx_tx);
300  coap_log(LOG_DEBUG, "* %s: sent %zd bytes\n",
301  coap_session_str(session), datalen);
302  } else if (bytes_written < 0) {
303  coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes\n",
304  coap_session_str(session), datalen );
305  }
306  return bytes_written;
307 }
308 
309 ssize_t
311  coap_queue_t *node)
312 {
313  if ( node ) {
314  coap_queue_t *removed = NULL;
315  coap_remove_from_queue(&session->context->sendqueue, session, node->id, &removed);
316  assert(removed == node);
318  node->session = NULL;
319  node->t = 0;
320  } else {
321  coap_queue_t *q = NULL;
322  /* Check that the same mid is not getting re-used in violation of RFC7252 */
323  LL_FOREACH(session->delayqueue, q) {
324  if (q->id == pdu->mid) {
325  coap_log(LOG_ERR, "** %s: mid=0x%x: already in-use - dropped\n",
326  coap_session_str(session), pdu->mid);
327  return COAP_INVALID_MID;
328  }
329  }
330  node = coap_new_node();
331  if (node == NULL)
332  return COAP_INVALID_MID;
333  node->id = pdu->mid;
334  node->pdu = pdu;
335  if (pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) {
336  uint8_t r;
337  coap_prng(&r, sizeof(r));
338  /* add timeout in range [ACK_TIMEOUT...ACK_TIMEOUT * ACK_RANDOM_FACTOR] */
339  node->timeout = coap_calc_timeout(session, r);
340  }
341  }
342  LL_APPEND(session->delayqueue, node);
343  coap_log(LOG_DEBUG, "** %s: mid=0x%x: delayed\n",
344  coap_session_str(session), node->id);
345  return COAP_PDU_DELAYED;
346 }
347 
348 #if !COAP_DISABLE_TCP
350  coap_pdu_t *pdu;
351  uint8_t buf[4];
352  assert(COAP_PROTO_RELIABLE(session->proto));
353  coap_log(LOG_DEBUG, "***%s: sending CSM\n", coap_session_str(session));
354  session->state = COAP_SESSION_STATE_CSM;
355  session->partial_write = 0;
356  if (session->mtu == 0)
357  session->mtu = COAP_DEFAULT_MTU; /* base value */
359  if ( pdu == NULL
361  coap_encode_var_safe(buf, sizeof(buf),
362  COAP_DEFAULT_MAX_PDU_RX_SIZE), buf) == 0
364  coap_encode_var_safe(buf, sizeof(buf),
365  0), buf) == 0
366  || coap_pdu_encode_header(pdu, session->proto) == 0
367  ) {
369  } else {
370  ssize_t bytes_written = coap_session_send_pdu(session, pdu);
371  if (bytes_written != (ssize_t)pdu->used_size + pdu->hdr_size)
373  }
374  if (pdu)
375  coap_delete_pdu(pdu);
376 }
377 #endif /* !COAP_DISABLE_TCP */
378 
380  coap_pdu_t *ping = NULL;
381  if (session->state != COAP_SESSION_STATE_ESTABLISHED)
382  return COAP_INVALID_MID;
383  if (COAP_PROTO_NOT_RELIABLE(session->proto)) {
384  uint16_t mid = coap_new_message_id (session);
385  ping = coap_pdu_init(COAP_MESSAGE_CON, 0, mid, 0);
386  }
387 #if !COAP_DISABLE_TCP
388  else {
390  }
391 #endif /* !COAP_DISABLE_TCP */
392  if (!ping)
393  return COAP_INVALID_MID;
394  return coap_send(session, ping);
395 }
396 
398  if (session->state != COAP_SESSION_STATE_ESTABLISHED) {
399  coap_log(LOG_DEBUG, "***%s: session connected\n",
400  coap_session_str(session));
401  if (session->state == COAP_SESSION_STATE_CSM)
403  }
404 
406  session->partial_write = 0;
407 
408  if ( session->proto==COAP_PROTO_DTLS) {
409  session->tls_overhead = coap_dtls_get_overhead(session);
410  if (session->tls_overhead >= session->mtu) {
411  session->tls_overhead = session->mtu;
412  coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n");
413  }
414  }
415 
416  while (session->delayqueue && session->state == COAP_SESSION_STATE_ESTABLISHED) {
417  ssize_t bytes_written;
418  coap_queue_t *q = session->delayqueue;
419  if (q->pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) {
420  if (session->con_active >= COAP_DEFAULT_NSTART)
421  break;
422  session->con_active++;
423  }
424  /* Take entry off the queue */
425  session->delayqueue = q->next;
426  q->next = NULL;
427 
428  coap_log(LOG_DEBUG, "** %s: mid=0x%x: transmitted after delay\n",
429  coap_session_str(session), (int)q->pdu->mid);
430  bytes_written = coap_session_send_pdu(session, q->pdu);
431  if (q->pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) {
432  if (coap_wait_ack(session->context, session, q) >= 0)
433  q = NULL;
434  }
435  if (COAP_PROTO_NOT_RELIABLE(session->proto)) {
436  if (q)
437  coap_delete_node(q);
438  if (bytes_written < 0)
439  break;
440  } else {
441  if (bytes_written <= 0 || (size_t)bytes_written < q->pdu->used_size + q->pdu->hdr_size) {
442  q->next = session->delayqueue;
443  session->delayqueue = q;
444  if (bytes_written > 0)
445  session->partial_write = (size_t)bytes_written;
446  break;
447  } else {
448  coap_delete_node(q);
449  }
450  }
451  }
452 }
453 
455 #if !COAP_DISABLE_TCP
456  coap_session_state_t state = session->state;
457 #endif /* !COAP_DISABLE_TCP */
458 
459  coap_log(LOG_DEBUG, "***%s: session disconnected (reason %d)\n",
460  coap_session_str(session), reason);
461  coap_delete_observers( session->context, session );
462 
463  if ( session->tls) {
464  if (session->proto == COAP_PROTO_DTLS)
465  coap_dtls_free_session(session);
466 #if !COAP_DISABLE_TCP
467  else if (session->proto == COAP_PROTO_TLS)
468  coap_tls_free_session(session);
469 #endif /* !COAP_DISABLE_TCP */
470  session->tls = NULL;
471  }
472 
473  if (session->proto == COAP_PROTO_UDP)
475  else
476  session->state = COAP_SESSION_STATE_NONE;
477 
478  session->con_active = 0;
479 
480  if (session->partial_pdu) {
481  coap_delete_pdu(session->partial_pdu);
482  session->partial_pdu = NULL;
483  }
484  session->partial_read = 0;
485 
486  while (session->delayqueue) {
487  coap_queue_t *q = session->delayqueue;
488  session->delayqueue = q->next;
489  q->next = NULL;
490  coap_log(LOG_DEBUG, "** %s: mid=0x%x: not transmitted after disconnect\n",
491  coap_session_str(session), q->id);
492  if (q->pdu->type==COAP_MESSAGE_CON
493  && COAP_PROTO_NOT_RELIABLE(session->proto)
494  && reason == COAP_NACK_ICMP_ISSUE)
495  {
496  /* Make sure that we try a re-transmit later on ICMP error */
497  if (coap_wait_ack(session->context, session, q) >= 0) {
498  if (session->context->nack_handler) {
499  session->context->nack_handler(session->context, session, q->pdu,
500  reason, q->id);
501  }
502  q = NULL;
503  }
504  }
505  if (q && q->pdu->type == COAP_MESSAGE_CON
506  && session->context->nack_handler)
507  {
508  session->context->nack_handler(session->context, session, q->pdu,
509  reason, q->id);
510  }
511  if (q)
512  coap_delete_node(q);
513  }
514  if (reason != COAP_NACK_ICMP_ISSUE) {
515  coap_cancel_session_messages(session->context, session, reason);
516  }
517  else if (session->context->nack_handler) {
518  coap_queue_t *q = session->context->sendqueue;
519  while (q) {
520  if (q->session == session) {
521  session->context->nack_handler(session->context, session, q->pdu,
522  reason, q->id);
523  }
524  q = q->next;
525  }
526  }
527 
528 #if !COAP_DISABLE_TCP
529  if (COAP_PROTO_RELIABLE(session->proto)) {
530  if (session->sock.flags != COAP_SOCKET_EMPTY) {
531  coap_socket_close(&session->sock);
532  coap_handle_event(session->context,
535  }
536  if (state != COAP_SESSION_STATE_NONE) {
537  coap_handle_event(session->context,
540  }
541  }
542 #endif /* !COAP_DISABLE_TCP */
543 }
544 
545 static void
547  const coap_addr_tuple_t *addr_info) {
548  memset(addr_hash, 0, sizeof(coap_addr_hash_t));
549  coap_address_copy(&addr_hash->remote, &addr_info->remote);
550  addr_hash->lport = coap_address_get_port(&addr_info->local);
551  addr_hash->proto = proto;
552 }
553 
556  const coap_packet_t *packet, coap_tick_t now) {
557  coap_session_t *session;
558  coap_session_t *rtmp;
559  unsigned int num_idle = 0;
560  unsigned int num_hs = 0;
561  coap_session_t *oldest = NULL;
562  coap_session_t *oldest_hs = NULL;
563  coap_addr_hash_t addr_hash;
564 
565  coap_make_addr_hash(&addr_hash, endpoint->proto, &packet->addr_info);
566  SESSIONS_FIND(endpoint->sessions, addr_hash, session);
567  if (session) {
568  /* Maybe mcast or unicast IP address which is not in the hash */
569  coap_address_copy(&session->addr_info.local, &packet->addr_info.local);
570  session->ifindex = packet->ifindex;
571  session->last_rx_tx = now;
572  return session;
573  }
574 
575  SESSIONS_ITER(endpoint->sessions, session, rtmp) {
576  if (session->ref == 0 && session->delayqueue == NULL) {
577  if (session->type == COAP_SESSION_TYPE_SERVER) {
578  ++num_idle;
579  if (oldest==NULL || session->last_rx_tx < oldest->last_rx_tx)
580  oldest = session;
581 
582  if (session->state == COAP_SESSION_STATE_HANDSHAKE) {
583  ++num_hs;
584  /* See if this is a partial (D)TLS session set up
585  which needs to be cleared down to prevent DOS */
586  if ((session->last_rx_tx + COAP_PARTIAL_SESSION_TIMEOUT_TICKS) < now) {
587  if (oldest_hs == NULL ||
588  session->last_rx_tx < oldest_hs->last_rx_tx)
589  oldest_hs = session;
590  }
591  }
592  }
593  else if (session->type == COAP_SESSION_TYPE_HELLO) {
594  ++num_hs;
595  /* See if this is a partial (D)TLS session set up for Client Hello
596  which needs to be cleared down to prevent DOS */
597  if ((session->last_rx_tx + COAP_PARTIAL_SESSION_TIMEOUT_TICKS) < now) {
598  if (oldest_hs == NULL ||
599  session->last_rx_tx < oldest_hs->last_rx_tx)
600  oldest_hs = session;
601  }
602  }
603  }
604  }
605 
606  if (endpoint->context->max_idle_sessions > 0 &&
607  num_idle >= endpoint->context->max_idle_sessions) {
608  coap_session_free(oldest);
609  }
610  else if (oldest_hs) {
611  coap_log(LOG_WARNING, "***%s: Incomplete session timed out\n",
612  coap_session_str(oldest_hs));
613  coap_session_free(oldest_hs);
614  }
615 
616  if (num_hs > (endpoint->context->max_handshake_sessions ?
617  endpoint->context->max_handshake_sessions :
619  /* Maxed out on number of sessions in (D)TLS negotiation state */
621  "Oustanding sessions in COAP_SESSION_STATE_HANDSHAKE too "
622  "large. New request ignored\n");
623  return NULL;
624  }
625 
626  if (endpoint->proto == COAP_PROTO_DTLS) {
627  /*
628  * Need to check that this actually is a Client Hello before wasting
629  * time allocating and then freeing off session.
630  */
631 
632  /*
633  * Generic header structure of the DTLS record layer.
634  * typedef struct __attribute__((__packed__)) {
635  * uint8_t content_type; content type of the included message
636  * uint16_t version; Protocol version
637  * uint16_t epoch; counter for cipher state changes
638  * uint8_t sequence_number[6]; sequence number
639  * uint16_t length; length of the following fragment
640  * uint8_t handshake; If content_type == DTLS_CT_HANDSHAKE
641  * } dtls_record_handshake_t;
642  */
643 #define OFF_CONTENT_TYPE 0 /* offset of content_type in dtls_record_handshake_t */
644 #define DTLS_CT_ALERT 21 /* Content Type Alert */
645 #define DTLS_CT_HANDSHAKE 22 /* Content Type Handshake */
646 #define OFF_HANDSHAKE_TYPE 13 /* offset of handshake in dtls_record_handshake_t */
647 #define DTLS_HT_CLIENT_HELLO 1 /* Client Hello handshake type */
648 
649 #ifdef WITH_LWIP
650  const uint8_t *payload = (const uint8_t*)packet->pbuf->payload;
651  size_t length = packet->pbuf->len;
652 #else /* ! WITH_LWIP */
653  const uint8_t *payload = (const uint8_t*)packet->payload;
654  size_t length = packet->length;
655 #endif /* ! WITH_LWIP */
656  if (length < (OFF_HANDSHAKE_TYPE + 1)) {
658  "coap_dtls_hello: ContentType %d Short Packet (%zu < %d) dropped\n",
659  payload[OFF_CONTENT_TYPE], length,
660  OFF_HANDSHAKE_TYPE + 1);
661  return NULL;
662  }
663  if (payload[OFF_CONTENT_TYPE] != DTLS_CT_HANDSHAKE ||
665  /* only log if not a late alert */
666  if (payload[OFF_CONTENT_TYPE] != DTLS_CT_ALERT)
668  "coap_dtls_hello: ContentType %d Handshake %d dropped\n",
669  payload[OFF_CONTENT_TYPE], payload[OFF_HANDSHAKE_TYPE]);
670  return NULL;
671  }
672  }
673  session = coap_make_session(endpoint->proto, COAP_SESSION_TYPE_SERVER,
674  &addr_hash, &packet->addr_info.local,
675  &packet->addr_info.remote,
676  packet->ifindex, endpoint->context, endpoint);
677  if (session) {
678  session->last_rx_tx = now;
679  if (endpoint->proto == COAP_PROTO_UDP)
681  else if (endpoint->proto == COAP_PROTO_DTLS) {
682  session->type = COAP_SESSION_TYPE_HELLO;
683  }
684  SESSIONS_ADD(endpoint->sessions, session);
685  coap_log(LOG_DEBUG, "***%s: new incoming session\n",
686  coap_session_str(session));
687  }
688  return session;
689 }
690 
693  coap_tick_t now) {
694  if (session) {
695  session->last_rx_tx = now;
696  session->type = COAP_SESSION_TYPE_SERVER;
697  session->tls = coap_dtls_new_server_session(session);
698  if (session->tls) {
700  } else {
701  coap_session_free(session);
702  session = NULL;
703  }
704  }
705  return session;
706 }
707 
708 #ifdef COAP_EPOLL_SUPPORT
709 static void
710 coap_epoll_ctl_add(coap_socket_t *sock,
711  uint32_t events,
712  const char *func
713 ) {
714  int ret;
715  struct epoll_event event;
716  coap_context_t *context;
717 
718  if (sock == NULL)
719  return;
720 
721  context = sock->session ? sock->session->context :
722  sock->endpoint ? sock->endpoint->context : NULL;
723  if (context == NULL)
724  return;
725 
726  /* Needed if running 32bit as ptr is only 32bit */
727  memset(&event, 0, sizeof(event));
728  event.events = events;
729  event.data.ptr = sock;
730 
731  ret = epoll_ctl(context->epfd, EPOLL_CTL_ADD, sock->fd, &event);
732  if (ret == -1) {
734  "%s: epoll_ctl ADD failed: %s (%d)\n",
735  func,
736  coap_socket_strerror(), errno);
737  }
738 }
739 #endif /* COAP_EPOLL_SUPPORT */
740 
741 static coap_session_t *
743  coap_context_t *ctx,
744  const coap_address_t *local_if,
745  const coap_address_t *server,
746  coap_proto_t proto
747 ) {
748  coap_session_t *session = NULL;
749 
750  assert(server);
751 
752  switch(proto) {
753  case COAP_PROTO_UDP:
754  break;
755  case COAP_PROTO_DTLS:
756  if (!coap_dtls_is_supported()) {
757  coap_log(LOG_CRIT, "coap_new_client_session*: DTLS not supported\n");
758  return NULL;
759  }
760  break;
761  case COAP_PROTO_TCP:
762  if (!coap_tcp_is_supported()) {
763  coap_log(LOG_CRIT, "coap_new_client_session*: TCP not supported\n");
764  return NULL;
765  }
766  break;
767  case COAP_PROTO_TLS:
768  if (!coap_tls_is_supported()) {
769  coap_log(LOG_CRIT, "coap_new_client_session*: TLS not supported\n");
770  return NULL;
771  }
772  break;
773  case COAP_PROTO_NONE:
774  default:
775  assert(0);
776  break;
777  }
778  session = coap_make_session(proto, COAP_SESSION_TYPE_CLIENT, NULL,
779  local_if, server, 0, ctx, NULL);
780  if (!session)
781  goto error;
782 
783  coap_session_reference(session);
784 
785  if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) {
786  if (!coap_socket_connect_udp(&session->sock, local_if, server,
788  &session->addr_info.local, &session->addr_info.remote)) {
789  goto error;
790  }
791 #if !COAP_DISABLE_TCP
792  } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) {
793  if (!coap_socket_connect_tcp1(&session->sock, local_if, server,
795  &session->addr_info.local, &session->addr_info.remote)) {
796  goto error;
797  }
798 #endif /* !COAP_DISABLE_TCP */
799  }
800 
801 #ifdef COAP_EPOLL_SUPPORT
802  session->sock.session = session;
803  coap_epoll_ctl_add(&session->sock,
804  EPOLLIN |
805  ((session->sock.flags & COAP_SOCKET_WANT_CONNECT) ?
806  EPOLLOUT : 0),
807  __func__);
808 #endif /* COAP_EPOLL_SUPPORT */
809 
811  if (local_if)
812  session->sock.flags |= COAP_SOCKET_BOUND;
813  SESSIONS_ADD(ctx->sessions, session);
814  return session;
815 
816 error:
817  coap_session_release(session);
818  return NULL;
819 }
820 
821 static coap_session_t *
823  if (session->proto == COAP_PROTO_UDP) {
825  } else if (session->proto == COAP_PROTO_DTLS) {
826  session->tls = coap_dtls_new_client_session(session);
827  if (session->tls) {
829  } else {
830  /* Need to free session object. As a new session may not yet
831  * have been referenced, we call coap_session_reference() first
832  * before trying to release the object.
833  */
834  coap_session_reference(session);
835  coap_session_release(session);
836  return NULL;
837  }
838 #if !COAP_DISABLE_TCP
839  } else {
840  if (session->proto == COAP_PROTO_TCP || session->proto == COAP_PROTO_TLS) {
841  if (session->sock.flags & COAP_SOCKET_WANT_CONNECT) {
843  } else if (session->proto == COAP_PROTO_TLS) {
844  int connected = 0;
845  session->tls = coap_tls_new_client_session(session, &connected);
846  if (session->tls) {
848  if (connected)
849  coap_session_send_csm(session);
850  } else {
851  /* Need to free session object. As a new session may not yet
852  * have been referenced, we call coap_session_reference()
853  * first before trying to release the object.
854  */
855  coap_session_reference(session);
856  coap_session_release(session);
857  return NULL;
858  }
859  } else {
860  coap_session_send_csm(session);
861  }
862  }
863 #endif /* !COAP_DISABLE_TCP */
864  }
865  coap_ticks(&session->last_rx_tx);
866  return session;
867 }
868 
869 static coap_session_t *
871 #if !COAP_DISABLE_TCP
872  if (session->proto == COAP_PROTO_TCP || session->proto == COAP_PROTO_TLS)
874  if (session->proto == COAP_PROTO_TCP) {
875  coap_session_send_csm(session);
876  } else if (session->proto == COAP_PROTO_TLS) {
877  int connected = 0;
878  session->tls = coap_tls_new_server_session(session, &connected);
879  if (session->tls) {
881  if (connected) {
883  coap_session_send_csm(session);
884  }
885  } else {
886  /* Need to free session object. As a new session may not yet
887  * have been referenced, we call coap_session_reference() first
888  * before trying to release the object.
889  */
890  coap_session_reference(session);
891  coap_session_release(session);
892  session = NULL;
893  }
894  }
895 #endif /* COAP_DISABLE_TCP */
896  return session;
897 }
898 
900  coap_context_t *ctx,
901  const coap_address_t *local_if,
902  const coap_address_t *server,
903  coap_proto_t proto
904 ) {
905  coap_session_t *session = coap_session_create_client(ctx, local_if, server, proto);
906  if (session) {
907  coap_log(LOG_DEBUG, "***%s: new outgoing session\n",
908  coap_session_str(session));
909  session = coap_session_connect(session);
910  }
911  return session;
912 }
913 
915  coap_context_t *ctx,
916  const coap_address_t *local_if,
917  const coap_address_t *server,
918  coap_proto_t proto,
919  const char *identity,
920  const uint8_t *key,
921  unsigned key_len
922 ) {
923  coap_dtls_cpsk_t setup_data;
924 
925  memset (&setup_data, 0, sizeof(setup_data));
926 
927  if (identity) {
928  setup_data.psk_info.identity.s = (const uint8_t *)identity;
929  setup_data.psk_info.identity.length = strlen(identity);
930  }
931 
932  if (key && key_len > 0) {
933  setup_data.psk_info.key.s = key;
934  setup_data.psk_info.key.length = key_len;
935  }
936 
937  return coap_new_client_session_psk2(ctx, local_if, server,
938  proto, &setup_data);
939 }
940 
942  coap_context_t *ctx,
943  const coap_address_t *local_if,
944  const coap_address_t *server,
945  coap_proto_t proto,
946  coap_dtls_cpsk_t *setup_data
947 ) {
948  coap_session_t *session = coap_session_create_client(ctx, local_if,
949  server, proto);
950 
951  if (!session)
952  return NULL;
953 
954  session->cpsk_setup_data = *setup_data;
955  if (setup_data->psk_info.identity.s) {
956  session->psk_identity =
958  setup_data->psk_info.identity.length);
959  if (!session->psk_identity) {
960  coap_log(LOG_WARNING, "Cannot store session Identity (PSK)\n");
961  coap_session_release(session);
962  return NULL;
963  }
964  }
965  else if (coap_dtls_is_supported()) {
966  coap_log(LOG_WARNING, "Identity (PSK) not defined\n");
967  coap_session_release(session);
968  return NULL;
969  }
970 
971  if (setup_data->psk_info.key.s && setup_data->psk_info.key.length > 0) {
972  session->psk_key = coap_new_bin_const(setup_data->psk_info.key.s,
973  setup_data->psk_info.key.length);
974  if (!session->psk_key) {
975  coap_log(LOG_WARNING, "Cannot store session pre-shared key (PSK)\n");
976  coap_session_release(session);
977  return NULL;
978  }
979  }
980  else if (coap_dtls_is_supported()) {
981  coap_log(LOG_WARNING, "Pre-shared key (PSK) not defined\n");
982  coap_session_release(session);
983  return NULL;
984  }
985 
986  if (coap_dtls_is_supported()) {
987  if (!coap_dtls_context_set_cpsk(ctx, setup_data)) {
988  coap_session_release(session);
989  return NULL;
990  }
991  }
992  coap_log(LOG_DEBUG, "***%s: new outgoing session\n",
993  coap_session_str(session));
994  return coap_session_connect(session);
995 }
996 
998  const coap_bin_const_t *psk_hint
999 ) {
1000  /* We may be refreshing the hint with the same hint */
1001  coap_bin_const_t *old_psk_hint = session->psk_hint;
1002 
1003  if (psk_hint && psk_hint->s) {
1004  if (session->psk_hint) {
1005  if (coap_binary_equal(session->psk_hint, psk_hint))
1006  return 1;
1007  }
1008  session->psk_hint = coap_new_bin_const(psk_hint->s,
1009  psk_hint->length);
1010  if (!session->psk_hint) {
1011  coap_log(LOG_ERR, "No memory to store identity hint (PSK)\n");
1012  if (old_psk_hint)
1013  coap_delete_bin_const(old_psk_hint);
1014  return 0;
1015  }
1016  }
1017  else {
1018  session->psk_hint = NULL;
1019  }
1020  if (old_psk_hint)
1021  coap_delete_bin_const(old_psk_hint);
1022 
1023  return 1;
1024 }
1025 
1027  const coap_bin_const_t *psk_key
1028 ) {
1029  /* We may be refreshing the key with the same key */
1030  coap_bin_const_t *old_psk_key = session->psk_key;
1031 
1032  if (psk_key && psk_key->s) {
1033  if (session->psk_key) {
1034  if (coap_binary_equal(session->psk_key, psk_key))
1035  return 1;
1036  }
1037  session->psk_key = coap_new_bin_const(psk_key->s, psk_key->length);
1038  if (!session->psk_key) {
1039  coap_log(LOG_ERR, "No memory to store pre-shared key (PSK)\n");
1040  if (old_psk_key)
1041  coap_delete_bin_const(old_psk_key);
1042  return 0;
1043  }
1044  }
1045  else {
1046  session->psk_key = NULL;
1047  }
1048  if (old_psk_key)
1049  coap_delete_bin_const(old_psk_key);
1050 
1051  return 1;
1052 }
1053 
1054 const coap_bin_const_t *
1056  if (session)
1057  return session->psk_hint;
1058  return NULL;
1059 }
1060 
1061 const coap_bin_const_t *
1063  if (session)
1064  return session->psk_key;
1065  return NULL;
1066 }
1067 
1069  coap_context_t *ctx,
1070  const coap_address_t *local_if,
1071  const coap_address_t *server,
1072  coap_proto_t proto,
1073  coap_dtls_pki_t* setup_data
1074 ) {
1075  coap_session_t *session;
1076 
1077  if (coap_dtls_is_supported()) {
1078  if (!setup_data) {
1079  return NULL;
1080  } else {
1081  if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION) {
1082  coap_log(LOG_ERR,
1083  "coap_new_client_session_pki: Wrong version of setup_data\n");
1084  return NULL;
1085  }
1086  }
1087 
1088  }
1089  session = coap_session_create_client(ctx, local_if, server, proto);
1090 
1091  if (!session) {
1092  return NULL;
1093  }
1094 
1095  if (coap_dtls_is_supported()) {
1096  /* we know that setup_data is not NULL */
1097  if (!coap_dtls_context_set_pki(ctx, setup_data, COAP_DTLS_ROLE_CLIENT)) {
1098  coap_session_release(session);
1099  return NULL;
1100  }
1101  }
1102  coap_log(LOG_DEBUG, "***%s: new outgoing session\n",
1103  coap_session_str(session));
1104  return coap_session_connect(session);
1105 }
1106 
1108  coap_context_t *ctx,
1109  coap_endpoint_t *ep
1110 ) {
1111  coap_session_t *session;
1113  NULL, NULL, NULL, 0, ctx, ep );
1114  if (!session)
1115  goto error;
1116 
1117 #if !COAP_DISABLE_TCP
1118  if (!coap_socket_accept_tcp(&ep->sock, &session->sock,
1119  &session->addr_info.local,
1120  &session->addr_info.remote))
1121  goto error;
1122  coap_make_addr_hash(&session->addr_hash, session->proto, &session->addr_info);
1123 
1124 #endif /* !COAP_DISABLE_TCP */
1127 #ifdef COAP_EPOLL_SUPPORT
1128  session->sock.session = session;
1129  coap_epoll_ctl_add(&session->sock,
1130  EPOLLIN,
1131  __func__);
1132 #endif /* COAP_EPOLL_SUPPORT */
1133  SESSIONS_ADD(ep->sessions, session);
1134  if (session) {
1135  coap_log(LOG_DEBUG, "***%s: new incoming session\n",
1136  coap_session_str(session));
1137  session = coap_session_accept(session);
1138  }
1139  return session;
1140 
1141 error:
1142  coap_session_free(session);
1143  return NULL;
1144 }
1145 
1146 void
1148  const uint8_t *data) {
1149  session->tx_token = coap_decode_var_bytes8(data, len);
1150 }
1151 
1152 void coap_session_new_token(coap_session_t *session, size_t *len,
1153  uint8_t *data) {
1154  *len = coap_encode_var_safe8(data,
1155  sizeof(session->tx_token), ++session->tx_token);
1156 }
1157 
1158 uint16_t
1160  return ++session->tx_mid;
1161 }
1162 
1163 const coap_address_t *
1165  if (session)
1166  return &session->addr_info.remote;
1167  return NULL;
1168 }
1169 
1170 const coap_address_t *
1172  if (session)
1173  return &session->addr_info.local;
1174  return NULL;
1175 }
1176 
1179  if (session)
1180  return session->context;
1181  return NULL;
1182 }
1183 
1186  if (session)
1187  return session->proto;
1188  return 0;
1189 }
1190 
1193  if (session)
1194  return session->type;
1195  return 0;
1196 }
1197 
1198 int
1200  if (session && session->type == COAP_SESSION_TYPE_SERVER) {
1201  coap_session_reference(session);
1202  session->type = COAP_SESSION_TYPE_CLIENT;
1203  return 1;
1204  }
1205  return 0;
1206 }
1207 
1210  if (session)
1211  return session->state;
1212  return 0;
1213 }
1214 
1216  if (session)
1217  return session->ifindex;
1218  return -1;
1219 }
1220 
1222  coap_tls_library_t *tls_lib) {
1223  if (session)
1224  return coap_dtls_get_tls(session, tls_lib);
1225  return NULL;
1226 }
1227 
1228 #ifndef WITH_LWIP
1230 coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto) {
1231  coap_endpoint_t *ep = NULL;
1232 
1233  assert(context);
1234  assert(listen_addr);
1235  assert(proto != COAP_PROTO_NONE);
1236 
1237  if (proto == COAP_PROTO_DTLS && !coap_dtls_is_supported()) {
1238  coap_log(LOG_CRIT, "coap_new_endpoint: DTLS not supported\n");
1239  goto error;
1240  }
1241 
1242  if (proto == COAP_PROTO_TLS && !coap_tls_is_supported()) {
1243  coap_log(LOG_CRIT, "coap_new_endpoint: TLS not supported\n");
1244  goto error;
1245  }
1246 
1247  if (proto == COAP_PROTO_TCP && !coap_tcp_is_supported()) {
1248  coap_log(LOG_CRIT, "coap_new_endpoint: TCP not supported\n");
1249  goto error;
1250  }
1251 
1252  if (proto == COAP_PROTO_DTLS || proto == COAP_PROTO_TLS) {
1253  if (!coap_dtls_context_check_keys_enabled(context)) {
1255  "coap_new_endpoint: one of coap_context_set_psk() or "
1256  "coap_context_set_pki() not called\n");
1257  goto error;
1258  }
1259  }
1260 
1261  ep = coap_malloc_endpoint();
1262  if (!ep) {
1263  coap_log(LOG_WARNING, "coap_new_endpoint: malloc");
1264  goto error;
1265  }
1266 
1267  memset(ep, 0, sizeof(coap_endpoint_t));
1268  ep->context = context;
1269  ep->proto = proto;
1270 
1271  if (proto==COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) {
1272  if (!coap_socket_bind_udp(&ep->sock, listen_addr, &ep->bind_addr))
1273  goto error;
1275 #if !COAP_DISABLE_TCP
1276  } else if (proto==COAP_PROTO_TCP || proto==COAP_PROTO_TLS) {
1277  if (!coap_socket_bind_tcp(&ep->sock, listen_addr, &ep->bind_addr))
1278  goto error;
1280 #endif /* !COAP_DISABLE_TCP */
1281  } else {
1282  coap_log(LOG_CRIT, "coap_new_endpoint: protocol not supported\n");
1283  goto error;
1284  }
1285 
1286  if (LOG_DEBUG <= coap_get_log_level()) {
1287 #ifndef INET6_ADDRSTRLEN
1288 #define INET6_ADDRSTRLEN 40
1289 #endif
1290  unsigned char addr_str[INET6_ADDRSTRLEN + 8];
1291 
1292  if (coap_print_addr(&ep->bind_addr, addr_str, INET6_ADDRSTRLEN + 8)) {
1293  coap_log(LOG_DEBUG, "created %s endpoint %s\n",
1294  ep->proto == COAP_PROTO_TLS ? "TLS "
1295  : ep->proto == COAP_PROTO_TCP ? "TCP "
1296  : ep->proto == COAP_PROTO_DTLS ? "DTLS" : "UDP ",
1297  addr_str);
1298  }
1299  }
1300 
1302 
1304 
1305 #ifdef COAP_EPOLL_SUPPORT
1306  ep->sock.endpoint = ep;
1307  coap_epoll_ctl_add(&ep->sock,
1308  EPOLLIN,
1309  __func__);
1310 #endif /* COAP_EPOLL_SUPPORT */
1311 
1312  LL_PREPEND(context->endpoint, ep);
1313  return ep;
1314 
1315 error:
1316  coap_free_endpoint(ep);
1317  return NULL;
1318 }
1319 
1321  ep->default_mtu = (uint16_t)mtu;
1322 }
1323 
1324 void
1326  if (ep) {
1327  coap_session_t *session, *rtmp;
1328 
1329  SESSIONS_ITER_SAFE(ep->sessions, session, rtmp) {
1330  assert(session->ref == 0);
1331  if (session->ref == 0) {
1332  coap_session_free(session);
1333  }
1334  }
1335  if (ep->sock.flags != COAP_SOCKET_EMPTY) {
1336  /*
1337  * ep->sock.endpoint is set in coap_new_endpoint().
1338  * ep->sock.session is never set.
1339  *
1340  * session->sock.session is set for both clients and servers (when a
1341  * new session is accepted), but does not affect the endpoint.
1342  *
1343  * So, it is safe to call coap_socket_close() after all the sessions
1344  * have been freed above as we are only working with the endpoint sock.
1345  */
1346 #ifdef COAP_EPOLL_SUPPORT
1347  assert(ep->sock.session == NULL);
1348 #endif /* COAP_EPOLL_SUPPORT */
1349  coap_socket_close(&ep->sock);
1350  }
1351 
1352  if (ep->context && ep->context->endpoint) {
1353  LL_DELETE(ep->context->endpoint, ep);
1354  }
1355  coap_mfree_endpoint(ep);
1356  }
1357 }
1358 #endif /* WITH_LWIP */
1359 
1362  const coap_address_t *remote_addr,
1363  int ifindex) {
1364  coap_session_t *s, *rtmp;
1365  coap_endpoint_t *ep;
1366  SESSIONS_ITER(ctx->sessions, s, rtmp) {
1367  if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote,
1368  remote_addr))
1369  return s;
1370  }
1371  LL_FOREACH(ctx->endpoint, ep) {
1372  SESSIONS_ITER(ep->sessions, s, rtmp) {
1373  if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote,
1374  remote_addr))
1375  return s;
1376  }
1377  }
1378  return NULL;
1379 }
1380 
1381 const char *coap_session_str(const coap_session_t *session) {
1382  static char szSession[2 * (INET6_ADDRSTRLEN + 8) + 24];
1383  char *p = szSession, *end = szSession + sizeof(szSession);
1384  if (coap_print_addr(&session->addr_info.local,
1385  (unsigned char*)p, end - p) > 0)
1386  p += strlen(p);
1387  if (p + 6 < end) {
1388  strcpy(p, " <-> ");
1389  p += 5;
1390  }
1391  if (p + 1 < end) {
1392  if (coap_print_addr(&session->addr_info.remote,
1393  (unsigned char*)p, end - p) > 0)
1394  p += strlen(p);
1395  }
1396  if (session->ifindex > 0 && p + 1 < end)
1397  p += snprintf(p, end - p, " (if%d)", session->ifindex);
1398  if (p + 6 < end) {
1399  if (session->proto == COAP_PROTO_UDP) {
1400  strcpy(p, " UDP ");
1401  p += 4;
1402  } else if (session->proto == COAP_PROTO_DTLS) {
1403  strcpy(p, " DTLS");
1404  p += 5;
1405  } else if (session->proto == COAP_PROTO_TCP) {
1406  strcpy(p, " TCP ");
1407  p += 4;
1408  } else if (session->proto == COAP_PROTO_TLS) {
1409  strcpy(p, " TLS ");
1410  p += 4;
1411  } else {
1412  strcpy(p, " NONE");
1413  p += 5;
1414  }
1415  }
1416 
1417  return szSession;
1418 }
1419 
1420 const char *coap_endpoint_str(const coap_endpoint_t *endpoint) {
1421  static char szEndpoint[128];
1422  char *p = szEndpoint, *end = szEndpoint + sizeof(szEndpoint);
1423  if (coap_print_addr(&endpoint->bind_addr, (unsigned char*)p, end - p) > 0)
1424  p += strlen(p);
1425  if (p + 6 < end) {
1426  if (endpoint->proto == COAP_PROTO_UDP) {
1427  strcpy(p, " UDP");
1428  p += 4;
1429  } else if (endpoint->proto == COAP_PROTO_DTLS) {
1430  strcpy(p, " DTLS");
1431  p += 5;
1432  } else {
1433  strcpy(p, " NONE");
1434  p += 5;
1435  }
1436  }
1437 
1438  return szEndpoint;
1439 }
1440 
1441 #endif /* COAP_SESSION_C_ */
void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
Definition: address.c:100
uint16_t coap_address_get_port(const coap_address_t *addr)
Returns the port from addr in host byte order.
Definition: address.c:31
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
Definition: address.c:58
COAP_STATIC_INLINE void coap_address_copy(coap_address_t *dst, const coap_address_t *src)
Definition: address.h:150
Pulls together all the internal only header files.
int coap_socket_connect_udp(coap_socket_t *sock, const coap_address_t *local_if, const coap_address_t *server, int default_port, coap_address_t *local_addr, coap_address_t *remote_addr)
Definition: coap_io.c:240
void coap_socket_close(coap_socket_t *sock)
Definition: coap_io.c:366
ssize_t coap_socket_send(coap_socket_t *sock, coap_session_t *session, const uint8_t *data, size_t data_len)
Definition: coap_io.c:1510
ssize_t coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len)
Definition: coap_io.c:425
int coap_socket_bind_udp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
Definition: coap_io.c:152
const char * coap_socket_strerror(void)
Definition: coap_io.c:1504
void coap_mfree_endpoint(coap_endpoint_t *ep)
Definition: coap_io.c:147
coap_endpoint_t * coap_malloc_endpoint(void)
Definition: coap_io.c:142
coap_nack_reason_t
Definition: coap_io.h:62
@ COAP_NACK_NOT_DELIVERABLE
Definition: coap_io.h:64
@ COAP_NACK_TLS_FAILED
Definition: coap_io.h:66
@ COAP_NACK_ICMP_ISSUE
Definition: coap_io.h:67
#define COAP_SOCKET_WANT_ACCEPT
non blocking server socket is waiting for accept
#define COAP_SOCKET_NOT_EMPTY
the socket is not empty
#define COAP_SOCKET_BOUND
the socket is bound
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
#define COAP_SOCKET_WANT_CONNECT
non blocking client socket is waiting for connect
#define COAP_SOCKET_CONNECTED
the socket is connected
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
void * coap_dtls_new_server_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:103
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
Definition: coap_notls.c:33
void * coap_dtls_new_client_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:107
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:157
void * coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:161
void * coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:165
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition: coap_notls.c:63
int coap_dtls_context_set_cpsk(coap_context_t *ctx COAP_UNUSED, coap_dtls_cpsk_t *setup_data COAP_UNUSED)
Definition: coap_notls.c:49
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:111
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition: coap_notls.c:74
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:169
unsigned int coap_session_get_max_transmit(const coap_session_t *session)
Get the CoAP maximum retransmit before failure.
Definition: coap_session.c:53
void coap_session_set_max_retransmit(coap_session_t *session, unsigned int value)
Set the CoAP maximum retransmit count before failure.
Definition: coap_session.c:23
coap_mid_t coap_session_send_ping(coap_session_t *session)
Send a ping message for the session.
Definition: coap_session.c:379
#define DTLS_HT_CLIENT_HELLO
#define OFF_HANDSHAKE_TYPE
void coap_session_set_ack_random_factor(coap_session_t *session, coap_fixed_point_t value)
Set the CoAP ack randomize factor.
Definition: coap_session.c:42
coap_fixed_point_t coap_session_get_ack_random_factor(const coap_session_t *session)
Get the CoAP ack randomize factor.
Definition: coap_session.c:63
static void coap_make_addr_hash(coap_addr_hash_t *addr_hash, coap_proto_t proto, const coap_addr_tuple_t *addr_info)
Definition: coap_session.c:546
#define DTLS_CT_HANDSHAKE
static coap_session_t * coap_session_create_client(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto)
Definition: coap_session.c:742
coap_session_t * coap_session_get_by_peer(const coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
void coap_session_set_ack_timeout(coap_session_t *session, coap_fixed_point_t value)
Set the CoAP initial ack response timeout before the next re-transmit.
Definition: coap_session.c:32
#define OFF_CONTENT_TYPE
static coap_session_t * coap_make_session(coap_proto_t proto, coap_session_type_t type, const coap_addr_hash_t *addr_hash, const coap_address_t *local_addr, const coap_address_t *remote_addr, int ifindex, coap_context_t *context, coap_endpoint_t *endpoint)
Definition: coap_session.c:108
static coap_session_t * coap_session_accept(coap_session_t *session)
Definition: coap_session.c:870
static coap_session_t * coap_session_connect(coap_session_t *session)
Definition: coap_session.c:822
coap_fixed_point_t coap_session_get_ack_timeout(const coap_session_t *session)
Get the CoAP initial ack response timeout before the next re-transmit.
Definition: coap_session.c:58
#define INET6_ADDRSTRLEN
#define DTLS_CT_ALERT
#define SESSIONS_ADD(e, obj)
#define SESSIONS_ITER_SAFE(e, el, rtmp)
#define COAP_PARTIAL_SESSION_TIMEOUT_TICKS
#define SESSIONS_DELETE(e, obj)
#define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS
#define SESSIONS_ITER(e, el, rtmp)
#define SESSIONS_FIND(e, k, res)
int coap_tcp_is_supported(void)
Check whether TCP is available.
Definition: coap_tcp.c:31
void coap_block_delete_lg_srcv(coap_session_t *session, coap_lg_srcv_t *lg_srcv)
Definition: block.c:895
void coap_block_delete_lg_crcv(coap_session_t *session, coap_lg_crcv_t *lg_crcv)
Definition: block.c:880
void coap_block_delete_lg_xmit(coap_session_t *session, coap_lg_xmit_t *lg_xmit)
Definition: block.c:908
int coap_cancel_observe(coap_session_t *session, coap_binary_t *token, coap_pdu_type_t type)
Cancel an observe that is being tracked by the client large receive logic when using coap_send_large(...
Definition: block.c:293
void coap_delete_cache_entry(coap_context_t *ctx, coap_cache_entry_t *cache_entry)
Remove a cache-entry from the hash list and free off all the appropriate contents apart from app_data...
Definition: coap_cache.c:205
#define COAP_DEFAULT_ACK_RANDOM_FACTOR
A factor that is used to randomize the wait time before a message is retransmitted to prevent synchro...
Definition: coap_session.h:410
#define COAP_DEFAULT_MAX_RETRANSMIT
Number of message retransmissions before message sending is stopped RFC 7252, Section 4....
Definition: coap_session.h:418
#define COAP_DEFAULT_ACK_TIMEOUT
Number of seconds when to expect an ACK or a response to an outstanding CON message.
Definition: coap_session.h:401
#define COAP_DEFAULT_NSTART
The number of simultaneous outstanding interactions that a client maintains to a given server.
Definition: coap_session.h:425
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:120
int coap_prng(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition: coap_prng.c:85
int coap_remove_from_queue(coap_queue_t **queue, coap_session_t *session, coap_mid_t id, coap_queue_t **node)
This function removes the element with given id from the list given list.
Definition: net.c:1935
int coap_delete_node(coap_queue_t *node)
Destroys specified node.
Definition: net.c:229
coap_queue_t * coap_new_node(void)
Creates a new node suitable for adding to the CoAP sendqueue.
Definition: net.c:258
unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r)
Calculates the initial timeout based on the session CoAP transmission parameters 'ack_timeout',...
Definition: net.c:944
coap_mid_t coap_wait_ack(coap_context_t *context, coap_session_t *session, coap_queue_t *node)
Definition: net.c:970
void coap_cancel_session_messages(coap_context_t *context, coap_session_t *session, coap_nack_reason_t reason)
Cancels all outstanding messages for session session.
Definition: net.c:1979
uint16_t coap_new_message_id(coap_session_t *session)
Returns a new message id and updates session->tx_mid accordingly.
int coap_handle_event(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition: net.c:3155
coap_mid_t coap_send(coap_session_t *session, coap_pdu_t *pdu)
Sends a CoAP message to given peer.
Definition: net.c:1154
coap_session_t * coap_session_new_dtls_session(coap_session_t *session, coap_tick_t now)
Create a new DTLS session for the session.
Definition: coap_session.c:692
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:20
#define COAP_DTLS_PKI_SETUP_VERSION
Latest PKI setup version.
Definition: coap_dtls.h:235
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_notls.c:15
coap_tls_library_t
Definition: coap_dtls.h:48
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition: coap_dtls.h:28
unsigned int coap_encode_var_safe(uint8_t *buf, size_t length, unsigned int val)
Encodes multiple-length byte sequences.
Definition: encode.c:38
uint64_t coap_decode_var_bytes8(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition: encode.c:58
unsigned int coap_encode_var_safe8(uint8_t *buf, size_t length, uint64_t val)
Encodes multiple-length byte sequences.
Definition: encode.c:68
#define COAP_EVENT_TCP_CLOSED
Definition: coap_event.h:39
#define COAP_EVENT_SESSION_CONNECTED
CSM exchange events for reliable protocols only.
Definition: coap_event.h:45
#define COAP_EVENT_SESSION_FAILED
Definition: coap_event.h:47
#define COAP_EVENT_TCP_FAILED
Definition: coap_event.h:40
#define COAP_EVENT_SESSION_CLOSED
Definition: coap_event.h:46
#define COAP_EVENT_DTLS_CONNECTED
Definition: coap_event.h:31
#define COAP_EVENT_TCP_CONNECTED
TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS.
Definition: coap_event.h:38
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition: coap_debug.c:61
size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len)
Print the address into the defined buffer.
Definition: coap_debug.c:171
const char * coap_session_str(const coap_session_t *session)
Get session description.
const char * coap_endpoint_str(const coap_endpoint_t *endpoint)
Get endpoint description.
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:150
@ LOG_ERR
Error.
Definition: coap_debug.h:53
@ LOG_CRIT
Critical.
Definition: coap_debug.h:52
@ LOG_INFO
Information.
Definition: coap_debug.h:56
@ LOG_WARNING
Warning.
Definition: coap_debug.h:54
@ LOG_DEBUG
Debug.
Definition: coap_debug.h:57
#define COAP_PDU_DELAYED
#define COAP_MAX_MESSAGE_SIZE_TCP8
#define COAP_DEFAULT_MAX_PDU_RX_SIZE
#define COAP_MAX_MESSAGE_SIZE_TCP0
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto)
Compose the protocol specific header for the specified PDU.
Definition: pdu.c:1125
#define COAP_MAX_MESSAGE_SIZE_TCP16
#define COAP_DEFAULT_PORT
Definition: pdu.h:33
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition: pdu.c:140
int coap_mid_t
coap_mid_t is used to store the CoAP Message ID of a CoAP PDU.
Definition: pdu.h:229
coap_proto_t
CoAP protocol types.
Definition: pdu.h:278
#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER
Definition: pdu.h:176
size_t coap_add_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, const uint8_t *data)
Adds option of given number to pdu that is passed as first parameter.
Definition: pdu.c:541
#define COAPS_DEFAULT_PORT
Definition: pdu.h:34
#define COAP_INVALID_MID
Indicates an invalid message id.
Definition: pdu.h:232
#define COAP_DEFAULT_MTU
Definition: pdu.h:37
coap_pdu_t * coap_pdu_init(coap_pdu_type_t type, coap_pdu_code_t code, coap_mid_t mid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size.
Definition: pdu.c:85
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
Definition: pdu.h:175
@ COAP_PROTO_DTLS
Definition: pdu.h:281
@ COAP_PROTO_UDP
Definition: pdu.h:280
@ COAP_PROTO_NONE
Definition: pdu.h:279
@ COAP_PROTO_TLS
Definition: pdu.h:283
@ COAP_PROTO_TCP
Definition: pdu.h:282
@ COAP_SIGNALING_CODE_CSM
Definition: pdu.h:329
@ COAP_SIGNALING_CODE_PING
Definition: pdu.h:330
@ COAP_MESSAGE_NON
Definition: pdu.h:56
@ COAP_MESSAGE_CON
Definition: pdu.h:55
coap_session_t * coap_endpoint_get_session(coap_endpoint_t *endpoint, const coap_packet_t *packet, coap_tick_t now)
Lookup the server session for the packet received on an endpoint, or create a new one.
Definition: coap_session.c:555
ssize_t coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node)
Definition: coap_session.c:310
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
Definition: coap_session.c:997
void coap_session_send_csm(coap_session_t *session)
Notify session transport has just connected and CSM exchange can now start.
Definition: coap_session.c:349
coap_session_t * coap_new_server_session(coap_context_t *ctx, coap_endpoint_t *ep)
Creates a new server session for the specified endpoint.
ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for datagram data transmission.
Definition: coap_session.c:275
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
Definition: coap_session.c:397
ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu)
Send a pdu according to the session's protocol.
Definition: net.c:764
void coap_session_free(coap_session_t *session)
Definition: coap_session.c:223
void coap_session_mfree(coap_session_t *session)
Definition: coap_session.c:157
ssize_t coap_session_write(coap_session_t *session, const uint8_t *data, size_t datalen)
Function interface for stream data transmission.
Definition: coap_session.c:296
void * coap_session_get_tls(const coap_session_t *session, coap_tls_library_t *tls_lib)
Get the session TLS security ptr (TLS type dependent)
coap_session_type_t
coap_session_type_t values
Definition: coap_session.h:39
void * coap_session_get_app_data(const coap_session_t *session)
Returns any application-specific data that has been stored with session using the function coap_sessi...
Definition: coap_session.c:102
void coap_free_endpoint(coap_endpoint_t *ep)
const coap_address_t * coap_session_get_addr_local(const coap_session_t *session)
Get the local IP address from the session.
void coap_session_set_mtu(coap_session_t *session, unsigned mtu)
Set the session MTU.
Definition: coap_session.c:263
const coap_bin_const_t * coap_session_get_psk_key(const coap_session_t *session)
Get the session's current pre-shared key (PSK).
coap_proto_t coap_session_get_proto(const coap_session_t *session)
Get the session protocol type.
coap_context_t * coap_session_get_context(const coap_session_t *session)
Get the session context.
size_t coap_session_max_pdu_size(const coap_session_t *session)
Get maximum acceptable PDU size.
Definition: coap_session.c:242
coap_session_state_t coap_session_get_state(const coap_session_t *session)
Get the session state.
coap_session_state_t
coap_session_state_t values
Definition: coap_session.h:50
coap_session_t * coap_new_client_session_psk(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, const char *identity, const uint8_t *key, unsigned key_len)
Creates a new client session to the designated server with PSK credentials.
Definition: coap_session.c:914
#define COAP_PROTO_NOT_RELIABLE(p)
Definition: coap_session.h:33
coap_session_t * coap_session_reference(coap_session_t *session)
Increment reference counter on a session.
Definition: coap_session.c:68
coap_session_t * coap_new_client_session(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto)
Creates a new client session to the designated server.
Definition: coap_session.c:899
void coap_session_init_token(coap_session_t *session, size_t len, const uint8_t *data)
Initializes the token value to use as a starting point.
#define COAP_PROTO_RELIABLE(p)
Definition: coap_session.h:34
void coap_session_new_token(coap_session_t *session, size_t *len, uint8_t *data)
Creates a new token for use.
void coap_session_set_app_data(coap_session_t *session, void *app_data)
Stores data with the given session.
Definition: coap_session.c:96
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
Definition: coap_session.c:74
coap_session_t * coap_new_client_session_pki(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, coap_dtls_pki_t *setup_data)
Creates a new client session to the designated server with PKI credentials.
void coap_endpoint_set_default_mtu(coap_endpoint_t *ep, unsigned mtu)
Set the endpoint's default MTU.
const coap_address_t * coap_session_get_addr_remote(const coap_session_t *session)
Get the remote IP address from the session.
const coap_bin_const_t * coap_session_get_psk_hint(const coap_session_t *session)
Get the server session's current Identity Hint (PSK).
coap_endpoint_t * coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto)
Create a new endpoint for communicating with peers.
int coap_session_set_type_client(coap_session_t *session)
Set the session type to client.
coap_session_t * coap_new_client_session_psk2(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, coap_dtls_cpsk_t *setup_data)
Creates a new client session to the designated server with PSK credentials.
Definition: coap_session.c:941
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:454
int coap_session_get_ifindex(const coap_session_t *session)
Get the session if index.
coap_session_type_t coap_session_get_type(const coap_session_t *session)
Get the session type.
@ COAP_SESSION_TYPE_HELLO
server-side ephemeral session for responding to a client hello
Definition: coap_session.h:43
@ COAP_SESSION_TYPE_SERVER
server-side
Definition: coap_session.h:42
@ COAP_SESSION_TYPE_CLIENT
client-side
Definition: coap_session.h:41
@ COAP_SESSION_STATE_HANDSHAKE
Definition: coap_session.h:53
@ COAP_SESSION_STATE_CSM
Definition: coap_session.h:54
@ COAP_SESSION_STATE_ESTABLISHED
Definition: coap_session.h:55
@ COAP_SESSION_STATE_NONE
Definition: coap_session.h:51
@ COAP_SESSION_STATE_CONNECTING
Definition: coap_session.h:52
void coap_delete_bin_const(coap_bin_const_t *s)
Deletes the given const binary data and releases any memory allocated.
Definition: str.c:102
#define coap_binary_equal(binary1, binary2)
Compares the two binary data for equality.
Definition: str.h:195
coap_bin_const_t * coap_new_bin_const(const uint8_t *data, size_t size)
Take the specified byte array (text) and create a coap_bin_const_t * Returns a new const binary objec...
Definition: str.c:93
void coap_delete_observers(coap_context_t *context, coap_session_t *session)
Removes any subscription for session and releases the allocated storage.
Definition: resource.c:830
int coap_socket_bind_tcp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
Create a new TCP socket and then listen for new incoming TCP sessions.
int coap_socket_connect_tcp1(coap_socket_t *sock, const coap_address_t *local_if, const coap_address_t *server, int default_port, coap_address_t *local_addr, coap_address_t *remote_addr)
Create a new TCP socket and initiate the connection.
int coap_socket_accept_tcp(coap_socket_t *server, coap_socket_t *new_client, coap_address_t *local_addr, coap_address_t *remote_addr)
Accept a new incoming TCP session.
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:103
@ COAP_SESSION
Definition: mem.h:44
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
Only used for servers for hashing incoming packets.
uint16_t lport
local port
coap_address_t remote
remote address and port
coap_proto_t proto
CoAP protocol.
coap_address_t remote
remote address and port
Definition: coap_io.h:49
coap_address_t local
local address and port
Definition: coap_io.h:50
multi-purpose address abstraction
Definition: address.h:94
CoAP binary data definition with const data.
Definition: str.h:56
size_t length
length of binary data
Definition: str.h:57
const uint8_t * s
read-only binary data
Definition: str.h:58
coap_session_t * session
The CoAP stack's global state is stored in a coap_context_t object.
coap_session_t * sessions
client sessions
coap_nack_handler_t nack_handler
unsigned int max_handshake_sessions
Maximum number of simultaneous negotating sessions per endpoint.
coap_queue_t * sendqueue
coap_cache_entry_t * cache
CoAP cache-entry cache.
coap_endpoint_t * endpoint
the endpoints used for listening
uint8_t block_mode
Zero or more COAP_BLOCK_ or'd options.
unsigned int max_idle_sessions
Maximum number of simultaneous unused sessions per endpoint.
coap_bin_const_t key
Definition: coap_dtls.h:305
coap_bin_const_t identity
Definition: coap_dtls.h:304
The structure used for defining the Client PSK setup data to be used.
Definition: coap_dtls.h:334
coap_dtls_cpsk_info_t psk_info
Client PSK definition.
Definition: coap_dtls.h:363
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:240
uint8_t version
Definition: coap_dtls.h:241
Abstraction of virtual endpoint that can be attached to coap_context_t.
coap_context_t * context
endpoint's context
uint16_t default_mtu
default mtu for this interface
coap_session_t * sessions
hash table or list of active sessions
coap_address_t bind_addr
local interface address
coap_socket_t sock
socket object for the interface, if any
coap_proto_t proto
protocol used on this interface
Abstraction of a fixed point number that can be used where necessary instead of a float.
Definition: coap_session.h:27
uint16_t fractional_part
Fractional part of fixed point variable 1/1000 (3 points) precision.
Definition: coap_session.h:29
uint16_t integer_part
Integer part of fixed point variable.
Definition: coap_session.h:28
Structure to hold large body (many blocks) client receive information.
coap_binary_t * app_token
app requesting PDU token
uint8_t observe_set
Set if this is an observe receive PDU.
Structure to hold large body (many blocks) server receive information.
Structure to hold large body (many blocks) transmission information.
size_t length
length of payload
coap_addr_tuple_t addr_info
local and remote addresses
unsigned char payload[COAP_RXBUFFER_SIZE]
payload
int ifindex
the interface index
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
uint8_t hdr_size
actual size used for protocol-specific header
coap_mid_t mid
message id, if any, in regular host byte order
size_t used_size
used bytes of storage for token, options and payload
coap_pdu_type_t type
message type
Queue entry.
coap_session_t * session
the CoAP session
coap_pdu_t * pdu
the CoAP PDU to send
unsigned int timeout
the randomized timeout value
struct coap_queue_t * next
coap_mid_t id
CoAP message id.
coap_tick_t t
when to send PDU for the next time
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
coap_lg_xmit_t * lg_xmit
list of large transmissions
coap_bin_const_t * psk_key
If client, this field contains the current pre-shared key for server; When this field is NULL,...
coap_endpoint_t * endpoint
session's endpoint
coap_socket_t sock
socket object for the session, if any
unsigned int max_retransmit
maximum re-transmit count (default 4)
coap_pdu_t * partial_pdu
incomplete incoming pdu
coap_bin_const_t * psk_identity
If client, this field contains the current identity for server; When this field is NULL,...
coap_session_state_t state
current state of relationaship with peer
uint64_t tx_token
Next token number to use.
uint8_t block_mode
Zero or more COAP_BLOCK_ or'd options.
coap_addr_tuple_t addr_info
key: remote/local address info
coap_proto_t proto
protocol used
uint16_t tx_mid
the last message id that was used in this session
coap_bin_const_t * psk_hint
If client, this field contains the server provided identity hint.
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
size_t mtu
path or CSM mtu
size_t partial_read
if > 0 indicates number of bytes already read for an incoming message
int dtls_event
Tracking any (D)TLS events on this sesison.
void * tls
security parameters
coap_fixed_point_t ack_random_factor
ack random factor backoff (default 1.5)
uint8_t con_active
Active CON request sent.
coap_queue_t * delayqueue
list of delayed messages waiting to be sent
size_t tls_overhead
overhead of TLS layer
void * app
application-specific data
coap_mid_t last_ping_mid
the last keepalive message id that was used in this session
coap_lg_srcv_t * lg_srcv
Server list of expected large receives.
coap_lg_crcv_t * lg_crcv
Client list of expected large receives.
coap_fixed_point_t ack_timeout
timeout waiting for ack (default 2 secs)
coap_session_type_t type
client or server side socket
coap_context_t * context
session's context
size_t partial_write
if > 0 indicates number of bytes already written from the pdu at the head of sendqueue
coap_addr_hash_t addr_hash
Address hash for server incoming packets.
int ifindex
interface index
coap_session_t * session
coap_endpoint_t * endpoint
coap_socket_flags_t flags
#define HASH_ITER(hh, head, el, tmp)
Definition: uthash.h:1059
#define LL_DELETE(head, del)
Definition: utlist.h:385
#define LL_FOREACH(head, el)
Definition: utlist.h:413
#define LL_PREPEND(head, add)
Definition: utlist.h:314
#define LL_APPEND(head, add)
Definition: utlist.h:338
#define LL_FOREACH_SAFE(head, el, tmp)
Definition: utlist.h:419