diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index ad0e42c6c..4aad2a829 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -969,6 +969,76 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, void (*f_dbg)(void *, int, const char *, int, const char *), void *p_dbg ); +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the date to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send less bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \return The callback must return the number of bytes received, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * + * \note The callback may receive less bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum nomber of millisecondes to wait for data + * 0 means no timeout (potentially wait forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive less bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); + /** * \brief Set the underlying BIO callbacks for write, read and * read-with-timeout. @@ -978,8 +1048,6 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, * \param f_send write callback * \param f_recv read callback * \param f_recv_timeout blocking read callback with timeout. - * The last argument is the timeout in milliseconds, - * 0 means no timeout (block forever until a message comes) * * \note One of f_recv or f_recv_timeout can be NULL, in which case * the other is used. If both are non-NULL, f_recv_timeout is @@ -991,12 +1059,20 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, * * \note For DTLS, you need to provide either a non-NULL * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_sent_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the convetions those callbacks must follow. + * + * \note On some platforms, net.c provides \c mbedtls_net_send(), + * \c mbedtls_net_recv() and \c mbedtls_net_recv_timeout() + * that are suitable to be used here. */ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, - void *p_bio, - int (*f_send)(void *, const unsigned char *, size_t), - int (*f_recv)(void *, unsigned char *, size_t), - int (*f_recv_timeout)(void *, unsigned char *, size_t, uint32_t) ); + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ); /** * \brief Set the timeout period for mbedtls_ssl_read() @@ -1017,24 +1093,67 @@ void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); /** - * \brief Set the timer callbacks - * (Mandatory for DTLS.) + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays is passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) * * \param ssl SSL context - * \param p_timer parameter (context) shared by timer callback + * \param p_timer parameter (context) shared by timer callbacks * \param f_set_timer set timer callback - * Accepts an intermediate and a final delay in milliseconcs - * If the final delay is 0, cancels the running timer. * \param f_get_timer get timer callback. Must return: - * -1 if cancelled - * 0 if none of the delays is expired - * 1 if the intermediate delay only is expired - * 2 if the final delay is expired + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must fallow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \note See also the "DTLS tutorial" article in our knowledge base. */ void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, void *p_timer, - void (*f_set_timer)(void *, uint32_t int_ms, uint32_t fin_ms), - int (*f_get_timer)(void *) ); + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ); /** * \brief Callback type: generate and write session ticket