• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * libwebsockets - small server side websockets and web server implementation
3   *
4   * Copyright (C) 2010 - 2019 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  
25  #include "private-lib-core.h"
26  #include "private-lib-abstract.h"
27  
28  typedef struct lws_abstxp_raw_skt_priv {
29  	struct lws_abs *abs;
30  	struct lws *wsi;
31  
32  	lws_dll2_t same_abs_transport_list;
33  
34  	uint8_t established:1;
35  	uint8_t connecting:1;
36  } abs_raw_skt_priv_t;
37  
38  struct vhd {
39  	lws_dll2_owner_t owner;
40  };
41  
42  static int
heartbeat_cb(struct lws_dll2 * d,void * user)43  heartbeat_cb(struct lws_dll2 *d, void *user)
44  {
45  	abs_raw_skt_priv_t *priv = lws_container_of(d, abs_raw_skt_priv_t,
46  						    same_abs_transport_list);
47  
48  	if (priv->abs->ap->heartbeat)
49  		priv->abs->ap->heartbeat(priv->abs->api);
50  
51  	return 0;
52  }
53  
54  static int
callback_abs_client_raw_skt(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)55  callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,
56  			    void *user, void *in, size_t len)
57  {
58  	abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)user;
59  	struct vhd *vhd = (struct vhd *)
60  		lws_protocol_vh_priv_get(lws_get_vhost(wsi),
61  					 lws_get_protocol(wsi));
62  
63  	switch (reason) {
64  	case LWS_CALLBACK_PROTOCOL_INIT:
65  		vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
66  				lws_get_protocol(wsi), sizeof(struct vhd));
67  		if (!vhd)
68  			return 1;
69  		lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
70  					       lws_get_protocol(wsi),
71  					       LWS_CALLBACK_USER, 1);
72  		break;
73  
74  	case LWS_CALLBACK_USER:
75  		/*
76  		 * This comes at 1Hz without a wsi context, so there is no
77  		 * valid priv.  We need to track the live abstract objects that
78  		 * are using our abstract protocol, and pass the heartbeat
79  		 * through to the ones that care.
80  		 */
81  		if (!vhd)
82  			break;
83  
84  		lws_dll2_foreach_safe(&vhd->owner, NULL, heartbeat_cb);
85  
86  		lws_timed_callback_vh_protocol(lws_get_vhost(wsi),
87  					       lws_get_protocol(wsi),
88  					       LWS_CALLBACK_USER, 1);
89  		break;
90  
91          case LWS_CALLBACK_RAW_CONNECTED:
92  		lwsl_debug("LWS_CALLBACK_RAW_CONNECTED\n");
93  		priv->connecting = 0;
94  		priv->established = 1;
95  		if (priv->abs->ap->accept)
96  			priv->abs->ap->accept(priv->abs->api);
97  		if (wsi->seq)
98  			/*
99  			 * we are bound to a sequencer who wants to know about
100  			 * our lifecycle events
101  			 */
102  
103  			lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONNECTED,
104  						  wsi, NULL);
105                  break;
106  
107  	case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
108  		lwsl_user("CONNECTION_ERROR\n");
109  		if (in)
110  			lwsl_user("   %s\n", (const char *)in);
111  
112  		if (wsi->seq)
113  			/*
114  			 * we are bound to a sequencer who wants to know about
115  			 * our lifecycle events
116  			 */
117  
118  			lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_FAIL,
119  					    wsi, NULL);
120  
121  		goto close_path;
122  
123  		/* fallthru */
124  	case LWS_CALLBACK_RAW_CLOSE:
125  		if (!user)
126  			break;
127  
128  		if (wsi->seq)
129  			/*
130  			 * we are bound to a sequencer who wants to know about
131  			 * our lifecycle events
132  			 */
133  
134  			lws_seq_queue_event(wsi->seq, LWSSEQ_WSI_CONN_CLOSE,
135  					    wsi, NULL);
136  
137  close_path:
138  		lwsl_debug("LWS_CALLBACK_RAW_CLOSE\n");
139  		priv->established = 0;
140  		priv->connecting = 0;
141  		if (priv->abs && priv->abs->ap->closed)
142  			priv->abs->ap->closed(priv->abs->api);
143  		lws_set_wsi_user(wsi, NULL);
144  		break;
145  
146  	case LWS_CALLBACK_RAW_RX:
147  		lwsl_debug("LWS_CALLBACK_RAW_RX (%d)\n", (int)len);
148  		return !!priv->abs->ap->rx(priv->abs->api, in, len);
149  
150  	case LWS_CALLBACK_RAW_WRITEABLE:
151  		lwsl_debug("LWS_CALLBACK_RAW_WRITEABLE\n");
152  		priv->abs->ap->writeable(priv->abs->api,
153  				lws_get_peer_write_allowance(priv->wsi));
154  		break;
155  
156  	case LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL:
157  		lws_dll2_add_tail(&priv->same_abs_transport_list, &vhd->owner);
158  		break;
159  
160  	case LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL:
161  		lws_dll2_remove(&priv->same_abs_transport_list);
162  		break;
163  
164  	default:
165  		break;
166  	}
167  
168  	return 0;
169  }
170  
171  static int
lws_atcrs_close(lws_abs_transport_inst_t * ati)172  lws_atcrs_close(lws_abs_transport_inst_t *ati)
173  {
174  	abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
175  	struct lws *wsi = priv->wsi;
176  
177  	if (!priv->wsi)
178  		return 0;
179  
180  	if (!lws_raw_transaction_completed(priv->wsi))
181  		return 0;
182  
183  	priv->wsi = NULL;
184  	lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC);
185  
186  	/* priv is destroyed in the CLOSE callback */
187  
188  	return 0;
189  }
190  
191  
192  const struct lws_protocols protocol_abs_client_raw_skt = {
193  	"lws-abs-cli-raw-skt", callback_abs_client_raw_skt,
194  	0, 1024, 1024, NULL, 0
195  };
196  
197  static int
lws_atcrs_tx(lws_abs_transport_inst_t * ati,uint8_t * buf,size_t len)198  lws_atcrs_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len)
199  {
200  	abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
201  
202  	if (!priv->wsi) {
203  		lwsl_err("%s: NULL priv->wsi\n", __func__);
204  		return 1;
205  	}
206  
207  	lwsl_debug("%s: priv %p, wsi %p, ro %p\n", __func__,
208  			priv, priv->wsi, priv->wsi->role_ops);
209  
210  	if (lws_write(priv->wsi, buf, len, LWS_WRITE_RAW) < 0)
211  		lws_atcrs_close(ati);
212  
213  	return 0;
214  }
215  
216  #if defined(LWS_WITH_CLIENT)
217  static int
lws_atcrs_client_conn(const lws_abs_t * abs)218  lws_atcrs_client_conn(const lws_abs_t *abs)
219  {
220  	abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)abs->ati;
221  	struct lws_client_connect_info i;
222  	const lws_token_map_t *tm;
223  
224  	if (priv->connecting)
225  		return 0;
226  
227  	if (priv->established) {
228  		lws_set_timeout(priv->wsi, PENDING_TIMEOUT_CLIENT_CONN_IDLE, 5);
229  
230  		return 0;
231  	}
232  
233  	memset(&i, 0, sizeof(i));
234  
235  	/* address and port are passed-in using the abstract transport tokens */
236  
237  	tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_V_DNS_ADDRESS);
238  	if (!tm) {
239  		lwsl_notice("%s: raw_skt needs LTMI_PEER_V_DNS_ADDRESS\n",
240  			    __func__);
241  
242  		return 1;
243  	}
244  	i.address = tm->u.value;
245  
246  	tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_PORT);
247  	if (!tm) {
248  		lwsl_notice("%s: raw_skt needs LTMI_PEER_LV_PORT\n", __func__);
249  
250  		return 1;
251  	}
252  	i.port = tm->u.lvalue;
253  
254  	/* optional */
255  	i.ssl_connection = 0;
256  	tm = lws_abs_get_token(abs->at_tokens, LTMI_PEER_LV_TLS_FLAGS);
257  	if (tm)
258  		i.ssl_connection = tm->u.lvalue;
259  
260  
261  	lwsl_debug("%s: raw_skt priv %p connecting to %s:%u %p\n",
262  		   __func__, priv, i.address, i.port, abs->vh->context);
263  
264  	i.path = "";
265  	i.method = "RAW";
266  	i.vhost = abs->vh;
267  	i.userdata = priv;
268  	i.host = i.address;
269  	i.pwsi = &priv->wsi;
270  	i.origin = i.address;
271  	i.context = abs->vh->context;
272  	i.local_protocol_name = "lws-abs-cli-raw-skt";
273  	i.seq = abs->seq;
274  	i.opaque_user_data = abs->opaque_user_data;
275  
276  	/*
277  	 * the protocol itself has some natural attributes we should pass on
278  	 */
279  
280  	if (abs->ap->flags & LWS_AP_FLAG_PIPELINE_TRANSACTIONS)
281  		i.ssl_connection |= LCCSCF_PIPELINE;
282  
283  	if (abs->ap->flags & LWS_AP_FLAG_MUXABLE_STREAM)
284  		i.ssl_connection |= LCCSCF_MUXABLE_STREAM;
285  
286  	priv->wsi = lws_client_connect_via_info(&i);
287  	if (!priv->wsi)
288  		return 1;
289  
290  	priv->connecting = 1;
291  
292  	return 0;
293  }
294  #endif
295  
296  static int
lws_atcrs_ask_for_writeable(lws_abs_transport_inst_t * ati)297  lws_atcrs_ask_for_writeable(lws_abs_transport_inst_t *ati)
298  {
299  	abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
300  
301  	if (!priv->wsi || !priv->established)
302  		return 1;
303  
304  	lws_callback_on_writable(priv->wsi);
305  
306  	return 0;
307  }
308  
309  static int
lws_atcrs_create(struct lws_abs * ai)310  lws_atcrs_create(struct lws_abs *ai)
311  {
312  	abs_raw_skt_priv_t *at = (abs_raw_skt_priv_t *)ai->ati;
313  
314  	memset(at, 0, sizeof(*at));
315  	at->abs = ai;
316  
317  	return 0;
318  }
319  
320  static void
lws_atcrs_destroy(lws_abs_transport_inst_t ** pati)321  lws_atcrs_destroy(lws_abs_transport_inst_t **pati)
322  {
323  	/*
324  	 * For ourselves, we don't free anything because the abstract layer
325  	 * combined our allocation with that of the abs instance, and it will
326  	 * free the whole thing after this.
327  	 */
328  	*pati = NULL;
329  }
330  
331  static int
lws_atcrs_set_timeout(lws_abs_transport_inst_t * ati,int reason,int secs)332  lws_atcrs_set_timeout(lws_abs_transport_inst_t *ati, int reason, int secs)
333  {
334  	abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
335  
336  	lws_set_timeout(priv->wsi, reason, secs);
337  
338  	return 0;
339  }
340  
341  static int
lws_atcrs_state(lws_abs_transport_inst_t * ati)342  lws_atcrs_state(lws_abs_transport_inst_t *ati)
343  {
344  	abs_raw_skt_priv_t *priv = (abs_raw_skt_priv_t *)ati;
345  
346  	if (!priv || !priv->wsi || (!priv->established && !priv->connecting))
347  		return 0;
348  
349  	return 1;
350  }
351  
352  static int
lws_atcrs_compare(lws_abs_t * abs1,lws_abs_t * abs2)353  lws_atcrs_compare(lws_abs_t *abs1, lws_abs_t *abs2)
354  {
355  	const lws_token_map_t *tm1, *tm2;
356  
357  	tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_V_DNS_ADDRESS);
358  	tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_V_DNS_ADDRESS);
359  
360  	/* Address token is mandatory and must match */
361  	if (!tm1 || !tm2 || strcmp(tm1->u.value, tm2->u.value))
362  		return 1;
363  
364  	/* Port token is mandatory and must match */
365  	tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_LV_PORT);
366  	tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_LV_PORT);
367  	if (!tm1 || !tm2 || tm1->u.lvalue != tm2->u.lvalue)
368  		return 1;
369  
370  	/* TLS is optional... */
371  	tm1 = lws_abs_get_token(abs1->at_tokens, LTMI_PEER_LV_TLS_FLAGS);
372  	tm2 = lws_abs_get_token(abs2->at_tokens, LTMI_PEER_LV_TLS_FLAGS);
373  
374  	/* ... but both must have the same situation with it given or not... */
375  	if (!!tm1 != !!tm2)
376  		return 1;
377  
378  	/* if not using TLS, then that's enough to call it */
379  	if (!tm1)
380  		return 0;
381  
382  	/* ...and if there are tls flags, both must have the same tls flags */
383  	if (tm1->u.lvalue != tm2->u.lvalue)
384  		return 1;
385  
386  	/* ... and both must use the same client tls ctx / vhost */
387  	return abs1->vh != abs2->vh;
388  }
389  
390  const lws_abs_transport_t lws_abs_transport_cli_raw_skt = {
391  	.name			= "raw_skt",
392  	.alloc			= sizeof(abs_raw_skt_priv_t),
393  
394  	.create			= lws_atcrs_create,
395  	.destroy		= lws_atcrs_destroy,
396  	.compare		= lws_atcrs_compare,
397  
398  	.tx			= lws_atcrs_tx,
399  #if !defined(LWS_WITH_CLIENT)
400  	.client_conn		= NULL,
401  #else
402  	.client_conn		= lws_atcrs_client_conn,
403  #endif
404  	.close			= lws_atcrs_close,
405  	.ask_for_writeable	= lws_atcrs_ask_for_writeable,
406  	.set_timeout		= lws_atcrs_set_timeout,
407  	.state			= lws_atcrs_state,
408  };
409