libcoap  4.2.1
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 "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  assert(session->ref > 0);
77  if (session->ref > 0)
78  --session->ref;
79  if (session->ref == 0 && session->type == COAP_SESSION_TYPE_CLIENT)
80  coap_session_free(session);
81  }
82 }
83 
84 void
85 coap_session_set_app_data(coap_session_t *session, void *app_data) {
86  assert(session);
87  session->app = app_data;
88 }
89 
90 void *
92  assert(session);
93  return session->app;
94 }
95 
96 static coap_session_t *
98  const coap_address_t *local_if, const coap_address_t *local_addr,
99  const coap_address_t *remote_addr, int ifindex, coap_context_t *context,
100  coap_endpoint_t *endpoint) {
102  if (!session)
103  return NULL;
104  memset(session, 0, sizeof(*session));
105  session->proto = proto;
106  session->type = type;
107  if (local_if)
108  coap_address_copy(&session->local_if, local_if);
109  else
110  coap_address_init(&session->local_if);
111  if (local_addr)
112  coap_address_copy(&session->addr_info.local, local_addr);
113  else
114  coap_address_init(&session->addr_info.local);
115  if (remote_addr)
116  coap_address_copy(&session->addr_info.remote, remote_addr);
117  else
119  session->ifindex = ifindex;
120  session->context = context;
121  session->endpoint = endpoint;
122  if (endpoint)
123  session->mtu = endpoint->default_mtu;
124  else
125  session->mtu = COAP_DEFAULT_MTU;
126  if (proto == COAP_PROTO_DTLS) {
127  session->tls_overhead = 29;
128  if (session->tls_overhead >= session->mtu) {
129  session->tls_overhead = session->mtu;
130  coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n");
131  }
132  }
136  session->dtls_event = -1;
137  session->last_ping_mid = COAP_INVALID_TID;
138 
139  /* initialize message id */
140  prng((unsigned char *)&session->tx_mid, sizeof(session->tx_mid));
141 
142  return session;
143 }
144 
146  coap_queue_t *q, *tmp;
147 
148  if (session->partial_pdu)
149  coap_delete_pdu(session->partial_pdu);
150  if (session->proto == COAP_PROTO_DTLS)
151  coap_dtls_free_session(session);
152  else if (session->proto == COAP_PROTO_TLS)
153  coap_tls_free_session(session);
154  if (session->sock.flags != COAP_SOCKET_EMPTY)
155  coap_socket_close(&session->sock);
156  if (session->psk_identity)
157  coap_free(session->psk_identity);
158  if (session->psk_key)
159  coap_free(session->psk_key);
160 
161  LL_FOREACH_SAFE(session->delayqueue, q, tmp) {
162  if (q->pdu->type==COAP_MESSAGE_CON && session->context && session->context->nack_handler)
163  session->context->nack_handler(session->context, session, q->pdu, session->proto == COAP_PROTO_DTLS ? COAP_NACK_TLS_FAILED : COAP_NACK_NOT_DELIVERABLE, q->id);
164  coap_delete_node(q);
165  }
166 }
167 
169  if (!session)
170  return;
171  assert(session->ref == 0);
172  if (session->ref)
173  return;
174  coap_session_mfree(session);
175  if (session->endpoint) {
176  if (session->endpoint->sessions)
177  SESSIONS_DELETE(session->endpoint->sessions, session);
178  } else if (session->context) {
179  if (session->context->sessions)
180  SESSIONS_DELETE(session->context->sessions, session);
181  }
182  coap_log(LOG_DEBUG, "***%s: session closed\n", coap_session_str(session));
183 
184  coap_free_type(COAP_SESSION, session);
185 }
186 
188  size_t max_with_header = (size_t)(session->mtu - session->tls_overhead);
189  if (COAP_PROTO_NOT_RELIABLE(session->proto))
190  return max_with_header > 4 ? max_with_header - 4 : 0;
191  /* we must assume there is no token to be on the safe side */
192  if (max_with_header <= 2)
193  return 0;
194  else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP0 + 2)
195  return max_with_header - 2;
196  else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP8 + 3)
197  return max_with_header - 3;
198  else if (max_with_header <= COAP_MAX_MESSAGE_SIZE_TCP16 + 4)
199  return max_with_header - 4;
200  else
201  return max_with_header - 6;
202 }
203 
204 void coap_session_set_mtu(coap_session_t *session, unsigned mtu) {
205 #if defined(WITH_CONTIKI) || defined(WITH_LWIP)
206  if (mtu > COAP_MAX_MESSAGE_SIZE_TCP16 + 4)
207  mtu = COAP_MAX_MESSAGE_SIZE_TCP16 + 4;
208 #endif
209  session->mtu = mtu;
210  if (session->tls_overhead >= session->mtu) {
211  session->tls_overhead = session->mtu;
212  coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n");
213  }
214 }
215 
216 ssize_t coap_session_send(coap_session_t *session, const uint8_t *data, size_t datalen) {
217  ssize_t bytes_written;
218 
219  coap_socket_t *sock = &session->sock;
220  if (sock->flags == COAP_SOCKET_EMPTY) {
221  assert(session->endpoint != NULL);
222  sock = &session->endpoint->sock;
223  }
224 
225  bytes_written = coap_socket_send(sock, session, data, datalen);
226  if (bytes_written == (ssize_t)datalen) {
227  coap_ticks(&session->last_rx_tx);
228  coap_log(LOG_DEBUG, "* %s: sent %zd bytes\n",
229  coap_session_str(session), datalen);
230  } else {
231  coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes\n",
232  coap_session_str(session), datalen);
233  }
234  return bytes_written;
235 }
236 
237 ssize_t coap_session_write(coap_session_t *session, const uint8_t *data, size_t datalen) {
238  ssize_t bytes_written = coap_socket_write(&session->sock, data, datalen);
239  if (bytes_written > 0) {
240  coap_ticks(&session->last_rx_tx);
241  coap_log(LOG_DEBUG, "* %s: sent %zd bytes\n",
242  coap_session_str(session), datalen);
243  } else if (bytes_written < 0) {
244  coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes\n",
245  coap_session_str(session), datalen );
246  }
247  return bytes_written;
248 }
249 
250 ssize_t
252  coap_queue_t *node)
253 {
254  if ( node ) {
255  coap_queue_t *removed = NULL;
256  coap_remove_from_queue(&session->context->sendqueue, session, node->id, &removed);
257  assert(removed == node);
259  node->session = NULL;
260  node->t = 0;
261  } else {
262  coap_queue_t *q = NULL;
263  /* Check that the same tid is not getting re-used in violation of RFC7252 */
264  LL_FOREACH(session->delayqueue, q) {
265  if (q->id == pdu->tid) {
266  coap_log(LOG_ERR, "** %s: tid=%d: already in-use - dropped\n", coap_session_str(session), pdu->tid);
267  return COAP_INVALID_TID;
268  }
269  }
270  node = coap_new_node();
271  if (node == NULL)
272  return COAP_INVALID_TID;
273  node->id = pdu->tid;
274  node->pdu = pdu;
275  if (pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) {
276  uint8_t r;
277  prng(&r, sizeof(r));
278  /* add timeout in range [ACK_TIMEOUT...ACK_TIMEOUT * ACK_RANDOM_FACTOR] */
279  node->timeout = coap_calc_timeout(session, r);
280  }
281  }
282  LL_APPEND(session->delayqueue, node);
283  coap_log(LOG_DEBUG, "** %s: tid=%d: delayed\n",
284  coap_session_str(session), node->id);
285  return COAP_PDU_DELAYED;
286 }
287 
289  coap_pdu_t *pdu;
290  uint8_t buf[4];
291  assert(COAP_PROTO_RELIABLE(session->proto));
292  coap_log(LOG_DEBUG, "***%s: sending CSM\n", coap_session_str(session));
293  session->state = COAP_SESSION_STATE_CSM;
294  session->partial_write = 0;
295  if (session->mtu == 0)
296  session->mtu = COAP_DEFAULT_MTU; /* base value */
298  if ( pdu == NULL
300  coap_encode_var_safe(buf, sizeof(buf),
301  COAP_DEFAULT_MAX_PDU_RX_SIZE), buf) == 0
302  || coap_pdu_encode_header(pdu, session->proto) == 0
303  ) {
305  } else {
306  ssize_t bytes_written = coap_session_send_pdu(session, pdu);
307  if (bytes_written != (ssize_t)pdu->used_size + pdu->hdr_size)
309  }
310  if (pdu)
311  coap_delete_pdu(pdu);
312 }
313 
315  coap_pdu_t *ping;
316  if (session->state != COAP_SESSION_STATE_ESTABLISHED)
317  return COAP_INVALID_TID;
318  if (COAP_PROTO_NOT_RELIABLE(session->proto)) {
319  uint16_t tid = coap_new_message_id (session);
320  ping = coap_pdu_init(COAP_MESSAGE_CON, 0, tid, 0);
321  }
322  else {
324  }
325  if (!ping)
326  return COAP_INVALID_TID;
327  return coap_send(session, ping);
328 }
329 
331  if (session->state != COAP_SESSION_STATE_ESTABLISHED) {
332  coap_log(LOG_DEBUG, "***%s: session connected\n",
333  coap_session_str(session));
334  if (session->state == COAP_SESSION_STATE_CSM)
336  }
337 
339  session->partial_write = 0;
340 
341  if ( session->proto==COAP_PROTO_DTLS) {
342  session->tls_overhead = coap_dtls_get_overhead(session);
343  if (session->tls_overhead >= session->mtu) {
344  session->tls_overhead = session->mtu;
345  coap_log(LOG_ERR, "DTLS overhead exceeds MTU\n");
346  }
347  }
348 
349  while (session->delayqueue && session->state == COAP_SESSION_STATE_ESTABLISHED) {
350  ssize_t bytes_written;
351  coap_queue_t *q = session->delayqueue;
352  if (q->pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) {
353  if (session->con_active >= COAP_DEFAULT_NSTART)
354  break;
355  session->con_active++;
356  }
357  /* Take entry off the queue */
358  session->delayqueue = q->next;
359  q->next = NULL;
360 
361  coap_log(LOG_DEBUG, "** %s: tid=%d: transmitted after delay\n",
362  coap_session_str(session), (int)q->pdu->tid);
363  bytes_written = coap_session_send_pdu(session, q->pdu);
364  if (q->pdu->type == COAP_MESSAGE_CON && COAP_PROTO_NOT_RELIABLE(session->proto)) {
365  if (coap_wait_ack(session->context, session, q) >= 0)
366  q = NULL;
367  }
368  if (COAP_PROTO_NOT_RELIABLE(session->proto)) {
369  if (q)
370  coap_delete_node(q);
371  if (bytes_written < 0)
372  break;
373  } else {
374  if (bytes_written <= 0 || (size_t)bytes_written < q->pdu->used_size + q->pdu->hdr_size) {
375  q->next = session->delayqueue;
376  session->delayqueue = q;
377  if (bytes_written > 0)
378  session->partial_write = (size_t)bytes_written;
379  break;
380  } else {
381  coap_delete_node(q);
382  }
383  }
384  }
385 }
386 
388  (void)reason;
389  coap_session_state_t state = session->state;
390 
391  coap_log(LOG_DEBUG, "***%s: session disconnected (reason %d)\n",
392  coap_session_str(session), reason);
393 #ifndef WITHOUT_OBSERVE
394  coap_delete_observers( session->context, session );
395 #endif
396 
397  if ( session->tls) {
398  if (session->proto == COAP_PROTO_DTLS)
399  coap_dtls_free_session(session);
400  else if (session->proto == COAP_PROTO_TLS)
401  coap_tls_free_session(session);
402  session->tls = NULL;
403  }
404 
405  if (session->proto == COAP_PROTO_UDP)
407  else
408  session->state = COAP_SESSION_STATE_NONE;
409 
410  session->con_active = 0;
411 
412  if (session->partial_pdu) {
413  coap_delete_pdu(session->partial_pdu);
414  session->partial_pdu = NULL;
415  }
416  session->partial_read = 0;
417 
418  while (session->delayqueue) {
419  coap_queue_t *q = session->delayqueue;
420  session->delayqueue = q->next;
421  q->next = NULL;
422  coap_log(LOG_DEBUG, "** %s: tid=%d: not transmitted after disconnect\n",
423  coap_session_str(session), q->id);
424  if (q->pdu->type==COAP_MESSAGE_CON
425  && COAP_PROTO_NOT_RELIABLE(session->proto)
426  && reason == COAP_NACK_ICMP_ISSUE)
427  {
428  /* Make sure that we try a re-transmit later on ICMP error */
429  if (coap_wait_ack(session->context, session, q) >= 0)
430  q = NULL;
431  }
432  if (q && q->pdu->type == COAP_MESSAGE_CON
433  && session->context->nack_handler)
434  {
435  session->context->nack_handler(session->context, session, q->pdu,
436  reason, q->id);
437  }
438  if (q)
439  coap_delete_node(q);
440  }
441  if (reason != COAP_NACK_ICMP_ISSUE)
442  coap_cancel_session_messages(session->context, session, reason);
443 
444  if ( COAP_PROTO_RELIABLE(session->proto) ) {
445  if (session->sock.flags != COAP_SOCKET_EMPTY) {
446  coap_socket_close(&session->sock);
447  coap_handle_event(session->context,
450  }
451  if (state != COAP_SESSION_STATE_NONE) {
452  coap_handle_event(session->context,
455  }
456  }
457 }
458 
461  const coap_packet_t *packet, coap_tick_t now) {
462  coap_session_t *session;
463  coap_session_t *rtmp;
464  unsigned int num_idle = 0;
465  unsigned int num_hs = 0;
466  coap_session_t *oldest = NULL;
467  coap_session_t *oldest_hs = NULL;
468 
469  SESSIONS_FIND(endpoint->sessions, packet->addr_info, session);
470  if (session) {
471  session->last_rx_tx = now;
472  return session;
473  }
474 
475  SESSIONS_ITER(endpoint->sessions, session, rtmp) {
476  if (session->ref == 0 && session->delayqueue == NULL) {
477  if (session->type == COAP_SESSION_TYPE_SERVER) {
478  ++num_idle;
479  if (oldest==NULL || session->last_rx_tx < oldest->last_rx_tx)
480  oldest = session;
481 
482  if (session->state == COAP_SESSION_STATE_HANDSHAKE) {
483  ++num_hs;
484  /* See if this is a partial (D)TLS session set up
485  which needs to be cleared down to prevent DOS */
486  if ((session->last_rx_tx + COAP_PARTIAL_SESSION_TIMEOUT_TICKS) < now) {
487  if (oldest_hs == NULL ||
488  session->last_rx_tx < oldest_hs->last_rx_tx)
489  oldest_hs = session;
490  }
491  }
492  }
493  else if (session->type == COAP_SESSION_TYPE_HELLO) {
494  ++num_hs;
495  /* See if this is a partial (D)TLS session set up for Client Hello
496  which needs to be cleared down to prevent DOS */
497  if ((session->last_rx_tx + COAP_PARTIAL_SESSION_TIMEOUT_TICKS) < now) {
498  if (oldest_hs == NULL ||
499  session->last_rx_tx < oldest_hs->last_rx_tx)
500  oldest_hs = session;
501  }
502  }
503  }
504  }
505 
506  if (endpoint->context->max_idle_sessions > 0 &&
507  num_idle >= endpoint->context->max_idle_sessions) {
508  coap_session_free(oldest);
509  }
510  else if (oldest_hs) {
511  coap_log(LOG_WARNING, "***%s: Incomplete session timed out\n",
512  coap_session_str(oldest_hs));
513  coap_session_free(oldest_hs);
514  }
515 
516  if (num_hs > (endpoint->context->max_handshake_sessions ?
517  endpoint->context->max_handshake_sessions :
519  /* Maxed out on number of sessions in (D)TLS negotiation state */
521  "Oustanding sessions in COAP_SESSION_STATE_HANDSHAKE too "
522  "large. New request ignored\n");
523  return NULL;
524  }
525 
526  if (endpoint->proto == COAP_PROTO_DTLS) {
527  /*
528  * Need to check that this actually is a Client Hello before wasting
529  * time allocating and then freeing off session.
530  */
531 
532  /*
533  * Generic header structure of the DTLS record layer.
534  * typedef struct __attribute__((__packed__)) {
535  * uint8_t content_type; content type of the included message
536  * uint16_t version; Protocol version
537  * uint16_t epoch; counter for cipher state changes
538  * uint8_t sequence_number[6]; sequence number
539  * uint16_t length; length of the following fragment
540  * uint8_t handshake; If content_type == DTLS_CT_HANDSHAKE
541  * } dtls_record_handshake_t;
542  */
543 #define OFF_CONTENT_TYPE 0 /* offset of content_type in dtls_record_handshake_t */
544 #define DTLS_CT_ALERT 21 /* Content Type Alert */
545 #define DTLS_CT_HANDSHAKE 22 /* Content Type Handshake */
546 #define OFF_HANDSHAKE_TYPE 13 /* offset of handshake in dtls_record_handshake_t */
547 #define DTLS_HT_CLIENT_HELLO 1 /* Client Hello handshake type */
548 
549 #ifdef WITH_LWIP
550  const uint8_t *payload = (const uint8_t*)packet->pbuf->payload;
551  size_t length = packet->pbuf->len;
552 #else /* ! WITH_LWIP */
553  const uint8_t *payload = (const uint8_t*)packet->payload;
554  size_t length = packet->length;
555 #endif /* ! WITH_LWIP */
556  if (length < (OFF_HANDSHAKE_TYPE + 1)) {
558  "coap_dtls_hello: ContentType %d Short Packet (%zu < %d) dropped\n",
559  payload[OFF_CONTENT_TYPE], length,
560  OFF_HANDSHAKE_TYPE + 1);
561  return NULL;
562  }
563  if (payload[OFF_CONTENT_TYPE] != DTLS_CT_HANDSHAKE ||
565  /* only log if not a late alert */
566  if (payload[OFF_CONTENT_TYPE] != DTLS_CT_ALERT)
568  "coap_dtls_hello: ContentType %d Handshake %d dropped\n",
569  payload[OFF_CONTENT_TYPE], payload[OFF_HANDSHAKE_TYPE]);
570  return NULL;
571  }
572  }
573  session = coap_make_session(endpoint->proto, COAP_SESSION_TYPE_SERVER,
574  NULL, &packet->addr_info.local,
575  &packet->addr_info.remote,
576  packet->ifindex, endpoint->context, endpoint);
577  if (session) {
578  session->last_rx_tx = now;
579  if (endpoint->proto == COAP_PROTO_UDP)
581  else if (endpoint->proto == COAP_PROTO_DTLS) {
582  session->type = COAP_SESSION_TYPE_HELLO;
583  }
584  SESSIONS_ADD(endpoint->sessions, session);
585  coap_log(LOG_DEBUG, "***%s: new incoming session\n",
586  coap_session_str(session));
587  }
588  return session;
589 }
590 
593  coap_tick_t now) {
594  if (session) {
595  session->last_rx_tx = now;
596  session->type = COAP_SESSION_TYPE_SERVER;
597  session->tls = coap_dtls_new_server_session(session);
598  if (session->tls) {
600  } else {
601  coap_session_free(session);
602  session = NULL;
603  }
604  }
605  return session;
606 }
607 
608 #ifdef COAP_EPOLL_SUPPORT
609 static void
610 coap_epoll_ctl_add(coap_socket_t *sock,
611  uint32_t events,
612  const char *func
613 ) {
614  int ret;
615  struct epoll_event event;
616  coap_context_t *context;
617 
618  if (sock == NULL)
619  return;
620 
621  context = sock->session ? sock->session->context :
622  sock->endpoint ? sock->endpoint->context : NULL;
623  if (context == NULL)
624  return;
625 
626  /* Needed if running 32bit as ptr is only 32bit */
627  memset(&event, 0, sizeof(event));
628  event.events = events;
629  event.data.ptr = sock;
630 
631  ret = epoll_ctl(context->epfd, EPOLL_CTL_ADD, sock->fd, &event);
632  if (ret == -1) {
634  "%s: epoll_ctl ADD failed: %s (%d)\n",
635  func,
636  coap_socket_strerror(), errno);
637  }
638 }
639 #endif /* COAP_EPOLL_SUPPORT */
640 
641 static coap_session_t *
643  coap_context_t *ctx,
644  const coap_address_t *local_if,
645  const coap_address_t *server,
646  coap_proto_t proto
647 ) {
648  coap_session_t *session = NULL;
649 
650  assert(server);
651  assert(proto != COAP_PROTO_NONE);
652 
653  session = coap_make_session(proto, COAP_SESSION_TYPE_CLIENT, local_if,
654  local_if, server, 0, ctx, NULL);
655  if (!session)
656  goto error;
657 
658  coap_session_reference(session);
659 
660  if (proto == COAP_PROTO_UDP || proto == COAP_PROTO_DTLS) {
661  if (!coap_socket_connect_udp(&session->sock, &session->local_if, server,
663  &session->addr_info.local, &session->addr_info.remote)) {
664  goto error;
665  }
666  } else if (proto == COAP_PROTO_TCP || proto == COAP_PROTO_TLS) {
667  if (!coap_socket_connect_tcp1(&session->sock, &session->local_if, server,
669  &session->addr_info.local, &session->addr_info.remote)) {
670  goto error;
671  }
672  }
673 
674  session->sock.session = session;
675 #ifdef COAP_EPOLL_SUPPORT
676  coap_epoll_ctl_add(&session->sock,
677  EPOLLIN |
678  ((session->sock.flags & COAP_SOCKET_WANT_CONNECT) ?
679  EPOLLOUT : 0),
680  __func__);
681 #endif /* COAP_EPOLL_SUPPORT */
682 
684  if (local_if)
685  session->sock.flags |= COAP_SOCKET_BOUND;
686  SESSIONS_ADD(ctx->sessions, session);
687  return session;
688 
689 error:
690  coap_session_release(session);
691  return NULL;
692 }
693 
694 static coap_session_t *
696  if (session->proto == COAP_PROTO_UDP) {
698  } else if (session->proto == COAP_PROTO_DTLS) {
699  session->tls = coap_dtls_new_client_session(session);
700  if (session->tls) {
702  } else {
703  /* Need to free session object. As a new session may not yet
704  * have been referenced, we call coap_session_reference() first
705  * before trying to release the object.
706  */
707  coap_session_reference(session);
708  coap_session_release(session);
709  return NULL;
710  }
711  } else if (session->proto == COAP_PROTO_TCP || session->proto == COAP_PROTO_TLS) {
712  if (session->sock.flags & COAP_SOCKET_WANT_CONNECT) {
714  } else if (session->proto == COAP_PROTO_TLS) {
715  int connected = 0;
716  session->tls = coap_tls_new_client_session(session, &connected);
717  if (session->tls) {
719  if (connected)
720  coap_session_send_csm(session);
721  } else {
722  /* Need to free session object. As a new session may not yet
723  * have been referenced, we call coap_session_reference()
724  * first before trying to release the object.
725  */
726  coap_session_reference(session);
727  coap_session_release(session);
728  return NULL;
729  }
730  } else {
731  coap_session_send_csm(session);
732  }
733  }
734  coap_ticks(&session->last_rx_tx);
735  return session;
736 }
737 
738 static coap_session_t *
740  if (session->proto == COAP_PROTO_TCP || session->proto == COAP_PROTO_TLS)
742  if (session->proto == COAP_PROTO_TCP) {
743  coap_session_send_csm(session);
744  } else if (session->proto == COAP_PROTO_TLS) {
745  int connected = 0;
746  session->tls = coap_tls_new_server_session(session, &connected);
747  if (session->tls) {
749  if (connected) {
751  coap_session_send_csm(session);
752  }
753  } else {
754  /* Need to free session object. As a new session may not yet
755  * have been referenced, we call coap_session_reference() first
756  * before trying to release the object.
757  */
758  coap_session_reference(session);
759  coap_session_release(session);
760  session = NULL;
761  }
762  }
763  return session;
764 }
765 
767  struct coap_context_t *ctx,
768  const coap_address_t *local_if,
769  const coap_address_t *server,
770  coap_proto_t proto
771 ) {
772  coap_session_t *session = coap_session_create_client(ctx, local_if, server, proto);
773  if (session) {
774  coap_log(LOG_DEBUG, "***%s: new outgoing session\n",
775  coap_session_str(session));
776  session = coap_session_connect(session);
777  }
778  return session;
779 }
780 
782  struct coap_context_t *ctx,
783  const coap_address_t *local_if,
784  const coap_address_t *server,
785  coap_proto_t proto,
786  const char *identity,
787  const uint8_t *key,
788  unsigned key_len
789 ) {
790  coap_session_t *session = coap_session_create_client(ctx, local_if, server, proto);
791 
792  if (!session)
793  return NULL;
794 
795  if (identity && (strlen(identity) > 0)) {
796  size_t identity_len = strlen(identity);
797  session->psk_identity = (uint8_t*)coap_malloc(identity_len);
798  if (session->psk_identity) {
799  memcpy(session->psk_identity, identity, identity_len);
800  session->psk_identity_len = identity_len;
801  } else {
802  coap_log(LOG_WARNING, "Cannot store session PSK identity\n");
803  coap_session_release(session);
804  return NULL;
805  }
806  }
807  else if (coap_dtls_is_supported()) {
808  coap_log(LOG_WARNING, "PSK identity not defined\n");
809  coap_session_release(session);
810  return NULL;
811  }
812 
813  if (key && key_len > 0) {
814  session->psk_key = (uint8_t*)coap_malloc(key_len);
815  if (session->psk_key) {
816  memcpy(session->psk_key, key, key_len);
817  session->psk_key_len = key_len;
818  } else {
819  coap_log(LOG_WARNING, "Cannot store session PSK key\n");
820  coap_session_release(session);
821  return NULL;
822  }
823  }
824  else if (coap_dtls_is_supported()) {
825  coap_log(LOG_WARNING, "PSK key not defined\n");
826  coap_session_release(session);
827  return NULL;
828  }
829 
830  if (coap_dtls_is_supported()) {
832  coap_session_release(session);
833  return NULL;
834  }
835  }
836  coap_log(LOG_DEBUG, "***%s: new outgoing session\n",
837  coap_session_str(session));
838  return coap_session_connect(session);
839 }
840 
842  struct coap_context_t *ctx,
843  const coap_address_t *local_if,
844  const coap_address_t *server,
845  coap_proto_t proto,
846  coap_dtls_pki_t* setup_data
847 ) {
848  coap_session_t *session;
849 
850  if (coap_dtls_is_supported()) {
851  if (!setup_data) {
852  return NULL;
853  } else {
854  if (setup_data->version != COAP_DTLS_PKI_SETUP_VERSION) {
856  "coap_new_client_session_pki: Wrong version of setup_data\n");
857  return NULL;
858  }
859  }
860 
861  }
862  session = coap_session_create_client(ctx, local_if, server, proto);
863 
864  if (!session) {
865  return NULL;
866  }
867 
868  if (coap_dtls_is_supported()) {
869  /* we know that setup_data is not NULL */
870  if (!coap_dtls_context_set_pki(ctx, setup_data, COAP_DTLS_ROLE_CLIENT)) {
871  coap_session_release(session);
872  return NULL;
873  }
874  }
875  coap_log(LOG_DEBUG, "***%s: new outgoing session\n",
876  coap_session_str(session));
877  return coap_session_connect(session);
878 }
879 
880 
882  struct coap_context_t *ctx,
883  coap_endpoint_t *ep
884 ) {
885  coap_session_t *session;
887  &ep->bind_addr, NULL, NULL, 0, ctx, ep );
888  if (!session)
889  goto error;
890 
891  if (!coap_socket_accept_tcp(&ep->sock, &session->sock,
892  &session->addr_info.local,
893  &session->addr_info.remote))
894  goto error;
897  session->sock.session = session;
898 #ifdef COAP_EPOLL_SUPPORT
899  coap_epoll_ctl_add(&session->sock,
900  EPOLLIN,
901  __func__);
902 #endif /* COAP_EPOLL_SUPPORT */
903  SESSIONS_ADD(ep->sessions, session);
904  if (session) {
905  coap_log(LOG_DEBUG, "***%s: new incoming session\n",
906  coap_session_str(session));
907  session = coap_session_accept(session);
908  }
909  return session;
910 
911 error:
912  coap_session_free(session);
913  return NULL;
914 }
915 
916 #ifndef WITH_LWIP
918 coap_new_endpoint(coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto) {
919  struct coap_endpoint_t *ep = NULL;
920 
921  assert(context);
922  assert(listen_addr);
923  assert(proto != COAP_PROTO_NONE);
924 
925  if (proto == COAP_PROTO_DTLS && !coap_dtls_is_supported()) {
926  coap_log(LOG_CRIT, "coap_new_endpoint: DTLS not supported\n");
927  goto error;
928  }
929 
930  if (proto == COAP_PROTO_TLS && !coap_tls_is_supported()) {
931  coap_log(LOG_CRIT, "coap_new_endpoint: TLS not supported\n");
932  goto error;
933  }
934 
935  if (proto == COAP_PROTO_DTLS || proto == COAP_PROTO_TLS) {
936  if (!coap_dtls_context_check_keys_enabled(context)) {
938  "coap_new_endpoint: one of coap_context_set_psk() or "
939  "coap_context_set_pki() not called\n");
940  goto error;
941  }
942  }
943 
944  ep = coap_malloc_endpoint();
945  if (!ep) {
946  coap_log(LOG_WARNING, "coap_new_endpoint: malloc");
947  goto error;
948  }
949 
950  memset(ep, 0, sizeof(struct coap_endpoint_t));
951  ep->context = context;
952  ep->proto = proto;
953 
954  if (proto==COAP_PROTO_TCP || proto==COAP_PROTO_TLS) {
955  if (!coap_socket_bind_tcp(&ep->sock, listen_addr, &ep->bind_addr))
956  goto error;
958  } else if (proto==COAP_PROTO_UDP || proto==COAP_PROTO_DTLS) {
959  if (!coap_socket_bind_udp(&ep->sock, listen_addr, &ep->bind_addr))
960  goto error;
962  } else {
963  coap_log(LOG_CRIT, "coap_new_endpoint: protocol not supported\n");
964  goto error;
965  }
966 
967  if (LOG_DEBUG <= coap_get_log_level()) {
968 #ifndef INET6_ADDRSTRLEN
969 #define INET6_ADDRSTRLEN 40
970 #endif
971  unsigned char addr_str[INET6_ADDRSTRLEN + 8];
972 
973  if (coap_print_addr(&ep->bind_addr, addr_str, INET6_ADDRSTRLEN + 8)) {
974  coap_log(LOG_DEBUG, "created %s endpoint %s\n",
975  ep->proto == COAP_PROTO_TLS ? "TLS "
976  : ep->proto == COAP_PROTO_TCP ? "TCP "
977  : ep->proto == COAP_PROTO_DTLS ? "DTLS" : "UDP ",
978  addr_str);
979  }
980  }
981 
983 
985 
986  ep->sock.endpoint = ep;
987 #ifdef COAP_EPOLL_SUPPORT
988  coap_epoll_ctl_add(&ep->sock,
989  EPOLLIN,
990  __func__);
991 #endif /* COAP_EPOLL_SUPPORT */
992 
993  LL_PREPEND(context->endpoint, ep);
994  return ep;
995 
996 error:
997  coap_free_endpoint(ep);
998  return NULL;
999 }
1000 
1002  ep->default_mtu = (uint16_t)mtu;
1003 }
1004 
1005 void
1007  if (ep) {
1008  coap_session_t *session, *rtmp;
1009 
1010  if (ep->sock.flags != COAP_SOCKET_EMPTY)
1011  coap_socket_close(&ep->sock);
1012 
1013  SESSIONS_ITER_SAFE(ep->sessions, session, rtmp) {
1014  assert(session->ref == 0);
1015  if (session->ref == 0) {
1016  coap_session_free(session);
1017  }
1018  }
1019 
1020  if (ep->context) {
1021  LL_DELETE(ep->context->endpoint, ep);
1022  }
1023  coap_mfree_endpoint(ep);
1024  }
1025 }
1026 #endif /* WITH_LWIP */
1027 
1030  const coap_address_t *remote_addr,
1031  int ifindex) {
1032  coap_session_t *s, *rtmp;
1033  coap_endpoint_t *ep;
1034  SESSIONS_ITER(ctx->sessions, s, rtmp) {
1035  if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote,
1036  remote_addr))
1037  return s;
1038  }
1039  LL_FOREACH(ctx->endpoint, ep) {
1040  SESSIONS_ITER(ep->sessions, s, rtmp) {
1041  if (s->ifindex == ifindex && coap_address_equals(&s->addr_info.remote,
1042  remote_addr))
1043  return s;
1044  }
1045  }
1046  return NULL;
1047 }
1048 
1049 const char *coap_session_str(const coap_session_t *session) {
1050  static char szSession[256];
1051  char *p = szSession, *end = szSession + sizeof(szSession);
1052  if (coap_print_addr(&session->addr_info.local,
1053  (unsigned char*)p, end - p) > 0)
1054  p += strlen(p);
1055  if (p + 6 < end) {
1056  strcpy(p, " <-> ");
1057  p += 5;
1058  }
1059  if (p + 1 < end) {
1060  if (coap_print_addr(&session->addr_info.remote,
1061  (unsigned char*)p, end - p) > 0)
1062  p += strlen(p);
1063  }
1064  if (session->ifindex > 0 && p + 1 < end)
1065  p += snprintf(p, end - p, " (if%d)", session->ifindex);
1066  if (p + 6 < end) {
1067  if (session->proto == COAP_PROTO_UDP) {
1068  strcpy(p, " UDP ");
1069  p += 4;
1070  } else if (session->proto == COAP_PROTO_DTLS) {
1071  strcpy(p, " DTLS");
1072  p += 5;
1073  } else if (session->proto == COAP_PROTO_TCP) {
1074  strcpy(p, " TCP ");
1075  p += 4;
1076  } else if (session->proto == COAP_PROTO_TLS) {
1077  strcpy(p, " TLS ");
1078  p += 4;
1079  } else {
1080  strcpy(p, " NONE");
1081  p += 5;
1082  }
1083  }
1084 
1085  return szSession;
1086 }
1087 
1088 const char *coap_endpoint_str(const coap_endpoint_t *endpoint) {
1089  static char szEndpoint[128];
1090  char *p = szEndpoint, *end = szEndpoint + sizeof(szEndpoint);
1091  if (coap_print_addr(&endpoint->bind_addr, (unsigned char*)p, end - p) > 0)
1092  p += strlen(p);
1093  if (p + 6 < end) {
1094  if (endpoint->proto == COAP_PROTO_UDP) {
1095  strcpy(p, " UDP");
1096  p += 4;
1097  } else if (endpoint->proto == COAP_PROTO_DTLS) {
1098  strcpy(p, " DTLS");
1099  p += 5;
1100  } else {
1101  strcpy(p, " NONE");
1102  p += 5;
1103  }
1104  }
1105 
1106  return szEndpoint;
1107 }
1108 
1109 #endif /* COAP_SESSION_C_ */
uint8_t type
message type
Definition: pdu.h:288
unsigned mtu
path or CSM mtu
Definition: coap_session.h:65
void coap_dtls_free_session(struct coap_dtls_context_t *dtls_context, struct coap_dtls_session_t *session)
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:288
#define LL_FOREACH(head, el)
Definition: utlist.h:413
coap_queue_t * sendqueue
Definition: net.h:164
#define COAP_SOCKET_EMPTY
coap_socket_flags_t values
Definition: coap_io.h:76
uint8_t * psk_identity
Definition: coap_session.h:87
#define COAP_DEFAULT_MTU
Definition: pdu.h:32
coap_address_t remote
remote address and port
Definition: coap_io.h:50
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:766
coap_tick_t last_rx_tx
Definition: coap_session.h:82
coap_tid_t last_ping_mid
the last keepalive message id that was used in this session
Definition: coap_session.h:76
uint8_t con_active
Active CON request sent.
Definition: coap_session.h:75
void * app
application-specific data
Definition: coap_session.h:91
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 COAP_SIGNALING_PING
Definition: pdu.h:181
uint8_t coap_proto_t
Definition: pdu.h:339
Abstraction of a fixed point number that can be used where necessary instead of a float...
Definition: coap_session.h:28
#define DTLS_HT_CLIENT_HELLO
#define COAP_SESSION_TYPE_CLIENT
coap_session_type_t values
Definition: coap_session.h:45
coap_tid_t coap_wait_ack(coap_context_t *context, coap_session_t *session, coap_queue_t *node)
Definition: net.c:888
#define COAP_SIGNALING_CSM
Definition: pdu.h:180
void coap_socket_close(coap_socket_t *sock)
Definition: coap_io.c:631
#define COAP_DTLS_PKI_SETUP_VERSION
Latest PKI setup version.
Definition: coap_dtls.h:188
void coap_tls_free_session(coap_session_t *coap_session UNUSED)
Definition: coap_notls.c:158
unsigned int coap_session_get_max_transmit(coap_session_t *session)
Get the CoAP maximum retransmit before failure.
Definition: coap_session.c:53
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
struct coap_context_t * context
session&#39;s context
Definition: coap_session.h:72
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.
Definition: coap_session.c:881
coap_fixed_point_t ack_timeout
timeout waiting for ack (default 2 secs)
Definition: coap_session.h:93
void * tls
security parameters
Definition: coap_session.h:73
#define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS
Definition: coap_session.h:36
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:91
coap_endpoint_t * endpoint
the endpoints used for listening
Definition: net.h:165
#define COAP_SESSION_STATE_HANDSHAKE
Definition: coap_session.h:55
#define COAP_SOCKET_CONNECTED
the socket is connected
Definition: coap_io.h:79
#define COAP_SOCKET_BOUND
the socket is bound
Definition: coap_io.h:78
multi-purpose address abstraction
Definition: address.h:62
coap_fd_t fd
Definition: coap_io.h:60
uint16_t tx_mid
the last message id that was used in this session
Definition: coap_session.h:74
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx UNUSED)
Definition: coap_notls.c:63
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:1657
unsigned ref
reference count from queues
Definition: coap_session.h:63
int coap_tid_t
coap_tid_t is used to store CoAP transaction id, i.e.
Definition: pdu.h:238
#define LL_PREPEND(head, add)
Definition: utlist.h:314
void coap_session_set_mtu(coap_session_t *session, unsigned mtu)
Set the session MTU.
Definition: coap_session.c:204
coap_tid_t coap_session_send_ping(coap_session_t *session)
Send a ping message for the session.
Definition: coap_session.c:314
unsigned tls_overhead
overhead of TLS layer
Definition: coap_session.h:64
uint8_t version
Definition: coap_dtls.h:194
#define COAP_MAX_MESSAGE_SIZE_TCP8
Definition: pdu.h:42
unsigned int coap_encode_var_safe(uint8_t *buf, size_t length, unsigned int val)
Encodes multiple-length byte sequences.
Definition: encode.c:38
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:592
int ifindex
the interface index
Definition: coap_io.h:219
coap_address_t local
local address and port
Definition: coap_io.h:51
#define COAP_PROTO_DTLS
Definition: pdu.h:345
int coap_socket_accept_tcp(coap_socket_t *server, coap_socket_t *new_client, coap_address_t *local_addr, coap_address_t *remote_addr)
Definition: coap_io.c:492
void * coap_dtls_new_client_session(coap_session_t *session UNUSED)
Definition: coap_notls.c:96
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.
Definition: coap_session.c:918
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:161
coap_tid_t coap_send(coap_session_t *session, coap_pdu_t *pdu)
Sends a CoAP message to given peer.
Definition: net.c:966
uint16_t default_mtu
default mtu for this interface
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:724
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)
Definition: coap_io.c:264
int coap_dtls_is_supported(void)
Returns 1 if support for DTLS is enabled, or 0 otherwise.
int coap_dtls_context_set_pki(coap_context_t *ctx UNUSED, coap_dtls_pki_t *setup_data UNUSED, coap_dtls_role_t role UNUSED)
Definition: coap_notls.c:39
void * coap_tls_new_server_session(coap_session_t *session UNUSED, int *connected UNUSED)
Definition: coap_notls.c:154
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.
Definition: coap_session.c:841
coap_address_t local_if
optional local interface address
Definition: coap_session.h:66
size_t coap_session_max_pdu_size(const coap_session_t *session)
Get maximum acceptable PDU size.
Definition: coap_session.c:187
#define COAP_EVENT_TCP_CONNECTED
TCP events for COAP_PROTO_TCP and COAP_PROTO_TLS.
Definition: coap_event.h:41
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:216
int dtls_event
Tracking any (D)TLS events on this sesison.
Definition: coap_session.h:96
coap_session_t * coap_session_get_by_peer(coap_context_t *ctx, const coap_address_t *remote_addr, int ifindex)
#define COAP_PDU_DELAYED
Definition: pdu.h:249
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
Debug.
Definition: coap_debug.h:55
void coap_endpoint_set_default_mtu(coap_endpoint_t *ep, unsigned mtu)
Set the endpoint&#39;s default MTU.
coap_nack_handler_t nack_handler
Definition: net.h:181
#define COAP_SOCKET_WANT_ACCEPT
non blocking server socket is waiting for accept
Definition: coap_io.h:82
#define COAP_MAX_MESSAGE_SIZE_TCP16
Definition: pdu.h:43
#define COAP_EVENT_TCP_FAILED
Definition: coap_event.h:43
coap_nack_reason_t
Definition: coap_io.h:226
unsigned char payload[COAP_RXBUFFER_SIZE]
payload
Definition: coap_io.h:221
#define COAP_EVENT_SESSION_FAILED
Definition: coap_event.h:50
struct coap_context_t * context
endpoint&#39;s context
coap_session_t * coap_session_reference(coap_session_t *session)
Increment reference counter on a session.
Definition: coap_session.c:68
const char * coap_endpoint_str(const coap_endpoint_t *endpoint)
Get endpoint description.
void * coap_tls_new_client_session(coap_session_t *session UNUSED, int *connected UNUSED)
Definition: coap_notls.c:150
Abstraction of virtual endpoint that can be attached to coap_context_t.
const char * coap_session_str(const coap_session_t *session)
Get session description.
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:390
const char * coap_socket_strerror(void)
Definition: coap_io.c:1651
struct coap_endpoint_t * endpoint
Definition: coap_io.h:67
#define COAP_SESSION_STATE_ESTABLISHED
Definition: coap_session.h:57
coap_tid_t id
CoAP transaction id.
Definition: net.h:45
unsigned int max_retransmit
maximum re-transmit count (default 4)
Definition: coap_session.h:92
#define SESSIONS_ITER_SAFE(e, el, rtmp)
Definition: coap_session.h:489
#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:382
uint16_t fractional_part
Fractional part of fixed point variable 1/1000 (3 points) precision.
Definition: coap_session.h:30
#define COAP_EVENT_SESSION_CONNECTED
CSM exchange events for reliable protocols only.
Definition: coap_event.h:48
void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
Definition: address.c:71
#define COAP_PROTO_UDP
Definition: pdu.h:344
COAP_STATIC_INLINE void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
Definition: mem.h:75
struct coap_endpoint_t * coap_malloc_endpoint(void)
Definition: coap_io.c:175
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:26
coap_pdu_t * pdu
the CoAP PDU to send
Definition: net.h:46
coap_tick_t t
when to send PDU for the next time
Definition: net.h:40
void coap_session_mfree(coap_session_t *session)
Definition: coap_session.c:145
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:568
#define OFF_HANDSHAKE_TYPE
#define COAP_PARTIAL_SESSION_TIMEOUT_TICKS
Definition: coap_session.h:35
#define COAP_INVALID_TID
Indicates an invalid transaction id.
Definition: pdu.h:241
coap_session_t * coap_endpoint_get_session(coap_endpoint_t *endpoint, const coap_packet_t *packet, coap_tick_t now)
Definition: coap_session.c:460
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
void coap_session_set_app_data(coap_session_t *session, void *app_data)
Stores data with the given session.
Definition: coap_session.c:85
unsigned int coap_calc_timeout(coap_session_t *session, unsigned char r)
Calculates the initial timeout based on the session CoAP transmission parameters &#39;ack_timeout&#39;, &#39;ack_random_factor&#39;, and COAP_TICKS_PER_SECOND.
Definition: net.c:862
structure for CoAP PDUs token, if any, follows the fixed size header, then options until payload mark...
Definition: pdu.h:287
#define COAP_SIGNALING_OPTION_MAX_MESSAGE_SIZE
Definition: pdu.h:187
struct coap_queue_t * delayqueue
list of delayed messages waiting to be sent
Definition: coap_session.h:77
coap_proto_t proto
protocol used
Definition: coap_session.h:60
coap_addr_tuple_t addr_info
key: remote/local address info
Definition: coap_session.h:68
Warning.
Definition: coap_debug.h:52
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:93
static coap_session_t * coap_session_accept(coap_session_t *session)
Definition: coap_session.c:739
void coap_free_endpoint(coap_endpoint_t *ep)
#define COAP_SOCKET_NOT_EMPTY
the socket is not empty
Definition: coap_io.h:77
unsigned int coap_dtls_get_overhead(coap_session_t *session UNUSED)
Definition: coap_notls.c:146
size_t partial_read
if > 0 indicates number of bytes already read for an incoming message
Definition: coap_session.h:80
coap_pdu_t * partial_pdu
incomplete incoming pdu
Definition: coap_session.h:81
ssize_t coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_queue_t *node)
Definition: coap_session.c:251
size_t used_size
used bytes of storage for token, options and payload
Definition: pdu.h:296
#define SESSIONS_ADD(e, obj)
Definition: coap_session.h:480
void coap_session_free(coap_session_t *session)
Definition: coap_session.c:168
struct coap_queue_t * next
Definition: net.h:39
#define DTLS_CT_HANDSHAKE
coap_socket_t sock
socket object for the session, if any
Definition: coap_session.h:70
ssize_t coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len)
Definition: coap_io.c:690
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
#define COAPS_DEFAULT_PORT
Definition: pdu.h:29
#define INET6_ADDRSTRLEN
int coap_dtls_context_set_psk(coap_context_t *ctx UNUSED, const char *hint UNUSED, coap_dtls_role_t role UNUSED)
Definition: coap_notls.c:55
coap_proto_t proto
protocol used on this interface
#define COAP_MESSAGE_CON
Definition: pdu.h:72
unsigned int timeout
the randomized timeout value
Definition: net.h:43
#define COAP_PROTO_TLS
Definition: pdu.h:347
#define LL_APPEND(head, add)
Definition: utlist.h:338
static coap_session_t * coap_session_connect(coap_session_t *session)
Definition: coap_session.c:695
COAP_STATIC_INLINE void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:82
Error.
Definition: coap_debug.h:51
coap_session_type_t type
client or server side socket
Definition: coap_session.h:61
#define COAP_DEFAULT_NSTART
The number of simultaneous outstanding interactions that a client maintains to a given server...
Definition: coap_session.h:395
#define COAP_EVENT_TCP_CLOSED
Definition: coap_event.h:42
coap_session_state_t state
current state of relationaship with peer
Definition: coap_session.h:62
Internal function invoked for client.
Definition: coap_dtls.h:267
size_t psk_identity_len
Definition: coap_session.h:88
#define COAP_SESSION_TYPE_SERVER
server-side
Definition: coap_session.h:46
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:215
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
Definition: coap_session.c:74
#define COAP_SESSION_TYPE_HELLO
server-side ephemeral session for responding to a client hello
Definition: coap_session.h:47
coap_fixed_point_t ack_random_factor
ack random factor backoff (default 1.5)
Definition: coap_session.h:94
int coap_remove_from_queue(coap_queue_t **queue, coap_session_t *session, coap_tid_t id, coap_queue_t **node)
This function removes the element with given id from the list given list.
Definition: net.c:1585
int ifindex
interface index
Definition: coap_session.h:69
#define COAP_DEFAULT_PORT
Definition: pdu.h:28
size_t partial_write
if > 0 indicates number of bytes already written from the pdu at the head of sendqueue ...
Definition: coap_session.h:78
unsigned int uint32_t
Definition: uthash.h:78
#define COAP_EVENT_DTLS_CONNECTED
Definition: coap_event.h:34
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
Definition: address.c:31
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:2542
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition: pdu.c:127
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:237
COAP_STATIC_INLINE void coap_address_copy(coap_address_t *dst, const coap_address_t *src)
Definition: address.h:108
size_t length
length of payload
Definition: coap_io.h:220
void * coap_dtls_new_server_session(coap_session_t *session UNUSED)
Definition: coap_notls.c:92
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
Definition: coap_session.c:330
#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:375
#define SESSIONS_FIND(e, k, res)
Definition: coap_session.h:492
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
Definition: coap_io.h:80
#define LL_FOREACH_SAFE(head, el, tmp)
Definition: utlist.h:419
#define COAP_PROTO_RELIABLE(p)
Definition: coap_session.h:39
#define COAP_SESSION_STATE_CONNECTING
Definition: coap_session.h:54
#define COAP_MAX_MESSAGE_SIZE_TCP0
Definition: pdu.h:41
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:193
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:642
uint8_t coap_session_type_t
Definition: coap_session.h:41
#define COAP_SOCKET_WANT_CONNECT
non blocking client socket is waiting for connect
Definition: coap_io.h:83
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.
#define LL_DELETE(head, del)
Definition: utlist.h:385
#define SESSIONS_DELETE(e, obj)
Definition: coap_session.h:483
#define COAP_PROTO_NOT_RELIABLE(p)
Definition: coap_session.h:38
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition: coap_debug.c:61
#define OFF_CONTENT_TYPE
unsigned int max_handshake_sessions
Maximum number of simultaneous negotating sessions per endpoint.
Definition: net.h:207
#define COAP_DEFAULT_MAX_PDU_RX_SIZE
Definition: pdu.h:51
struct coap_session_t * sessions
hash table or list of active sessions
uint8_t hdr_size
actaul size used for protocol-specific header
Definition: pdu.h:291
size_t psk_key_len
Definition: coap_session.h:90
#define DTLS_CT_ALERT
coap_socket_flags_t flags
Definition: coap_io.h:62
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:387
coap_session_t * sessions
client sessions
Definition: net.h:166
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:129
coap_addr_tuple_t addr_info
local and remote addresses
Definition: coap_io.h:218
static coap_session_t * coap_make_session(coap_proto_t proto, coap_session_type_t type, const coap_address_t *local_if, 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:97
coap_socket_t sock
socket object for the interface, if any
ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu)
Send a pdu according to the session&#39;s protocol.
Definition: net.c:683
coap_pdu_t * coap_pdu_init(uint8_t type, uint8_t code, uint16_t tid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size...
Definition: pdu.c:79
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:529
coap_session_t * session
the CoAP session
Definition: net.h:44
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
#define COAP_PROTO_NONE
coap_proto_t values
Definition: pdu.h:343
#define COAP_EVENT_SESSION_CLOSED
Definition: coap_event.h:49
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:781
unsigned char uint8_t
Definition: uthash.h:79
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:1635
struct coap_endpoint_t * endpoint
session&#39;s endpoint
Definition: coap_session.h:71
#define prng(Buf, Length)
Fills Buf with Length bytes of random data.
Definition: prng.h:112
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
Critical.
Definition: coap_debug.h:50
int coap_socket_bind_udp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
Definition: coap_io.c:185
#define COAP_SESSION_STATE_NONE
coap_session_state_t values
Definition: coap_session.h:53
Information.
Definition: coap_debug.h:54
#define SESSIONS_ITER(e, el, rtmp)
Definition: coap_session.h:486
int coap_socket_bind_tcp(coap_socket_t *sock, const coap_address_t *listen_addr, coap_address_t *bound_addr)
Definition: coap_io.c:412
uint16_t integer_part
Integer part of fixed point variable.
Definition: coap_session.h:29
void coap_mfree_endpoint(struct coap_endpoint_t *ep)
Definition: coap_io.c:180
Queue entry.
Definition: net.h:38
uint8_t coap_session_state_t
Definition: coap_session.h:49
coap_queue_t * coap_new_node(void)
Creates a new node suitable for adding to the CoAP sendqueue.
Definition: net.c:248
coap_address_t bind_addr
local interface address
#define COAP_PROTO_TCP
Definition: pdu.h:346
uint8_t * psk_key
Definition: coap_session.h:89
The CoAP stack&#39;s global state is stored in a coap_context_t object.
Definition: net.h:147
uint16_t tid
transaction id, if any, in regular host byte order
Definition: pdu.h:293
unsigned int max_idle_sessions
Maximum number of simultaneous unused sessions per endpoint.
Definition: net.h:206
#define COAP_DEFAULT_MAX_RETRANSMIT
Number of message retransmissions before message sending is stopped RFC 7252, Section 4...
Definition: coap_session.h:388
int coap_delete_node(coap_queue_t *node)
Destroys specified node.
Definition: net.c:219
struct coap_session_t * session
Definition: coap_io.h:63
Pulls together all the internal only header files.
#define COAP_SESSION_STATE_CSM
Definition: coap_session.h:56