/*! \brief WebSocket connection handler. */ static void websocket_cb(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers) { struct ast_taskprocessor *serializer; struct transport_create_data create_data; struct ws_transport *transport; struct transport_read_data read_data; if (ast_websocket_set_nonblock(session)) { ast_websocket_unref(session); return; } if (ast_websocket_set_timeout(session, get_write_timeout())) { ast_websocket_unref(session); return; } serializer = create_websocket_serializer(); if (!serializer) { ast_websocket_unref(session); return; } create_data.ws_session = session; if (ast_sip_push_task_synchronous(serializer, transport_create, &create_data)) { ast_log(LOG_ERROR, "Could not create WebSocket transport.\n"); ast_websocket_unref(session); return; } transport = create_data.transport; read_data.transport = transport; while (ast_wait_for_input(ast_websocket_fd(session), -1) > 0) { enum ast_websocket_opcode opcode; int fragmented; if (ast_websocket_read(session, &read_data.payload, &read_data.payload_len, &opcode, &fragmented)) { break; } if (opcode == AST_WEBSOCKET_OPCODE_TEXT || opcode == AST_WEBSOCKET_OPCODE_BINARY) { ast_sip_push_task_synchronous(serializer, transport_read, &read_data); } else if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) { break; } } ast_sip_push_task_synchronous(serializer, transport_shutdown, transport); ast_taskprocessor_unreference(serializer); ast_websocket_unref(session); }
struct ast_json *ast_ari_websocket_session_read( struct ast_ari_websocket_session *session) { RAII_VAR(struct ast_json *, message, NULL, ast_json_unref); if (ast_websocket_fd(session->ws_session) < 0) { return NULL; } while (!message) { int res; char *payload; uint64_t payload_len; enum ast_websocket_opcode opcode; int fragmented; res = ast_wait_for_input( ast_websocket_fd(session->ws_session), -1); if (res <= 0) { ast_log(LOG_WARNING, "WebSocket poll error: %s\n", strerror(errno)); return NULL; } res = ast_websocket_read(session->ws_session, &payload, &payload_len, &opcode, &fragmented); if (res != 0) { ast_log(LOG_WARNING, "WebSocket read error: %s\n", strerror(errno)); return NULL; } switch (opcode) { case AST_WEBSOCKET_OPCODE_CLOSE: ast_debug(1, "WebSocket closed\n"); return NULL; case AST_WEBSOCKET_OPCODE_TEXT: message = ast_json_load_buf(payload, payload_len, NULL); if (message == NULL) { ast_log(LOG_WARNING, "WebSocket input failed to parse\n"); } break; default: /* Ignore all other message types */ break; } } return ast_json_ref(message); }