• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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