X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuclient.git;a=blobdiff_plain;f=uclient-example.c;h=e0e90153d45f01cb13d337b12e726205c823c43a;hp=b66468a7fb7a598be5ad8506ebb1a965afbfa776;hb=bd38e778dc28dbf3e5f0a249689fad2b2c6b7243;hpb=c280d54e1bc79de4424fabc3fad011cc15587b81 diff --git a/uclient-example.c b/uclient-example.c index b66468a..e0e9015 100644 --- a/uclient-example.c +++ b/uclient-example.c @@ -1,18 +1,57 @@ +/* + * uclient - ustream based protocol client library + * + * Copyright (C) 2014 Felix Fietkau + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + #include #include "uclient.h" +#ifdef __APPLE__ +#define LIB_EXT "dylib" +#else +#define LIB_EXT "so" +#endif + +static struct ustream_ssl_ctx *ssl_ctx; +static const struct ustream_ssl_ops *ssl_ops; + static void example_header_done(struct uclient *cl) { struct blob_attr *cur; + char local[INET6_ADDRSTRLEN], remote[INET6_ADDRSTRLEN]; + int local_port, remote_port; int rem; - fprintf(stderr, "Headers: \n"); + uclient_get_addr(local, &local_port, &cl->local_addr); + uclient_get_addr(remote, &remote_port, &cl->remote_addr); + + fprintf(stderr, "Connected: %s:%d -> %s:%d\n", + local, local_port, remote, remote_port); + + printf("Headers (%d): \n", cl->status_code); blobmsg_for_each_attr(cur, cl->meta, rem) { - fprintf(stderr, "%s=%s\n", blobmsg_name(cur), (char *) blobmsg_data(cur)); + printf("%s=%s\n", blobmsg_name(cur), (char *) blobmsg_data(cur)); } - fprintf(stderr, "Contents:\n"); + printf("Contents:\n"); } static void example_read_data(struct uclient *cl) @@ -25,7 +64,7 @@ static void example_read_data(struct uclient *cl) if (!len) return; - fwrite(buf, len, 1, stderr); + write(STDOUT_FILENO, buf, len); } } @@ -45,7 +84,6 @@ static void example_request_sm(struct uclient *cl) uclient_request(cl); break; default: - uclient_free(cl); uloop_end(); break; }; @@ -53,6 +91,20 @@ static void example_request_sm(struct uclient *cl) static void example_eof(struct uclient *cl) { + static int retries; + + if (retries < 10 && uclient_http_redirect(cl)) { + retries++; + return; + } + + retries = 0; + example_request_sm(cl); +} + +static void example_error(struct uclient *cl, int code) +{ + fprintf(stderr, "Error %d!\n", code); example_request_sm(cl); } @@ -60,26 +112,94 @@ static const struct uclient_cb cb = { .header_done = example_header_done, .data_read = example_read_data, .data_eof = example_eof, + .error = example_error, }; +static int usage(const char *progname) +{ + fprintf(stderr, + "Usage: %s [options] \n" + "Options:\n" + " -c : Load CA certificates from file \n" + " -C: Skip certificate CN verification against hostname\n" + "\n", progname); + return 1; +} + + +static void init_ustream_ssl(void) +{ + void *dlh; + + dlh = dlopen("libustream-ssl." LIB_EXT, RTLD_LAZY | RTLD_LOCAL); + if (!dlh) + return; + + ssl_ops = dlsym(dlh, "ustream_ssl_ops"); + if (!ssl_ops) + return; + + ssl_ctx = ssl_ops->context_new(false); +} + +static int no_ssl(const char *progname) +{ + fprintf(stderr, "%s: SSL support not available, please install ustream-ssl\n", progname); + return 1; +} + + int main(int argc, char **argv) { + const char *progname = argv[0]; struct uclient *cl; + bool verify = true; + int ch; - if (argc != 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); - return 1; + init_ustream_ssl(); + + while ((ch = getopt(argc, argv, "Cc:")) != -1) { + switch(ch) { + case 'c': + if (ssl_ctx) + ssl_ops->context_add_ca_crt_file(ssl_ctx, optarg); + break; + case 'C': + verify = false; + break; + default: + return usage(progname); + } } + argv += optind; + argc -= optind; + + if (argc != 1) + return usage(progname); + + if (!strncmp(argv[0], "https", 5) && !ssl_ctx) + return no_ssl(progname); + uloop_init(); - cl = uclient_new(argv[1], &cb); + + cl = uclient_new(argv[0], NULL, &cb); if (!cl) { fprintf(stderr, "Failed to allocate uclient context\n"); return 1; } + + if (ssl_ctx) + uclient_http_set_ssl_ctx(cl, ssl_ops, ssl_ctx, verify); + example_request_sm(cl); uloop_run(); uloop_done(); + uclient_free(cl); + + if (ssl_ctx) + ssl_ops->context_free(ssl_ctx); + return 0; }