aboutsummaryrefslogtreecommitdiff
path: root/src/spdy2http/proxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdy2http/proxy.c')
-rw-r--r--src/spdy2http/proxy.c480
1 files changed, 363 insertions, 117 deletions
diff --git a/src/spdy2http/proxy.c b/src/spdy2http/proxy.c
index 0c303823..e495cc72 100644
--- a/src/spdy2http/proxy.c
+++ b/src/spdy2http/proxy.c
@@ -21,6 +21,9 @@
21 * @brief Translates incoming SPDY requests to http server on localhost. 21 * @brief Translates incoming SPDY requests to http server on localhost.
22 * Uses libcurl. 22 * Uses libcurl.
23 * No error handling for curl requests. 23 * No error handling for curl requests.
24 * TODO:
25 * - test all options!
26 * - don't abort on lack of memory
24 * @author Andrey Uzunov 27 * @author Andrey Uzunov
25 */ 28 */
26 29
@@ -36,6 +39,36 @@
36#include "microspdy.h" 39#include "microspdy.h"
37#include <curl/curl.h> 40#include <curl/curl.h>
38#include <assert.h> 41#include <assert.h>
42#include <getopt.h>
43#include <regex.h>
44
45
46struct global_options
47{
48 char *http_backend;
49 char *cert;
50 char *cert_key;
51 uint16_t listen_port;
52 bool verbose;
53 bool curl_verbose;
54 bool transparent;
55 bool http10;
56} glob_opt;
57
58
59struct URI
60{
61 char * full_uri;
62 char * scheme;
63 char * host_and_port;
64 //char * host_and_port_for_connecting;
65 char * host;
66 char * path;
67 char * path_and_more;
68 char * query;
69 char * fragment;
70 uint16_t port;
71};
39 72
40 73
41#define PRINT_INFO(msg) do{\ 74#define PRINT_INFO(msg) do{\
@@ -54,6 +87,26 @@
54 while(0) 87 while(0)
55 88
56 89
90#define PRINT_VERBOSE(msg) do{\
91 if(glob_opt.verbose){\
92 printf("%i:%s\n", __LINE__, msg);\
93 fflush(stdout);\
94 }\
95 }\
96 while(0)
97
98
99#define PRINT_VERBOSE2(fmt, ...) do{\
100 if(glob_opt.verbose){\
101 printf("%i\n", __LINE__);\
102 printf(fmt,##__VA_ARGS__);\
103 printf("\n");\
104 fflush(stdout);\
105 }\
106 }\
107 while(0)
108
109
57#define CURL_SETOPT(handle, opt, val) do{\ 110#define CURL_SETOPT(handle, opt, val) do{\
58 int ret; \ 111 int ret; \
59 if(CURLE_OK != (ret = curl_easy_setopt(handle, opt, val))) \ 112 if(CURLE_OK != (ret = curl_easy_setopt(handle, opt, val))) \
@@ -63,17 +116,25 @@
63 } \ 116 } \
64 }\ 117 }\
65 while(0) 118 while(0)
119
66 120
121#define DIE(msg) do{\
122 printf("FATAL ERROR (line %i): %s\n", __LINE__, msg);\
123 fflush(stdout);\
124 exit(EXIT_FAILURE);\
125 }\
126 while(0)
67 127
68int run = 1; 128
69char* http_host; 129int loop = 1;
70CURLM *multi_handle; 130CURLM *multi_handle;
71int still_running = 0; /* keep number of running handles */ 131int still_running = 0; /* keep number of running handles */
72int http10=0; 132regex_t uri_preg;
133
73 134
74struct Proxy 135struct Proxy
75{ 136{
76 char *path; 137 char *url;
77 struct SPDY_Request *request; 138 struct SPDY_Request *request;
78 struct SPDY_Response *response; 139 struct SPDY_Response *response;
79 CURL *curl_handle; 140 CURL *curl_handle;
@@ -89,6 +150,114 @@ struct Proxy
89}; 150};
90 151
91 152
153void
154free_uri(struct URI * uri)
155{
156 if(NULL != uri)
157 {
158 free(uri->full_uri);
159 free(uri->scheme);
160 free(uri->host_and_port);
161 //free(uri->host_and_port_for_connecting);
162 free(uri->host);
163 free(uri->path);
164 free(uri->path_and_more);
165 free(uri->query);
166 free(uri->fragment);
167 uri->port = 0;
168 free(uri);
169 }
170}
171
172int
173init_parse_uri(regex_t * preg)
174{
175 // RFC 2396
176 // ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
177 /*
178 scheme = $2
179 authority = $4
180 path = $5
181 query = $7
182 fragment = $9
183 */
184
185 return regcomp(preg, "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", REG_EXTENDED);
186}
187
188void
189deinit_parse_uri(regex_t * preg)
190{
191 regfree(preg);
192}
193
194int
195parse_uri(regex_t * preg, char * full_uri, struct URI ** uri)
196{
197 int ret;
198 char *colon;
199 long long port;
200 size_t nmatch = 10;
201 regmatch_t pmatch[10];
202
203 if (0 != (ret = regexec(preg, full_uri, nmatch, pmatch, 0)))
204 return ret;
205
206 *uri = malloc(sizeof(struct URI));
207 if(NULL == *uri)
208 return -200;
209
210 (*uri)->full_uri = strdup(full_uri);
211
212 asprintf(&((*uri)->scheme), "%.*s",pmatch[2].rm_eo - pmatch[2].rm_so, &full_uri[pmatch[2].rm_so]);
213 asprintf(&((*uri)->host_and_port), "%.*s",pmatch[4].rm_eo - pmatch[4].rm_so, &full_uri[pmatch[4].rm_so]);
214 asprintf(&((*uri)->path), "%.*s",pmatch[5].rm_eo - pmatch[5].rm_so, &full_uri[pmatch[5].rm_so]);
215 asprintf(&((*uri)->path_and_more), "%.*s",pmatch[9].rm_eo - pmatch[5].rm_so, &full_uri[pmatch[5].rm_so]);
216 asprintf(&((*uri)->query), "%.*s",pmatch[7].rm_eo - pmatch[7].rm_so, &full_uri[pmatch[7].rm_so]);
217 asprintf(&((*uri)->fragment), "%.*s",pmatch[9].rm_eo - pmatch[9].rm_so, &full_uri[pmatch[9].rm_so]);
218
219 colon = strrchr((*uri)->host_and_port, ':');
220 if(NULL == colon)
221 {
222 (*uri)->host = strdup((*uri)->host_and_port);
223 /*if(0 == strcasecmp("http", uri->scheme))
224 {
225 uri->port = 80;
226 asprintf(&(uri->host_and_port_for_connecting), "%s:80", uri->host_and_port);
227 }
228 else if(0 == strcasecmp("https", uri->scheme))
229 {
230 uri->port = 443;
231 asprintf(&(uri->host_and_port_for_connecting), "%s:443", uri->host_and_port);
232 }
233 else
234 {
235 PRINT_INFO("no standard scheme!");
236 */(*uri)->port = 0;
237 /*uri->host_and_port_for_connecting = strdup(uri->host_and_port);
238 }*/
239 return 0;
240 }
241
242 port = atoi(colon + 1);
243 if(port<1 || port >= 256 * 256)
244 {
245 free_uri(*uri);
246 return -100;
247 }
248 (*uri)->port = port;
249 asprintf(&((*uri)->host), "%.*s", (int)(colon - (*uri)->host_and_port), (*uri)->host_and_port);
250
251 return 0;
252}
253
254
255static void catch_signal(int signal)
256{
257 loop = 0;
258}
259
260
92ssize_t 261ssize_t
93response_callback (void *cls, 262response_callback (void *cls,
94 void *buffer, 263 void *buffer,
@@ -146,10 +315,6 @@ response_done_callback(void *cls,
146 struct Proxy *proxy = (struct Proxy *)cls; 315 struct Proxy *proxy = (struct Proxy *)cls;
147 int ret; 316 int ret;
148 317
149 //printf("response_done_callback\n");
150
151 //printf("answer for %s was sent\n", (char *)cls);
152
153 if(SPDY_RESPONSE_RESULT_SUCCESS != status) 318 if(SPDY_RESPONSE_RESULT_SUCCESS != status)
154 { 319 {
155 printf("answer was NOT sent, %i\n",status); 320 printf("answer was NOT sent, %i\n",status);
@@ -163,8 +328,7 @@ response_done_callback(void *cls,
163 328
164 SPDY_destroy_request(request); 329 SPDY_destroy_request(request);
165 SPDY_destroy_response(response); 330 SPDY_destroy_response(response);
166 if(!strcmp("/close",proxy->path)) run = 0; 331 free(proxy->url);
167 free(proxy->path);
168 free(proxy); 332 free(proxy);
169} 333}
170 334
@@ -200,10 +364,7 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
200 &response_callback, 364 &response_callback,
201 proxy, 365 proxy,
202 0))) 366 0)))
203 { 367 DIE("no response");
204 PRINT_INFO("no response");
205 abort();
206 }
207 368
208 SPDY_name_value_destroy(proxy->headers); 369 SPDY_name_value_destroy(proxy->headers);
209 free(proxy->status_msg); 370 free(proxy->status_msg);
@@ -215,10 +376,7 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
215 false, 376 false,
216 &response_done_callback, 377 &response_done_callback,
217 proxy)) 378 proxy))
218 { 379 DIE("no queue");
219 PRINT_INFO("no queue");
220 abort();
221 }
222 380
223 return realsize; 381 return realsize;
224 } 382 }
@@ -230,24 +388,15 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
230 //version 388 //version
231 for(i=pos; i<realsize && ' '!=line[i]; ++i); 389 for(i=pos; i<realsize && ' '!=line[i]; ++i);
232 if(i == realsize) 390 if(i == realsize)
233 { 391 DIE("error on parsing headers");
234 PRINT_INFO("error on parsing headers");
235 abort();
236 }
237 if(NULL == (proxy->version = strndup(line, i - pos))) 392 if(NULL == (proxy->version = strndup(line, i - pos)))
238 { 393 DIE("No memory");
239 PRINT_INFO("no memory");
240 abort();
241 }
242 pos = i+1; 394 pos = i+1;
243 395
244 //status (number) 396 //status (number)
245 for(i=pos; i<realsize && ' '!=line[i] && '\r'!=line[i]; ++i); 397 for(i=pos; i<realsize && ' '!=line[i] && '\r'!=line[i]; ++i);
246 if(NULL == (status = strndup(&(line[pos]), i - pos))) 398 if(NULL == (status = strndup(&(line[pos]), i - pos)))
247 { 399 DIE("No memory");
248 PRINT_INFO("no memory");
249 abort();
250 }
251 proxy->status = atoi(status); 400 proxy->status = atoi(status);
252 free(status); 401 free(status);
253 if(i<realsize && '\r'!=line[i]) 402 if(i<realsize && '\r'!=line[i])
@@ -256,10 +405,7 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
256 pos = i+1; 405 pos = i+1;
257 for(i=pos; i<realsize && '\r'!=line[i]; ++i); 406 for(i=pos; i<realsize && '\r'!=line[i]; ++i);
258 if(NULL == (proxy->status_msg = strndup(&(line[pos]), i - pos))) 407 if(NULL == (proxy->status_msg = strndup(&(line[pos]), i - pos)))
259 { 408 DIE("No memory");
260 PRINT_INFO("no memory");
261 abort();
262 }
263 } 409 }
264 return realsize; 410 return realsize;
265 } 411 }
@@ -269,10 +415,7 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
269 for(i=pos; i<realsize && ':'!=line[i] && '\r'!=line[i]; ++i) 415 for(i=pos; i<realsize && ':'!=line[i] && '\r'!=line[i]; ++i)
270 line[i] = tolower(line[i]); //spdy requires lower case 416 line[i] = tolower(line[i]); //spdy requires lower case
271 if(NULL == (name = strndup(line, i - pos))) 417 if(NULL == (name = strndup(line, i - pos)))
272 { 418 DIE("No memory");
273 PRINT_INFO("no memory");
274 abort();
275 }
276 if(0 == strcmp(SPDY_HTTP_HEADER_CONNECTION, name) 419 if(0 == strcmp(SPDY_HTTP_HEADER_CONNECTION, name)
277 || 0 == strcmp(SPDY_HTTP_HEADER_KEEP_ALIVE, name)) 420 || 0 == strcmp(SPDY_HTTP_HEADER_KEEP_ALIVE, name))
278 { 421 {
@@ -284,10 +427,7 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
284 { 427 {
285 //no value. is it possible? 428 //no value. is it possible?
286 if(SPDY_YES != SPDY_name_value_add(proxy->headers, name, "")) 429 if(SPDY_YES != SPDY_name_value_add(proxy->headers, name, ""))
287 { 430 DIE("SPDY_name_value_add failed");
288 PRINT_INFO("SPDY_name_value_add failed");
289 abort();
290 }
291 return realsize; 431 return realsize;
292 } 432 }
293 433
@@ -296,10 +436,7 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
296 while(pos<realsize && isspace(line[pos])) ++pos; //remove leading space 436 while(pos<realsize && isspace(line[pos])) ++pos; //remove leading space
297 for(i=pos; i<realsize && '\r'!=line[i]; ++i); 437 for(i=pos; i<realsize && '\r'!=line[i]; ++i);
298 if(NULL == (value = strndup(&(line[pos]), i - pos))) 438 if(NULL == (value = strndup(&(line[pos]), i - pos)))
299 { 439 DIE("No memory");
300 PRINT_INFO("no memory");
301 abort();
302 }
303 if(SPDY_YES != (ret = SPDY_name_value_add(proxy->headers, name, value))) 440 if(SPDY_YES != (ret = SPDY_name_value_add(proxy->headers, name, value)))
304 { 441 {
305 abort_it=true; 442 abort_it=true;
@@ -365,12 +502,8 @@ iterate_cb (void *cls, const char *name, const char * const * value, int num_val
365 line_len += strlen(value[i]); 502 line_len += strlen(value[i]);
366 } 503 }
367 504
368 if(NULL == (line = malloc(line_len))) 505 if(NULL == (line = malloc(line_len)))//no recovery
369 { 506 DIE("No memory");
370 //no recovory
371 PRINT_INFO("no memory");
372 abort();
373 }
374 line[0] = 0; 507 line[0] = 0;
375 508
376 strcat(line, name); 509 strcat(line, name);
@@ -384,11 +517,8 @@ iterate_cb (void *cls, const char *name, const char * const * value, int num_val
384 if(i) strcat(line, ", "); 517 if(i) strcat(line, ", ");
385 strcat(line, value[i]); 518 strcat(line, value[i]);
386 } 519 }
387 if(NULL == (*curl_headers = curl_slist_append(*curl_headers, line))) 520 if(NULL == (*curl_headers = curl_slist_append(*curl_headers, line)))
388 { 521 DIE("curl_slist_append failed");
389 PRINT_INFO("curl_slist_append failed");
390 abort();
391 }
392 free(line); 522 free(line);
393 523
394 return SPDY_YES; 524 return SPDY_YES;
@@ -411,43 +541,54 @@ standard_request_handler(void *cls,
411 (void)host; 541 (void)host;
412 (void)scheme; 542 (void)scheme;
413 543
414 char *url;
415 struct Proxy *proxy; 544 struct Proxy *proxy;
416 int ret; 545 int ret;
546 struct URI *uri;
417 547
418 //printf("received request for '%s %s %s'\n", method, path, version); 548 PRINT_VERBOSE2("received request for '%s %s %s'\n", method, path, version);
419 if(NULL == (proxy = malloc(sizeof(struct Proxy)))) 549 if(NULL == (proxy = malloc(sizeof(struct Proxy))))
420 { 550 DIE("No memory");
421 PRINT_INFO("No memory");
422 abort();
423 }
424 memset(proxy, 0, sizeof(struct Proxy)); 551 memset(proxy, 0, sizeof(struct Proxy));
425 proxy->request = request; 552 proxy->request = request;
426 if(NULL == (proxy->headers = SPDY_name_value_create())) 553 if(NULL == (proxy->headers = SPDY_name_value_create()))
427 { 554 DIE("No memory");
428 PRINT_INFO("No memory"); 555
429 abort(); 556 if(glob_opt.transparent)
430 } 557 {
431 558 if(NULL != glob_opt.http_backend) //use always same host
432 //TODO add https 559 ret = asprintf(&(proxy->url),"%s://%s%s", scheme, glob_opt.http_backend, path);
433 if(0 == strcmp(http_host, "any")) 560 else //use host header
434 ret = asprintf(&url,"%s%s%s","http://", host, path); 561 ret = asprintf(&(proxy->url),"%s://%s%s", scheme, host, path);
435 else 562 if(-1 == ret)
436 ret = asprintf(&url,"%s%s%s","http://", http_host, path); 563 DIE("No memory");
437 564
438 if(-1 == ret) 565 ret = parse_uri(&uri_preg, proxy->url, &uri);
439 { 566 if(ret != 0)
440 PRINT_INFO("No memory"); 567 DIE("parsing built uri failed");
441 abort(); 568 }
442 } 569 else
443 570 {
444 if(NULL == (proxy->path = strdup(path))) 571 ret = parse_uri(&uri_preg, path, &uri);
445 { 572 PRINT_INFO2("path %s '%s' '%s'", path, uri->scheme, uri->host);
446 PRINT_INFO("No memory"); 573 if(ret != 0 || !strlen(uri->scheme) || !strlen(uri->host))
447 abort(); 574 DIE("parsing received uri failed");
448 } 575
576 if(NULL != glob_opt.http_backend) //use backend host
577 {
578 ret = asprintf(&(proxy->url),"%s://%s%s", uri->scheme, glob_opt.http_backend, uri->path_and_more);
579 if(-1 == ret)
580 DIE("No memory");
581 }
582 else //use request path
583 if(NULL == (proxy->url = strdup(path)))
584 DIE("No memory");
585 }
586
587 free(uri);
588
589 PRINT_VERBOSE2("curl will request '%s'", proxy->url);
449 590
450 SPDY_name_value_iterate(headers, &iterate_cb, proxy); 591 SPDY_name_value_iterate(headers, &iterate_cb, proxy);
451 592
452 if(NULL == (proxy->curl_handle = curl_easy_init())) 593 if(NULL == (proxy->curl_handle = curl_easy_init()))
453 { 594 {
@@ -455,10 +596,10 @@ standard_request_handler(void *cls,
455 abort(); 596 abort();
456 } 597 }
457 598
458 //CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1); 599 if(glob_opt.curl_verbose)
459 CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, url); 600 CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1);
460 free(url); 601 CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url);
461 if(http10) 602 if(glob_opt.http10)
462 CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 603 CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
463 CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEFUNCTION, curl_write_cb); 604 CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEFUNCTION, curl_write_cb);
464 CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEDATA, proxy); 605 CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEDATA, proxy);
@@ -484,9 +625,9 @@ standard_request_handler(void *cls,
484} 625}
485 626
486int 627int
487main (int argc, char *const *argv) 628run()
488{ 629{
489 unsigned long long timeoutlong=0; 630 unsigned long long timeoutlong=0;
490 long curl_timeo = -1; 631 long curl_timeo = -1;
491 struct timeval timeout; 632 struct timeval timeout;
492 int ret; 633 int ret;
@@ -504,20 +645,18 @@ main (int argc, char *const *argv)
504 645
505 signal(SIGPIPE, SIG_IGN); 646 signal(SIGPIPE, SIG_IGN);
506 647
507 if(argc != 6) 648 if (signal(SIGINT, catch_signal) == SIG_ERR)
508 { 649 PRINT_VERBOSE("signal failed");
509 printf("Usage: %s cert-file key-file host port http/1.0(yes/no)\n\ 650
510\n\ 651 srand(time(NULL));
511Example for transparent proxy (':host' header is used to know which HTTP server to connect):\n\ 652 if(init_parse_uri(&uri_preg))
512%s cert.pem key.pem any 8080 no\n", argv[0], argv[0]); 653 DIE("Regexp compilation failed");
513 return 1; 654
514 }
515
516 SPDY_init(); 655 SPDY_init();
517 656
518 daemon = SPDY_start_daemon(atoi(argv[4]), 657 daemon = SPDY_start_daemon(glob_opt.listen_port,
519 argv[1], 658 glob_opt.cert,
520 argv[2], 659 glob_opt.cert_key,
521 NULL, 660 NULL,
522 NULL, 661 NULL,
523 &standard_request_handler, 662 &standard_request_handler,
@@ -533,21 +672,13 @@ Example for transparent proxy (':host' header is used to know which HTTP server
533 } 672 }
534 673
535 multi_handle = curl_multi_init(); 674 multi_handle = curl_multi_init();
536 675 if(NULL==multi_handle)
537 if(NULL==multi_handle){ 676 DIE("no multi_handle");
538 PRINT_INFO("no multi_handle"); 677
539 abort();
540 }
541
542 if(!strcmp("yes", argv[5]))
543 http10 = 1;
544
545 http_host = argv[3];
546 timeout.tv_usec = 0; 678 timeout.tv_usec = 0;
547 679
548 do 680 do
549 { 681 {
550 //printf("still %i\n", still_running);
551 FD_ZERO(&rs); 682 FD_ZERO(&rs);
552 FD_ZERO(&ws); 683 FD_ZERO(&ws);
553 FD_ZERO(&es); 684 FD_ZERO(&es);
@@ -653,14 +784,129 @@ Example for transparent proxy (':host' header is used to know which HTTP server
653 else PRINT_INFO("shouldn't happen"); 784 else PRINT_INFO("shouldn't happen");
654 } 785 }
655 } 786 }
656 while(run); 787 while(loop);
657 788
658 curl_multi_cleanup(multi_handle); 789 curl_multi_cleanup(multi_handle);
659 790
660 SPDY_stop_daemon(daemon); 791 SPDY_stop_daemon(daemon);
661 792
662 SPDY_deinit(); 793 SPDY_deinit();
794
795 deinit_parse_uri(&uri_preg);
663 796
664 return 0; 797 return 0;
665} 798}
666 799
800void
801display_usage()
802{
803 printf(
804 "Usage: microspdy2http [-vh0t] [-b <HTTP-SERVER>] -p <PORT> -c <CERTIFICATE> -k <CERT-KEY>\n\n"
805 "OPTIONS:\n"
806 " -p, --port Listening port.\n"
807 " -c, --certificate Path to a certificate file.\n"
808 " -k, --certificate-key Path to a key file for the certificate.\n"
809 " -b, --backend-server If set, the proxy will connect always to it.\n"
810 " Otherwise the proxy will connect to the URL\n"
811 " which is specified in the path or 'Host:'.\n"
812 " -v, --verbose Print debug information.\n"
813 " -h, --curl-verbose Print debug information for curl.\n"
814 " -0, --http10 Prefer HTTP/1.0 connections to the next hop.\n"
815 " -t, --transparent If set, the proxy will fetch an URL which\n"
816 " is based on 'Host:' header and requested path.\n"
817 " Otherwise, full URL in the requested path is required.\n\n"
818
819 );
820}
821
822int
823main (int argc, char *const *argv)
824{
825
826 int getopt_ret;
827 int option_index;
828 struct option long_options[] = {
829 {"port", required_argument, 0, 'p'},
830 {"certificate", required_argument, 0, 'c'},
831 {"certificate-key", required_argument, 0, 'k'},
832 {"backend-server", required_argument, 0, 'b'},
833 {"verbose", no_argument, 0, 'v'},
834 {"curl-verbose", no_argument, 0, 'h'},
835 {"http10", no_argument, 0, '0'},
836 {"transparent", no_argument, 0, 't'},
837 {0, 0, 0, 0}
838 };
839
840 while (1)
841 {
842 getopt_ret = getopt_long( argc, argv, "p:c:k:b:v0t", long_options, &option_index);
843 if (getopt_ret == -1)
844 break;
845
846 switch(getopt_ret)
847 {
848 case 'p':
849 glob_opt.listen_port = atoi(optarg);
850 break;
851
852 case 'c':
853 glob_opt.cert = strdup(optarg);
854 if(NULL == glob_opt.cert)
855 return 1;
856 break;
857
858 case 'k':
859 glob_opt.cert_key = strdup(optarg);
860 if(NULL == glob_opt.cert_key)
861 return 1;
862 break;
863
864 case 'b':
865 glob_opt.http_backend = strdup(optarg);
866 if(NULL == glob_opt.http_backend)
867 return 1;
868 break;
869
870 case 'v':
871 glob_opt.verbose = true;
872 break;
873
874 case 'h':
875 glob_opt.curl_verbose = true;
876 break;
877
878 case '0':
879 glob_opt.http10 = true;
880 break;
881
882 case 't':
883 glob_opt.transparent = true;
884 break;
885
886 case 0:
887 PRINT_INFO("0 from getopt");
888 break;
889
890 case '?':
891 display_usage();
892 return 1;
893
894 default:
895 DIE("default from getopt");
896 }
897 }
898
899 if(
900 0 == glob_opt.listen_port
901 || NULL == glob_opt.cert
902 || NULL == glob_opt.cert_key
903 //|| !glob_opt.transparent && NULL != glob_opt.http_backend
904 )
905 {
906 display_usage();
907 return 1;
908 }
909
910 return run();
911}
912