Imported Upstream version 3.2
[platform/upstream/libwebsockets.git] / minimal-examples / http-client / minimal-http-client-hugeurl / minimal-http-client-hugeurl.c
1 /*
2  * lws-minimal-http-client hugeurl
3  *
4  * Written in 2010-2019 by Andy Green <andy@warmcat.com>
5  *
6  * This file is made available under the Creative Commons CC0 1.0
7  * Universal Public Domain Dedication.
8  *
9  * This demonstrates the a minimal http client using lws.
10  *
11  * It visits https://warmcat.com/?fakeparam=<2KB> and receives the html
12  * page there.  You can dump the page data by changing the #if 0 below.
13  */
14
15 #include <libwebsockets.h>
16 #include <string.h>
17 #include <signal.h>
18
19 static int interrupted, bad = 1, status;
20 static struct lws *client_wsi;
21
22 static const char * const uri =
23         "/?fakeparam="
24         "00000000000000000000000000000000000000000000000000"
25         "00000000000000000000000000000000000000000000000000"
26         "00000000000000000000000000000000000000000000000000"
27         "00000000000000000000000000000000000000000000000000"
28         "00000000000000000000000000000000000000000000000000"
29         "00000000000000000000000000000000000000000000000000"
30         "00000000000000000000000000000000000000000000000000"
31         "00000000000000000000000000000000000000000000000000"
32         "00000000000000000000000000000000000000000000000000"
33         "00000000000000000000000000000000000000000000000000" /* 500 */
34         "11111111111111111111111111111111111111111111111111"
35         "11111111111111111111111111111111111111111111111111"
36         "11111111111111111111111111111111111111111111111111"
37         "11111111111111111111111111111111111111111111111111"
38         "11111111111111111111111111111111111111111111111111"
39         "11111111111111111111111111111111111111111111111111"
40         "11111111111111111111111111111111111111111111111111"
41         "11111111111111111111111111111111111111111111111111"
42         "11111111111111111111111111111111111111111111111111"
43         "11111111111111111111111111111111111111111111111111" /* 1000 */
44         "22222222222222222222222222222222222222222222222222"
45         "22222222222222222222222222222222222222222222222222"
46         "22222222222222222222222222222222222222222222222222"
47         "22222222222222222222222222222222222222222222222222"
48         "22222222222222222222222222222222222222222222222222"
49         "22222222222222222222222222222222222222222222222222"
50         "22222222222222222222222222222222222222222222222222"
51         "22222222222222222222222222222222222222222222222222"
52         "22222222222222222222222222222222222222222222222222"
53         "22222222222222222222222222222222222222222222222222" /* 1500 */
54         "33333333333333333333333333333333333333333333333333"
55         "33333333333333333333333333333333333333333333333333"
56         "33333333333333333333333333333333333333333333333333"
57         "33333333333333333333333333333333333333333333333333"
58         "33333333333333333333333333333333333333333333333333"
59         "33333333333333333333333333333333333333333333333333"
60         "33333333333333333333333333333333333333333333333333"
61         "33333333333333333333333333333333333333333333333333"
62         "33333333333333333333333333333333333333333333333333"
63         "33333333333333333333333333333333333333333333333333" /* 2000 */
64 ;
65
66 static int
67 callback_http(struct lws *wsi, enum lws_callback_reasons reason,
68               void *user, void *in, size_t len)
69 {
70         switch (reason) {
71
72         /* because we are protocols[0] ... */
73         case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
74                 lwsl_err("CLIENT_CONNECTION_ERROR: %s\n",
75                          in ? (char *)in : "(null)");
76                 client_wsi = NULL;
77                 break;
78
79         case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
80                 status = lws_http_client_http_response(wsi);
81                 lwsl_user("Connected with server response: %d\n", status);
82                 break;
83
84         /* chunks of chunked content, with header removed */
85         case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
86                 lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len);
87 #if 0  /* enable to dump the html */
88                 {
89                         const char *p = in;
90
91                         while (len--)
92                                 if (*p < 0x7f)
93                                         putchar(*p++);
94                                 else
95                                         putchar('.');
96                 }
97 #endif
98                 return 0; /* don't passthru */
99
100         /* uninterpreted http content */
101         case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
102                 {
103                         char buffer[1024 + LWS_PRE];
104                         char *px = buffer + LWS_PRE;
105                         int lenx = sizeof(buffer) - LWS_PRE;
106
107                         if (lws_http_client_read(wsi, &px, &lenx) < 0)
108                                 return -1;
109                 }
110                 return 0; /* don't passthru */
111
112         case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
113                 client_wsi = NULL;
114                 bad = status != 200;
115                 lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
116                 break;
117
118         case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
119                 client_wsi = NULL;
120                 bad = status != 200;
121                 lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
122                 break;
123
124         default:
125                 break;
126         }
127
128         return lws_callback_http_dummy(wsi, reason, user, in, len);
129 }
130
131 static const struct lws_protocols protocols[] = {
132         {
133                 "http",
134                 callback_http,
135                 0,
136                 0,
137         },
138         { NULL, NULL, 0, 0 }
139 };
140
141 static void
142 sigint_handler(int sig)
143 {
144         interrupted = 1;
145 }
146
147 int main(int argc, const char **argv)
148 {
149         struct lws_context_creation_info info;
150         struct lws_client_connect_info i;
151         struct lws_context *context;
152         const char *p;
153         int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
154                         /* for LLL_ verbosity above NOTICE to be built into lws,
155                          * lws must have been configured and built with
156                          * -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
157                         /* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
158                         /* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
159                         /* | LLL_DEBUG */;
160
161         if ((p = lws_cmdline_option(argc, argv, "-d")))
162                 logs = atoi(p);
163
164         signal(SIGINT, sigint_handler);
165         lws_set_log_level(logs, NULL);
166         lwsl_user("LWS minimal http client hugeurl [-d <verbosity>] [-l] [--h1]\n");
167
168         memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
169         info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
170         info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
171         info.protocols = protocols;
172         /*
173          * since we know this lws context is only ever going to be used with
174          * one client wsis / fds / sockets at a time, let lws know it doesn't
175          * have to use the default allocations for fd tables up to ulimit -n.
176          * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we
177          * will use.
178          */
179         info.fd_limit_per_thread = 1 + 1 + 1;
180
181 #if defined(LWS_WITH_MBEDTLS)
182         /*
183          * OpenSSL uses the system trust store.  mbedTLS has to be told which
184          * CA to trust explicitly.
185          */
186         info.client_ssl_ca_filepath = "./warmcat.com.cer";
187 #endif
188
189         context = lws_create_context(&info);
190         if (!context) {
191                 lwsl_err("lws init failed\n");
192                 return 1;
193         }
194
195         memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
196         i.context = context;
197         i.ssl_connection = LCCSCF_USE_SSL;
198
199         if (lws_cmdline_option(argc, argv, "-l")) {
200                 i.port = 7681;
201                 i.address = "localhost";
202                 i.ssl_connection |= LCCSCF_ALLOW_SELFSIGNED;
203         } else {
204                 i.port = 443;
205                 i.address = "warmcat.com";
206         }
207
208         if (lws_cmdline_option(argc, argv, "--h1"))
209                 i.alpn = "http/1.1";
210
211         i.path = uri;
212         i.host = i.address;
213         i.origin = i.address;
214         i.method = "GET";
215         i.protocol = protocols[0].name;
216         i.pwsi = &client_wsi;
217
218         lws_client_connect_via_info(&i);
219
220         while (n >= 0 && client_wsi && !interrupted)
221                 n = lws_service(context, 0);
222
223         lws_context_destroy(context);
224         lwsl_user("Completed: %s\n", bad? "failed": "OK");
225
226         return bad;
227 }