raw-skt.c 9.9 KB

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