static enum websocket_callback_return ws_handle_frame(struct websocket *s, uint8_t *frame, size_t length) { enum websocket_callback_return ret = WS_OK; switch (s->ws_flags.opcode) { case WS_CONTINUATION_FRAME: log_err("Fragmented websocket frame not supported!\n"); handle_error(s, WS_CLOSE_UNSUPPORTED); ret = WS_CLOSED; break; case WS_BINARY_FRAME: if (likely(s->binary_message_received != NULL)) { ret = s->binary_message_received(s, frame, length); } else { handle_error(s, WS_CLOSE_UNSUPPORTED); ret = WS_CLOSED; } break; case WS_TEXT_FRAME: if (likely(s->text_message_received != NULL)) { ret = s->text_message_received(s, (char *)frame, length); } else { handle_error(s, WS_CLOSE_UNSUPPORTED); ret = WS_CLOSED; } break; case WS_PING_FRAME: { int pong_ret = websocket_send_pong_frame(s, frame, length); if (unlikely(pong_ret < 0)) { // TODO: maybe call the error callback? ret = WS_ERROR; } else { if (s->ping_received != NULL) { ret = s->ping_received(s, frame, length); } } break; } case WS_PONG_FRAME: if (s->pong_received != NULL) { ret = s->pong_received(s, frame, length); } break; case WS_CLOSE_FRAME: { uint16_t status_code = 0; if (length >= 2) { memcpy(&status_code, frame, sizeof(status_code)); status_code = jet_be16toh(status_code); } websocket_close(s, WS_CLOSE_GOING_AWAY); if (s->close_received != NULL) { s->close_received(s, (enum ws_status_code)status_code); } ret = WS_CLOSED; break; } default: log_err("Unsupported websocket frame!\n"); handle_error(s, WS_CLOSE_UNSUPPORTED); ret = WS_CLOSED; break; } return ret; }
static void free_ab_ws_peer_on_error(void *context) { struct ab_ws_peer *ws_peer = (struct ab_ws_peer *)context; websocket_close(&ws_peer->websocket, WS_CLOSE_GOING_AWAY); free_ab_ws_peer(ws_peer); }
static void handle_error(struct websocket *s, uint16_t status_code) { websocket_close(s, status_code); s->on_error(s); }