ops-raw-proxy.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. static int
  26. rops_handle_POLLIN_raw_proxy(struct lws_context_per_thread *pt, struct lws *wsi,
  27. struct lws_pollfd *pollfd)
  28. {
  29. struct lws_tokens ebuf;
  30. int n, buffered;
  31. /* pending truncated sends have uber priority */
  32. if (lws_has_buffered_out(wsi)) {
  33. if (!(pollfd->revents & LWS_POLLOUT))
  34. return LWS_HPI_RET_HANDLED;
  35. /* drain the output buflist */
  36. if (lws_issue_raw(wsi, NULL, 0) < 0)
  37. goto fail;
  38. /*
  39. * we can't afford to allow input processing to send
  40. * something new, so spin around he event loop until
  41. * he doesn't have any partials
  42. */
  43. return LWS_HPI_RET_HANDLED;
  44. }
  45. if ((pollfd->revents & pollfd->events & LWS_POLLIN) &&
  46. /* any tunnel has to have been established... */
  47. lwsi_state(wsi) != LRS_SSL_ACK_PENDING &&
  48. !(wsi->favoured_pollin &&
  49. (pollfd->revents & pollfd->events & LWS_POLLOUT))) {
  50. ebuf.token = NULL;
  51. ebuf.len = 0;
  52. buffered = lws_buflist_aware_read(pt, wsi, &ebuf, 1, __func__);
  53. if (buffered < 0)
  54. goto fail;
  55. switch (ebuf.len) {
  56. case 0:
  57. lwsl_info("%s: read 0 len\n", __func__);
  58. wsi->seen_zero_length_recv = 1;
  59. if (lws_change_pollfd(wsi, LWS_POLLIN, 0))
  60. goto fail;
  61. /*
  62. * we need to go to fail here, since it's the only
  63. * chance we get to understand that the socket has
  64. * closed
  65. */
  66. // goto try_pollout;
  67. goto fail;
  68. case LWS_SSL_CAPABLE_ERROR:
  69. goto fail;
  70. case LWS_SSL_CAPABLE_MORE_SERVICE:
  71. goto try_pollout;
  72. }
  73. n = user_callback_handle_rxflow(wsi->a.protocol->callback,
  74. wsi, lwsi_role_client(wsi) ?
  75. LWS_CALLBACK_RAW_PROXY_CLI_RX :
  76. LWS_CALLBACK_RAW_PROXY_SRV_RX,
  77. wsi->user_space, ebuf.token,
  78. ebuf.len);
  79. if (n < 0) {
  80. lwsl_info("LWS_CALLBACK_RAW_PROXY_*_RX fail\n");
  81. goto fail;
  82. }
  83. if (lws_buflist_aware_finished_consuming(wsi, &ebuf, ebuf.len,
  84. buffered, __func__))
  85. return LWS_HPI_RET_PLEASE_CLOSE_ME;
  86. } else
  87. if (wsi->favoured_pollin &&
  88. (pollfd->revents & pollfd->events & LWS_POLLOUT))
  89. /* we balanced the last favouring of pollin */
  90. wsi->favoured_pollin = 0;
  91. try_pollout:
  92. if (!(pollfd->revents & LWS_POLLOUT))
  93. return LWS_HPI_RET_HANDLED;
  94. if (lws_handle_POLLOUT_event(wsi, pollfd)) {
  95. lwsl_debug("POLLOUT event closed it\n");
  96. return LWS_HPI_RET_PLEASE_CLOSE_ME;
  97. }
  98. #if defined(LWS_WITH_CLIENT)
  99. if (lws_client_socket_service(wsi, pollfd))
  100. return LWS_HPI_RET_WSI_ALREADY_DIED;
  101. #endif
  102. return LWS_HPI_RET_HANDLED;
  103. fail:
  104. lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "raw svc fail");
  105. return LWS_HPI_RET_WSI_ALREADY_DIED;
  106. }
  107. static int
  108. rops_adoption_bind_raw_proxy(struct lws *wsi, int type,
  109. const char *vh_prot_name)
  110. {
  111. /* no http but socket... must be raw skt */
  112. if ((type & LWS_ADOPT_HTTP) || !(type & LWS_ADOPT_SOCKET) ||
  113. (!(type & LWS_ADOPT_FLAG_RAW_PROXY)) || (type & _LWS_ADOPT_FINISH))
  114. return 0; /* no match */
  115. #if defined(LWS_WITH_UDP)
  116. if (type & LWS_ADOPT_FLAG_UDP)
  117. /*
  118. * these can be >128 bytes, so just alloc for UDP
  119. */
  120. wsi->udp = lws_malloc(sizeof(*wsi->udp), "udp struct");
  121. #endif
  122. lws_role_transition(wsi, LWSIFR_SERVER, (type & LWS_ADOPT_ALLOW_SSL) ?
  123. LRS_SSL_INIT : LRS_ESTABLISHED,
  124. &role_ops_raw_proxy);
  125. if (vh_prot_name)
  126. lws_bind_protocol(wsi, wsi->a.protocol, __func__);
  127. else
  128. /* this is the only time he will transition */
  129. lws_bind_protocol(wsi,
  130. &wsi->a.vhost->protocols[wsi->a.vhost->raw_protocol_index],
  131. __func__);
  132. return 1; /* bound */
  133. }
  134. static int
  135. rops_client_bind_raw_proxy(struct lws *wsi,
  136. const struct lws_client_connect_info *i)
  137. {
  138. if (!i) {
  139. /* finalize */
  140. if (!wsi->user_space && wsi->stash->cis[CIS_METHOD])
  141. if (lws_ensure_user_space(wsi))
  142. return 1;
  143. return 0;
  144. }
  145. /* we are a fallback if nothing else matched */
  146. if (i->local_protocol_name && !strcmp(i->local_protocol_name, "raw-proxy"))
  147. lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
  148. &role_ops_raw_proxy);
  149. return 0;
  150. }
  151. static int
  152. rops_handle_POLLOUT_raw_proxy(struct lws *wsi)
  153. {
  154. if (lwsi_state(wsi) == LRS_ESTABLISHED)
  155. return LWS_HP_RET_USER_SERVICE;
  156. if (lwsi_role_client(wsi))
  157. return LWS_HP_RET_USER_SERVICE;
  158. return LWS_HP_RET_BAIL_OK;
  159. }
  160. const struct lws_role_ops role_ops_raw_proxy = {
  161. /* role name */ "raw-proxy",
  162. /* alpn id */ NULL,
  163. /* check_upgrades */ NULL,
  164. /* pt_init_destroy */ NULL,
  165. /* init_vhost */ NULL,
  166. /* destroy_vhost */ NULL,
  167. /* service_flag_pending */ NULL,
  168. /* handle_POLLIN */ rops_handle_POLLIN_raw_proxy,
  169. /* handle_POLLOUT */ rops_handle_POLLOUT_raw_proxy,
  170. /* perform_user_POLLOUT */ NULL,
  171. /* callback_on_writable */ NULL,
  172. /* tx_credit */ NULL,
  173. /* write_role_protocol */ NULL,
  174. /* encapsulation_parent */ NULL,
  175. /* alpn_negotiated */ NULL,
  176. /* close_via_role_protocol */ NULL,
  177. /* close_role */ NULL,
  178. /* close_kill_connection */ NULL,
  179. /* destroy_role */ NULL,
  180. /* adoption_bind */ rops_adoption_bind_raw_proxy,
  181. /* client_bind */ rops_client_bind_raw_proxy,
  182. /* issue_keepalive */ NULL,
  183. /* adoption_cb clnt, srv */ { LWS_CALLBACK_RAW_PROXY_CLI_ADOPT,
  184. LWS_CALLBACK_RAW_PROXY_SRV_ADOPT },
  185. /* rx_cb clnt, srv */ { LWS_CALLBACK_RAW_PROXY_CLI_RX,
  186. LWS_CALLBACK_RAW_PROXY_SRV_RX },
  187. /* writeable cb clnt, srv */ { LWS_CALLBACK_RAW_PROXY_CLI_WRITEABLE,
  188. LWS_CALLBACK_RAW_PROXY_SRV_WRITEABLE, },
  189. /* close cb clnt, srv */ { LWS_CALLBACK_RAW_PROXY_CLI_CLOSE,
  190. LWS_CALLBACK_RAW_PROXY_SRV_CLOSE },
  191. /* protocol_bind cb c, srv */ { LWS_CALLBACK_RAW_PROXY_CLI_BIND_PROTOCOL,
  192. LWS_CALLBACK_RAW_PROXY_SRV_BIND_PROTOCOL },
  193. /* protocol_unbind cb c, srv */ { LWS_CALLBACK_RAW_PROXY_CLI_DROP_PROTOCOL,
  194. LWS_CALLBACK_RAW_PROXY_SRV_DROP_PROTOCOL },
  195. /* file_handle */ 0,
  196. };