ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/vendor/serf/1.3.9/test/serf_bwtp.c
Revision: 9260
Committed: Mon Feb 20 02:15:06 2017 UTC (7 years, 2 months ago) by laffer1
Content type: text/plain
File size: 20061 byte(s)
Log Message:
serf 1.3.9

File Contents

# Content
1 /* ====================================================================
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 * ====================================================================
19 */
20
21 #include <stdlib.h>
22
23 #include <apr.h>
24 #include <apr_uri.h>
25 #include <apr_strings.h>
26 #include <apr_atomic.h>
27 #include <apr_base64.h>
28 #include <apr_getopt.h>
29 #include <apr_version.h>
30
31 #include "serf.h"
32
33 typedef struct {
34 int count;
35 int using_ssl;
36 serf_ssl_context_t *ssl_ctx;
37 serf_bucket_alloc_t *bkt_alloc;
38 } app_baton_t;
39
40 typedef struct {
41 #if APR_MAJOR_VERSION > 0
42 apr_uint32_t requests_outstanding;
43 #else
44 apr_atomic_t requests_outstanding;
45 #endif
46 int print_headers;
47
48 serf_response_acceptor_t acceptor;
49 app_baton_t *acceptor_baton;
50
51 serf_response_handler_t handler;
52
53 const char *host;
54 const char *method;
55 const char *path;
56 const char *req_body_path;
57 const char *authn;
58 } handler_baton_t;
59
60 /* Kludges for APR 0.9 support. */
61 #if APR_MAJOR_VERSION == 0
62 #define apr_atomic_inc32 apr_atomic_inc
63 #define apr_atomic_dec32 apr_atomic_dec
64 #define apr_atomic_read32 apr_atomic_read
65 #endif
66
67 static void closed_connection(serf_connection_t *conn,
68 void *closed_baton,
69 apr_status_t why,
70 apr_pool_t *pool)
71 {
72 if (why) {
73 abort();
74 }
75 }
76
77 static apr_status_t ignore_all_cert_errors(void *data, int failures,
78 const serf_ssl_certificate_t *cert)
79 {
80 /* In a real application, you would normally would not want to do this */
81 return APR_SUCCESS;
82 }
83
84 static apr_status_t conn_setup(apr_socket_t *skt,
85 serf_bucket_t **input_bkt,
86 serf_bucket_t **output_bkt,
87 void *setup_baton,
88 apr_pool_t *pool)
89 {
90 serf_bucket_t *c;
91 app_baton_t *ctx = setup_baton;
92
93 c = serf_bucket_socket_create(skt, ctx->bkt_alloc);
94 if (ctx->using_ssl) {
95 c = serf_bucket_ssl_decrypt_create(c, ctx->ssl_ctx, ctx->bkt_alloc);
96 if (!ctx->ssl_ctx) {
97 ctx->ssl_ctx = serf_bucket_ssl_decrypt_context_get(c);
98 }
99 serf_ssl_server_cert_callback_set(ctx->ssl_ctx, ignore_all_cert_errors, NULL);
100
101 *output_bkt = serf_bucket_ssl_encrypt_create(*output_bkt, ctx->ssl_ctx,
102 ctx->bkt_alloc);
103 }
104
105 *input_bkt = c;
106
107 return APR_SUCCESS;
108 }
109
110 static serf_bucket_t* accept_response(serf_request_t *request,
111 serf_bucket_t *stream,
112 void *acceptor_baton,
113 apr_pool_t *pool)
114 {
115 serf_bucket_t *c;
116 serf_bucket_alloc_t *bkt_alloc;
117
118 /* get the per-request bucket allocator */
119 bkt_alloc = serf_request_get_alloc(request);
120
121 /* Create a barrier so the response doesn't eat us! */
122 c = serf_bucket_barrier_create(stream, bkt_alloc);
123
124 return serf_bucket_response_create(c, bkt_alloc);
125 }
126
127 static serf_bucket_t* accept_bwtp(serf_request_t *request,
128 serf_bucket_t *stream,
129 void *acceptor_baton,
130 apr_pool_t *pool)
131 {
132 serf_bucket_t *c;
133 app_baton_t *app_ctx = acceptor_baton;
134
135 /* Create a barrier so the response doesn't eat us! */
136 c = serf_bucket_barrier_create(stream, app_ctx->bkt_alloc);
137
138 return serf_bucket_bwtp_incoming_frame_create(c, app_ctx->bkt_alloc);
139 }
140
141 /* fwd declare */
142 static apr_status_t handle_bwtp_upgrade(serf_request_t *request,
143 serf_bucket_t *response,
144 void *handler_baton,
145 apr_pool_t *pool);
146
147 static apr_status_t setup_request(serf_request_t *request,
148 void *setup_baton,
149 serf_bucket_t **req_bkt,
150 serf_response_acceptor_t *acceptor,
151 void **acceptor_baton,
152 serf_response_handler_t *handler,
153 void **handler_baton,
154 apr_pool_t *pool)
155 {
156 handler_baton_t *ctx = setup_baton;
157 serf_bucket_t *hdrs_bkt;
158 serf_bucket_t *body_bkt;
159
160 if (ctx->req_body_path) {
161 apr_file_t *file;
162 apr_status_t status;
163
164 status = apr_file_open(&file, ctx->req_body_path, APR_READ,
165 APR_OS_DEFAULT, pool);
166
167 if (status) {
168 printf("Error opening file (%s)\n", ctx->req_body_path);
169 return status;
170 }
171
172 body_bkt = serf_bucket_file_create(file,
173 serf_request_get_alloc(request));
174 }
175 else {
176 body_bkt = NULL;
177 }
178
179 /*
180 *req_bkt = serf_bucket_bwtp_message_create(0, body_bkt,
181 serf_request_get_alloc(request));
182 */
183
184 *req_bkt = serf_bucket_bwtp_header_create(0, "MESSAGE",
185 serf_request_get_alloc(request));
186
187 hdrs_bkt = serf_bucket_bwtp_frame_get_headers(*req_bkt);
188
189 /* FIXME: Shouldn't we be able to figure out the host ourselves? */
190 serf_bucket_headers_setn(hdrs_bkt, "Host", ctx->host);
191 serf_bucket_headers_setn(hdrs_bkt, "User-Agent",
192 "Serf/" SERF_VERSION_STRING);
193 /* Shouldn't serf do this for us? */
194 serf_bucket_headers_setn(hdrs_bkt, "Accept-Encoding", "gzip");
195
196 if (ctx->authn != NULL) {
197 serf_bucket_headers_setn(hdrs_bkt, "Authorization", ctx->authn);
198 }
199
200 *acceptor = ctx->acceptor;
201 *acceptor_baton = ctx->acceptor_baton;
202 *handler = ctx->handler;
203 *handler_baton = ctx;
204
205 return APR_SUCCESS;
206 }
207
208 static apr_status_t setup_bwtp_upgrade(serf_request_t *request,
209 void *setup_baton,
210 serf_bucket_t **req_bkt,
211 serf_response_acceptor_t *acceptor,
212 void **acceptor_baton,
213 serf_response_handler_t *handler,
214 void **handler_baton,
215 apr_pool_t *pool)
216 {
217 serf_bucket_t *hdrs_bkt;
218 handler_baton_t *ctx = setup_baton;
219
220 *req_bkt = serf_bucket_request_create("OPTIONS", "*", NULL,
221 serf_request_get_alloc(request));
222
223 hdrs_bkt = serf_bucket_request_get_headers(*req_bkt);
224
225 serf_bucket_headers_setn(hdrs_bkt, "Upgrade", "BWTP/1.0");
226 serf_bucket_headers_setn(hdrs_bkt, "Connection", "Upgrade");
227
228 *acceptor = ctx->acceptor;
229 *acceptor_baton = ctx->acceptor_baton;
230 *handler = handle_bwtp_upgrade;
231 *handler_baton = ctx;
232
233 return APR_SUCCESS;
234 }
235
236 static apr_status_t setup_channel(serf_request_t *request,
237 void *setup_baton,
238 serf_bucket_t **req_bkt,
239 serf_response_acceptor_t *acceptor,
240 void **acceptor_baton,
241 serf_response_handler_t *handler,
242 void **handler_baton,
243 apr_pool_t *pool)
244 {
245 handler_baton_t *ctx = setup_baton;
246 serf_bucket_t *hdrs_bkt;
247
248 *req_bkt = serf_bucket_bwtp_channel_open(0, ctx->path,
249 serf_request_get_alloc(request));
250
251 hdrs_bkt = serf_bucket_bwtp_frame_get_headers(*req_bkt);
252
253 /* FIXME: Shouldn't we be able to figure out the host ourselves? */
254 serf_bucket_headers_setn(hdrs_bkt, "Host", ctx->host);
255 serf_bucket_headers_setn(hdrs_bkt, "User-Agent",
256 "Serf/" SERF_VERSION_STRING);
257 /* Shouldn't serf do this for us? */
258 serf_bucket_headers_setn(hdrs_bkt, "Accept-Encoding", "gzip");
259
260 if (ctx->authn != NULL) {
261 serf_bucket_headers_setn(hdrs_bkt, "Authorization", ctx->authn);
262 }
263
264 *acceptor = ctx->acceptor;
265 *acceptor_baton = ctx->acceptor_baton;
266 *handler = ctx->handler;
267 *handler_baton = ctx;
268
269 return APR_SUCCESS;
270 }
271
272 static apr_status_t setup_close(serf_request_t *request,
273 void *setup_baton,
274 serf_bucket_t **req_bkt,
275 serf_response_acceptor_t *acceptor,
276 void **acceptor_baton,
277 serf_response_handler_t *handler,
278 void **handler_baton,
279 apr_pool_t *pool)
280 {
281 handler_baton_t *ctx = setup_baton;
282
283 *req_bkt = serf_bucket_bwtp_channel_close(0, serf_request_get_alloc(request));
284
285 *acceptor = ctx->acceptor;
286 *acceptor_baton = ctx->acceptor_baton;
287 *handler = ctx->handler;
288 *handler_baton = ctx;
289
290 return APR_SUCCESS;
291 }
292
293 static apr_status_t handle_bwtp(serf_request_t *request,
294 serf_bucket_t *response,
295 void *handler_baton,
296 apr_pool_t *pool)
297 {
298 const char *data;
299 apr_size_t len;
300 apr_status_t status;
301
302 if (!response) {
303 /* A NULL response can come back if the request failed completely */
304 return APR_EGENERAL;
305 }
306 status = serf_bucket_bwtp_incoming_frame_wait_for_headers(response);
307 if (SERF_BUCKET_READ_ERROR(status) || APR_STATUS_IS_EAGAIN(status)) {
308 return status;
309 }
310 printf("BWTP %p frame: %d %d %s\n",
311 response, serf_bucket_bwtp_frame_get_channel(response),
312 serf_bucket_bwtp_frame_get_type(response),
313 serf_bucket_bwtp_frame_get_phrase(response));
314
315
316 while (1) {
317 status = serf_bucket_read(response, 2048, &data, &len);
318 if (SERF_BUCKET_READ_ERROR(status))
319 return status;
320
321 /* got some data. print it out. */
322 if (len) {
323 puts("BWTP body:\n---");
324 fwrite(data, 1, len, stdout);
325 puts("\n---");
326 }
327
328 /* are we done yet? */
329 if (APR_STATUS_IS_EOF(status)) {
330 return APR_EOF;
331 }
332
333 /* have we drained the response so far? */
334 if (APR_STATUS_IS_EAGAIN(status))
335 return status;
336
337 /* loop to read some more. */
338 }
339 /* NOTREACHED */
340 }
341
342 static apr_status_t handle_bwtp_upgrade(serf_request_t *request,
343 serf_bucket_t *response,
344 void *handler_baton,
345 apr_pool_t *pool)
346 {
347 const char *data;
348 apr_size_t len;
349 serf_status_line sl;
350 apr_status_t status;
351 handler_baton_t *ctx = handler_baton;
352
353 if (!response) {
354 /* A NULL response can come back if the request failed completely */
355 return APR_EGENERAL;
356 }
357 status = serf_bucket_response_status(response, &sl);
358 if (status) {
359 return status;
360 }
361
362 while (1) {
363 status = serf_bucket_read(response, 2048, &data, &len);
364 if (SERF_BUCKET_READ_ERROR(status))
365 return status;
366
367 /* got some data. print it out. */
368 fwrite(data, 1, len, stdout);
369
370 /* are we done yet? */
371 if (APR_STATUS_IS_EOF(status)) {
372 int i;
373 serf_connection_t *conn;
374 serf_request_t *new_req;
375
376 conn = serf_request_get_conn(request);
377
378 serf_connection_set_async_responses(conn,
379 accept_bwtp, ctx->acceptor_baton, handle_bwtp, NULL);
380
381 new_req = serf_connection_request_create(conn, setup_channel, ctx);
382 for (i = 0; i < ctx->acceptor_baton->count; i++) {
383 new_req = serf_connection_request_create(conn,
384 setup_request,
385 ctx);
386 }
387
388 return APR_EOF;
389 }
390
391 /* have we drained the response so far? */
392 if (APR_STATUS_IS_EAGAIN(status))
393 return status;
394
395 /* loop to read some more. */
396 }
397 /* NOTREACHED */
398 }
399
400 static apr_status_t handle_response(serf_request_t *request,
401 serf_bucket_t *response,
402 void *handler_baton,
403 apr_pool_t *pool)
404 {
405 const char *data;
406 apr_size_t len;
407 serf_status_line sl;
408 apr_status_t status;
409 handler_baton_t *ctx = handler_baton;
410
411 if (!response) {
412 /* A NULL response can come back if the request failed completely */
413 return APR_EGENERAL;
414 }
415 status = serf_bucket_response_status(response, &sl);
416 if (status) {
417 return status;
418 }
419
420 while (1) {
421 status = serf_bucket_read(response, 2048, &data, &len);
422 if (SERF_BUCKET_READ_ERROR(status))
423 return status;
424
425 /* got some data. print it out. */
426 fwrite(data, 1, len, stdout);
427
428 /* are we done yet? */
429 if (APR_STATUS_IS_EOF(status)) {
430 if (ctx->print_headers) {
431 serf_bucket_t *hdrs;
432 hdrs = serf_bucket_response_get_headers(response);
433 while (1) {
434 status = serf_bucket_read(hdrs, 2048, &data, &len);
435 if (SERF_BUCKET_READ_ERROR(status))
436 return status;
437
438 fwrite(data, 1, len, stdout);
439 if (APR_STATUS_IS_EOF(status)) {
440 break;
441 }
442 }
443 }
444
445 apr_atomic_dec32(&ctx->requests_outstanding);
446 if (!ctx->requests_outstanding) {
447 serf_connection_t *conn;
448 serf_request_t *new_req;
449
450 conn = serf_request_get_conn(request);
451 new_req =
452 serf_connection_request_create(conn, setup_close, ctx);
453 }
454 return APR_EOF;
455 }
456
457 /* have we drained the response so far? */
458 if (APR_STATUS_IS_EAGAIN(status))
459 return status;
460
461 /* loop to read some more. */
462 }
463 /* NOTREACHED */
464 }
465
466 static void print_usage(apr_pool_t *pool)
467 {
468 puts("serf_get [options] URL");
469 puts("-h\tDisplay this help");
470 puts("-v\tDisplay version");
471 puts("-H\tPrint response headers");
472 puts("-n <count> Fetch URL <count> times");
473 puts("-a <user:password> Present Basic authentication credentials");
474 puts("-m <method> Use the <method> HTTP Method");
475 puts("-f <file> Use the <file> as the request body");
476 }
477
478 int main(int argc, const char **argv)
479 {
480 apr_status_t status;
481 apr_pool_t *pool;
482 apr_sockaddr_t *address;
483 serf_context_t *context;
484 serf_connection_t *connection;
485 serf_request_t *request;
486 app_baton_t app_ctx;
487 handler_baton_t handler_ctx;
488 apr_uri_t url;
489 const char *raw_url, *method, *req_body_path = NULL;
490 int i;
491 int print_headers;
492 char *authn = NULL;
493 apr_getopt_t *opt;
494 char opt_c;
495 const char *opt_arg;
496
497 apr_initialize();
498 atexit(apr_terminate);
499
500 apr_pool_create(&pool, NULL);
501 /* serf_initialize(); */
502
503 /* Default to one round of fetching. */
504 app_ctx.count = 1;
505 /* Default to GET. */
506 method = "GET";
507 /* Do not print headers by default. */
508 print_headers = 0;
509
510 apr_getopt_init(&opt, pool, argc, argv);
511
512 while ((status = apr_getopt(opt, "a:f:hHm:n:v", &opt_c, &opt_arg)) ==
513 APR_SUCCESS) {
514 int srclen, enclen;
515
516 switch (opt_c) {
517 case 'a':
518 srclen = strlen(opt_arg);
519 enclen = apr_base64_encode_len(srclen);
520 authn = apr_palloc(pool, enclen + 6);
521 strcpy(authn, "Basic ");
522 (void) apr_base64_encode(&authn[6], opt_arg, srclen);
523 break;
524 case 'f':
525 req_body_path = opt_arg;
526 break;
527 case 'h':
528 print_usage(pool);
529 exit(0);
530 break;
531 case 'H':
532 print_headers = 1;
533 break;
534 case 'm':
535 method = opt_arg;
536 break;
537 case 'n':
538 errno = 0;
539 app_ctx.count = apr_strtoi64(opt_arg, NULL, 10);
540 if (errno) {
541 printf("Problem converting number of times to fetch URL (%d)\n",
542 errno);
543 return errno;
544 }
545 break;
546 case 'v':
547 puts("Serf version: " SERF_VERSION_STRING);
548 exit(0);
549 default:
550 break;
551 }
552 }
553
554 if (opt->ind != opt->argc - 1) {
555 print_usage(pool);
556 exit(-1);
557 }
558
559 raw_url = argv[opt->ind];
560
561 apr_uri_parse(pool, raw_url, &url);
562 if (!url.port) {
563 url.port = apr_uri_port_of_scheme(url.scheme);
564 }
565 if (!url.path) {
566 url.path = "/";
567 }
568
569 if (strcasecmp(url.scheme, "https") == 0) {
570 app_ctx.using_ssl = 1;
571 }
572 else {
573 app_ctx.using_ssl = 0;
574 }
575
576 status = apr_sockaddr_info_get(&address,
577 url.hostname, APR_UNSPEC, url.port, 0,
578 pool);
579 if (status) {
580 printf("Error creating address: %d\n", status);
581 apr_pool_destroy(pool);
582 exit(1);
583 }
584
585 context = serf_context_create(pool);
586
587 /* ### Connection or Context should have an allocator? */
588 app_ctx.bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
589 app_ctx.ssl_ctx = NULL;
590
591 connection = serf_connection_create(context, address,
592 conn_setup, &app_ctx,
593 closed_connection, &app_ctx,
594 pool);
595
596 handler_ctx.requests_outstanding = 0;
597 handler_ctx.print_headers = print_headers;
598
599 handler_ctx.host = url.hostinfo;
600 handler_ctx.method = method;
601 handler_ctx.path = url.path;
602 handler_ctx.authn = authn;
603
604 handler_ctx.req_body_path = req_body_path;
605
606 handler_ctx.acceptor = accept_response;
607 handler_ctx.acceptor_baton = &app_ctx;
608 handler_ctx.handler = handle_response;
609
610 request = serf_connection_request_create(connection, setup_bwtp_upgrade,
611 &handler_ctx);
612
613 for (i = 0; i < app_ctx.count; i++) {
614 apr_atomic_inc32(&handler_ctx.requests_outstanding);
615 }
616
617 while (1) {
618 status = serf_context_run(context, SERF_DURATION_FOREVER, pool);
619 if (APR_STATUS_IS_TIMEUP(status))
620 continue;
621 if (status) {
622 char buf[200];
623
624 printf("Error running context: (%d) %s\n", status,
625 apr_strerror(status, buf, sizeof(buf)));
626 apr_pool_destroy(pool);
627 exit(1);
628 }
629 if (!apr_atomic_read32(&handler_ctx.requests_outstanding)) {
630 break;
631 }
632 /* Debugging purposes only! */
633 serf_debug__closed_conn(app_ctx.bkt_alloc);
634 }
635
636 serf_connection_close(connection);
637
638 apr_pool_destroy(pool);
639 return 0;
640 }