1/*
2 * lws-minimal-secure-streams-cpp
3 *
4 * Written in 2020 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 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
17static int interrupted, bad = 1, concurrent = 1, completed;
18
19static int
20lss_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
39static void
40sigint_handler(int sig)
41{
42	interrupted = 1;
43}
44
45int 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