diff options
Diffstat (limited to 'src/examples/mhd2spdy_spdy.c')
-rw-r--r-- | src/examples/mhd2spdy_spdy.c | 329 |
1 files changed, 180 insertions, 149 deletions
diff --git a/src/examples/mhd2spdy_spdy.c b/src/examples/mhd2spdy_spdy.c index 8640df35..413de7f3 100644 --- a/src/examples/mhd2spdy_spdy.c +++ b/src/examples/mhd2spdy_spdy.c | |||
@@ -35,29 +35,27 @@ | |||
35 | #include "mhd2spdy_spdy.h" | 35 | #include "mhd2spdy_spdy.h" |
36 | #include "mhd2spdy_http.h" | 36 | #include "mhd2spdy_http.h" |
37 | 37 | ||
38 | enum | ||
39 | { | ||
40 | IO_NONE, | ||
41 | WANT_READ, | ||
42 | WANT_WRITE | ||
43 | }; | ||
44 | |||
45 | 38 | ||
46 | /* | 39 | /* |
47 | * Prints error containing the function name |func| and message |msg| | 40 | * Prints error containing the function name |func| and message |msg| |
48 | * and exit. | 41 | * and exit. |
49 | */ | 42 | */ |
50 | static void spdy_dief(const char *func, const char *msg) | 43 | static void |
44 | spdy_dief(const char *func, | ||
45 | const char *msg) | ||
51 | { | 46 | { |
52 | fprintf(stderr, "FATAL: %s: %s\n", func, msg); | 47 | fprintf(stderr, "FATAL: %s: %s\n", func, msg); |
53 | exit(EXIT_FAILURE); | 48 | exit(EXIT_FAILURE); |
54 | } | 49 | } |
55 | 50 | ||
51 | |||
56 | /* | 52 | /* |
57 | * Prints error containing the function name |func| and error code | 53 | * Prints error containing the function name |func| and error code |
58 | * |error_code| and exit. | 54 | * |error_code| and exit. |
59 | */ | 55 | */ |
60 | void spdy_diec(const char *func, int error_code) | 56 | void |
57 | spdy_diec(const char *func, | ||
58 | int error_code) | ||
61 | { | 59 | { |
62 | fprintf(stderr, "FATAL: %s: error_code=%d, msg=%s\n", func, error_code, | 60 | fprintf(stderr, "FATAL: %s: error_code=%d, msg=%s\n", func, error_code, |
63 | spdylay_strerror(error_code)); | 61 | spdylay_strerror(error_code)); |
@@ -71,11 +69,12 @@ void spdy_diec(const char *func, int error_code) | |||
71 | * bytes actually written. See the documentation of | 69 | * bytes actually written. See the documentation of |
72 | * spdylay_send_callback for the details. | 70 | * spdylay_send_callback for the details. |
73 | */ | 71 | */ |
74 | static ssize_t spdy_cb_send(spdylay_session *session, | 72 | static ssize_t |
75 | const uint8_t *data, | 73 | spdy_cb_send(spdylay_session *session, |
76 | size_t length, | 74 | const uint8_t *data, |
77 | int flags, | 75 | size_t length, |
78 | void *user_data) | 76 | int flags, |
77 | void *user_data) | ||
79 | { | 78 | { |
80 | (void)session; | 79 | (void)session; |
81 | (void)flags; | 80 | (void)flags; |
@@ -126,15 +125,19 @@ static ssize_t spdy_cb_send(spdylay_session *session, | |||
126 | return rv; | 125 | return rv; |
127 | } | 126 | } |
128 | 127 | ||
128 | |||
129 | /* | 129 | /* |
130 | * The implementation of spdylay_recv_callback type. Here we read data | 130 | * The implementation of spdylay_recv_callback type. Here we read data |
131 | * from the network and write them in |buf|. The capacity of |buf| is | 131 | * from the network and write them in |buf|. The capacity of |buf| is |
132 | * |length| bytes. Returns the number of bytes stored in |buf|. See | 132 | * |length| bytes. Returns the number of bytes stored in |buf|. See |
133 | * the documentation of spdylay_recv_callback for the details. | 133 | * the documentation of spdylay_recv_callback for the details. |
134 | */ | 134 | */ |
135 | static ssize_t spdy_cb_recv(spdylay_session *session, | 135 | static ssize_t |
136 | uint8_t *buf, size_t length, int flags, | 136 | spdy_cb_recv(spdylay_session *session, |
137 | void *user_data) | 137 | uint8_t *buf, |
138 | size_t length, | ||
139 | int flags, | ||
140 | void *user_data) | ||
138 | { | 141 | { |
139 | (void)session; | 142 | (void)session; |
140 | (void)flags; | 143 | (void)flags; |
@@ -191,63 +194,47 @@ static ssize_t spdy_cb_recv(spdylay_session *session, | |||
191 | return rv; | 194 | return rv; |
192 | } | 195 | } |
193 | 196 | ||
194 | /* | ||
195 | * The implementation of spdylay_before_ctrl_send_callback type. We | ||
196 | * use this function to get stream ID of the request. This is because | ||
197 | * stream ID is not known when we submit the request | ||
198 | * (spdylay_spdy_submit_request). | ||
199 | */ | ||
200 | /*static void spdy_cb_before_ctrl_send(spdylay_session *session, | ||
201 | spdylay_frame_type type, | ||
202 | spdylay_frame *frame, | ||
203 | void *user_data) | ||
204 | { | ||
205 | }*/ | ||
206 | |||
207 | 197 | ||
208 | static void spdy_cb_on_ctrl_send(spdylay_session *session, | 198 | static void |
209 | spdylay_frame_type type, | 199 | spdy_cb_on_ctrl_send(spdylay_session *session, |
210 | spdylay_frame *frame, void *user_data) | 200 | spdylay_frame_type type, |
201 | spdylay_frame *frame, | ||
202 | void *user_data) | ||
211 | { | 203 | { |
212 | (void)user_data; | 204 | (void)user_data; |
213 | 205 | ||
214 | //char **nv; | ||
215 | //const char *name = NULL; | ||
216 | int32_t stream_id; | 206 | int32_t stream_id; |
217 | //size_t i; | ||
218 | struct Proxy *proxy; | 207 | struct Proxy *proxy; |
219 | 208 | ||
220 | switch(type) { | 209 | switch(type) { |
221 | case SPDYLAY_SYN_STREAM: | 210 | case SPDYLAY_SYN_STREAM: |
222 | //nv = frame->syn_stream.nv; | 211 | stream_id = frame->syn_stream.stream_id; |
223 | //name = "SYN_STREAM"; | 212 | proxy = spdylay_session_get_stream_user_data(session, stream_id); |
224 | stream_id = frame->syn_stream.stream_id; | 213 | ++glob_opt.streams_opened; |
225 | proxy = spdylay_session_get_stream_user_data(session, stream_id); | 214 | ++proxy->spdy_connection->streams_opened; |
226 | ++glob_opt.streams_opened; | 215 | PRINT_INFO2("opening stream: str open %i; %s", glob_opt.streams_opened, proxy->url); |
227 | ++proxy->spdy_connection->streams_opened; | 216 | break; |
228 | PRINT_INFO2("opening stream: str open %i; %s", glob_opt.streams_opened, proxy->url); | 217 | default: |
229 | break; | 218 | break; |
230 | default: | ||
231 | break; | ||
232 | } | 219 | } |
233 | } | 220 | } |
234 | 221 | ||
235 | void spdy_cb_on_ctrl_recv(spdylay_session *session, | 222 | |
236 | spdylay_frame_type type, | 223 | void |
237 | spdylay_frame *frame, void *user_data) | 224 | spdy_cb_on_ctrl_recv(spdylay_session *session, |
225 | spdylay_frame_type type, | ||
226 | spdylay_frame *frame, | ||
227 | void *user_data) | ||
238 | { | 228 | { |
239 | (void)user_data; | 229 | (void)user_data; |
240 | 230 | ||
241 | //struct SPDY_Request *req; | ||
242 | char **nv; | 231 | char **nv; |
243 | //const char *name = NULL; | ||
244 | int32_t stream_id; | 232 | int32_t stream_id; |
245 | struct Proxy * proxy; | 233 | struct Proxy * proxy; |
246 | 234 | ||
247 | switch(type) { | 235 | switch(type) { |
248 | case SPDYLAY_SYN_REPLY: | 236 | case SPDYLAY_SYN_REPLY: |
249 | nv = frame->syn_reply.nv; | 237 | nv = frame->syn_reply.nv; |
250 | //name = "SYN_REPLY"; | ||
251 | stream_id = frame->syn_reply.stream_id; | 238 | stream_id = frame->syn_reply.stream_id; |
252 | break; | 239 | break; |
253 | case SPDYLAY_RST_STREAM: | 240 | case SPDYLAY_RST_STREAM: |
@@ -255,7 +242,6 @@ void spdy_cb_on_ctrl_recv(spdylay_session *session, | |||
255 | break; | 242 | break; |
256 | case SPDYLAY_HEADERS: | 243 | case SPDYLAY_HEADERS: |
257 | nv = frame->headers.nv; | 244 | nv = frame->headers.nv; |
258 | //name = "HEADERS"; | ||
259 | stream_id = frame->headers.stream_id; | 245 | stream_id = frame->headers.stream_id; |
260 | break; | 246 | break; |
261 | default: | 247 | default: |
@@ -269,34 +255,37 @@ void spdy_cb_on_ctrl_recv(spdylay_session *session, | |||
269 | 255 | ||
270 | switch(type) { | 256 | switch(type) { |
271 | case SPDYLAY_SYN_REPLY: | 257 | case SPDYLAY_SYN_REPLY: |
272 | PRINT_INFO2("received headers for %s", proxy->url); | 258 | PRINT_INFO2("received headers for %s", proxy->url); |
273 | http_create_response(proxy, nv); | 259 | http_create_response(proxy, nv); |
274 | break; | 260 | break; |
275 | case SPDYLAY_RST_STREAM: | 261 | case SPDYLAY_RST_STREAM: |
276 | PRINT_INFO2("received reset stream for %s", proxy->url); | 262 | PRINT_INFO2("received reset stream for %s", proxy->url); |
277 | proxy->error = true; | 263 | proxy->error = true; |
278 | break; | 264 | break; |
279 | case SPDYLAY_HEADERS: | 265 | case SPDYLAY_HEADERS: |
280 | PRINT_INFO2("received headers for %s", proxy->url); | 266 | PRINT_INFO2("received headers for %s", proxy->url); |
281 | http_create_response(proxy, nv); | 267 | http_create_response(proxy, nv); |
282 | break; | 268 | break; |
283 | default: | 269 | default: |
284 | return; | 270 | return; |
285 | break; | 271 | break; |
286 | } | 272 | } |
273 | |||
287 | glob_opt.spdy_data_received = true; | 274 | glob_opt.spdy_data_received = true; |
288 | } | 275 | } |
289 | 276 | ||
277 | |||
290 | /* | 278 | /* |
291 | * The implementation of spdylay_on_stream_close_callback type. We use | 279 | * The implementation of spdylay_on_stream_close_callback type. We use |
292 | * this function to know the response is fully received. Since we just | 280 | * this function to know the response is fully received. Since we just |
293 | * fetch 1 resource in this program, after reception of the response, | 281 | * fetch 1 resource in this program, after reception of the response, |
294 | * we submit GOAWAY and close the session. | 282 | * we submit GOAWAY and close the session. |
295 | */ | 283 | */ |
296 | static void spdy_cb_on_stream_close(spdylay_session *session, | 284 | static void |
297 | int32_t stream_id, | 285 | spdy_cb_on_stream_close(spdylay_session *session, |
298 | spdylay_status_code status_code, | 286 | int32_t stream_id, |
299 | void *user_data) | 287 | spdylay_status_code status_code, |
288 | void *user_data) | ||
300 | { | 289 | { |
301 | (void)status_code; | 290 | (void)status_code; |
302 | (void)user_data; | 291 | (void)user_data; |
@@ -315,24 +304,24 @@ static void spdy_cb_on_stream_close(spdylay_session *session, | |||
315 | proxy->spdy_active = false; | 304 | proxy->spdy_active = false; |
316 | else | 305 | else |
317 | free_proxy(proxy); | 306 | free_proxy(proxy); |
318 | return; | ||
319 | } | 307 | } |
320 | 308 | ||
321 | #define SPDY_MAX_OUTLEN 4096 | ||
322 | 309 | ||
323 | /* | 310 | /* |
324 | * The implementation of spdylay_on_data_chunk_recv_callback type. We | 311 | * The implementation of spdylay_on_data_chunk_recv_callback type. We |
325 | * use this function to print the received response body. | 312 | * use this function to print the received response body. |
326 | */ | 313 | */ |
327 | static void spdy_cb_on_data_chunk_recv(spdylay_session *session, uint8_t flags, | 314 | static void |
328 | int32_t stream_id, | 315 | spdy_cb_on_data_chunk_recv(spdylay_session *session, |
329 | const uint8_t *data, size_t len, | 316 | uint8_t flags, |
330 | void *user_data) | 317 | int32_t stream_id, |
318 | const uint8_t *data, | ||
319 | size_t len, | ||
320 | void *user_data) | ||
331 | { | 321 | { |
332 | (void)flags; | 322 | (void)flags; |
333 | (void)user_data; | 323 | (void)user_data; |
334 | 324 | ||
335 | //struct SPDY_Request *req; | ||
336 | struct Proxy *proxy; | 325 | struct Proxy *proxy; |
337 | proxy = spdylay_session_get_stream_user_data(session, stream_id); | 326 | proxy = spdylay_session_get_stream_user_data(session, stream_id); |
338 | 327 | ||
@@ -348,12 +337,17 @@ static void spdy_cb_on_data_chunk_recv(spdylay_session *session, uint8_t flags, | |||
348 | 337 | ||
349 | memcpy(proxy->http_body + proxy->http_body_size, data, len); | 338 | memcpy(proxy->http_body + proxy->http_body_size, data, len); |
350 | proxy->http_body_size += len; | 339 | proxy->http_body_size += len; |
351 | PRINT_INFO2("received data for %s; %zu bytes", proxy->url, len); | 340 | PRINT_INFO2("received data for %s; %zu bytes", proxy->url, len); |
352 | glob_opt.spdy_data_received = true; | 341 | glob_opt.spdy_data_received = true; |
353 | } | 342 | } |
354 | 343 | ||
355 | static void spdy_cb_on_data_recv(spdylay_session *session, | 344 | |
356 | uint8_t flags, int32_t stream_id, int32_t length, void *user_data) | 345 | static void |
346 | spdy_cb_on_data_recv(spdylay_session *session, | ||
347 | uint8_t flags, | ||
348 | int32_t stream_id, | ||
349 | int32_t length, | ||
350 | void *user_data) | ||
357 | { | 351 | { |
358 | (void)length; | 352 | (void)length; |
359 | (void)user_data; | 353 | (void)user_data; |
@@ -367,18 +361,19 @@ static void spdy_cb_on_data_recv(spdylay_session *session, | |||
367 | } | 361 | } |
368 | } | 362 | } |
369 | 363 | ||
364 | |||
370 | /* | 365 | /* |
371 | * Setup callback functions. Spdylay API offers many callback | 366 | * Setup callback functions. Spdylay API offers many callback |
372 | * functions, but most of them are optional. The send_callback is | 367 | * functions, but most of them are optional. The send_callback is |
373 | * always required. Since we use spdylay_session_recv(), the | 368 | * always required. Since we use spdylay_session_recv(), the |
374 | * recv_callback is also required. | 369 | * recv_callback is also required. |
375 | */ | 370 | */ |
376 | static void spdy_setup_spdylay_callbacks(spdylay_session_callbacks *callbacks) | 371 | static void |
372 | spdy_setup_spdylay_callbacks(spdylay_session_callbacks *callbacks) | ||
377 | { | 373 | { |
378 | memset(callbacks, 0, sizeof(spdylay_session_callbacks)); | 374 | memset(callbacks, 0, sizeof(spdylay_session_callbacks)); |
379 | callbacks->send_callback = spdy_cb_send; | 375 | callbacks->send_callback = spdy_cb_send; |
380 | callbacks->recv_callback = spdy_cb_recv; | 376 | callbacks->recv_callback = spdy_cb_recv; |
381 | //callbacks->before_ctrl_send_callback = spdy_cb_before_ctrl_send; | ||
382 | callbacks->on_ctrl_send_callback = spdy_cb_on_ctrl_send; | 377 | callbacks->on_ctrl_send_callback = spdy_cb_on_ctrl_send; |
383 | callbacks->on_ctrl_recv_callback = spdy_cb_on_ctrl_recv; | 378 | callbacks->on_ctrl_recv_callback = spdy_cb_on_ctrl_recv; |
384 | callbacks->on_stream_close_callback = spdy_cb_on_stream_close; | 379 | callbacks->on_stream_close_callback = spdy_cb_on_stream_close; |
@@ -386,21 +381,25 @@ static void spdy_setup_spdylay_callbacks(spdylay_session_callbacks *callbacks) | |||
386 | callbacks->on_data_recv_callback = spdy_cb_on_data_recv; | 381 | callbacks->on_data_recv_callback = spdy_cb_on_data_recv; |
387 | } | 382 | } |
388 | 383 | ||
384 | |||
389 | /* | 385 | /* |
390 | * Callback function for SSL/TLS NPN. Since this program only supports | 386 | * Callback function for SSL/TLS NPN. Since this program only supports |
391 | * SPDY protocol, if server does not offer SPDY protocol the Spdylay | 387 | * SPDY protocol, if server does not offer SPDY protocol the Spdylay |
392 | * library supports, we terminate program. | 388 | * library supports, we terminate program. |
393 | */ | 389 | */ |
394 | static int spdy_cb_ssl_select_next_proto(SSL* ssl, | 390 | static int |
395 | unsigned char **out, unsigned char *outlen, | 391 | spdy_cb_ssl_select_next_proto(SSL* ssl, |
396 | const unsigned char *in, unsigned int inlen, | 392 | unsigned char **out, |
393 | unsigned char *outlen, | ||
394 | const unsigned char *in, | ||
395 | unsigned int inlen, | ||
397 | void *arg) | 396 | void *arg) |
398 | { | 397 | { |
399 | (void)ssl; | 398 | (void)ssl; |
400 | 399 | ||
401 | //PRINT_INFO("spdy_cb_ssl_select_next_proto"); | ||
402 | int rv; | 400 | int rv; |
403 | uint16_t *spdy_proto_version; | 401 | uint16_t *spdy_proto_version; |
402 | |||
404 | /* spdylay_select_next_protocol() selects SPDY protocol version the | 403 | /* spdylay_select_next_protocol() selects SPDY protocol version the |
405 | Spdylay library supports. */ | 404 | Spdylay library supports. */ |
406 | rv = spdylay_select_next_protocol(out, outlen, in, inlen); | 405 | rv = spdylay_select_next_protocol(out, outlen, in, inlen); |
@@ -413,11 +412,14 @@ static int spdy_cb_ssl_select_next_proto(SSL* ssl, | |||
413 | return SSL_TLSEXT_ERR_OK; | 412 | return SSL_TLSEXT_ERR_OK; |
414 | } | 413 | } |
415 | 414 | ||
415 | |||
416 | /* | 416 | /* |
417 | * Setup SSL context. We pass |spdy_proto_version| to get negotiated | 417 | * Setup SSL context. We pass |spdy_proto_version| to get negotiated |
418 | * SPDY protocol version in NPN callback. | 418 | * SPDY protocol version in NPN callback. |
419 | */ | 419 | */ |
420 | void spdy_ssl_init_ssl_ctx(SSL_CTX *ssl_ctx, uint16_t *spdy_proto_version) | 420 | void |
421 | spdy_ssl_init_ssl_ctx(SSL_CTX *ssl_ctx, | ||
422 | uint16_t *spdy_proto_version) | ||
421 | { | 423 | { |
422 | /* Disable SSLv2 and enable all workarounds for buggy servers */ | 424 | /* Disable SSLv2 and enable all workarounds for buggy servers */ |
423 | SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION); | 425 | SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION); |
@@ -428,153 +430,184 @@ void spdy_ssl_init_ssl_ctx(SSL_CTX *ssl_ctx, uint16_t *spdy_proto_version) | |||
428 | spdy_proto_version); | 430 | spdy_proto_version); |
429 | } | 431 | } |
430 | 432 | ||
431 | static int spdy_ssl_handshake(SSL *ssl, int fd) | 433 | |
434 | static int | ||
435 | spdy_ssl_handshake(SSL *ssl, | ||
436 | int fd) | ||
432 | { | 437 | { |
433 | int rv; | 438 | int rv; |
434 | if(SSL_set_fd(ssl, fd) == 0) { | 439 | |
440 | if(SSL_set_fd(ssl, fd) == 0) | ||
435 | spdy_dief("SSL_set_fd", ERR_error_string(ERR_get_error(), NULL)); | 441 | spdy_dief("SSL_set_fd", ERR_error_string(ERR_get_error(), NULL)); |
436 | } | 442 | |
437 | ERR_clear_error(); | 443 | ERR_clear_error(); |
438 | rv = SSL_connect(ssl); | 444 | rv = SSL_connect(ssl); |
439 | if(rv <= 0) { | 445 | if(rv <= 0) |
440 | PRINT_INFO2("SSL_connect %s", ERR_error_string(ERR_get_error(), NULL)); | 446 | PRINT_INFO2("SSL_connect %s", ERR_error_string(ERR_get_error(), NULL)); |
441 | } | ||
442 | 447 | ||
443 | return rv; | 448 | return rv; |
444 | } | 449 | } |
445 | 450 | ||
451 | |||
446 | /* | 452 | /* |
447 | * Connects to the host |host| and port |port|. This function returns | 453 | * Connects to the host |host| and port |port|. This function returns |
448 | * the file descriptor of the client socket. | 454 | * the file descriptor of the client socket. |
449 | */ | 455 | */ |
450 | static int spdy_socket_connect_to(const char *host, uint16_t port) | 456 | static int |
457 | spdy_socket_connect_to(const char *host, | ||
458 | uint16_t port) | ||
451 | { | 459 | { |
452 | struct addrinfo hints; | 460 | struct addrinfo hints; |
453 | int fd = -1; | 461 | int fd = -1; |
454 | int rv; | 462 | int rv; |
455 | char service[NI_MAXSERV]; | 463 | char service[NI_MAXSERV]; |
456 | struct addrinfo *res, *rp; | 464 | struct addrinfo *res, *rp; |
465 | |||
466 | //TODO checks | ||
457 | snprintf(service, sizeof(service), "%u", port); | 467 | snprintf(service, sizeof(service), "%u", port); |
458 | memset(&hints, 0, sizeof(struct addrinfo)); | 468 | memset(&hints, 0, sizeof(struct addrinfo)); |
459 | hints.ai_family = AF_UNSPEC; | 469 | hints.ai_family = AF_UNSPEC; |
460 | hints.ai_socktype = SOCK_STREAM; | 470 | hints.ai_socktype = SOCK_STREAM; |
461 | rv = getaddrinfo(host, service, &hints, &res); | 471 | rv = getaddrinfo(host, service, &hints, &res); |
462 | if(rv != 0) { | 472 | if(rv != 0) |
473 | { | ||
463 | printf("%s\n",host); | 474 | printf("%s\n",host); |
464 | spdy_dief("getaddrinfo", gai_strerror(rv)); | 475 | spdy_dief("getaddrinfo", gai_strerror(rv)); |
465 | } | 476 | } |
466 | for(rp = res; rp; rp = rp->ai_next) { | 477 | for(rp = res; rp; rp = rp->ai_next) |
478 | { | ||
467 | fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); | 479 | fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); |
468 | if(fd == -1) { | 480 | if(fd == -1) |
469 | continue; | 481 | continue; |
470 | } | ||
471 | while((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 && | 482 | while((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 && |
472 | errno == EINTR); | 483 | errno == EINTR); |
473 | if(rv == 0) { | 484 | if(rv == 0) |
474 | break; | 485 | break; |
475 | } | ||
476 | close(fd); | 486 | close(fd); |
477 | fd = -1; | 487 | fd = -1; |
478 | } | 488 | } |
479 | freeaddrinfo(res); | 489 | freeaddrinfo(res); |
490 | |||
480 | return fd; | 491 | return fd; |
481 | } | 492 | } |
482 | 493 | ||
483 | static void spdy_socket_make_non_block(int fd) | 494 | |
495 | static void | ||
496 | spdy_socket_make_non_block(int fd) | ||
484 | { | 497 | { |
485 | int flags, rv; | 498 | int flags; |
499 | int rv; | ||
500 | |||
486 | while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR); | 501 | while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR); |
487 | if(flags == -1) { | 502 | |
503 | if(flags == -1) | ||
488 | spdy_dief("fcntl", strerror(errno)); | 504 | spdy_dief("fcntl", strerror(errno)); |
489 | } | 505 | |
490 | while((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR); | 506 | while((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR); |
491 | if(rv == -1) { | 507 | |
508 | if(rv == -1) | ||
492 | spdy_dief("fcntl", strerror(errno)); | 509 | spdy_dief("fcntl", strerror(errno)); |
493 | } | ||
494 | } | 510 | } |
495 | 511 | ||
512 | |||
496 | /* | 513 | /* |
497 | * Setting TCP_NODELAY is not mandatory for the SPDY protocol. | 514 | * Setting TCP_NODELAY is not mandatory for the SPDY protocol. |
498 | */ | 515 | */ |
499 | static void spdy_socket_set_tcp_nodelay(int fd) | 516 | static void |
517 | spdy_socket_set_tcp_nodelay(int fd) | ||
500 | { | 518 | { |
501 | int val = 1; | 519 | int val = 1; |
502 | int rv; | 520 | int rv; |
521 | |||
503 | rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)); | 522 | rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)); |
504 | if(rv == -1) { | 523 | if(rv == -1) |
505 | spdy_dief("setsockopt", strerror(errno)); | 524 | spdy_dief("setsockopt", strerror(errno)); |
506 | } | ||
507 | } | 525 | } |
508 | 526 | ||
509 | /* | 527 | /* |
510 | * Update |pollfd| based on the state of |connection|. | 528 | * Update |pollfd| based on the state of |connection|. |
511 | */ | 529 | */ |
512 | void spdy_ctl_poll(struct pollfd *pollfd, struct SPDY_Connection *connection) | 530 | void |
531 | spdy_ctl_poll(struct pollfd *pollfd, | ||
532 | struct SPDY_Connection *connection) | ||
513 | { | 533 | { |
514 | pollfd->events = 0; | 534 | pollfd->events = 0; |
515 | if(spdylay_session_want_read(connection->session) || | 535 | if(spdylay_session_want_read(connection->session) || |
516 | connection->want_io == WANT_READ) { | 536 | connection->want_io == WANT_READ) |
537 | { | ||
517 | pollfd->events |= POLLIN; | 538 | pollfd->events |= POLLIN; |
518 | } | 539 | } |
519 | if(spdylay_session_want_write(connection->session) || | 540 | if(spdylay_session_want_write(connection->session) || |
520 | connection->want_io == WANT_WRITE) { | 541 | connection->want_io == WANT_WRITE) |
542 | { | ||
521 | pollfd->events |= POLLOUT; | 543 | pollfd->events |= POLLOUT; |
522 | } | 544 | } |
523 | } | 545 | } |
524 | 546 | ||
547 | |||
525 | /* | 548 | /* |
526 | * Update |selectfd| based on the state of |connection|. | 549 | * Update |selectfd| based on the state of |connection|. |
527 | */ | 550 | */ |
528 | bool spdy_ctl_select(fd_set * read_fd_set, | 551 | bool |
529 | fd_set * write_fd_set, | 552 | spdy_ctl_select(fd_set * read_fd_set, |
530 | fd_set * except_fd_set, | 553 | fd_set * write_fd_set, |
531 | struct SPDY_Connection *connection) | 554 | fd_set * except_fd_set, |
555 | struct SPDY_Connection *connection) | ||
532 | { | 556 | { |
533 | (void)except_fd_set; | 557 | (void)except_fd_set; |
534 | 558 | ||
535 | bool ret = false; | 559 | bool ret = false; |
536 | 560 | ||
537 | if(spdylay_session_want_read(connection->session) || | 561 | if(spdylay_session_want_read(connection->session) || |
538 | connection->want_io == WANT_READ) { | 562 | connection->want_io == WANT_READ) |
563 | { | ||
539 | FD_SET(connection->fd, read_fd_set); | 564 | FD_SET(connection->fd, read_fd_set); |
540 | ret = true; | 565 | ret = true; |
541 | } | 566 | } |
542 | if(spdylay_session_want_write(connection->session) || | 567 | if(spdylay_session_want_write(connection->session) || |
543 | connection->want_io == WANT_WRITE) { | 568 | connection->want_io == WANT_WRITE) |
569 | { | ||
544 | FD_SET(connection->fd, write_fd_set); | 570 | FD_SET(connection->fd, write_fd_set); |
545 | ret = true; | 571 | ret = true; |
546 | } | 572 | } |
573 | |||
547 | return ret; | 574 | return ret; |
548 | } | 575 | } |
549 | 576 | ||
577 | |||
550 | /* | 578 | /* |
551 | * Performs the network I/O. | 579 | * Performs the network I/O. |
552 | */ | 580 | */ |
553 | int spdy_exec_io(struct SPDY_Connection *connection) | 581 | int |
582 | spdy_exec_io(struct SPDY_Connection *connection) | ||
554 | { | 583 | { |
555 | int rv; | 584 | int rv; |
585 | |||
556 | rv = spdylay_session_recv(connection->session); | 586 | rv = spdylay_session_recv(connection->session); |
557 | if(rv != 0) { | 587 | if(rv != 0) |
588 | { | ||
558 | PRINT_INFO2("spdylay_session_recv %i", rv); | 589 | PRINT_INFO2("spdylay_session_recv %i", rv); |
559 | return rv; | 590 | return rv; |
560 | } | 591 | } |
561 | rv = spdylay_session_send(connection->session); | 592 | rv = spdylay_session_send(connection->session); |
562 | if(rv != 0) { | 593 | if(rv != 0) |
563 | PRINT_INFO2("spdylay_session_send %i", rv); | 594 | PRINT_INFO2("spdylay_session_send %i", rv); |
564 | } | 595 | |
565 | return rv; | 596 | return rv; |
566 | } | 597 | } |
567 | 598 | ||
599 | |||
568 | /* | 600 | /* |
569 | * Fetches the resource denoted by |uri|. | 601 | * Fetches the resource denoted by |uri|. |
570 | */ | 602 | */ |
571 | struct SPDY_Connection * spdy_connect(const struct URI *uri, uint16_t port, bool is_tls) | 603 | struct SPDY_Connection * |
604 | spdy_connect(const struct URI *uri, | ||
605 | uint16_t port, | ||
606 | bool is_tls) | ||
572 | { | 607 | { |
573 | spdylay_session_callbacks callbacks; | 608 | spdylay_session_callbacks callbacks; |
574 | int fd; | 609 | int fd; |
575 | //SSL_CTX *ssl_ctx; | ||
576 | SSL *ssl=NULL; | 610 | SSL *ssl=NULL; |
577 | //struct SPDY_Request req; | ||
578 | struct SPDY_Connection * connection; | 611 | struct SPDY_Connection * connection; |
579 | int rv; | 612 | int rv; |
580 | 613 | ||
@@ -583,19 +616,14 @@ struct SPDY_Connection * spdy_connect(const struct URI *uri, uint16_t port, bool | |||
583 | /* Establish connection and setup SSL */ | 616 | /* Establish connection and setup SSL */ |
584 | PRINT_INFO2("connecting to %s:%i", uri->host, port); | 617 | PRINT_INFO2("connecting to %s:%i", uri->host, port); |
585 | fd = spdy_socket_connect_to(uri->host, port); | 618 | fd = spdy_socket_connect_to(uri->host, port); |
586 | if(fd == -1) { | 619 | if(fd == -1) |
620 | { | ||
587 | PRINT_INFO("Could not open file descriptor"); | 621 | PRINT_INFO("Could not open file descriptor"); |
588 | return NULL;//glob_opt.spdy_connection; | 622 | return NULL; |
589 | } | 623 | } |
590 | 624 | ||
591 | if(is_tls) | 625 | if(is_tls) |
592 | { | 626 | { |
593 | /*ssl_ctx = SSL_CTX_new(SSLv23_client_method()); | ||
594 | if(ssl_ctx == NULL) { | ||
595 | spdy_dief("SSL_CTX_new", ERR_error_string(ERR_get_error(), NULL)); | ||
596 | } | ||
597 | spdy_ssl_init_ssl_ctx(ssl_ctx, &spdy_proto_version); | ||
598 | */ | ||
599 | ssl = SSL_new(glob_opt.ssl_ctx); | 627 | ssl = SSL_new(glob_opt.ssl_ctx); |
600 | if(ssl == NULL) { | 628 | if(ssl == NULL) { |
601 | spdy_dief("SSL_new", ERR_error_string(ERR_get_error(), NULL)); | 629 | spdy_dief("SSL_new", ERR_error_string(ERR_get_error(), NULL)); |
@@ -624,7 +652,6 @@ struct SPDY_Connection * spdy_connect(const struct URI *uri, uint16_t port, bool | |||
624 | 652 | ||
625 | if(NULL == (connection = au_malloc(sizeof(struct SPDY_Connection)))) | 653 | if(NULL == (connection = au_malloc(sizeof(struct SPDY_Connection)))) |
626 | return NULL; | 654 | return NULL; |
627 | //memset(connection, 0 , sizeof(struct SPDY_Connection)); | ||
628 | 655 | ||
629 | connection->is_tls = is_tls; | 656 | connection->is_tls = is_tls; |
630 | connection->ssl = ssl; | 657 | connection->ssl = ssl; |
@@ -647,6 +674,7 @@ struct SPDY_Connection * spdy_connect(const struct URI *uri, uint16_t port, bool | |||
647 | return connection; | 674 | return connection; |
648 | } | 675 | } |
649 | 676 | ||
677 | |||
650 | void | 678 | void |
651 | spdy_free_connection(struct SPDY_Connection * connection) | 679 | spdy_free_connection(struct SPDY_Connection * connection) |
652 | { | 680 | { |
@@ -659,8 +687,10 @@ spdy_free_connection(struct SPDY_Connection * connection) | |||
659 | } | 687 | } |
660 | } | 688 | } |
661 | 689 | ||
690 | |||
662 | int | 691 | int |
663 | spdy_request(const char **nv, struct Proxy *proxy) | 692 | spdy_request(const char **nv, |
693 | struct Proxy *proxy) | ||
664 | { | 694 | { |
665 | int ret; | 695 | int ret; |
666 | uint16_t port; | 696 | uint16_t port; |
@@ -714,13 +744,18 @@ spdy_request(const char **nv, struct Proxy *proxy) | |||
714 | 744 | ||
715 | 745 | ||
716 | void | 746 | void |
717 | spdy_get_pollfdset(struct pollfd fds[], struct SPDY_Connection *connections[], unsigned int max_size, nfds_t *real_size) | 747 | spdy_get_pollfdset(struct pollfd fds[], |
748 | struct SPDY_Connection *connections[], | ||
749 | unsigned int max_size, | ||
750 | nfds_t *real_size) | ||
718 | { | 751 | { |
719 | struct SPDY_Connection *connection; | 752 | struct SPDY_Connection *connection; |
720 | struct Proxy *proxy; | 753 | struct Proxy *proxy; |
721 | 754 | ||
722 | *real_size = 0; | 755 | *real_size = 0; |
723 | if(max_size<1) return; | 756 | if(max_size<1) |
757 | return; | ||
758 | |||
724 | if(NULL != glob_opt.spdy_connection) | 759 | if(NULL != glob_opt.spdy_connection) |
725 | { | 760 | { |
726 | spdy_ctl_poll(&(fds[*real_size]), glob_opt.spdy_connection); | 761 | spdy_ctl_poll(&(fds[*real_size]), glob_opt.spdy_connection); |
@@ -781,9 +816,11 @@ spdy_get_pollfdset(struct pollfd fds[], struct SPDY_Connection *connections[], u | |||
781 | 816 | ||
782 | int | 817 | int |
783 | spdy_get_selectfdset(fd_set * read_fd_set, | 818 | spdy_get_selectfdset(fd_set * read_fd_set, |
784 | fd_set * write_fd_set, | 819 | fd_set * write_fd_set, |
785 | fd_set * except_fd_set, | 820 | fd_set * except_fd_set, |
786 | struct SPDY_Connection *connections[], unsigned int max_size, nfds_t *real_size) | 821 | struct SPDY_Connection *connections[], |
822 | unsigned int max_size, | ||
823 | nfds_t *real_size) | ||
787 | { | 824 | { |
788 | struct SPDY_Connection *connection; | 825 | struct SPDY_Connection *connection; |
789 | struct Proxy *proxy; | 826 | struct Proxy *proxy; |
@@ -791,7 +828,9 @@ spdy_get_selectfdset(fd_set * read_fd_set, | |||
791 | int maxfd = 0; | 828 | int maxfd = 0; |
792 | 829 | ||
793 | *real_size = 0; | 830 | *real_size = 0; |
794 | if(max_size<1) return 0; | 831 | if(max_size<1) |
832 | return 0; | ||
833 | |||
795 | if(NULL != glob_opt.spdy_connection) | 834 | if(NULL != glob_opt.spdy_connection) |
796 | { | 835 | { |
797 | ret = spdy_ctl_select(read_fd_set, | 836 | ret = spdy_ctl_select(read_fd_set, |
@@ -857,12 +896,13 @@ spdy_get_selectfdset(fd_set * read_fd_set, | |||
857 | 896 | ||
858 | 897 | ||
859 | void | 898 | void |
860 | spdy_run(struct pollfd fds[], struct SPDY_Connection *connections[], int size) | 899 | spdy_run(struct pollfd fds[], |
900 | struct SPDY_Connection *connections[], | ||
901 | int size) | ||
861 | { | 902 | { |
862 | int i; | 903 | int i; |
863 | int ret; | 904 | int ret; |
864 | struct Proxy *proxy; | 905 | struct Proxy *proxy; |
865 | //PRINT_INFO2("size is %i", size); | ||
866 | 906 | ||
867 | for(i=0; i<size; ++i) | 907 | for(i=0; i<size; ++i) |
868 | { | 908 | { |
@@ -898,21 +938,20 @@ spdy_run(struct pollfd fds[], struct SPDY_Connection *connections[], int size) | |||
898 | } | 938 | } |
899 | } | 939 | } |
900 | else | 940 | else |
901 | { | ||
902 | PRINT_INFO("not called"); | 941 | PRINT_INFO("not called"); |
903 | } | ||
904 | } | 942 | } |
905 | } | 943 | } |
906 | 944 | ||
907 | void | 945 | void |
908 | spdy_run_select(fd_set * read_fd_set, | 946 | spdy_run_select(fd_set * read_fd_set, |
909 | fd_set * write_fd_set, | 947 | fd_set * write_fd_set, |
910 | fd_set * except_fd_set, struct SPDY_Connection *connections[], int size) | 948 | fd_set * except_fd_set, |
949 | struct SPDY_Connection *connections[], | ||
950 | int size) | ||
911 | { | 951 | { |
912 | int i; | 952 | int i; |
913 | int ret; | 953 | int ret; |
914 | struct Proxy *proxy; | 954 | struct Proxy *proxy; |
915 | //PRINT_INFO2("size is %i", size); | ||
916 | 955 | ||
917 | for(i=0; i<size; ++i) | 956 | for(i=0; i<size; ++i) |
918 | { | 957 | { |
@@ -920,12 +959,6 @@ spdy_run_select(fd_set * read_fd_set, | |||
920 | if(FD_ISSET(connections[i]->fd, read_fd_set) || FD_ISSET(connections[i]->fd, write_fd_set) || FD_ISSET(connections[i]->fd, except_fd_set)) | 959 | if(FD_ISSET(connections[i]->fd, read_fd_set) || FD_ISSET(connections[i]->fd, write_fd_set) || FD_ISSET(connections[i]->fd, except_fd_set)) |
921 | { | 960 | { |
922 | ret = spdy_exec_io(connections[i]); | 961 | ret = spdy_exec_io(connections[i]); |
923 | //PRINT_INFO2("%i",ret); | ||
924 | //if((spdy_pollfds[i].revents & POLLHUP) || (spdy_pollfds[0].revents & POLLERR)) | ||
925 | // PRINT_INFO("SPDY SPDY_Connection error"); | ||
926 | |||
927 | //TODO POLLRDHUP | ||
928 | // always close on ret != 0? | ||
929 | 962 | ||
930 | if(0 != ret) | 963 | if(0 != ret) |
931 | { | 964 | { |
@@ -948,8 +981,6 @@ spdy_run_select(fd_set * read_fd_set, | |||
948 | } | 981 | } |
949 | } | 982 | } |
950 | else | 983 | else |
951 | { | ||
952 | PRINT_INFO("not called"); | 984 | PRINT_INFO("not called"); |
953 | } | ||
954 | } | 985 | } |
955 | } | 986 | } |