2D Run-and-gun shooter inspired by One Man's Doomsday, Counter-Strike, and Metal Slug.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

316 lines
8.5 KiB

  1. #include "IZ_app_net.h"
  2. void IZ_AppHandleNetworkingInboundBinaryEvents(struct IZ_App* app, void* binary_raw, size_t len) {
  3. if (len < 1) {
  4. return;
  5. }
  6. u8* binary = binary_raw;
  7. size_t i;
  8. char binary_string[len * 3 + 1];
  9. IZ_memset(binary_string, 0, len * 3 + 1);
  10. sprintf(binary_string, "%02x", binary[0]);
  11. for (i = 1; i < len; i += 1) {
  12. sprintf(binary_string, "%s %02x", binary_string, binary[i]);
  13. }
  14. IZ_LogInfo(IZ_LOG_CATEGORY_INPUT, "net/ws", "Received binary(length: %d): %s", len, binary_string);
  15. }
  16. void IZ_AppHandleNetworkingInboundTextEvents(struct IZ_App* app, const char* text, size_t len) {
  17. IZ_LogInfo(IZ_LOG_CATEGORY_INPUT, "net/ws", "Received string(length: %d): %s", len, text);
  18. }
  19. void IZ_AppHandleOutboundNetworking(struct IZ_App* app) {
  20. // TODO implement queueing of messages
  21. IZ_NetClientState* net_state = IZ_AppGetNetState(app);
  22. IZ_InputState* input_state = IZ_AppGetInputState(app);
  23. u8 player_index;
  24. for (player_index = 0; player_index < IZ_PLAYERS; player_index += 1) {
  25. if (net_state->action[player_index] != input_state->action[player_index]) {
  26. u8 player_actions_count = 1;
  27. IZ_AppActionSyncMessage* msg = IZ_malloc(
  28. sizeof(IZ_AppMessageHeader)
  29. + sizeof(u8)
  30. + (sizeof(IZ_AppPlayerActionSyncMessage) * player_actions_count)
  31. );
  32. msg->header.client_elapsed_time = IZ_AppGetTicks(app);
  33. msg->header.message_kind = IZ_MESSAGE_KIND_ACTION_SYNC;
  34. msg->action.player_actions_count = player_actions_count;
  35. msg->action.player[0].index = player_index;
  36. msg->action.player[0].value = input_state->action[player_index];
  37. msg->action.player[0].state = 0;
  38. IZ_NetClientSendBinaryMessage(
  39. net_state,
  40. msg,
  41. sizeof(*msg)
  42. );
  43. IZ_free(msg);
  44. }
  45. net_state->action[player_index] = input_state->action[player_index];
  46. }
  47. }
  48. void IZ_WSClientAttemptConnect(struct lws_sorted_usec_list *sul) {
  49. IZ_WSClientVHostData* vhd = lws_container_of(sul, IZ_WSClientVHostData, sul);
  50. vhd->i.context = vhd->context;
  51. vhd->i.port = *vhd->port;
  52. vhd->i.address = vhd->address;
  53. vhd->i.path = vhd->path;
  54. vhd->i.host = vhd->i.address;
  55. vhd->i.origin = vhd->i.address;
  56. vhd->i.ssl_connection = 0;
  57. vhd->i.protocol = NETWORK_PROTOCOL;
  58. vhd->i.pwsi = &vhd->client_wsi;
  59. struct IZ_App* app = (struct IZ_App*) vhd->app;
  60. IZ_NetClientState* net_state = IZ_AppGetNetState(app);
  61. net_state->status = IZ_NET_CLIENT_STATUS_CONNECTING;
  62. if (lws_client_connect_via_info(&vhd->i)) {
  63. return;
  64. }
  65. lws_sul_schedule(
  66. vhd->context,
  67. 0,
  68. &vhd->sul,
  69. IZ_WSClientAttemptConnect,
  70. 10 * LWS_US_PER_SEC
  71. );
  72. }
  73. IZ_ProcedureResult IZ_WSClientProtocolInitialize(struct lws* wsi, void* in) {
  74. const struct lws_protocols* protocols = lws_get_protocol(wsi);
  75. struct lws_vhost* vhost = lws_get_vhost(wsi);
  76. IZ_WSClientVHostData* vhd_instance = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(vhost,protocols);
  77. IZ_WSClientVHostData** vhd = &vhd_instance;
  78. *vhd = lws_protocol_vh_priv_zalloc(vhost, protocols, sizeof(IZ_WSClientVHostData));
  79. (*vhd)->ring = lws_ring_create(
  80. sizeof(IZ_WebsocketMessage),
  81. RING_COUNT,
  82. IZ_WebsocketDestroyMessage
  83. );
  84. if (!(*vhd)->ring) {
  85. return -1;
  86. }
  87. (*vhd)->context = lws_get_context(wsi);
  88. (*vhd)->protocol = protocols;
  89. (*vhd)->vhost = vhost;
  90. (*vhd)->port = (u16*) lws_pvo_search(
  91. (const struct lws_protocol_vhost_options *)in,
  92. "port"
  93. )->value;
  94. (*vhd)->address = lws_pvo_search(
  95. (const struct lws_protocol_vhost_options *)in,
  96. "address"
  97. )->value;
  98. (*vhd)->path = lws_pvo_search(
  99. (const struct lws_protocol_vhost_options *)in,
  100. "path"
  101. )->value;
  102. (*vhd)->app = lws_pvo_search(
  103. (const struct lws_protocol_vhost_options *)in,
  104. "app"
  105. )->value;
  106. IZ_WSClientAttemptConnect(&(*vhd)->sul);
  107. return 0;
  108. }
  109. void IZ_WSClientProtocolTeardown(struct lws* wsi) {
  110. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  111. lws_get_vhost(wsi),
  112. lws_get_protocol(wsi)
  113. );
  114. if (vhd->ring) {
  115. lws_ring_destroy(vhd->ring);
  116. }
  117. lws_sul_cancel(&vhd->sul);
  118. struct IZ_App* app = (struct IZ_App*) vhd->app;
  119. IZ_NetClientState* net_state = IZ_AppGetNetState(app);
  120. net_state->status = IZ_NET_CLIENT_STATUS_PRISTINE;
  121. }
  122. IZ_ProcedureResult IZ_WSClientConnectionError(struct lws* wsi, void* in) {
  123. lwsl_err("CLIENT_CONNECTION_ERROR: %s\n", in ? (char *)in : "(null)");
  124. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  125. lws_get_vhost(wsi),
  126. lws_get_protocol(wsi)
  127. );
  128. if (!vhd) {
  129. return -1;
  130. }
  131. struct IZ_App* app = (struct IZ_App*) vhd->app;
  132. IZ_AppBindConnection(app, NULL);
  133. vhd->client_wsi = NULL;
  134. IZ_NetClientState* net_state = IZ_AppGetNetState(app);
  135. if (net_state->retries == net_state->config.max_reconnect_retries) {
  136. lwsl_err("Max number of retries reached!\n");
  137. net_state->status = IZ_NET_CLIENT_STATUS_PRISTINE;
  138. return -1;
  139. }
  140. net_state->status = IZ_NET_CLIENT_STATUS_ERROR;
  141. net_state->retries += 1;
  142. lws_sul_schedule(
  143. vhd->context,
  144. 0,
  145. &vhd->sul,
  146. IZ_WSClientAttemptConnect,
  147. net_state->config.reconnect_interval_secs * LWS_US_PER_SEC
  148. );
  149. return 0;
  150. }
  151. IZ_ProcedureResult IZ_WSClientOnOpen(struct lws* wsi, IZ_WSClientSessionData* pss) {
  152. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  153. lws_get_vhost(wsi),
  154. lws_get_protocol(wsi)
  155. );
  156. struct IZ_App* app = (struct IZ_App*) vhd->app;
  157. IZ_NetClientState* net_state = IZ_AppGetNetState(app);
  158. pss->ring = lws_ring_create(sizeof(IZ_WebsocketMessage), RING_COUNT,IZ_WebsocketDestroyMessage);
  159. if (!pss->ring) {
  160. net_state->status = IZ_NET_CLIENT_STATUS_ERROR;
  161. return -1;
  162. }
  163. IZ_AppBindConnection(app, wsi);
  164. net_state->status = IZ_NET_CLIENT_STATUS_CONNECTED;
  165. net_state->retries = 0;
  166. pss->tail = 0;
  167. return 0;
  168. }
  169. void IZ_WSClientOnClose(struct lws* wsi) {
  170. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  171. lws_get_vhost(wsi),
  172. lws_get_protocol(wsi)
  173. );
  174. struct IZ_App* app = (struct IZ_App*) vhd->app;
  175. IZ_AppBindConnection(app, NULL);
  176. vhd->client_wsi = NULL;
  177. lws_sul_schedule(
  178. vhd->context,
  179. 0,
  180. &vhd->sul,
  181. IZ_WSClientAttemptConnect,
  182. LWS_US_PER_SEC
  183. );
  184. }
  185. IZ_ProcedureResult IZ_WSClientWritable(struct lws* wsi) {
  186. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  187. lws_get_vhost(wsi),
  188. lws_get_protocol(wsi)
  189. );
  190. const IZ_WebsocketMessage* pmsg = lws_ring_get_element(vhd->ring, &vhd->tail);
  191. if (!pmsg) {
  192. return 0;
  193. }
  194. /* notice we allowed for LWS_PRE in the payload already */
  195. i32 m = lws_write(
  196. wsi,
  197. ((unsigned char*) pmsg->payload) + LWS_PRE,
  198. pmsg->len,
  199. pmsg->binary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT
  200. );
  201. if (m < (i32)pmsg->len) {
  202. lwsl_err("ERROR %d writing to ws socket\n", m);
  203. return -1;
  204. }
  205. lws_ring_consume_single_tail(vhd->ring, &vhd->tail, 1);
  206. /* more to do for us? */
  207. if (lws_ring_get_element(vhd->ring, &vhd->tail)) {
  208. /* come back as soon as we can write more */
  209. lws_callback_on_writable(wsi);
  210. }
  211. return 0;
  212. }
  213. void IZ_WSClientOnReceive(struct lws* wsi, IZ_WSClientSessionData* pss, void* in, size_t len) {
  214. i32 n = (i32) lws_ring_get_count_free_elements(pss->ring);
  215. if (!n) {
  216. lwsl_user("dropping!\n");
  217. return;
  218. }
  219. lwsl_user("LWS_CALLBACK_CLIENT_RECEIVE: %4d (rpp %5d, first %d, last %d, bin %d)\n",
  220. (int)len, (int)lws_remaining_packet_payload(wsi),
  221. lws_is_first_fragment(wsi),
  222. lws_is_final_fragment(wsi),
  223. lws_frame_is_binary(wsi));
  224. // lwsl_hexdump_notice(in, len);
  225. IZ_WebsocketMessage amsg;
  226. i32 result = (
  227. lws_frame_is_binary(wsi)
  228. ? IZ_WebsocketCreateBinaryMessage(wsi, &amsg, in, len)
  229. : IZ_WebsocketCreateTextMessage(wsi, &amsg, in, len)
  230. );
  231. if (result < 0) {
  232. lwsl_user("OOM: dropping\n");
  233. return;
  234. }
  235. IZ_WSClientVHostData* vhd = (IZ_WSClientVHostData*) lws_protocol_vh_priv_get(
  236. lws_get_vhost(wsi),
  237. lws_get_protocol(wsi)
  238. );
  239. struct IZ_App* app = (struct IZ_App*) vhd->app;
  240. if (amsg.binary) {
  241. IZ_AppHandleNetworkingInboundBinaryEvents(app, in, len);
  242. } else {
  243. IZ_AppHandleNetworkingInboundTextEvents(app, in, len);
  244. }
  245. if (!lws_ring_insert(pss->ring, &amsg, 1)) {
  246. IZ_WebsocketDestroyMessage(&amsg);
  247. lwsl_user("dropping!\n");
  248. return;
  249. }
  250. lws_ring_consume_single_tail(pss->ring, &pss->tail, 1);
  251. lws_callback_on_writable(wsi);
  252. if (!pss->flow_controlled && n < 3) {
  253. pss->flow_controlled = true;
  254. lws_rx_flow_control(wsi, 0);
  255. }
  256. }
  257. IZ_ProcedureResult IZ_AppRunNetworkingThread(struct IZ_App* app) {
  258. IZ_NetClientState* net_state = IZ_AppGetNetState(app);
  259. if (IZ_WSClientInitialize(&net_state->binding, net_state->params)) {
  260. return -1;
  261. }
  262. i32 result = 0;
  263. while (true) {
  264. if (IZ_WSClientHandle(&net_state->binding)) {
  265. result = -1;
  266. break;
  267. }
  268. if (net_state->binding.interrupted) {
  269. break;
  270. }
  271. }
  272. IZ_WSClientTeardown(&net_state->binding);
  273. return result;
  274. }