1 #define min(x,y) ((x)<(y)?(x):(y))
3 extern const char *side;
5 #define HANDSHAKE_EXPECT(c, s, clierr, serverr) \
6 sret = cret = GNUTLS_E_AGAIN; \
9 if (cret == GNUTLS_E_AGAIN) \
12 cret = gnutls_handshake (c); \
13 if (cret == GNUTLS_E_INTERRUPTED) cret = GNUTLS_E_AGAIN; \
15 if (sret == GNUTLS_E_AGAIN) \
18 sret = gnutls_handshake (s); \
19 if (sret == GNUTLS_E_INTERRUPTED) sret = GNUTLS_E_AGAIN; \
22 while ((cret == GNUTLS_E_AGAIN || (cret == 0 && sret == GNUTLS_E_AGAIN)) && (sret == GNUTLS_E_AGAIN || (sret == 0 && cret == GNUTLS_E_AGAIN))); \
23 if (cret != clierr || sret != serverr) \
25 fprintf(stderr, "client: %s\n", gnutls_strerror(cret)); \
26 fprintf(stderr, "server: %s\n", gnutls_strerror(sret)); \
27 fail("Handshake failed\n"); \
31 #define HANDSHAKE(c, s) \
32 HANDSHAKE_EXPECT(c,s,0,0)
34 #define HANDSHAKE_DTLS_EXPECT(c, s, clierr, serverr) \
35 sret = cret = GNUTLS_E_LARGE_PACKET; \
38 if (cret == GNUTLS_E_LARGE_PACKET) \
40 unsigned int mtu = gnutls_dtls_get_mtu(s); \
41 gnutls_dtls_set_mtu(s, mtu/2); \
43 if (cret < 0 && gnutls_error_is_fatal(cret) == 0) \
46 cret = gnutls_handshake (c); \
48 if (sret == GNUTLS_E_LARGE_PACKET) \
50 unsigned int mtu = gnutls_dtls_get_mtu(s); \
51 gnutls_dtls_set_mtu(s, mtu/2); \
53 if (sret < 0 && gnutls_error_is_fatal(sret) == 0) \
56 sret = gnutls_handshake (s); \
59 while (((gnutls_error_is_fatal(cret) == 0 && gnutls_error_is_fatal(sret) == 0)) && (cret < 0 || sret < 0)); \
60 if (cret != clierr || sret != serverr) \
62 fprintf(stderr, "client: %s\n", gnutls_strerror(cret)); \
63 fprintf(stderr, "server: %s\n", gnutls_strerror(sret)); \
64 fail("Handshake failed\n"); \
68 #define HANDSHAKE_DTLS(c, s) \
69 HANDSHAKE_DTLS_EXPECT(c,s,0,0)
71 #define HANDSHAKE(c, s) \
72 HANDSHAKE_EXPECT(c,s,0,0)
74 #define TRANSFER2(c, s, msg, msglen, buf, buflen, retry_send_with_null) \
76 ret = record_send_loop (c, msg, msglen, retry_send_with_null); \
78 if (ret < 0) fail ("client send error: %s\n", gnutls_strerror (ret)); \
85 ret = gnutls_record_recv (s, buf, buflen); \
87 while(ret == GNUTLS_E_AGAIN); \
89 fail ("server: didn't receive any data\n"); \
92 fail ("server: error: %s\n", gnutls_strerror (ret)); \
99 ns = record_send_loop (server, msg, msglen, retry_send_with_null); \
100 if (ns < 0) fail ("server send error: %s\n", gnutls_strerror (ret)); \
104 ret = gnutls_record_recv (client, buf, buflen); \
106 while(ret == GNUTLS_E_AGAIN); \
109 fail ("client: Peer has closed the TLS connection\n"); \
114 fputs ("!", stdout); \
115 fail ("client: Error: %s\n", gnutls_strerror (ret)); \
119 if (msglen != ret || memcmp (buf, msg, msglen) != 0) \
121 fail ("client: Transmitted data do not match\n"); \
125 ns = record_send_loop (client, buf, msglen, retry_send_with_null); \
126 if (ns < 0) fail ("client send error: %s\n", gnutls_strerror (ret)); \
127 transferred += ret; \
129 fputs (".", stdout); \
132 while (transferred < 70000)
134 #define TRANSFER(c, s, msg, msglen, buf, buflen) \
135 TRANSFER2(c, s, msg, msglen, buf, buflen, 0); \
136 TRANSFER2(c, s, msg, msglen, buf, buflen, 1)
138 static char to_server[64 * 1024];
139 static size_t to_server_len = 0;
141 static char to_client[64 * 1024];
142 static size_t to_client_len = 0;
145 #define RETURN_RND_EAGAIN(session) \
146 static unsigned char rnd = 0; \
147 if (rnd++ % 2 == 0) \
149 gnutls_transport_set_errno (session, EAGAIN); \
153 #define RETURN_RND_EAGAIN(session)
158 client_push(gnutls_transport_ptr_t tr, const void *data, size_t len)
161 RETURN_RND_EAGAIN(tr);
163 len = min(len, sizeof(to_server) - to_server_len);
165 newlen = to_server_len + len;
166 memcpy(to_server + to_server_len, data, len);
167 to_server_len = newlen;
169 fprintf(stderr, "eagain: pushed %d bytes to server (avail: %d)\n",
170 (int) len, (int) to_server_len);
178 client_pull(gnutls_transport_ptr_t tr, void *data, size_t len)
180 RETURN_RND_EAGAIN(tr);
182 if (to_client_len == 0) {
185 "eagain: Not enough data by server (asked for: %d, have: %d)\n",
186 (int) len, (int) to_client_len);
188 gnutls_transport_set_errno((gnutls_session_t) tr, EAGAIN);
192 len = min(len, to_client_len);
194 memcpy(data, to_client, len);
196 memmove(to_client, to_client + len, to_client_len - len);
197 to_client_len -= len;
199 fprintf(stderr, "eagain: pulled %d bytes by client (avail: %d)\n",
200 (int) len, (int) to_client_len);
206 server_pull(gnutls_transport_ptr_t tr, void *data, size_t len)
208 //success ("server_pull len %d has %d\n", len, to_server_len);
209 RETURN_RND_EAGAIN(tr);
211 if (to_server_len == 0) {
214 "eagain: Not enough data by client (asked for: %d, have: %d)\n",
215 (int) len, (int) to_server_len);
217 gnutls_transport_set_errno((gnutls_session_t) tr, EAGAIN);
221 len = min(len, to_server_len);
223 fprintf(stderr, "eagain: pulled %d bytes by server (avail: %d)\n",
224 (int) len, (int) to_server_len);
226 memcpy(data, to_server, len);
228 memmove(to_server, to_server + len, to_server_len - len);
229 to_server_len -= len;
236 server_push(gnutls_transport_ptr_t tr, const void *data, size_t len)
239 RETURN_RND_EAGAIN(tr);
241 // hexprint (data, len);
243 len = min(len, sizeof(to_client) - to_client_len);
245 newlen = to_client_len + len;
246 memcpy(to_client + to_client_len, data, len);
247 to_client_len = newlen;
249 fprintf(stderr, "eagain: pushed %d bytes to client (avail: %d)\n",
250 (int) len, (int) to_client_len);
258 /* inline is used to avoid a gcc warning if used in mini-eagain */
259 inline static int server_pull_timeout_func(gnutls_transport_ptr_t ptr,
264 if (to_server_len > 0)
265 ret = 1; /* available data */
267 ret = 0; /* timeout */
271 "eagain: server_pull_timeout: %d (avail: cli %d, serv %d)\n",
272 ret, (int) to_client_len, (int) to_server_len);
278 inline static int client_pull_timeout_func(gnutls_transport_ptr_t ptr,
283 if (to_client_len > 0)
290 "eagain: client_pull_timeout: %d (avail: cli %d, serv %d)\n",
291 ret, (int) to_client_len, (int) to_server_len);
297 inline static void reset_buffers(void)
303 inline static int record_send_loop(gnutls_session_t session,
304 const void *data, size_t sizeofdata,
305 int use_null_on_retry)
308 const void *retry_data;
309 size_t retry_sizeofdata;
311 if (use_null_on_retry) {
313 retry_sizeofdata = 0;
316 retry_sizeofdata = sizeofdata;
319 ret = gnutls_record_send(session, data, sizeofdata);
320 while (ret == GNUTLS_E_AGAIN) {
322 gnutls_record_send(session, retry_data,