Next: , Previous: , Up: How to use GnuTLS in applications   [Contents][Index]


6.7 Data transfer and termination

Once the handshake is complete and peer’s identity has been verified data can be exchanged. The available functions resemble the POSIX recv and send functions. It is suggested to use gnutls_error_is_fatal to check whether the error codes returned by these functions are fatal for the protocol or can be ignored.

Function: ssize_t gnutls_record_send (gnutls_session_t session, const void * data, size_t data_size)

session: is a gnutls_session_t type.

data: contains the data to send

data_size: is the length of the data

This function has the similar semantics with send() . The only difference is that it accepts a GnuTLS session, and uses different error codes. Note that if the send buffer is full, send() will block this function. See the send() documentation for more information.

You can replace the default push function which is send() , by using gnutls_transport_set_push_function() .

If the EINTR is returned by the internal push function then GNUTLS_E_INTERRUPTED will be returned. If GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN is returned, you must call this function again with the exact same parameters, or provide a NULL pointer for data and 0 for data_size , in order to write the same data as before. If you wish to discard the previous data instead of retrying, you must call gnutls_record_discard_queued() before calling this function with different parameters. Note that the latter works only on special transports (e.g., UDP). cf. gnutls_record_get_direction() .

Note that in DTLS this function will return the GNUTLS_E_LARGE_PACKET error code if the send data exceed the data MTU value - as returned by gnutls_dtls_get_data_mtu() . The errno value EMSGSIZE also maps to GNUTLS_E_LARGE_PACKET . Note that since 3.2.13 this function can be called under cork in DTLS mode, and will refuse to send data over the MTU size by returning GNUTLS_E_LARGE_PACKET .

Returns: The number of bytes sent, or a negative error code. The number of bytes sent might be less than data_size . The maximum number of bytes this function can send in a single call depends on the negotiated maximum record size.

Function: ssize_t gnutls_record_recv (gnutls_session_t session, void * data, size_t data_size)

session: is a gnutls_session_t type.

data: the buffer that the data will be read into

data_size: the number of requested bytes

This function has the similar semantics with recv() . The only difference is that it accepts a GnuTLS session, and uses different error codes. In the special case that the peer requests a renegotiation, the caller will receive an error code of GNUTLS_E_REHANDSHAKE . In case of a client, this message may be simply ignored, replied with an alert GNUTLS_A_NO_RENEGOTIATION , or replied with a new handshake, depending on the client’s will. A server receiving this error code can only initiate a new handshake or terminate the session.

If EINTR is returned by the internal pull function (the default is recv() ) then GNUTLS_E_INTERRUPTED will be returned. If GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN is returned, you must call this function again to get the data. See also gnutls_record_get_direction() .

Returns: The number of bytes received and zero on EOF (for stream connections). A negative error code is returned in case of an error. The number of bytes received might be less than the requested data_size .

Function: int gnutls_error_is_fatal (int error)

error: is a GnuTLS error code, a negative error code

If a GnuTLS function returns a negative error code you may feed that value to this function to see if the error condition is fatal to a TLS session (i.e., must be terminated).

Note that you may also want to check the error code manually, since some non-fatal errors to the protocol (such as a warning alert or a rehandshake request) may be fatal for your program.

This function is only useful if you are dealing with errors from functions that relate to a TLS session (e.g., record layer or handshake layer handling functions).

Returns: Non-zero value on fatal errors or zero on non-fatal.

Although, in the TLS protocol the receive function can be called at any time, when DTLS is used the GnuTLS receive functions must be called once a message is available for reading, even if no data are expected. This is because in DTLS various (internal) actions may be required due to retransmission timers. Moreover, an extended receive function is shown below, which allows the extraction of the message’s sequence number. Due to the unreliable nature of the protocol, this field allows distinguishing out-of-order messages.

Function: ssize_t gnutls_record_recv_seq (gnutls_session_t session, void * data, size_t data_size, unsigned char * seq)

session: is a gnutls_session_t type.

data: the buffer that the data will be read into

data_size: the number of requested bytes

seq: is the packet’s 64-bit sequence number. Should have space for 8 bytes.

This function is the same as gnutls_record_recv() , except that it returns in addition to data, the sequence number of the data. This is useful in DTLS where record packets might be received out-of-order. The returned 8-byte sequence number is an integer in big-endian format and should be treated as a unique message identification.

Returns: The number of bytes received and zero on EOF. A negative error code is returned in case of an error. The number of bytes received might be less than data_size .

Since: 3.0

The gnutls_record_check_pending helper function is available to allow checking whether data are available to be read in a GnuTLS session buffers. Note that this function complements but does not replace poll, i.e., gnutls_record_check_pending reports no data to be read, poll should be called to check for data in the network buffers.

Function: size_t gnutls_record_check_pending (gnutls_session_t session)

session: is a gnutls_session_t type.

This function checks if there are unread data in the gnutls buffers. If the return value is non-zero the next call to gnutls_record_recv() is guaranteed not to block.

Returns: Returns the size of the data or zero.

int gnutls_record_get_direction (gnutls_session_t session)

Once a TLS or DTLS session is no longer needed, it is recommended to use gnutls_bye to terminate the session. That way the peer is notified securely about the intention of termination, which allows distinguishing it from a malicious connection termination. A session can be deinitialized with the gnutls_deinit function.

Function: int gnutls_bye (gnutls_session_t session, gnutls_close_request_t how)

session: is a gnutls_session_t type.

how: is an integer

Terminates the current TLS/SSL connection. The connection should have been initiated using gnutls_handshake() . how should be one of GNUTLS_SHUT_RDWR , GNUTLS_SHUT_WR .

In case of GNUTLS_SHUT_RDWR the TLS session gets terminated and further receives and sends will be disallowed. If the return value is zero you may continue using the underlying transport layer. GNUTLS_SHUT_RDWR sends an alert containing a close request and waits for the peer to reply with the same message.

In case of GNUTLS_SHUT_WR the TLS session gets terminated and further sends will be disallowed. In order to reuse the connection you should wait for an EOF from the peer. GNUTLS_SHUT_WR sends an alert containing a close request.

Note that not all implementations will properly terminate a TLS connection. Some of them, usually for performance reasons, will terminate only the underlying transport layer, and thus not distinguishing between a malicious party prematurely terminating the connection and normal termination.

This function may also return GNUTLS_E_AGAIN or GNUTLS_E_INTERRUPTED ; cf. gnutls_record_get_direction() .

Returns: GNUTLS_E_SUCCESS on success, or an error code, see function documentation for entire semantics.

Function: void gnutls_deinit (gnutls_session_t session)

session: is a gnutls_session_t type.

This function clears all buffers associated with the session . This function will also remove session data from the session database if the session was terminated abnormally.


Next: , Previous: , Up: How to use GnuTLS in applications   [Contents][Index]