1 /*
2 * Captive portal detect for Secure Streams
3 *
4 * libwebsockets - small server side websockets and web server implementation
5 *
6 * Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to
10 * deal in the Software without restriction, including without limitation the
11 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 * sell copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 */
26
27 #include <private-lib-core.h>
28
29 typedef struct ss_cpd {
30 struct lws_ss_handle *ss;
31 void *opaque_data;
32 /* ... application specific state ... */
33
34 lws_sorted_usec_list_t sul;
35 } ss_cpd_t;
36
37 static lws_ss_state_return_t
ss_cpd_state(void * userobj,void * sh,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)38 ss_cpd_state(void *userobj, void *sh, lws_ss_constate_t state,
39 lws_ss_tx_ordinal_t ack)
40 {
41 ss_cpd_t *m = (ss_cpd_t *)userobj;
42 struct lws_context *cx = (struct lws_context *)m->opaque_data;
43
44 lwsl_ss_info(m->ss, "%s, ord 0x%x\n", lws_ss_state_name((int)state),
45 (unsigned int)ack);
46
47 switch (state) {
48 case LWSSSCS_CREATING:
49 lws_ss_start_timeout(m->ss, 3 * LWS_US_PER_SEC);
50 return lws_ss_request_tx(m->ss);
51
52 case LWSSSCS_QOS_ACK_REMOTE:
53 lws_system_cpd_set(cx, LWS_CPD_INTERNET_OK);
54 cx->ss_cpd = NULL;
55 return LWSSSSRET_DESTROY_ME;
56
57 case LWSSSCS_TIMEOUT:
58 case LWSSSCS_ALL_RETRIES_FAILED:
59 case LWSSSCS_DISCONNECTED:
60 /*
61 * First result reported sticks... if nothing else, this will
62 * cover the situation we didn't connect to anything
63 */
64 lws_system_cpd_set(cx, LWS_CPD_NO_INTERNET);
65 cx->ss_cpd = NULL;
66 return LWSSSSRET_DESTROY_ME;
67
68 default:
69 break;
70 }
71
72 return LWSSSSRET_OK;
73 }
74
75 static const lws_ss_info_t ssi_cpd = {
76 .handle_offset = offsetof(ss_cpd_t, ss),
77 .opaque_user_data_offset = offsetof(ss_cpd_t, opaque_data),
78 .state = ss_cpd_state,
79 .user_alloc = sizeof(ss_cpd_t),
80 .streamtype = "captive_portal_detect",
81 };
82
83 int
lws_ss_sys_cpd(struct lws_context * cx)84 lws_ss_sys_cpd(struct lws_context *cx)
85 {
86 if (cx->ss_cpd) {
87 lwsl_cx_notice(cx, "CPD already ongoing");
88 return 0;
89 }
90
91 if (lws_ss_create(cx, 0, &ssi_cpd, cx, &cx->ss_cpd, NULL, NULL)) {
92 lwsl_cx_info(cx, "Create stream failed (policy?)");
93
94 return 1;
95 }
96
97 return 0;
98 }
99