better doc
[gnutls.git] / tests / mini-dtls-heartbeat.c
blobddda1275bb95aa333194a949b166cd6d41eed7c2
1 /*
2 * Copyright (C) 2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * GnuTLS is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * GnuTLS is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GnuTLS; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdio.h>
28 #include <stdlib.h>
30 #if defined(_WIN32)
32 int
33 main ()
35 exit (77);
38 #else
40 #include <string.h>
41 #include <sys/types.h>
42 #include <netinet/in.h>
43 #include <sys/socket.h>
44 #include <sys/wait.h>
45 #include <arpa/inet.h>
46 #include <unistd.h>
47 #include <gnutls/gnutls.h>
48 #include <gnutls/dtls.h>
50 #include "utils.h"
52 static void terminate (void);
54 /* This program tests the rehandshake in DTLS
57 static void
58 server_log_func (int level, const char *str)
60 fprintf (stderr, "server|<%d>| %s", level, str);
63 static void
64 client_log_func (int level, const char *str)
66 fprintf (stderr, "client|<%d>| %s", level, str);
69 /* These are global */
70 static pid_t child;
72 /* A very basic DTLS client, with anonymous authentication, that exchanges heartbeats.
75 #define MAX_BUF 1024
78 static void
79 client (int fd, int server_init)
81 gnutls_session_t session;
82 int ret, ret2;
83 char buffer[MAX_BUF + 1];
84 gnutls_anon_client_credentials_t anoncred;
85 /* Need to enable anonymous KX specifically. */
87 gnutls_global_init ();
89 if (debug)
91 gnutls_global_set_log_function (client_log_func);
92 gnutls_global_set_log_level (4711);
95 gnutls_anon_allocate_client_credentials (&anoncred);
97 /* Initialize TLS session
99 gnutls_init (&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM);
100 gnutls_heartbeat_enable (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND);
101 gnutls_dtls_set_mtu (session, 1500);
103 /* Use default priorities */
104 gnutls_priority_set_direct (session,
105 "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
106 NULL);
108 /* put the anonymous credentials to the current session
110 gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
112 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);
114 /* Perform the TLS handshake
118 ret = gnutls_handshake (session);
120 while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
122 if (ret < 0)
124 fail ("client: Handshake failed\n");
125 gnutls_perror (ret);
126 exit (1);
128 else
130 if (debug)
131 success ("client: Handshake was completed\n");
134 if (debug)
135 success ("client: DTLS version is: %s\n",
136 gnutls_protocol_get_name (gnutls_protocol_get_version
137 (session)));
139 if (!server_init)
143 ret =
144 gnutls_record_recv (session, buffer, sizeof (buffer));
146 if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED)
148 if (debug)
149 success ("Ping received. Replying with pong.\n");
150 ret2 = gnutls_heartbeat_pong (session, 0);
151 if (ret2 < 0)
153 fail ("pong: %s\n", gnutls_strerror (ret));
154 terminate ();
158 while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED
159 || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);
161 else
165 ret =
166 gnutls_heartbeat_ping (session, 256, 5,
167 GNUTLS_HEARTBEAT_WAIT);
169 if (debug)
170 success ("Ping sent.\n");
172 while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
174 if (ret < 0)
176 fail ("ping: %s\n", gnutls_strerror (ret));
177 terminate ();
181 gnutls_bye (session, GNUTLS_SHUT_WR);
183 close (fd);
185 gnutls_deinit (session);
187 gnutls_anon_free_client_credentials (anoncred);
189 gnutls_global_deinit ();
194 static gnutls_session_t
195 initialize_tls_session (void)
197 gnutls_session_t session;
199 gnutls_init (&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
200 gnutls_heartbeat_enable (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND);
201 gnutls_dtls_set_mtu (session, 1500);
203 /* avoid calling all the priority functions, since the defaults
204 * are adequate.
206 gnutls_priority_set_direct (session,
207 "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-ECDH:+CURVE-ALL",
208 NULL);
210 return session;
213 static void
214 terminate (void)
216 int status;
218 kill (child, SIGTERM);
219 wait (&status);
220 exit (1);
223 static void
224 server (int fd, int server_init)
226 int ret, ret2;
227 char buffer[MAX_BUF + 1];
228 gnutls_session_t session;
229 gnutls_anon_server_credentials_t anoncred;
230 /* this must be called once in the program
232 gnutls_global_init ();
234 if (debug)
236 gnutls_global_set_log_function (server_log_func);
237 gnutls_global_set_log_level (4711);
240 gnutls_anon_allocate_server_credentials (&anoncred);
242 session = initialize_tls_session ();
243 gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
245 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) fd);
249 ret = gnutls_handshake (session);
251 while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
252 if (ret < 0)
254 close (fd);
255 gnutls_deinit (session);
256 fail ("server: Handshake has failed (%s)\n\n",
257 gnutls_strerror (ret));
258 terminate ();
260 if (debug)
261 success ("server: Handshake was completed\n");
263 if (debug)
264 success ("server: TLS version is: %s\n",
265 gnutls_protocol_get_name (gnutls_protocol_get_version
266 (session)));
268 /* see the Getting peer's information example */
269 /* print_info(session); */
271 if (server_init)
275 ret =
276 gnutls_record_recv (session, buffer, sizeof (buffer));
278 if (ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED)
280 if (debug)
281 success ("Ping received. Replying with pong.\n");
282 ret2 = gnutls_heartbeat_pong (session, 0);
283 if (ret2 < 0)
285 fail ("pong: %s\n", gnutls_strerror (ret));
286 terminate ();
290 while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED
291 || ret == GNUTLS_E_HEARTBEAT_PING_RECEIVED);
293 else
297 ret =
298 gnutls_heartbeat_ping (session, 256, 5,
299 GNUTLS_HEARTBEAT_WAIT);
301 if (debug)
302 success ("Ping sent.\n");
304 while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
306 if (ret < 0)
308 fail ("ping: %s\n", gnutls_strerror (ret));
309 terminate ();
313 /* do not wait for the peer to close the connection.
315 gnutls_bye (session, GNUTLS_SHUT_WR);
317 close (fd);
318 gnutls_deinit (session);
320 gnutls_anon_free_server_credentials (anoncred);
322 gnutls_global_deinit ();
324 if (debug)
325 success ("server: finished\n");
328 static void
329 start (int server_initiated)
331 int fd[2];
332 int ret;
334 ret = socketpair (AF_UNIX, SOCK_DGRAM, 0, fd);
335 if (ret < 0)
337 perror ("socketpair");
338 exit (1);
341 child = fork ();
342 if (child < 0)
344 perror ("fork");
345 fail ("fork");
346 exit (1);
349 if (child)
351 int status;
352 /* parent */
354 server (fd[0], server_initiated);
355 wait (&status);
356 if (WEXITSTATUS (status) != 0)
357 fail ("Child died with status %d\n", WEXITSTATUS (status));
359 else
361 close (fd[0]);
362 client (fd[1], server_initiated);
363 exit (0);
367 void
368 doit (void)
370 start (0);
371 start (1);
374 #endif /* _WIN32 */