• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * libwebsockets - small server side websockets and web server implementation
3   *
4   * Copyright (C) 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   * C++ classes for Secure Streams
25   */
26  
27  #include <libwebsockets.hxx>
28  
29  static const char *pcols[] = {
30  	"http://",	/* LWSSSP_H1 */
31  	"https://",
32  	"h2://",	/* LWSSSP_H2 */
33  	"h2s://",
34  	"ws://",	/* LWSSSP_WS */
35  	"wss://",
36  	"mqtt://",	/* LWSSSP_MQTT */
37  	"mqtts://",
38  	"raw://",	/* LWSSSP_RAW */
39  	"raws://",
40  };
41  
42  static const uint8_t pcols_len[] = {
43  	7, 8, 5, 6, 5, 6, 7, 8, 6, 7
44  };
45  
46  static const uint16_t pcols_port[] = {
47  	80, 443, 443, 443, 80, 443, 1883, 8883, 80, 443
48  };
49  
lss(lws_ctx_t _ctx,std::string _uri,lsscomp_t _comp,bool _psh,lws_sscb_rx rx,lws_sscb_tx tx,lws_sscb_state state)50  lss::lss(lws_ctx_t _ctx, std::string _uri, lsscomp_t _comp, bool _psh,
51  	 lws_sscb_rx rx, lws_sscb_tx tx, lws_sscb_state state)
52  {
53  	const char *p, *urlpath;
54  	lws_ss_info_t ssi;
55  	int n, port;
56  
57  	memset(&ssi, 0, sizeof(ssi));
58  	memset(&pol, 0, sizeof(pol));
59  
60  	ctx		= _ctx;
61  	comp		= _comp;
62  	comp_done	= 0;
63  	rxlen		= 0;
64  
65  	/*
66  	 * We have a common stub userdata, our "real" userdata is in the
67  	 * derived class members.   The Opaque user pointer points to the
68  	 * lss itself.
69  	 */
70  
71  	ssi.handle_offset	    = offsetof(lssPriv, lssPriv::m_ss);
72  	ssi.opaque_user_data_offset = offsetof(lssPriv, lssPriv::m_plss);
73  
74  	ssi.user_alloc	= sizeof(lssPriv);
75  	ssi.rx		= rx;
76  	ssi.tx		= tx;
77  	ssi.state	= state;
78  	ssi.policy	= &pol; /* we will provide our own policy */
79  
80  	/*
81  	 * _uri is like "https://warmcat.com:443/index.html"... we need to
82  	 * deconstruct it into its policy implications
83  	 */
84  
85  	uri = strdup(_uri.c_str());
86  
87  	for (n = 0; n < LWS_ARRAY_SIZE(pcols); n++)
88  		if (!strncmp(uri, pcols[n], pcols_len[n]))
89  			break;
90  
91  	if (n == LWS_ARRAY_SIZE(pcols))
92  		throw lssException("unknown uri protocol://");
93  
94  	pol.protocol = n >> 1;
95  	if (n & 1)
96  		pol.flags |= LWSSSPOLF_TLS;
97  
98  	n = pcols_port[n];
99  
100  	if (lws_parse_uri(uri, &p, &pol.endpoint, &n, &urlpath))
101  		throw lssException("unable to parse uri://");
102  
103  	pol.port = (uint16_t)n;
104  
105  	if (pol.protocol <= LWSSSP_WS) {
106  		pol.u.http.url = urlpath;
107  
108  		/*
109  		 * These are workarounds for common h2 server noncompliances
110  		 */
111  
112  		pol.flags |= LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM |
113  			     LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR |
114  			     LWSSSPOLF_H2_QUIRK_UNCLEAN_HPACK_STATE;
115  
116  		if (pol.protocol < LWSSSP_WS)
117  			pol.u.http.method = _psh ? "POST" : "GET";
118  	}
119  
120  	us_start = lws_now_usecs();
121  
122  	if (lws_ss_create(ctx, 0, &ssi, (void *)this, &m_ss, NULL, NULL))
123  		goto blow;
124  
125  	if (pol.protocol <= LWSSSP_WS)
126  		lws_ss_client_connect(m_ss);
127  
128  	return;
129  
130  blow:
131  	if (uri)
132  		free(uri);
133  	throw lssException("ss creation failed");
134  }
135  
~lss()136  lss::~lss()
137  {
138  	if (uri)
139  		free(uri);
140  	if (m_ss)
141  		lws_ss_destroy(&m_ss);
142  }
143  
call_completion(lws_ss_constate_t state)144  int lss::call_completion(lws_ss_constate_t state)
145  {
146  	if (comp_done)
147  		return 0;
148  	if (!comp)
149  		return 0;
150  
151  	comp_done = 1;
152  
153  	return comp(this, state, NULL);
154  }
155