• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* coap_session.h -- 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 /**
10  * @file coap_session.h
11  * @brief Defines the application visible session information
12  */
13 
14 #ifndef COAP_SESSION_H_
15 #define COAP_SESSION_H_
16 
17 
18 #include "coap_forward_decls.h"
19 #include "coap_io.h"
20 #include "coap_time.h"
21 #include "pdu.h"
22 #include "uthash.h"
23 
24 /**
25 * Abstraction of a fixed point number that can be used where necessary instead
26 * of a float.  1,000 fractional bits equals one integer
27 */
28 typedef struct coap_fixed_point_t {
29   uint16_t integer_part;    /**< Integer part of fixed point variable */
30   uint16_t fractional_part; /**< Fractional part of fixed point variable
31                                 1/1000 (3 points) precision */
32 } coap_fixed_point_t;
33 
34 #define COAP_DEFAULT_SESSION_TIMEOUT 300
35 #define COAP_PARTIAL_SESSION_TIMEOUT_TICKS (30 * COAP_TICKS_PER_SECOND)
36 #define COAP_DEFAULT_MAX_HANDSHAKE_SESSIONS 100
37 
38 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS)
39 #define COAP_PROTO_NOT_RELIABLE(p) ((p)==COAP_PROTO_UDP || (p)==COAP_PROTO_DTLS)
40 #else
41 #define COAP_PROTO_NOT_RELIABLE(p) ((p)==COAP_PROTO_UDP)
42 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */
43 #ifndef COAP_NO_TCP
44 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS)
45 #define COAP_PROTO_RELIABLE(p) ((p)==COAP_PROTO_TCP || (p)==COAP_PROTO_TLS)
46 #else
47 #define COAP_PROTO_RELIABLE(p) ((p)==COAP_PROTO_TCP)
48 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */
49 #endif
50 
51 typedef uint8_t coap_session_type_t;
52 /**
53  * coap_session_type_t values
54  */
55 #define COAP_SESSION_TYPE_CLIENT 1  /**< client-side */
56 #define COAP_SESSION_TYPE_SERVER 2  /**< server-side */
57 #define COAP_SESSION_TYPE_HELLO  3  /**< server-side ephemeral session for responding to a client hello */
58 
59 typedef uint8_t coap_session_state_t;
60 /**
61  * coap_session_state_t values
62  */
63 #define COAP_SESSION_STATE_NONE                0
64 #define COAP_SESSION_STATE_CONNECTING          1
65 #define COAP_SESSION_STATE_HANDSHAKE           2
66 #define COAP_SESSION_STATE_CSM                 3
67 #define COAP_SESSION_STATE_ESTABLISHED         4
68 
69 typedef struct coap_session_t {
70   coap_proto_t proto;               /**< protocol used */
71   coap_session_type_t type;         /**< client or server side socket */
72   coap_session_state_t state;       /**< current state of relationaship with peer */
73   unsigned ref;                     /**< reference count from queues */
74 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS)
75   unsigned tls_overhead;            /**< overhead of TLS layer */
76 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */
77   unsigned mtu;                     /**< path or CSM mtu */
78   coap_address_t local_if;          /**< optional local interface address */
79   UT_hash_handle hh;
80   coap_addr_tuple_t addr_info;      /**< key: remote/local address info */
81   int ifindex;                      /**< interface index */
82   coap_socket_t sock;               /**< socket object for the session, if any */
83   struct coap_endpoint_t *endpoint; /**< session's endpoint */
84   struct coap_context_t *context;   /**< session's context */
85 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS)
86   void *tls;                        /**< security parameters */
87 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */
88   uint16_t tx_mid;                  /**< the last message id that was used in this session */
89   uint8_t con_active;               /**< Active CON request sent */
90   coap_tid_t last_ping_mid;         /**< the last keepalive message id that was used in this session */
91   struct coap_queue_t *delayqueue;  /**< list of delayed messages waiting to be sent */
92   size_t partial_write;             /**< if > 0 indicates number of bytes already written from the pdu at the head of sendqueue */
93   uint8_t read_header[8];           /**< storage space for header of incoming message header */
94   size_t partial_read;              /**< if > 0 indicates number of bytes already read for an incoming message */
95   coap_pdu_t *partial_pdu;          /**< incomplete incoming pdu */
96   coap_tick_t last_rx_tx;
97   coap_tick_t last_tx_rst;
98   coap_tick_t last_ping;
99   coap_tick_t last_pong;
100   coap_tick_t csm_tx;
101 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS)
102   uint8_t *psk_identity;
103   size_t psk_identity_len;
104   uint8_t *psk_key;
105   size_t psk_key_len;
106 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */
107   void *app;                        /**< application-specific data */
108   unsigned int max_retransmit;      /**< maximum re-transmit count (default 4) */
109   coap_fixed_point_t ack_timeout;   /**< timeout waiting for ack (default 2 secs) */
110   coap_fixed_point_t ack_random_factor; /**< ack random factor backoff (default 1.5) */
111 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS)
112   unsigned int dtls_timeout_count;      /**< dtls setup retry counter */
113   int dtls_event;                       /**< Tracking any (D)TLS events on this sesison */
114 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */
115 } coap_session_t;
116 
117 /**
118 * Increment reference counter on a session.
119 *
120 * @param session The CoAP session.
121 * @return same as session
122 */
123 coap_session_t *coap_session_reference(coap_session_t *session);
124 
125 /**
126 * Decrement reference counter on a session.
127 * Note that the session may be deleted as a result and should not be used
128 * after this call.
129 *
130 * @param session The CoAP session.
131 */
132 void coap_session_release(coap_session_t *session);
133 
134 /**
135 * Stores @p data with the given session. This function overwrites any value
136 * that has previously been stored with @p session.
137 */
138 void coap_session_set_app_data(coap_session_t *session, void *data);
139 
140 /**
141 * Returns any application-specific data that has been stored with @p
142 * session using the function coap_session_set_app_data(). This function will
143 * return @c NULL if no data has been stored.
144 */
145 void *coap_session_get_app_data(const coap_session_t *session);
146 
147 /**
148 * Notify session that it has failed.
149 *
150 * @param session The CoAP session.
151 * @param reason The reason why the session was disconnected.
152 */
153 void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason);
154 
155 /**
156 * Notify session transport has just connected and CSM exchange can now start.
157 *
158 * @param session The CoAP session.
159 */
160 void coap_session_send_csm(coap_session_t *session);
161 
162 /**
163 * Notify session that it has just connected or reconnected.
164 *
165 * @param session The CoAP session.
166 */
167 void coap_session_connected(coap_session_t *session);
168 
169 /**
170 * Set the session MTU. This is the maximum message size that can be sent,
171 * excluding IP and UDP overhead.
172 *
173 * @param session The CoAP session.
174 * @param mtu maximum message size
175 */
176 void coap_session_set_mtu(coap_session_t *session, unsigned mtu);
177 
178 /**
179  * Get maximum acceptable PDU size
180  *
181  * @param session The CoAP session.
182  * @return maximum PDU size, not including header (but including token).
183  */
184 size_t coap_session_max_pdu_size(const coap_session_t *session);
185 
186 /**
187 * Creates a new client session to the designated server.
188 * @param ctx The CoAP context.
189 * @param local_if Address of local interface. It is recommended to use NULL to let the operating system choose a suitable local interface. If an address is specified, the port number should be zero, which means that a free port is automatically selected.
190 * @param server The server's address. If the port number is zero, the default port for the protocol will be used.
191 * @param proto Protocol.
192 *
193 * @return A new CoAP session or NULL if failed. Call coap_session_release to free.
194 */
195 coap_session_t *coap_new_client_session(
196   struct coap_context_t *ctx,
197   const coap_address_t *local_if,
198   const coap_address_t *server,
199   coap_proto_t proto
200 );
201 
202 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS)
203 /**
204 * Creates a new client session to the designated server with PSK credentials
205 * @param ctx The CoAP context.
206 * @param local_if Address of local interface. It is recommended to use NULL to let the operating system choose a suitable local interface. If an address is specified, the port number should be zero, which means that a free port is automatically selected.
207 * @param server The server's address. If the port number is zero, the default port for the protocol will be used.
208 * @param proto Protocol.
209 * @param identity PSK client identity
210 * @param key PSK shared key
211 * @param key_len PSK shared key length
212 *
213 * @return A new CoAP session or NULL if failed. Call coap_session_release to free.
214 */
215 coap_session_t *coap_new_client_session_psk(
216   struct coap_context_t *ctx,
217   const coap_address_t *local_if,
218   const coap_address_t *server,
219   coap_proto_t proto,
220   const char *identity,
221   const uint8_t *key,
222   unsigned key_len
223 );
224 
225 /**
226 * Creates a new client session to the designated server with PKI credentials
227 * @param ctx The CoAP context.
228 * @param local_if Address of local interface. It is recommended to use NULL to
229 *                 let the operating system choose a suitable local interface.
230 *                 If an address is specified, the port number should be zero,
231 *                 which means that a free port is automatically selected.
232 * @param server The server's address. If the port number is zero, the default
233 *               port for the protocol will be used.
234 * @param proto CoAP Protocol.
235 * @param setup_data PKI parameters.
236 *
237 * @return A new CoAP session or NULL if failed. Call coap_session_release()
238 *         to free.
239 */
240 coap_session_t *coap_new_client_session_pki(
241   struct coap_context_t *ctx,
242   const coap_address_t *local_if,
243   const coap_address_t *server,
244   coap_proto_t proto,
245   struct coap_dtls_pki_t *setup_data
246 );
247 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */
248 
249 /**
250 * Creates a new server session for the specified endpoint.
251 * @param ctx The CoAP context.
252 * @param ep An endpoint where an incoming connection request is pending.
253 *
254 * @return A new CoAP session or NULL if failed. Call coap_session_release to free.
255 */
256 coap_session_t *coap_new_server_session(
257   struct coap_context_t *ctx,
258   struct coap_endpoint_t *ep
259 );
260 
261 /**
262 * Function interface for datagram data transmission. This function returns
263 * the number of bytes that have been transmitted, or a value less than zero
264 * on error.
265 *
266 * @param session          Session to send data on.
267 * @param data             The data to send.
268 * @param datalen          The actual length of @p data.
269 *
270 * @return                 The number of bytes written on success, or a value
271 *                         less than zero on error.
272 */
273 ssize_t coap_session_send(coap_session_t *session,
274   const uint8_t *data, size_t datalen);
275 
276 /**
277 * Function interface for stream data transmission. This function returns
278 * the number of bytes that have been transmitted, or a value less than zero
279 * on error. The number of bytes written may be less than datalen because of
280 * congestion control.
281 *
282 * @param session          Session to send data on.
283 * @param data             The data to send.
284 * @param datalen          The actual length of @p data.
285 *
286 * @return                 The number of bytes written on success, or a value
287 *                         less than zero on error.
288 */
289 ssize_t coap_session_write(coap_session_t *session,
290   const uint8_t *data, size_t datalen);
291 
292 /**
293 * Send a pdu according to the session's protocol. This function returns
294 * the number of bytes that have been transmitted, or a value less than zero
295 * on error.
296 *
297 * @param session          Session to send pdu on.
298 * @param pdu              The pdu to send.
299 *
300 * @return                 The number of bytes written on success, or a value
301 *                         less than zero on error.
302 */
303 ssize_t coap_session_send_pdu(coap_session_t *session, coap_pdu_t *pdu);
304 
305 
306 /**
307  * @ingroup logging
308  * Get session description.
309  *
310  * @param session  The CoAP session.
311  * @return description string.
312  */
313 const char *coap_session_str(const coap_session_t *session);
314 
315 ssize_t
316 coap_session_delay_pdu(coap_session_t *session, coap_pdu_t *pdu,
317                        struct coap_queue_t *node);
318 
319 /**
320 * Create a new endpoint for communicating with peers.
321 *
322 * @param context        The coap context that will own the new endpoint
323 * @param listen_addr    Address the endpoint will listen for incoming requests on or originate outgoing requests from. Use NULL to specify that no incoming request will be accepted and use a random endpoint.
324 * @param proto          Protocol used on this endpoint
325 */
326 
327 coap_endpoint_t *coap_new_endpoint(struct coap_context_t *context, const coap_address_t *listen_addr, coap_proto_t proto);
328 
329 /**
330 * Set the endpoint's default MTU. This is the maximum message size that can be
331 * sent, excluding IP and UDP overhead.
332 *
333 * @param endpoint The CoAP endpoint.
334 * @param mtu maximum message size
335 */
336 void coap_endpoint_set_default_mtu(coap_endpoint_t *endpoint, unsigned mtu);
337 
338 void coap_free_endpoint(coap_endpoint_t *ep);
339 
340 
341 /**
342  * @ingroup logging
343 * Get endpoint description.
344 *
345 * @param endpoint  The CoAP endpoint.
346 * @return description string.
347 */
348 const char *coap_endpoint_str(const coap_endpoint_t *endpoint);
349 
350 /**
351 * Lookup the server session for the packet received on an endpoint, or create
352 * a new one.
353 *
354 * @param endpoint Active endpoint the packet was received on.
355 * @param packet Received packet.
356 * @param now The current time in ticks.
357 * @return The CoAP session or @c NULL if error.
358 */
359 coap_session_t *coap_endpoint_get_session(coap_endpoint_t *endpoint,
360   const struct coap_packet_t *packet, coap_tick_t now);
361 
362 #if defined(HAVE_LIBTINYDTLS) || defined(HAVE_OPENSSL) || defined(HAVE_LIBGNUTLS)
363 /**
364  * Create a new DTLS session for the @p session.
365  * Note: the @p session is released if no DTLS server session can be created.
366  *
367  * @ingroup dtls_internal
368  *
369  * @param session   Session to add DTLS session to
370  * @param now       The current time in ticks.
371  *
372  * @return CoAP session or @c NULL if error.
373  */
374 coap_session_t *coap_session_new_dtls_session(coap_session_t *session,
375   coap_tick_t now);
376 #endif /* HAVE_LIBTINYDTLS || HAVE_OPENSSL || HAVE_LIBGNUTLS */
377 
378 coap_session_t *coap_session_get_by_peer(struct coap_context_t *ctx,
379   const struct coap_address_t *remote_addr, int ifindex);
380 
381 void coap_session_free(coap_session_t *session);
382 void coap_session_mfree(coap_session_t *session);
383 
384  /**
385   * @defgroup cc Rate Control
386   * The transmission parameters for CoAP rate control ("Congestion
387   * Control" in stream-oriented protocols) are defined in
388   * https://tools.ietf.org/html/rfc7252#section-4.8
389   * @{
390   */
391 
392   /**
393    * Number of seconds when to expect an ACK or a response to an
394    * outstanding CON message.
395    * RFC 7252, Section 4.8 Default value of ACK_TIMEOUT is 2
396    */
397 #define COAP_DEFAULT_ACK_TIMEOUT ((coap_fixed_point_t){2,0})
398 
399    /**
400     * A factor that is used to randomize the wait time before a message
401     * is retransmitted to prevent synchronization effects.
402     * RFC 7252, Section 4.8 Default value of ACK_RANDOM_FACTOR is 1.5
403     */
404 #define COAP_DEFAULT_ACK_RANDOM_FACTOR ((coap_fixed_point_t){1,500})
405 
406     /**
407      * Number of message retransmissions before message sending is stopped
408      * RFC 7252, Section 4.8 Default value of MAX_RETRANSMIT is 4
409      */
410 #define COAP_DEFAULT_MAX_RETRANSMIT  4
411 
412      /**
413       * The number of simultaneous outstanding interactions that a client
414       * maintains to a given server.
415       * RFC 7252, Section 4.8 Default value of NSTART is 1
416       */
417 #define COAP_DEFAULT_NSTART 1
418 
419       /** @} */
420 
421 /**
422 * Set the CoAP maximum retransmit count before failure
423 *
424 * Number of message retransmissions before message sending is stopped
425 *
426 * @param session The CoAP session.
427 * @param value The value to set to. The default is 4 and should not normally
428 *              get changed.
429 */
430 void coap_session_set_max_retransmit(coap_session_t *session,
431                                      unsigned int value);
432 
433 /**
434 * Set the CoAP initial ack response timeout before the next re-transmit
435 *
436 * Number of seconds when to expect an ACK or a response to an
437 * outstanding CON message.
438 *
439 * @param session The CoAP session.
440 * @param value The value to set to. The default is 2 and should not normally
441 *              get changed.
442 */
443 void coap_session_set_ack_timeout(coap_session_t *session,
444                                   coap_fixed_point_t value);
445 
446 /**
447 * Set the CoAP ack randomize factor
448 *
449 * A factor that is used to randomize the wait time before a message
450 * is retransmitted to prevent synchronization effects.
451 *
452 * @param session The CoAP session.
453 * @param value The value to set to. The default is 1.5 and should not normally
454 *              get changed.
455 */
456 void coap_session_set_ack_random_factor(coap_session_t *session,
457                                         coap_fixed_point_t value);
458 
459 /**
460 * Get the CoAP maximum retransmit before failure
461 *
462 * Number of message retransmissions before message sending is stopped
463 *
464 * @param session The CoAP session.
465 *
466 * @return Current maximum retransmit value
467 */
468 unsigned int coap_session_get_max_transmit(coap_session_t *session);
469 
470 /**
471 * Get the CoAP initial ack response timeout before the next re-transmit
472 *
473 * Number of seconds when to expect an ACK or a response to an
474 * outstanding CON message.
475 *
476 * @param session The CoAP session.
477 *
478 * @return Current ack response timeout value
479 */
480 coap_fixed_point_t coap_session_get_ack_timeout(coap_session_t *session);
481 
482 /**
483 * Get the CoAP ack randomize factor
484 *
485 * A factor that is used to randomize the wait time before a message
486 * is retransmitted to prevent synchronization effects.
487 *
488 * @param session The CoAP session.
489 *
490 * @return Current ack randomize value
491 */
492 coap_fixed_point_t coap_session_get_ack_random_factor(coap_session_t *session);
493 
494 /**
495  * Send a ping message for the session.
496  * @param session The CoAP session.
497  *
498  * @return COAP_INVALID_TID if there is an error
499  */
500 coap_tid_t coap_session_send_ping(coap_session_t *session);
501 
502 #define SESSIONS_ADD(e, obj) \
503   HASH_ADD(hh, (e), addr_info, sizeof((obj)->addr_info), (obj))
504 
505 #define SESSIONS_DELETE(e, obj) \
506   HASH_DELETE(hh, (e), (obj))
507 
508 #define SESSIONS_ITER(e, el, rtmp)  \
509   HASH_ITER(hh, (e), el, rtmp)
510 
511 #define SESSIONS_ITER_SAFE(e, el, rtmp) \
512 for ((el) = (e); (el) && ((rtmp) = (el)->hh.next, 1); (el) = (rtmp))
513 
514 #define SESSIONS_FIND(e, k, res) {                     \
515     HASH_FIND(hh, (e), &(k), sizeof(k), (res)); \
516   }
517 
518 #endif  /* COAP_SESSION_H */
519