Tizen 2.0 Release
[external/libgnutls26.git] / tests / eagain-common.h
1 #define min(x,y) ((x)<(y)?(x):(y))
2 //#define EAGAIN_DEBUG
3
4 #define HANDSHAKE_EXPECT(c, s, clierr, serverr) \
5   sret = cret = GNUTLS_E_AGAIN; \
6   do \
7     { \
8       if (cret == GNUTLS_E_AGAIN) \
9         { \
10           cret = gnutls_handshake (c); \
11         } \
12       if (sret == GNUTLS_E_AGAIN) \
13         { \
14           sret = gnutls_handshake (s); \
15         } \
16     } \
17   while ((cret == GNUTLS_E_AGAIN || (cret == 0 && sret == GNUTLS_E_AGAIN)) && (sret == GNUTLS_E_AGAIN || (sret == 0 && cret == GNUTLS_E_AGAIN))); \
18   if (cret != clierr || sret != serverr) \
19     { \
20       fprintf(stderr, "client: %s\n", gnutls_strerror(cret)); \
21       fprintf(stderr, "server: %s\n", gnutls_strerror(sret)); \
22       fail("Handshake failed\n"); \
23       exit(1); \
24     }
25
26 #define HANDSHAKE(c, s) \
27   HANDSHAKE_EXPECT(c,s,0,0)
28
29 #define TRANSFER(c, s, msg, msglen, buf, buflen) \
30   do \
31     { \
32       ret = gnutls_record_send (c, msg, msglen); \
33     } \
34   while(ret == GNUTLS_E_AGAIN); \
35   do \
36     { \
37       do \
38         { \
39           ret = gnutls_record_recv (s, buf, buflen); \
40         } \
41       while(ret == GNUTLS_E_AGAIN); \
42       if (ret == 0) \
43         fail ("server: didn't receive any data\n"); \
44       else if (ret < 0) \
45         { \
46           fail ("server: error: %s\n", gnutls_strerror (ret)); \
47         } \
48       else \
49         { \
50           transferred += ret; \
51         } \
52       do \
53         { \
54           ns = gnutls_record_send (server, msg, msglen); \
55         } \
56       while (ns == GNUTLS_E_AGAIN); \
57       do \
58         { \
59           ret = gnutls_record_recv (client, buf, buflen); \
60         } \
61       while(ret == GNUTLS_E_AGAIN); \
62       if (ret == 0) \
63         { \
64           fail ("client: Peer has closed the TLS connection\n"); \
65         } \
66       else if (ret < 0) \
67         { \
68           if (debug) \
69             fputs ("!", stdout); \
70           fail ("client: Error: %s\n", gnutls_strerror (ret)); \
71         } \
72       else \
73         { \
74           if (msglen != ret || memcmp (buf, msg, msglen) != 0) \
75             { \
76               fail ("client: Transmitted data do not match\n"); \
77             } \
78           /* echo back */ \
79           do \
80             { \
81               ns = gnutls_record_send (client, buf, msglen); \
82             } \
83           while (ns == GNUTLS_E_AGAIN); \
84           transferred += ret; \
85           if (debug) \
86             fputs (".", stdout); \
87         } \
88     } \
89   while (transferred < 70000)
90
91
92 static char to_server[64*1024];
93 static size_t to_server_len = 0;
94
95 static char to_client[64*1024];
96 static size_t to_client_len = 0;
97
98 #ifdef RANDOMIZE
99 #define RETURN_RND_EAGAIN(session) \
100   static unsigned char rnd = 0; \
101   if (rnd++ % 2 == 0) \
102     { \
103       gnutls_transport_set_errno (session, EAGAIN); \
104       return -1; \
105     }
106 #else
107 #define RETURN_RND_EAGAIN(session)
108 #endif
109
110 static ssize_t
111 client_push (gnutls_transport_ptr_t tr, const void *data, size_t len)
112 {
113   size_t newlen;
114   RETURN_RND_EAGAIN(tr);
115
116   len = min(len, sizeof(to_server)-to_server_len);
117
118   newlen = to_server_len + len;
119   memcpy (to_server + to_server_len, data, len);
120   to_server_len = newlen;
121 #ifdef EAGAIN_DEBUG
122   fprintf(stderr, "eagain: pushed %d bytes to server (avail: %d)\n", (int)len, (int)to_server_len);
123 #endif
124   return len;
125 }
126
127 static ssize_t
128 client_pull (gnutls_transport_ptr_t tr, void *data, size_t len)
129 {
130   RETURN_RND_EAGAIN(tr);
131
132   if (to_client_len == 0)
133     {
134 #ifdef EAGAIN_DEBUG
135       fprintf(stderr, "eagain: Not enough data by server (asked for: %d, have: %d)\n", (int)len, (int)to_client_len);
136 #endif
137       gnutls_transport_set_errno ((gnutls_session_t)tr, EAGAIN);
138       return -1;
139     }
140
141   len = min(len, to_client_len);
142
143   memcpy (data, to_client, len);
144
145   memmove (to_client, to_client + len, to_client_len - len);
146   to_client_len -= len;
147 #ifdef EAGAIN_DEBUG
148   fprintf(stderr, "eagain: pulled %d bytes by client (avail: %d)\n", (int)len, (int)to_client_len);
149 #endif
150   return len;
151 }
152
153 static ssize_t
154 server_pull (gnutls_transport_ptr_t tr, void *data, size_t len)
155 {
156   //success ("server_pull len %d has %d\n", len, to_server_len);
157   RETURN_RND_EAGAIN(tr);
158
159   if (to_server_len == 0)
160     {
161 #ifdef EAGAIN_DEBUG
162       fprintf(stderr, "eagain: Not enough data by client (asked for: %d, have: %d)\n", (int)len, (int)to_server_len);
163 #endif
164       gnutls_transport_set_errno ((gnutls_session_t)tr, EAGAIN);
165       return -1;
166     }
167
168   len = min(len, to_server_len);
169 #ifdef EAGAIN_DEBUG
170   fprintf(stderr, "eagain: pulled %d bytes by server (avail: %d)\n", (int)len, (int)to_server_len);
171 #endif
172   memcpy (data, to_server, len);
173
174   memmove (to_server, to_server + len, to_server_len - len);
175   to_server_len -= len;
176
177   return len;
178 }
179
180 static ssize_t
181 server_push (gnutls_transport_ptr_t tr, const void *data, size_t len)
182 {
183   size_t newlen;
184   RETURN_RND_EAGAIN(tr);
185
186 //  hexprint (data, len);
187
188   len = min(len, sizeof(to_client)-to_client_len);
189
190   newlen = to_client_len + len;
191   memcpy (to_client + to_client_len, data, len);
192   to_client_len = newlen;
193 #ifdef EAGAIN_DEBUG
194   fprintf(stderr, "eagain: pushed %d bytes to client (avail: %d)\n", (int)len, (int)to_client_len);
195 #endif
196
197   return len;
198 }
199
200 /* inline is used to avoid a gcc warning if used in mini-eagain */
201 inline static int server_pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms)
202 {
203 int ret;
204
205   if (to_server_len > 0)
206     ret = 1; /* available data */
207   else
208     ret = 0; /* timeout */
209
210 #ifdef EAGAIN_DEBUG
211   fprintf(stderr, "eagain: server_pull_timeout: %d\n", ret);
212 #endif
213
214   return ret;
215 }
216
217 inline static int client_pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms)
218 {
219 int ret;
220
221   if (to_client_len > 0)
222     ret = 1;
223   else
224     ret = 0;
225
226 #ifdef EAGAIN_DEBUG
227   fprintf(stderr, "eagain: client_pull_timeout: %d\n", ret);
228 #endif
229
230   return ret;
231 }