• 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