Add `gnutls/dtls.h' to the distribution.
[gnutls.git] / tests / mini-eagain.c
blob9bb7e2c321385054cd47e9faee7649ea772ac80b
1 /*
2 * Copyright (C) 2008, 2010 Free Software Foundation, Inc.
4 * Author: Simon Josefsson, 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>
29 #include <string.h>
30 #include <errno.h>
31 #include <gnutls/gnutls.h>
32 #include <gnutls/crypto.h>
34 #include "utils.h"
36 static void
37 tls_log_func (int level, const char *str)
39 fprintf (stderr, "|<%d>| %s", level, str);
42 static int handshake = 0;
44 char *to_server;
45 size_t to_server_len;
47 char *to_client;
48 size_t to_client_len;
51 static ssize_t
52 client_pull (gnutls_transport_ptr_t tr, void *data, size_t len)
54 // success ("client_pull len %d has %d\n", len, to_client_len);
55 static unsigned char rnd = 0;
57 if (rnd++ % 2 == 0 || to_client_len < len)
59 gnutls_transport_set_global_errno (EAGAIN);
60 return -1;
63 memcpy (data, to_client, len);
65 memmove (to_client, to_client + len, to_client_len - len);
66 to_client_len -= len;
68 return len;
71 static ssize_t
72 client_push (gnutls_transport_ptr_t tr, const void *data, size_t len)
74 char *tmp;
75 size_t newlen = to_server_len + len;
76 static unsigned char rnd = 0;
78 if (rnd++ % 2 == 0)
80 gnutls_transport_set_global_errno (EAGAIN);
81 return -1;
84 tmp = realloc (to_server, newlen);
85 if (!tmp)
87 fail ("Memory allocation failure...\n");
88 exit (1);
90 to_server = tmp;
92 memcpy (to_server + to_server_len, data, len);
93 to_server_len = newlen;
95 return len;
98 static ssize_t
99 server_pull (gnutls_transport_ptr_t tr, void *data, size_t len)
101 //success ("server_pull len %d has %d\n", len, to_server_len);
102 static unsigned char rnd = 0;
104 if (rnd++ % 2 == 0 || to_server_len < len)
106 gnutls_transport_set_global_errno (EAGAIN);
107 return -1;
110 memcpy (data, to_server, len);
112 memmove (to_server, to_server + len, to_server_len - len);
113 to_server_len -= len;
115 return len;
118 static ssize_t
119 server_push (gnutls_transport_ptr_t tr, const void *data, size_t len)
121 char *tmp;
122 size_t newlen = to_client_len + len;
123 static unsigned char rnd = 0;
125 if (rnd++ % 2 == 0)
127 gnutls_transport_set_global_errno (EAGAIN);
128 return -1;
131 // hexprint (data, len);
133 tmp = realloc (to_client, newlen);
134 if (!tmp)
136 fail ("Memory allocation failure...\n");
137 exit (1);
139 to_client = tmp;
141 memcpy (to_client + to_client_len, data, len);
142 to_client_len = newlen;
144 return len;
147 #define MAX_BUF 1024
148 #define MSG "Hello TLS, and hi and how are you and more data here... and more... and even more and even more more data..."
150 void
151 doit (void)
153 /* Server stuff. */
154 gnutls_anon_server_credentials_t s_anoncred;
155 const gnutls_datum_t p3 = { (char *) pkcs3, strlen (pkcs3) };
156 static gnutls_dh_params_t dh_params;
157 gnutls_session_t server;
158 int sret = GNUTLS_E_AGAIN;
159 /* Client stuff. */
160 gnutls_anon_client_credentials_t c_anoncred;
161 gnutls_session_t client;
162 int cret = GNUTLS_E_AGAIN;
163 /* Need to enable anonymous KX specifically. */
164 char buffer[MAX_BUF + 1];
165 ssize_t ns;
166 int ret, transferred = 0, msglen;
168 /* General init. */
169 gnutls_global_init ();
170 gnutls_global_set_log_function (tls_log_func);
171 if (debug)
172 gnutls_global_set_log_level (99);
174 /* Init server */
175 gnutls_anon_allocate_server_credentials (&s_anoncred);
176 gnutls_dh_params_init (&dh_params);
177 gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
178 gnutls_anon_set_server_dh_params (s_anoncred, dh_params);
179 gnutls_init (&server, GNUTLS_SERVER);
180 gnutls_priority_set_direct (server, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL);
181 gnutls_credentials_set (server, GNUTLS_CRD_ANON, s_anoncred);
182 gnutls_dh_set_prime_bits (server, 1024);
183 gnutls_transport_set_push_function (server, server_push);
184 gnutls_transport_set_pull_function (server, server_pull);
186 /* Init client */
187 gnutls_anon_allocate_client_credentials (&c_anoncred);
188 gnutls_init (&client, GNUTLS_CLIENT);
189 gnutls_priority_set_direct (client, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL);
190 gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred);
191 gnutls_transport_set_push_function (client, client_push);
192 gnutls_transport_set_pull_function (client, client_pull);
194 handshake = 1;
197 if (cret == GNUTLS_E_AGAIN)
199 //success ("loop invoking client:\n");
200 cret = gnutls_handshake (client);
201 //success ("client %d: %s\n", cret, gnutls_strerror (cret));
204 if (sret == GNUTLS_E_AGAIN)
206 //success ("loop invoking server:\n");
207 sret = gnutls_handshake (server);
208 //success ("server %d: %s\n", sret, gnutls_strerror (sret));
211 while (cret == GNUTLS_E_AGAIN || sret == GNUTLS_E_AGAIN);
213 handshake = 0;
214 if (debug)
215 success ("Handshake established\n");
217 ns = gnutls_record_send (client, MSG, strlen (MSG));
218 //success ("client: sent %d\n", ns);
222 //success("transferred: %d\n", transferred);
224 ret = gnutls_record_recv (server, buffer, MAX_BUF);
225 if (ret == 0)
226 fail ("server: didn't receive any data\n");
227 else if (ret < 0)
229 // if (debug)
230 // fputs ("#", stdout);
231 if (ret != GNUTLS_E_AGAIN)
233 fail ("server: error: %s\n", gnutls_strerror (ret));
234 break;
237 else
239 transferred += ret;
240 // if (debug)
241 // fputs ("*", stdout);
244 msglen = strlen (MSG);
247 ns = gnutls_record_send (server, MSG, msglen);
249 while (ns == GNUTLS_E_AGAIN);
251 ret = gnutls_record_recv (client, buffer, MAX_BUF);
252 if (ret == 0)
254 fail ("client: Peer has closed the TLS connection\n");
256 else if (ret < 0)
258 if (debug)
259 fputs ("!", stdout);
260 if (ret != GNUTLS_E_AGAIN)
262 fail ("client: Error: %s\n", gnutls_strerror (ret));
263 break;
266 else
268 if (msglen != ret || memcmp (buffer, MSG, msglen) != 0)
270 fail ("client: Transmitted data do not match\n");
273 /* echo back */
276 ns = gnutls_record_send (client, buffer, msglen);
278 while (ns == GNUTLS_E_AGAIN);
280 transferred += ret;
281 if (debug)
282 fputs (".", stdout);
285 while (transferred < 70000);
286 if (debug)
287 fputs ("\n", stdout);
289 gnutls_bye (client, GNUTLS_SHUT_WR);
290 gnutls_bye (server, GNUTLS_SHUT_WR);
292 gnutls_deinit (client);
293 gnutls_deinit (server);
295 free (to_server);
296 free (to_client);
298 gnutls_anon_free_client_credentials (c_anoncred);
299 gnutls_anon_free_server_credentials (s_anoncred);
301 gnutls_dh_params_deinit (dh_params);
303 gnutls_global_deinit ();