int check_command(gnutls_session_t session, const char *str) { size_t len = strnlen(str, 128); int ret; fprintf(stderr, "*** Processing %u bytes command: %s\n", (unsigned)len, str); if (len > 2 && str[0] == str[1] && str[0] == '*') { if (strncmp (str, "**REHANDSHAKE**", sizeof("**REHANDSHAKE**") - 1) == 0) { fprintf(stderr, "*** Sending rehandshake request\n"); gnutls_rehandshake(session); return 1; } else if (strncmp (str, "**HEARTBEAT**", sizeof("**HEARTBEAT**") - 1) == 0) { ret = gnutls_heartbeat_ping(session, 300, 5, GNUTLS_HEARTBEAT_WAIT); if (ret < 0) { if (ret == GNUTLS_E_INVALID_REQUEST) { fprintf(stderr, "No heartbeat in this session\n"); } else { fprintf(stderr, "ping: %s\n", gnutls_strerror(ret)); exit(1); } } return 2; } } return 0; }
static void client (int fd, int server_init) { gnutls_session_t session; int ret, ret2; char buffer[MAX_BUF + 1]; gnutls_anon_client_credentials_t anoncred; /* Need to enable anonymous KX specifically. */ gnutls_global_init (); if (debug) { gnutls_global_set_log_function (client_log_func); gnutls_global_set_log_level (4711); } gnutls_anon_allocate_client_credentials (&anoncred); /* Initialize TLS session */ gnutls_init (&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM); gnutls_heartbeat_enable (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND); gnutls_dtls_set_mtu (session, 1500); /* Use default priorities */ gnutls_priority_set_direct (session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL", NULL); /* put the anonymous credentials to the current session */ gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd); /* Perform the TLS handshake */ do { ret = gnutls_handshake (session); } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); if (ret < 0) { fail ("client: Handshake failed\n"); gnutls_perror (ret); exit (1); } else { if (debug) success ("client: Handshake was completed\n"); } if (debug) success ("client: DTLS version is: %s\n", gnutls_protocol_get_name (gnutls_protocol_get_version (session))); if (!server_init) { do { ret = gnutls_record_recv (session, buffer, sizeof (buffer)); if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED) { if (debug) success ("Ping received. Replying with pong.\n"); ret2 = gnutls_heartbeat_pong (session, 0); if (ret2 < 0) { fail ("pong: %s\n", gnutls_strerror (ret)); terminate (); } } } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED); } else { do { ret = gnutls_heartbeat_ping (session, 256, 5, GNUTLS_HEARTBEAT_WAIT); if (debug) success ("Ping sent.\n"); } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret < 0) { fail ("ping: %s\n", gnutls_strerror (ret)); terminate (); } } gnutls_bye (session, GNUTLS_SHUT_WR); close (fd); gnutls_deinit (session); gnutls_anon_free_client_credentials (anoncred); gnutls_global_deinit (); }
static void server (int fd, int server_init) { int ret, ret2; char buffer[MAX_BUF + 1]; gnutls_session_t session; gnutls_anon_server_credentials_t anoncred; /* this must be called once in the program */ gnutls_global_init (); if (debug) { gnutls_global_set_log_function (server_log_func); gnutls_global_set_log_level (4711); } gnutls_anon_allocate_server_credentials (&anoncred); session = initialize_tls_session (); gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd); do { ret = gnutls_handshake (session); } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); if (ret < 0) { close (fd); gnutls_deinit (session); fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret)); terminate (); } if (debug) success ("server: Handshake was completed\n"); if (debug) success ("server: TLS version is: %s\n", gnutls_protocol_get_name (gnutls_protocol_get_version (session))); /* see the Getting peer's information example */ /* print_info(session); */ if (server_init) { do { ret = gnutls_record_recv (session, buffer, sizeof (buffer)); if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED) { if (debug) success ("Ping received. Replying with pong.\n"); ret2 = gnutls_heartbeat_pong (session, 0); if (ret2 < 0) { fail ("pong: %s\n", gnutls_strerror (ret)); terminate (); } } } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED); } else { do { ret = gnutls_heartbeat_ping (session, 256, 5, GNUTLS_HEARTBEAT_WAIT); if (debug) success ("Ping sent.\n"); } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret < 0) { fail ("ping: %s\n", gnutls_strerror (ret)); terminate (); } } /* do not wait for the peer to close the connection. */ gnutls_bye (session, GNUTLS_SHUT_WR); close (fd); gnutls_deinit (session); gnutls_anon_free_server_credentials (anoncred); gnutls_global_deinit (); if (debug) success ("server: finished\n"); }