1 /*
2  * lws-minimal-secure-streams-cpp
3  *
4  * Written in 2020 by Andy Green <[email protected]>
5  *
6  * This file is made available under the Creative Commons CC0 1.0
7  * Universal Public Domain Dedication.
8  *
9  * This demonstrates a minimal http client using secure streams C++ api to
10  * fetch files over https to the local filesystem
11  */
12 
13 #include <libwebsockets.hxx>
14 #include <string.h>
15 #include <signal.h>
16 
17 static int interrupted, bad = 1, concurrent = 1, completed;
18 
19 static int
lss_completion(lss * lss,lws_ss_constate_t state,void * arg)20 lss_completion(lss *lss, lws_ss_constate_t state, void *arg)
21 {
22 	lssFile *lf = (lssFile *)lss;
23 
24 	if (state == LWSSSCS_QOS_ACK_REMOTE) {
25 		lwsl_notice("%s: %s: len %llu, done OK %dms\n", __func__,
26 			    lf->path.c_str(), (unsigned long long)lf->rxlen,
27 			    (int)((lws_now_usecs() - lf->us_start) / 1000));
28 	} else
29 		lwsl_notice("%s: %s: failed\n", __func__, lf->path.c_str());
30 
31 	if (++completed == concurrent) {
32 		interrupted = 1;
33 		bad = 0;
34 	}
35 
36 	return 0;
37 }
38 
39 static void
sigint_handler(int sig)40 sigint_handler(int sig)
41 {
42 	interrupted = 1;
43 }
44 
main(int argc,const char ** argv)45 int main(int argc, const char **argv)
46 {
47 	struct lws_context_creation_info info;
48 	struct lws_context *context;
49 	const char *p;
50 
51 	signal(SIGINT, sigint_handler);
52 
53 	memset(&info, 0, sizeof info);
54 	lws_cmdline_option_handle_builtin(argc, argv, &info);
55 
56 	if ((p = lws_cmdline_option(argc, argv, "-c")))
57 		concurrent = atoi(p);
58 
59 	if (concurrent > 12)
60 		concurrent = 12;
61 
62 	lwsl_user("LWS secure streams cpp test client "
63 			"[-d<verb>] [-c<concurrent>]\n");
64 
65 	info.fd_limit_per_thread = 1 + 12 + 1;
66 	info.port = CONTEXT_PORT_NO_LISTEN;
67 	info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
68 
69 	/* create the context */
70 
71 	context = lws_create_context(&info);
72 	if (!context) {
73 		lwsl_err("lws init failed\n");
74 		return 1;
75 	}
76 
77 	try {
78 
79 		for (int n = 0; n < concurrent; n++) {
80 			std::string url, filepath;
81 
82 			url = "https://warmcat.com/test-";
83 			url += ('a' + n);
84 			url += ".bin";
85 
86 			filepath = "/tmp/test-";
87 			filepath += ('a' + n);
88 			filepath += ".bin";
89 
90 			new lssFile(context, url, filepath, lss_completion, 0);
91 		}
92 	} catch (std::exception &e) {
93 		lwsl_err("%s: failed to create ss: %s\n", __func__, e.what());
94 		interrupted = 1;
95 	}
96 
97 	/* the event loop */
98 
99 	while (!interrupted && lws_service(context, 0) >= 0)
100 		;
101 
102 	lws_context_destroy(context);
103 
104 	lwsl_user("Completed: %s\n", bad ? "failed" : "OK");
105 
106 	return bad;
107 }
108