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