• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  * This is the glue that wires up raw-socket to Secure Streams.
25  */
26 
27 #include <private-lib-core.h>
28 
29 int
secstream_raw(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)30 secstream_raw(struct lws *wsi, enum lws_callback_reasons reason, void *user,
31 	      void *in, size_t len)
32 {
33 #if defined(LWS_WITH_SERVER)
34 	struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
35 #endif
36 	lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi);
37 	uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE],
38 		*end = &buf[sizeof(buf) - 1];
39 	lws_ss_state_return_t r;
40 	size_t buflen;
41 	int f = 0;
42 
43 	switch (reason) {
44 
45 	case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
46 		assert(h);
47 		assert(h->policy);
48 		lwsl_info("%s: %s, %s CLIENT_CONNECTION_ERROR: %s\n", __func__,
49 			  lws_ss_tag(h), h->policy->streamtype, in ? (char *)in : "(null)");
50 
51 #if defined(LWS_WITH_CONMON)
52 		lws_conmon_ss_json(h);
53 #endif
54 
55 		r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE);
56 		if (r == LWSSSSRET_DESTROY_ME)
57 			return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h);
58 		h->wsi = NULL;
59 		r = lws_ss_backoff(h);
60 		if (r != LWSSSSRET_OK)
61 			return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h);
62 		break;
63 
64 	case LWS_CALLBACK_RAW_CLOSE:
65 		if (!h)
66 			break;
67 		lws_sul_cancel(&h->sul_timeout);
68 
69 #if defined(LWS_WITH_CONMON)
70 		lws_conmon_ss_json(h);
71 #endif
72 
73 		lwsl_info("%s: %s, %s RAW_CLOSE\n", __func__, lws_ss_tag(h),
74 			  h->policy ? h->policy->streamtype : "no policy");
75 		h->wsi = NULL;
76 #if defined(LWS_WITH_SERVER)
77 		lws_pt_lock(pt, __func__);
78 		lws_dll2_remove(&h->cli_list);
79 		lws_pt_unlock(pt);
80 #endif
81 
82 		/* wsi is going down anyway */
83 		r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED);
84 		if (r == LWSSSSRET_DESTROY_ME)
85 			return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h);
86 
87 		if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) &&
88 #if defined(LWS_WITH_SERVER)
89 			    !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */
90 #endif
91 		    !h->txn_ok && !wsi->a.context->being_destroyed) {
92 			r = lws_ss_backoff(h);
93 			if (r != LWSSSSRET_OK)
94 				return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h);
95 			break;
96 		}
97 
98 		break;
99 
100 	case LWS_CALLBACK_RAW_CONNECTED:
101 		lwsl_info("%s: RAW_CONNECTED\n", __func__);
102 
103 		h->retry = 0;
104 		h->seqstate = SSSEQ_CONNECTED;
105 		lws_sul_cancel(&h->sul);
106 #if defined(LWS_WITH_SYS_METRICS)
107 		/*
108 		 * If any hanging caliper measurement, dump it, and free any tags
109 		 */
110 		lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL);
111 #endif
112 		r = lws_ss_event_helper(h, LWSSSCS_CONNECTED);
113 		if (r != LWSSSSRET_OK)
114 			return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h);
115 
116 		lws_validity_confirmed(wsi);
117 		break;
118 
119 	case LWS_CALLBACK_RAW_ADOPT:
120 		lwsl_info("%s: RAW_ADOPT\n", __func__);
121 		break;
122 
123 	/* chunks of chunked content, with header removed */
124 	case LWS_CALLBACK_RAW_RX:
125 		if (!h || !h->info.rx)
126 			return 0;
127 
128 		r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, 0);
129 		if (r != LWSSSSRET_OK)
130 			return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h);
131 
132 		return 0; /* don't passthru */
133 
134 	case LWS_CALLBACK_RAW_WRITEABLE:
135 		lwsl_info("%s: RAW_WRITEABLE\n", __func__);
136 		if (!h || !h->info.tx)
137 			return 0;
138 
139 		buflen = lws_ptr_diff_size_t(end, p);
140 		r = h->info.tx(ss_to_userobj(h),  h->txord++, p, &buflen, &f);
141 		if (r == LWSSSSRET_TX_DONT_SEND)
142 			return 0;
143 		if (r < 0)
144 			return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h);
145 
146 		/*
147 		 * flags are ignored with raw, there are no protocol payload
148 		 * boundaries, just an arbitrarily-fragmented bytestream
149 		 */
150 
151 		p += buflen;
152 		if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff_size_t(p, buf + LWS_PRE),
153 			 LWS_WRITE_HTTP) != lws_ptr_diff(p, buf + LWS_PRE)) {
154 			lwsl_err("%s: write failed\n", __func__);
155 			return -1;
156 		}
157 
158 		lws_set_timeout(wsi, 0, 0);
159 		break;
160 
161 	default:
162 		break;
163 	}
164 
165 	return 0;
166 }
167 
168 static int
secstream_connect_munge_raw(lws_ss_handle_t * h,char * buf,size_t len,struct lws_client_connect_info * i,union lws_ss_contemp * ct)169 secstream_connect_munge_raw(lws_ss_handle_t *h, char *buf, size_t len,
170 			   struct lws_client_connect_info *i,
171 			   union lws_ss_contemp *ct)
172 {
173 	i->method = "RAW";
174 
175 	return 0;
176 }
177 
178 
179 const struct lws_protocols protocol_secstream_raw = {
180 	"lws-secstream-raw",
181 	secstream_raw,
182 	0,
183 	0,
184 	0, NULL, 0
185 };
186 
187 const struct ss_pcols ss_pcol_raw = {
188 	"raw",
189 	"",
190 	&protocol_secstream_raw,
191 	secstream_connect_munge_raw,
192 	NULL, NULL
193 };
194