libcoap  4.3.0rc1
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 "coap2/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  (void)reason;
456 #if !COAP_DISABLE_TCP
457  coap_session_state_t state = session->state;
458 #endif /* !COAP_DISABLE_TCP */
459 
460  coap_log(LOG_DEBUG, "***%s: session disconnected (reason %d)\n",
461  coap_session_str(session), reason);
462  coap_delete_observers( session->context, session );
463 
464  if ( session->tls) {
465  if (session->proto == COAP_PROTO_DTLS)
466  coap_dtls_free_session(session);
467 #if !COAP_DISABLE_TCP
468  else if (session->proto == COAP_PROTO_TLS)
469  coap_tls_free_session(session);
470 #endif /* !COAP_DISABLE_TCP */
471  session->tls = NULL;
472  }
473 
474  if (session->proto == COAP_PROTO_UDP)
476  else
477  session->state = COAP_SESSION_STATE_NONE;
478 
479  session->con_active = 0;
480 
481  if (session->partial_pdu) {
482  coap_delete_pdu(session->partial_pdu);
483  session->partial_pdu = NULL;
484  }
485  session->partial_read = 0;
486 
487  while (session->delayqueue) {
488  coap_queue_t *q = session->delayqueue;
489  session->delayqueue = q->next;
490  q->next = NULL;
491  coap_log(LOG_DEBUG, "** %s: mid=0x%x: not transmitted after disconnect\n",
492  coap_session_str(session), q->id);
493  if (q->pdu->type==COAP_MESSAGE_CON
494  && COAP_PROTO_NOT_RELIABLE(session->proto)
495  && reason == COAP_NACK_ICMP_ISSUE)
496  {
497  /* Make sure that we try a re-transmit later on ICMP error */
498  if (coap_wait_ack(session->context, session, q) >= 0) {
499  if (session->context->nack_handler) {
500  session->context->nack_handler(session->context, session, q->pdu,
501  reason, q->id);
502  }
503  q = NULL;
504  }
505  }
506  if (q && q->pdu->type == COAP_MESSAGE_CON
507  && session->context->nack_handler)
508  {
509  session->context->nack_handler(session->context, session, q->pdu,
510  reason, q->id);
511  }
512  if (q)
513  coap_delete_node(q);
514  }
515  if (reason != COAP_NACK_ICMP_ISSUE) {
516  coap_cancel_session_messages(session->context, session, reason);
517  }
518  else if (session->context->nack_handler) {
519  coap_queue_t *q = session->context->sendqueue;
520  while (q) {
521  if (q->session == session) {
522  session->context->nack_handler(session->context, session, q->pdu,
523  reason, q->id);
524  }
525  q = q->next;
526  }
527  }
528 
529 #if !COAP_DISABLE_TCP
530  if (COAP_PROTO_RELIABLE(session->proto)) {
531  if (session->sock.flags != COAP_SOCKET_EMPTY) {
532  coap_socket_close(&session->sock);
533  coap_handle_event(session->context,
536  }
537  if (state != COAP_SESSION_STATE_NONE) {
538  coap_handle_event(session->context,
541  }
542  }
543 #endif /* !COAP_DISABLE_TCP */
544 }
545 
546 static void
548  const coap_addr_tuple_t *addr_info) {
549  memset(addr_hash, 0, sizeof(coap_addr_hash_t));
550  coap_address_copy(&addr_hash->remote, &addr_info->remote);
551  addr_hash->lport = coap_address_get_port(&addr_info->local);
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, &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  session->sock.session = session;
802 #ifdef COAP_EPOLL_SUPPORT
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  struct 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  struct 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  struct 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 
1055  struct coap_context_t *ctx,
1056  const coap_address_t *local_if,
1057  const coap_address_t *server,
1058  coap_proto_t proto,
1059  coap_dtls_pki_t* setup_data
1060 ) {
1061  coap_session_t *session;
1062 
1063  if (coap_dtls_is_supported()) {
1064  if (!setup_data) {
1065  return NULL;
1066  } else {
1067  if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION) {
1068  coap_log(LOG_ERR,
1069  "coap_new_client_session_pki: Wrong version of setup_data\n");
1070  return NULL;
1071  }
1072  }
1073 
1074  }
1075  session = coap_session_create_client(ctx, local_if, server, proto);
1076 
1077  if (!session) {
1078  return NULL;
1079  }
1080 
1081  if (coap_dtls_is_supported()) {
1082  /* we know that setup_data is not NULL */
1083  if (!coap_dtls_context_set_pki(ctx, setup_data, COAP_DTLS_ROLE_CLIENT)) {
1084  coap_session_release(session);
1085  return NULL;
1086  }
1087  }
1088  coap_log(LOG_DEBUG, "***%s: new outgoing session\n",
1089  coap_session_str(session));
1090  return coap_session_connect(session);
1091 }
1092 
1094  struct coap_context_t *ctx,
1095  coap_endpoint_t *ep
1096 ) {
1097  coap_session_t *session;
1099  NULL, NULL, NULL, 0, ctx, ep );
1100  if (!session)
1101  goto error;
1102 
1103 #if !COAP_DISABLE_TCP
1104  if (!coap_socket_accept_tcp(&ep->sock, &session->sock,
1105  &session->addr_info.local,
1106  &session->addr_info.remote))
1107  goto error;
1108  coap_make_addr_hash(&session->addr_hash, &session->addr_info);
1109 
1110 #endif /* !COAP_DISABLE_TCP */
1113  session->sock.session = session;
1114 #ifdef COAP_EPOLL_SUPPORT
1115  coap_epoll_ctl_add(&session->sock,
1116  EPOLLIN,
1117  __func__);
1118 #endif /* COAP_EPOLL_SUPPORT */
1119  SESSIONS_ADD(ep->sessions, session);
1120  if (session) {
1121  coap_log(LOG_DEBUG, "***%s: new incoming session\n",
1122  coap_session_str(session));
1123  session = coap_session_accept(session);
1124  }
1125  return session;
1126 
1127 error:
1128  coap_session_free(session);
1129  return NULL;
1130 }
1131 
1132 void
1134  const uint8_t *data) {
1135  session->tx_token = coap_decode_var_bytes8(data, len);
1136 }
1137 
1138 void coap_session_new_token(coap_session_t *session, size_t *len,
1139  uint8_t *data) {
1140  *len = coap_encode_var_safe8(data,
1141  sizeof(session->tx_token), ++session->tx_token);
1142 }
1143 
1144 #ifndef WITH_LWIP
1146 coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto) {
1147  coap_endpoint_t *ep = NULL;
1148 
1149  assert(context);
1150  assert(listen_addr);
1151  assert(proto != COAP_PROTO_NONE);
1152 
1153  if (proto == COAP_PROTO_DTLS && !coap_dtls_is_supported()) {
1154  coap_log(LOG_CRIT, "coap_new_endpoint: DTLS not supported\n");
1155  goto error;
1156  }
1157 
1158  if (proto == COAP_PROTO_TLS && !coap_tls_is_supported()) {
1159  coap_log(LOG_CRIT, "coap_new_endpoint: TLS not supported\n");
1160  goto error;
1161  }
1162 
1163  if (proto == COAP_PROTO_TCP && !coap_tcp_is_supported()) {
1164  coap_log(LOG_CRIT, "coap_new_endpoint: TCP not supported\n");
1165  goto error;
1166  }
1167 
1168  if (proto == COAP_PROTO_DTLS || proto == COAP_PROTO_TLS) {
1169  if (!coap_dtls_context_check_keys_enabled(context)) {
1171  "coap_new_endpoint: one of coap_context_set_psk() or "
1172  "coap_context_set_pki() not called\n");
1173  goto error;
1174  }
1175  }
1176 
1177  ep = coap_malloc_endpoint();
1178  if (!ep) {
1179  coap_log(LOG_WARNING, "coap_new_endpoint: malloc");
1180  goto error;
1181  }
1182 
1183  memset(ep, 0, sizeof(coap_endpoint_t));
1184  ep->context = context;
1185  ep->proto = proto;
1186 
1187  if (proto==COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) {
1188  if (!coap_socket_bind_udp(&ep->sock, listen_addr, &ep->bind_addr))
1189  goto error;
1191 #if !COAP_DISABLE_TCP
1192  } else if (proto==COAP_PROTO_TCP || proto==COAP_PROTO_TLS) {
1193  if (!coap_socket_bind_tcp(&ep->sock, listen_addr, &ep->bind_addr))
1194  goto error;
1196 #endif /* !COAP_DISABLE_TCP */
1197  } else {
1198  coap_log(LOG_CRIT, "coap_new_endpoint: protocol not supported\n");
1199  goto error;
1200  }
1201 
1202  if (LOG_DEBUG <= coap_get_log_level()) {
1203 #ifndef INET6_ADDRSTRLEN
1204 #define INET6_ADDRSTRLEN 40
1205 #endif
1206  unsigned char addr_str[INET6_ADDRSTRLEN + 8];
1207 
1208  if (coap_print_addr(&ep->bind_addr, addr_str, INET6_ADDRSTRLEN + 8)) {
1209  coap_log(LOG_DEBUG, "created %s endpoint %s\n",
1210  ep->proto == COAP_PROTO_TLS ? "TLS "
1211  : ep->proto == COAP_PROTO_TCP ? "TCP "
1212  : ep->proto == COAP_PROTO_DTLS ? "DTLS" : "UDP ",
1213  addr_str);
1214  }
1215  }
1216 
1218 
1220 
1221  ep->sock.endpoint = ep;
1222 #ifdef COAP_EPOLL_SUPPORT
1223  coap_epoll_ctl_add(&ep->sock,
1224  EPOLLIN,
1225  __func__);
1226 #endif /* COAP_EPOLL_SUPPORT */
1227 
1228  LL_PREPEND(context->endpoint, ep);
1229  return ep;
1230 
1231 error:
1232  coap_free_endpoint(ep);
1233  return NULL;
1234 }
1235 
1237  ep->default_mtu = (uint16_t)mtu;
1238 }
1239 
1240 void
1242  if (ep) {
1243  coap_session_t *session, *rtmp;
1244 
1245  SESSIONS_ITER_SAFE(ep->sessions, session, rtmp) {
1246  assert(session->ref == 0);
1247  if (session->ref == 0) {
1248  coap_session_free(session);
1249  }
1250  }
1251  if (ep->sock.flags != COAP_SOCKET_EMPTY) {
1252  /*
1253  * ep->sock.endpoint is set in coap_new_endpoint().
1254  * ep->sock.session is never set.
1255  *
1256  * session->sock.session is set for both clients and servers (when a
1257  * new session is accepted), but does not affect the endpoint.
1258  *
1259  * So, it is safe to call coap_socket_close() after all the sessions
1260  * have been freed above as we are only working with the endpoint sock.
1261  */
1262 #ifdef COAP_EPOLL_SUPPORT
1263  assert(ep->sock.session == NULL);
1264 #endif /* COAP_EPOLL_SUPPORT */
1265  coap_socket_close(&ep->sock);
1266  }
1267 
1268  if (ep->context && ep->context->endpoint) {
1269  LL_DELETE(ep->context->endpoint, ep);
1270  }
1271  coap_mfree_endpoint(ep);
1272  }
1273 }
1274 #endif /* WITH_LWIP */
1275 
1278  const coap_address_t *remote_addr,
1279  int ifindex) {
1280  coap_session_t *s, *rtmp;
1281  coap_endpoint_t *ep;
1282  SESSIONS_ITER(ctx->sessions, s, rtmp) {
1283  if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote,
1284  remote_addr))
1285  return s;
1286  }
1287  LL_FOREACH(ctx->endpoint, ep) {
1288  SESSIONS_ITER(ep->sessions, s, rtmp) {
1289  if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote,
1290  remote_addr))
1291  return s;
1292  }
1293  }
1294  return NULL;
1295 }
1296 
1297 const char *coap_session_str(const coap_session_t *session) {
1298  static char szSession[2 * (INET6_ADDRSTRLEN + 8) + 24];
1299  char *p = szSession, *end = szSession + sizeof(szSession);
1300  if (coap_print_addr(&session->addr_info.local,
1301  (unsigned char*)p, end - p) > 0)
1302  p += strlen(p);
1303  if (p + 6 < end) {
1304  strcpy(p, " <-> ");
1305  p += 5;
1306  }
1307  if (p + 1 < end) {
1308  if (coap_print_addr(&session->addr_info.remote,
1309  (unsigned char*)p, end - p) > 0)
1310  p += strlen(p);
1311  }
1312  if (session->ifindex > 0 && p + 1 < end)
1313  p += snprintf(p, end - p, " (if%d)", session->ifindex);
1314  if (p + 6 < end) {
1315  if (session->proto == COAP_PROTO_UDP) {
1316  strcpy(p, " UDP ");
1317  p += 4;
1318  } else if (session->proto == COAP_PROTO_DTLS) {
1319  strcpy(p, " DTLS");
1320  p += 5;
1321  } else if (session->proto == COAP_PROTO_TCP) {
1322  strcpy(p, " TCP ");
1323  p += 4;
1324  } else if (session->proto == COAP_PROTO_TLS) {
1325  strcpy(p, " TLS ");
1326  p += 4;
1327  } else {
1328  strcpy(p, " NONE");
1329  p += 5;
1330  }
1331  }
1332 
1333  return szSession;
1334 }
1335 
1336 const char *coap_endpoint_str(const coap_endpoint_t *endpoint) {
1337  static char szEndpoint[128];
1338  char *p = szEndpoint, *end = szEndpoint + sizeof(szEndpoint);
1339  if (coap_print_addr(&endpoint->bind_addr, (unsigned char*)p, end - p) > 0)
1340  p += strlen(p);
1341  if (p + 6 < end) {
1342  if (endpoint->proto == COAP_PROTO_UDP) {
1343  strcpy(p, " UDP");
1344  p += 4;
1345  } else if (endpoint->proto == COAP_PROTO_DTLS) {
1346  strcpy(p, " DTLS");
1347  p += 5;
1348  } else {
1349  strcpy(p, " NONE");
1350  p += 5;
1351  }
1352  }
1353 
1354  return szEndpoint;
1355 }
1356 
1357 #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
void coap_dtls_free_session(struct coap_dtls_context_t *dtls_context, struct coap_dtls_session_t *session)
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:236
void coap_socket_close(coap_socket_t *sock)
Definition: coap_io.c:362
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:1494
ssize_t coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len)
Definition: coap_io.c:421
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:1488
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
#define COAP_SOCKET_WANT_ACCEPT
non blocking server socket is waiting for accept
Definition: coap_io.h:94
#define COAP_SOCKET_NOT_EMPTY
the socket is not empty
Definition: coap_io.h:89
#define COAP_SOCKET_BOUND
the socket is bound
Definition: coap_io.h:90
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
Definition: coap_io.h:92
coap_nack_reason_t
Definition: coap_io.h:223
@ COAP_NACK_NOT_DELIVERABLE
Definition: coap_io.h:225
@ COAP_NACK_TLS_FAILED
Definition: coap_io.h:227
@ COAP_NACK_ICMP_ISSUE
Definition: coap_io.h:228
#define COAP_SOCKET_WANT_CONNECT
non blocking client socket is waiting for connect
Definition: coap_io.h:95
#define COAP_SOCKET_CONNECTED
the socket is connected
Definition: coap_io.h:91
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
Definition: coap_io.h:88
void * coap_dtls_new_server_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:95
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:99
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:149
void * coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:153
void * coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:157
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_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:161
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_session_t * coap_endpoint_get_session(coap_endpoint_t *endpoint, const coap_packet_t *packet, coap_tick_t now)
Definition: coap_session.c:555
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)
ssize_t coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node)
Definition: coap_session.c:310
coap_mid_t coap_session_send_ping(coap_session_t *session)
Send a ping message for the session.
Definition: coap_session.c:379
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_set_mtu(coap_session_t *session, unsigned mtu)
Set the session MTU.
Definition: coap_session.c:263
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Definition: coap_session.c:997
#define DTLS_HT_CLIENT_HELLO
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
#define OFF_HANDSHAKE_TYPE
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.
coap_session_t * coap_new_client_session_psk(struct 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
size_t coap_session_max_pdu_size(const coap_session_t *session)
Get maximum acceptable PDU size.
Definition: coap_session.c:242
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
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
unsigned int coap_session_get_max_transmit(coap_session_t *session)
Get the CoAP maximum retransmit before failure.
Definition: coap_session.c:53
static void coap_make_addr_hash(coap_addr_hash_t *addr_hash, const coap_addr_tuple_t *addr_info)
Definition: coap_session.c:547
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_psk2(struct 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
#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
void coap_session_new_token(coap_session_t *session, size_t *len, uint8_t *data)
Creates a new token for use.
coap_session_t * coap_session_get_by_peer(coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
void coap_endpoint_set_default_mtu(coap_endpoint_t *ep, unsigned mtu)
Set the endpoint's default MTU.
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
Definition: coap_session.c:74
coap_fixed_point_t coap_session_get_ack_timeout(coap_session_t *session)
Get the CoAP initial ack response timeout before the next re-transmit.
Definition: coap_session.c:58
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
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
#define OFF_CONTENT_TYPE
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
Definition: coap_session.c:397
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
void coap_session_free(coap_session_t *session)
Definition: coap_session.c:223
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.
void coap_session_mfree(coap_session_t *session)
Definition: coap_session.c:157
coap_session_t * coap_new_client_session_pki(struct 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.
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_session_t * coap_new_server_session(struct coap_context_t *ctx, coap_endpoint_t *ep)
Creates a new server session for the specified endpoint.
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:454
coap_session_t * coap_new_client_session(struct 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
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
coap_fixed_point_t coap_session_get_ack_random_factor(coap_session_t *session)
Get the CoAP ack randomize factor.
Definition: coap_session.c:63
#define INET6_ADDRSTRLEN
#define DTLS_CT_ALERT
#define SESSIONS_ADD(e, obj)
Definition: coap_session.h:657
#define SESSIONS_ITER_SAFE(e, el, rtmp)
Definition: coap_session.h:666
#define COAP_PARTIAL_SESSION_TIMEOUT_TICKS
Definition: coap_session.h:36
#define COAP_SESSION_STATE_HANDSHAKE
Definition: coap_session.h:56
uint8_t coap_session_state_t
Definition: coap_session.h:50
#define COAP_SESSION_STATE_CSM
Definition: coap_session.h:57
#define SESSIONS_DELETE(e, obj)
Definition: coap_session.h:660
#define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS
Definition: coap_session.h:37
uint8_t coap_session_type_t
Definition: coap_session.h:42
#define COAP_SESSION_TYPE_CLIENT
coap_session_type_t values
Definition: coap_session.h:46
#define COAP_SESSION_TYPE_HELLO
server-side ephemeral session for responding to a client hello
Definition: coap_session.h:48
#define COAP_PROTO_NOT_RELIABLE(p)
Definition: coap_session.h:39
#define COAP_SESSION_STATE_CONNECTING
Definition: coap_session.h:55
#define COAP_PROTO_RELIABLE(p)
Definition: coap_session.h:40
#define COAP_SESSION_STATE_NONE
coap_session_state_t values
Definition: coap_session.h:54
#define COAP_SESSION_STATE_ESTABLISHED
Definition: coap_session.h:58
#define SESSIONS_ITER(e, el, rtmp)
Definition: coap_session.h:663
#define COAP_SESSION_TYPE_SERVER
server-side
Definition: coap_session.h:47
#define SESSIONS_FIND(e, k, res)
Definition: coap_session.h:669
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, uint8_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:488
#define COAP_DEFAULT_MAX_RETRANSMIT
Number of message retransmissions before message sending is stopped RFC 7252, Section 4....
Definition: coap_session.h:496
#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:479
#define COAP_DEFAULT_NSTART
The number of simultaneous outstanding interactions that a client maintains to a given server.
Definition: coap_session.h:503
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
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
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition: coap_dtls.h:482
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:240
int coap_dtls_is_supported(void)
Returns 1 if support for DTLS is enabled, or 0 otherwise.
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
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().
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:1887
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
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:3069
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:899
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:720
coap_mid_t coap_wait_ack(coap_context_t *context, coap_session_t *session, coap_queue_t *node)
Definition: net.c:925
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:1931
coap_mid_t coap_send(coap_session_t *session, coap_pdu_t *pdu)
Sends a CoAP message to given peer.
Definition: net.c:1109
COAP_STATIC_INLINE uint16_t coap_new_message_id(coap_session_t *session)
Returns a new message id and updates session->tx_mid accordingly.
Definition: net.h:412
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition: pdu.c:133
coap_pdu_t * coap_pdu_init(uint8_t type, uint8_t code, uint16_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
size_t coap_add_option(coap_pdu_t *pdu, uint16_t type, size_t len, const uint8_t *data)
Adds option of given type to pdu that is passed as first parameter.
Definition: pdu.c:535
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:1120
#define COAP_PROTO_NONE
coap_proto_t values
Definition: pdu.h:349
#define COAP_PROTO_TCP
Definition: pdu.h:352
#define COAP_DEFAULT_PORT
Definition: pdu.h:27
int coap_mid_t
coap_mid_t is used to store the CoAP Message ID of a CoAP PDU.
Definition: pdu.h:244
#define COAP_PDU_DELAYED
Definition: pdu.h:255
#define COAP_SIGNALING_CSM
Definition: pdu.h:183
#define COAP_PROTO_TLS
Definition: pdu.h:353
#define COAP_MAX_MESSAGE_SIZE_TCP8
Definition: pdu.h:45
#define COAP_DEFAULT_MAX_PDU_RX_SIZE
Definition: pdu.h:54
#define COAP_SIGNALING_OPTION_BLOCK_WISE_TRANSFER
Definition: pdu.h:191
#define COAP_MESSAGE_NON
Definition: pdu.h:76
#define COAP_MAX_MESSAGE_SIZE_TCP0
Definition: pdu.h:44
uint8_t coap_proto_t
Definition: pdu.h:345
#define COAP_MESSAGE_CON
Definition: pdu.h:75
#define COAPS_DEFAULT_PORT
Definition: pdu.h:28
#define COAP_PROTO_DTLS
Definition: pdu.h:351
#define COAP_INVALID_MID
Indicates an invalid message id.
Definition: pdu.h:247
#define COAP_DEFAULT_MTU
Definition: pdu.h:31
#define COAP_SIGNALING_PING
Definition: pdu.h:184
#define COAP_MAX_MESSAGE_SIZE_TCP16
Definition: pdu.h:46
#define COAP_PROTO_UDP
Definition: pdu.h:350
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
Definition: pdu.h:190
Only used for servers for hashing incoming packets.
Definition: coap_io.h:52
uint16_t lport
local port
Definition: coap_io.h:54
coap_address_t remote
remote address and port
Definition: coap_io.h:53
coap_address_t remote
remote address and port
Definition: coap_io.h:58
coap_address_t local
local address and port
Definition: coap_io.h:59
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.
Definition: net.h:150
coap_session_t * sessions
client sessions
Definition: net.h:174
coap_nack_handler_t nack_handler
Definition: net.h:189
unsigned int max_handshake_sessions
Maximum number of simultaneous negotating sessions per endpoint.
Definition: net.h:213
coap_queue_t * sendqueue
Definition: net.h:172
coap_cache_entry_t * cache
CoAP cache-entry cache.
Definition: net.h:220
coap_endpoint_t * endpoint
the endpoints used for listening
Definition: net.h:173
uint8_t block_mode
Zero or more COAP_BLOCK_ or'd options.
Definition: net.h:217
unsigned int max_idle_sessions
Maximum number of simultaneous unused sessions per endpoint.
Definition: net.h:212
coap_bin_const_t key
Definition: coap_dtls.h:310
coap_bin_const_t identity
Definition: coap_dtls.h:309
The structure used for defining the Client PSK setup data to be used.
Definition: coap_dtls.h:339
coap_dtls_cpsk_info_t psk_info
Client PSK definition.
Definition: coap_dtls.h:368
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:245
uint8_t version
Definition: coap_dtls.h:246
Abstraction of virtual endpoint that can be attached to coap_context_t.
struct coap_context_t * context
endpoint's context
uint16_t default_mtu
default mtu for this interface
struct 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:29
uint16_t fractional_part
Fractional part of fixed point variable 1/1000 (3 points) precision.
Definition: coap_session.h:31
uint16_t integer_part
Integer part of fixed point variable.
Definition: coap_session.h:30
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
Definition: coap_io.h:217
coap_addr_tuple_t addr_info
local and remote addresses
Definition: coap_io.h:215
unsigned char payload[COAP_RXBUFFER_SIZE]
payload
Definition: coap_io.h:218
int ifindex
the interface index
Definition: coap_io.h:216
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
Definition: pdu.h:287
uint8_t type
message type
Definition: pdu.h:288
uint16_t mid
message id, if any, in regular host byte order
Definition: pdu.h:293
uint8_t hdr_size
actual size used for protocol-specific header
Definition: pdu.h:291
size_t used_size
used bytes of storage for token, options and payload
Definition: pdu.h:296
Queue entry.
Definition: net.h:37
coap_session_t * session
the CoAP session
Definition: net.h:43
coap_pdu_t * pdu
the CoAP PDU to send
Definition: net.h:45
unsigned int timeout
the randomized timeout value
Definition: net.h:42
struct coap_queue_t * next
Definition: net.h:38
coap_mid_t id
CoAP message id.
Definition: net.h:44
coap_tick_t t
when to send PDU for the next time
Definition: net.h:39
coap_lg_xmit_t * lg_xmit
list of large transmissions
Definition: coap_session.h:80
coap_bin_const_t * psk_key
If client, this field contains the current pre-shared key for server; When this field is NULL,...
Definition: coap_session.h:103
coap_endpoint_t * endpoint
session's endpoint
Definition: coap_session.h:72
coap_tick_t last_rx_tx
Definition: coap_session.h:87
coap_socket_t sock
socket object for the session, if any
Definition: coap_session.h:71
unsigned int max_retransmit
maximum re-transmit count (default 4)
Definition: coap_session.h:122
coap_pdu_t * partial_pdu
incomplete incoming pdu
Definition: coap_session.h:86
coap_bin_const_t * psk_identity
If client, this field contains the current identity for server; When this field is NULL,...
Definition: coap_session.h:94
coap_session_state_t state
current state of relationaship with peer
Definition: coap_session.h:63
uint64_t tx_token
Next token number to use.
Definition: coap_session.h:128
uint8_t block_mode
Zero or more COAP_BLOCK_ or'd options.
Definition: coap_session.h:127
coap_addr_tuple_t addr_info
key: remote/local address info
Definition: coap_session.h:69
coap_proto_t proto
protocol used
Definition: coap_session.h:61
uint16_t tx_mid
the last message id that was used in this session
Definition: coap_session.h:75
coap_bin_const_t * psk_hint
If client, this field contains the server provided identity hint.
Definition: coap_session.h:112
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
Definition: coap_session.h:92
struct coap_queue_t * delayqueue
list of delayed messages waiting to be sent
Definition: coap_session.h:79
size_t mtu
path or CSM mtu
Definition: coap_session.h:66
struct coap_context_t * context
session's context
Definition: coap_session.h:73
size_t partial_read
if > 0 indicates number of bytes already read for an incoming message
Definition: coap_session.h:85
int dtls_event
Tracking any (D)TLS events on this sesison.
Definition: coap_session.h:126
void * tls
security parameters
Definition: coap_session.h:74
coap_fixed_point_t ack_random_factor
ack random factor backoff (default 1.5)
Definition: coap_session.h:124
uint8_t con_active
Active CON request sent.
Definition: coap_session.h:76
size_t tls_overhead
overhead of TLS layer
Definition: coap_session.h:65
void * app
application-specific data
Definition: coap_session.h:121
coap_mid_t last_ping_mid
the last keepalive message id that was used in this session
Definition: coap_session.h:78
coap_lg_srcv_t * lg_srcv
Server list of expected large receives.
Definition: coap_session.h:82
coap_lg_crcv_t * lg_crcv
Client list of expected large receives.
Definition: coap_session.h:81
coap_fixed_point_t ack_timeout
timeout waiting for ack (default 2 secs)
Definition: coap_session.h:123
coap_session_type_t type
client or server side socket
Definition: coap_session.h:62
size_t partial_write
if > 0 indicates number of bytes already written from the pdu at the head of sendqueue
Definition: coap_session.h:83
coap_addr_hash_t addr_hash
Address hash for server incoming packets.
Definition: coap_session.h:67
int ifindex
interface index
Definition: coap_session.h:70
coap_endpoint_t * endpoint
Definition: coap_io.h:78
coap_fd_t fd
Definition: coap_io.h:68
struct coap_session_t * session
Definition: coap_io.h:74
coap_socket_flags_t flags
Definition: coap_io.h:73
#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