2
0

ops-raw-skt.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010-2018 Andy Green <[email protected]>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation:
  9. * version 2.1 of the License.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  19. * MA 02110-1301 USA
  20. */
  21. #include <core/private.h>
  22. static int
  23. rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
  24. struct lws_pollfd *pollfd)
  25. {
  26. struct lws_tokens ebuf;
  27. int n, buffered;
  28. /* pending truncated sends have uber priority */
  29. if (lws_has_buffered_out(wsi)) {
  30. if (!(pollfd->revents & LWS_POLLOUT))
  31. return LWS_HPI_RET_HANDLED;
  32. /* drain the output buflist */
  33. if (lws_issue_raw(wsi, NULL, 0) < 0)
  34. goto fail;
  35. /*
  36. * we can't afford to allow input processing to send
  37. * something new, so spin around he event loop until
  38. * he doesn't have any partials
  39. */
  40. return LWS_HPI_RET_HANDLED;
  41. }
  42. if ((pollfd->revents & pollfd->events & LWS_POLLIN) &&
  43. /* any tunnel has to have been established... */
  44. lwsi_state(wsi) != LRS_SSL_ACK_PENDING &&
  45. !(wsi->favoured_pollin &&
  46. (pollfd->revents & pollfd->events & LWS_POLLOUT))) {
  47. buffered = lws_buflist_aware_read(pt, wsi, &ebuf);
  48. switch (ebuf.len) {
  49. case 0:
  50. lwsl_info("%s: read 0 len\n", __func__);
  51. wsi->seen_zero_length_recv = 1;
  52. lws_change_pollfd(wsi, LWS_POLLIN, 0);
  53. /*
  54. * we need to go to fail here, since it's the only
  55. * chance we get to understand that the socket has
  56. * closed
  57. */
  58. // goto try_pollout;
  59. goto fail;
  60. case LWS_SSL_CAPABLE_ERROR:
  61. goto fail;
  62. case LWS_SSL_CAPABLE_MORE_SERVICE:
  63. goto try_pollout;
  64. }
  65. n = user_callback_handle_rxflow(wsi->protocol->callback,
  66. wsi, LWS_CALLBACK_RAW_RX,
  67. wsi->user_space, ebuf.token,
  68. ebuf.len);
  69. if (n < 0) {
  70. lwsl_info("LWS_CALLBACK_RAW_RX_fail\n");
  71. goto fail;
  72. }
  73. if (lws_buflist_aware_consume(wsi, &ebuf, ebuf.len, buffered))
  74. return LWS_HPI_RET_PLEASE_CLOSE_ME;
  75. } else
  76. if (wsi->favoured_pollin &&
  77. (pollfd->revents & pollfd->events & LWS_POLLOUT))
  78. /* we balanced the last favouring of pollin */
  79. wsi->favoured_pollin = 0;
  80. try_pollout:
  81. /* this handles POLLOUT for http serving fragments */
  82. if (!(pollfd->revents & LWS_POLLOUT))
  83. return LWS_HPI_RET_HANDLED;
  84. /* one shot */
  85. if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
  86. lwsl_notice("%s a\n", __func__);
  87. goto fail;
  88. }
  89. /* clear back-to-back write detection */
  90. wsi->could_have_pending = 0;
  91. lws_stats_atomic_bump(wsi->context, pt,
  92. LWSSTATS_C_WRITEABLE_CB, 1);
  93. #if defined(LWS_WITH_STATS)
  94. if (wsi->active_writable_req_us) {
  95. uint64_t ul = lws_time_in_microseconds() -
  96. wsi->active_writable_req_us;
  97. lws_stats_atomic_bump(wsi->context, pt,
  98. LWSSTATS_MS_WRITABLE_DELAY, ul);
  99. lws_stats_atomic_max(wsi->context, pt,
  100. LWSSTATS_MS_WORST_WRITABLE_DELAY, ul);
  101. wsi->active_writable_req_us = 0;
  102. }
  103. #endif
  104. n = user_callback_handle_rxflow(wsi->protocol->callback,
  105. wsi, LWS_CALLBACK_RAW_WRITEABLE,
  106. wsi->user_space, NULL, 0);
  107. if (n < 0) {
  108. lwsl_info("writeable_fail\n");
  109. goto fail;
  110. }
  111. return LWS_HPI_RET_HANDLED;
  112. fail:
  113. lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "raw svc fail");
  114. return LWS_HPI_RET_WSI_ALREADY_DIED;
  115. }
  116. #if !defined(LWS_NO_SERVER)
  117. static int
  118. rops_adoption_bind_raw_skt(struct lws *wsi, int type, const char *vh_prot_name)
  119. {
  120. /* no http but socket... must be raw skt */
  121. if ((type & LWS_ADOPT_HTTP) || !(type & LWS_ADOPT_SOCKET) ||
  122. (type & _LWS_ADOPT_FINISH))
  123. return 0; /* no match */
  124. #if !defined(LWS_WITH_ESP32)
  125. if (type & LWS_ADOPT_FLAG_UDP)
  126. /*
  127. * these can be >128 bytes, so just alloc for UDP
  128. */
  129. wsi->udp = lws_malloc(sizeof(*wsi->udp), "udp struct");
  130. #endif
  131. lws_role_transition(wsi, 0, (type & LWS_ADOPT_ALLOW_SSL) ? LRS_SSL_INIT :
  132. LRS_ESTABLISHED, &role_ops_raw_skt);
  133. if (vh_prot_name)
  134. lws_bind_protocol(wsi, wsi->protocol, __func__);
  135. else
  136. /* this is the only time he will transition */
  137. lws_bind_protocol(wsi,
  138. &wsi->vhost->protocols[wsi->vhost->raw_protocol_index],
  139. __func__);
  140. return 1; /* bound */
  141. }
  142. #endif
  143. #if !defined(LWS_NO_CLIENT)
  144. static int
  145. rops_client_bind_raw_skt(struct lws *wsi,
  146. const struct lws_client_connect_info *i)
  147. {
  148. if (!i) {
  149. /* finalize */
  150. if (!wsi->user_space && wsi->stash->method)
  151. if (lws_ensure_user_space(wsi))
  152. return 1;
  153. return 0;
  154. }
  155. /* we are a fallback if nothing else matched */
  156. lws_role_transition(wsi, LWSIFR_CLIENT, LRS_UNCONNECTED,
  157. &role_ops_raw_skt);
  158. return 1; /* matched */
  159. }
  160. #endif
  161. struct lws_role_ops role_ops_raw_skt = {
  162. /* role name */ "raw-skt",
  163. /* alpn id */ NULL,
  164. /* check_upgrades */ NULL,
  165. /* init_context */ NULL,
  166. /* init_vhost */ NULL,
  167. /* destroy_vhost */ NULL,
  168. /* periodic_checks */ NULL,
  169. /* service_flag_pending */ NULL,
  170. /* handle_POLLIN */ rops_handle_POLLIN_raw_skt,
  171. /* handle_POLLOUT */ NULL,
  172. /* perform_user_POLLOUT */ NULL,
  173. /* callback_on_writable */ NULL,
  174. /* tx_credit */ NULL,
  175. /* write_role_protocol */ NULL,
  176. /* encapsulation_parent */ NULL,
  177. /* alpn_negotiated */ NULL,
  178. /* close_via_role_protocol */ NULL,
  179. /* close_role */ NULL,
  180. /* close_kill_connection */ NULL,
  181. /* destroy_role */ NULL,
  182. #if !defined(LWS_NO_SERVER)
  183. /* adoption_bind */ rops_adoption_bind_raw_skt,
  184. #else
  185. NULL,
  186. #endif
  187. #if !defined(LWS_NO_CLIENT)
  188. /* client_bind */ rops_client_bind_raw_skt,
  189. #else
  190. NULL,
  191. #endif
  192. /* writeable cb clnt, srv */ { LWS_CALLBACK_RAW_WRITEABLE, 0 },
  193. /* close cb clnt, srv */ { LWS_CALLBACK_RAW_CLOSE, 0 },
  194. /* protocol_bind cb c, srv */ { LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL,
  195. LWS_CALLBACK_RAW_SKT_BIND_PROTOCOL },
  196. /* protocol_unbind cb c, srv */ { LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL,
  197. LWS_CALLBACK_RAW_SKT_DROP_PROTOCOL },
  198. /* file_handle */ 0,
  199. };