12a13 > #include 13a15 > 22a25,31 > struct req_data_t { > napi_ref sock_ref; > napi_ref resp_ref; > napi_ref conn_ref; > }; > > 27a37 > nxt_unit_debug(NULL, "Unit::Unit()"); 33a44,45 > > nxt_unit_debug(NULL, "Unit::~Unit()"); 41c53 < napi_value cons; --- > napi_value ctor; 43c55 < napi_property_descriptor properties[] = { --- > napi_property_descriptor unit_props[] = { 46d57 < { "_read", 0, _read, 0, 0, 0, napi_default, 0 } 50,51c61,62 < cons = napi.define_class("Unit", create, 3, properties); < constructor_ = napi.create_reference(cons); --- > ctor = napi.define_class("Unit", create, 2, unit_props); > constructor_ = napi.create_reference(ctor); 53,54c64,65 < napi.set_named_property(exports, "Unit", cons); < napi.set_named_property(exports, "unit_response_headers", --- > napi.set_named_property(exports, "Unit", ctor); > napi.set_named_property(exports, "response_send_headers", 56,57c67,72 < napi.set_named_property(exports, "unit_response_write", response_write); < napi.set_named_property(exports, "unit_response_end", response_end); --- > napi.set_named_property(exports, "response_write", response_write); > napi.set_named_property(exports, "response_end", response_end); > napi.set_named_property(exports, "websocket_send_frame", > websocket_send_frame); > napi.set_named_property(exports, "websocket_set_sock", > websocket_set_sock); 81c96 < napi_value target, cons, instance, jsthis; --- > napi_value target, ctor, instance, jsthis; 97,98c112,113 < cons = napi.get_reference_value(constructor_); < instance = napi.new_instance(cons); --- > ctor = napi.get_reference_value(constructor_); > instance = napi.new_instance(ctor); 133,136c148,153 < unit_init.callbacks.request_handler = request_handler; < unit_init.callbacks.add_port = add_port; < unit_init.callbacks.remove_port = remove_port; < unit_init.callbacks.quit = quit; --- > unit_init.callbacks.request_handler = request_handler_cb; > unit_init.callbacks.websocket_handler = websocket_handler_cb; > unit_init.callbacks.close_handler = close_handler_cb; > unit_init.callbacks.add_port = add_port; > unit_init.callbacks.remove_port = remove_port; > unit_init.callbacks.quit = quit_cb; 137a155,156 > unit_init.request_data_size = sizeof(req_data_t); > 160,161c179,180 < napi_value < Unit::_read(napi_env env, napi_callback_info info) --- > void > Unit::request_handler_cb(nxt_unit_request_info_t *req) 163,167c182 < void *data; < size_t argc; < nxt_napi napi(env); < napi_value buffer, argv; < nxt_unit_request_info_t *req; --- > Unit *obj; 169c184 < argc = 1; --- > obj = reinterpret_cast(req->unit->data); 170a186,196 > obj->request_handler(req); > } > > > void > Unit::request_handler(nxt_unit_request_info_t *req) > { > napi_value socket, request, response, server_obj, emit_request; > > memset(req->data, 0, sizeof(req_data_t)); > 172c198 < napi.get_cb_info(info, argc, &argv); --- > nxt_handle_scope scope(env()); 174,175c200 < req = napi.get_request_info(argv); < buffer = napi.create_buffer((size_t) req->content_length, &data); --- > server_obj = get_server_object(); 176a202,215 > socket = create_socket(server_obj, req); > request = create_request(server_obj, socket); > response = create_response(server_obj, request, req); > > create_headers(req, request); > > emit_request = get_named_property(server_obj, "emit_request"); > > nxt_async_context async_context(env(), "request_handler"); > nxt_callback_scope async_scope(async_context); > > make_callback(async_context, server_obj, emit_request, request, > response); > 178,179c217 < napi.throw_error(e); < return nullptr; --- > nxt_unit_req_warn(req, "request_handler: %s", e.str); 180a219 > } 182d220 < nxt_unit_request_read(req, data, req->content_length); 184c222,229 < return buffer; --- > void > Unit::websocket_handler_cb(nxt_unit_websocket_frame_t *ws) > { > Unit *obj; > > obj = reinterpret_cast(ws->req->unit->data); > > obj->websocket_handler(ws); 189c234 < Unit::request_handler(nxt_unit_request_info_t *req) --- > Unit::websocket_handler(nxt_unit_websocket_frame_t *ws) 191,194c236,237 < Unit *obj; < napi_value socket, request, response, server_obj; < napi_value emit_events; < napi_value events_args[3]; --- > napi_value frame, server_obj, process_frame, conn; > req_data_t *req_data; 196c239 < obj = reinterpret_cast(req->unit->data); --- > req_data = (req_data_t *) ws->req->data; 199c242 < nxt_handle_scope scope(obj->env()); --- > nxt_handle_scope scope(env()); 201c244 < server_obj = obj->get_server_object(); --- > server_obj = get_server_object(); 203,205c246 < socket = obj->create_socket(server_obj, req); < request = obj->create_request(server_obj, socket); < response = obj->create_response(server_obj, socket, request, req); --- > frame = create_websocket_frame(server_obj, ws); 207c248 < obj->create_headers(req, request); --- > conn = get_reference_value(req_data->conn_ref); 209c250 < emit_events = obj->get_named_property(server_obj, "emit_events"); --- > process_frame = get_named_property(conn, "processFrame"); 211,215c252 < events_args[0] = server_obj; < events_args[1] = request; < events_args[2] = response; < < nxt_async_context async_context(obj->env(), "unit_request_handler"); --- > nxt_async_context async_context(env(), "websocket_handler"); 218,219c255 < obj->make_callback(async_context, server_obj, emit_events, < 3, events_args); --- > make_callback(async_context, conn, process_frame, frame); 222c258 < obj->throw_error(e); --- > nxt_unit_req_warn(ws->req, "websocket_handler: %s", e.str); 223a260,261 > > nxt_unit_websocket_done(ws); 227a266,311 > Unit::close_handler_cb(nxt_unit_request_info_t *req) > { > Unit *obj; > > obj = reinterpret_cast(req->unit->data); > > obj->close_handler(req); > } > > > void > Unit::close_handler(nxt_unit_request_info_t *req) > { > napi_value conn_handle_close, conn; > req_data_t *req_data; > > req_data = (req_data_t *) req->data; > > try { > nxt_handle_scope scope(env()); > > conn = get_reference_value(req_data->conn_ref); > > conn_handle_close = get_named_property(conn, "handleSocketClose"); > > nxt_async_context async_context(env(), "close_handler"); > nxt_callback_scope async_scope(async_context); > > make_callback(async_context, conn, conn_handle_close, > nxt_napi::create(0)); > > remove_wrap(req_data->sock_ref); > remove_wrap(req_data->resp_ref); > remove_wrap(req_data->conn_ref); > > } catch (exception &e) { > nxt_unit_req_warn(req, "close_handler: %s", e.str); > > return; > } > > nxt_unit_request_done(req, NXT_UNIT_OK); > } > > > static void 247,248c331,332 < obj->throw_error("Failed to upgrade read" < " file descriptor to O_NONBLOCK"); --- > nxt_unit_warn(ctx, "fcntl(%d, O_NONBLOCK) failed: %s (%d)", > port->in_fd, strerror(errno), errno); 254c338 < obj->throw_error("Failed to get uv.loop"); --- > nxt_unit_warn(ctx, "Failed to get uv.loop"); 262c346 < obj->throw_error("Failed to init uv.poll"); --- > nxt_unit_warn(ctx, "Failed to init uv.poll"); 268c352 < obj->throw_error("Failed to start uv.poll"); --- > nxt_unit_warn(ctx, "Failed to start uv.poll"); 311c395 < Unit::quit(nxt_unit_ctx_t *ctx) --- > Unit::quit_cb(nxt_unit_ctx_t *ctx) 313,314c397 < Unit *obj; < napi_value server_obj, emit_close; --- > Unit *obj; 317a401,409 > obj->quit(ctx); > } > > > void > Unit::quit(nxt_unit_ctx_t *ctx) > { > napi_value server_obj, emit_close; > 319c411 < nxt_handle_scope scope(obj->env()); --- > nxt_handle_scope scope(env()); 321c413 < server_obj = obj->get_server_object(); --- > server_obj = get_server_object(); 323c415 < emit_close = obj->get_named_property(server_obj, "emit_close"); --- > emit_close = get_named_property(server_obj, "emit_close"); 325c417 < nxt_async_context async_context(obj->env(), "unit_quit"); --- > nxt_async_context async_context(env(), "unit_quit"); 328c420 < obj->make_callback(async_context, server_obj, emit_close, 0, NULL); --- > make_callback(async_context, server_obj, emit_close); 331c423 < obj->throw_error(e); --- > nxt_unit_debug(ctx, "quit: %s", e.str); 351a444 > void *data; 353c446 < napi_value headers, raw_headers; --- > napi_value headers, raw_headers, buffer; 375a469,475 > > set_named_property(request, "_websocket_handshake", r->websocket_handshake); > > buffer = create_buffer((size_t) req->content_length, &data); > nxt_unit_request_read(req, data, req->content_length); > > set_named_property(request, "_data", buffer); 412a513 > req_data_t *req_data; 417c518 < constructor = get_named_property(server_obj, "socket"); --- > constructor = get_named_property(server_obj, "Socket"); 421c522,524 < set_named_property(res, "req_pointer", (intptr_t) req); --- > req_data = (req_data_t *) req->data; > req_data->sock_ref = wrap(res, req, sock_destroy); > 432c535 < napi_value constructor, return_val; --- > napi_value constructor; 434c537 < constructor = get_named_property(server_obj, "request"); --- > constructor = get_named_property(server_obj, "ServerRequest"); 436c539,540 < return_val = new_instance(constructor, server_obj); --- > return new_instance(constructor, server_obj, socket); > } 438,439d541 < set_named_property(return_val, "socket", socket); < set_named_property(return_val, "connection", socket); 441c543,557 < return return_val; --- > napi_value > Unit::create_response(napi_value server_obj, napi_value request, > nxt_unit_request_info_t *req) > { > napi_value constructor, res; > req_data_t *req_data; > > constructor = get_named_property(server_obj, "ServerResponse"); > > res = new_instance(constructor, request); > > req_data = (req_data_t *) req->data; > req_data->resp_ref = wrap(res, req, resp_destroy); > > return res; 446,447c562,563 < Unit::create_response(napi_value server_obj, napi_value socket, < napi_value request, nxt_unit_request_info_t *req) --- > Unit::create_websocket_frame(napi_value server_obj, > nxt_unit_websocket_frame_t *ws) 449c565,567 < napi_value constructor, return_val; --- > void *data; > napi_value constructor, res, buffer; > uint8_t sc[2]; 451c569 < constructor = get_named_property(server_obj, "response"); --- > constructor = get_named_property(server_obj, "WebSocketFrame"); 453c571 < return_val = new_instance(constructor, request); --- > res = new_instance(constructor); 455,457c573,575 < set_named_property(return_val, "socket", socket); < set_named_property(return_val, "connection", socket); < set_named_property(return_val, "_req_point", (intptr_t) req); --- > set_named_property(res, "fin", (bool) ws->header->fin); > set_named_property(res, "opcode", ws->header->opcode); > set_named_property(res, "length", (int64_t) ws->payload_len); 459c577,594 < return return_val; --- > if (ws->header->opcode == NXT_WEBSOCKET_OP_CLOSE) { > if (ws->payload_len >= 2) { > nxt_unit_websocket_read(ws, sc, 2); > > set_named_property(res, "closeStatus", > (((uint16_t) sc[0]) << 8) | sc[1]); > > } else { > set_named_property(res, "closeStatus", -1); > } > } > > buffer = create_buffer((size_t) ws->content_length, &data); > nxt_unit_websocket_read(ws, data, ws->content_length); > > set_named_property(res, "binaryPayload", buffer); > > return res; 475c610 < napi_value req_num, array_entry; --- > napi_value array_entry; 479c614 < napi_value argv[5]; --- > napi_value argv[4]; 481c616 < argc = 5; --- > argc = 4; 485c620 < if (argc != 5) { --- > if (argc != 4) { 492c627,630 < req_num = napi.get_named_property(argv[0], "_req_point"); --- > req = napi.get_request_info(this_arg); > status_code = napi.get_value_uint32(argv[0]); > keys_count = napi.get_value_uint32(argv[2]); > header_len = napi.get_value_uint32(argv[3]); 494,499d631 < req = napi.get_request_info(req_num); < < status_code = napi.get_value_uint32(argv[1]); < keys_count = napi.get_value_uint32(argv[3]); < header_len = napi.get_value_uint32(argv[4]); < 503c635 < headers = argv[2]; --- > headers = argv[1]; 614c746 < char *ptr; --- > void *ptr; 618,619c750 < napi_value this_arg, req_num; < napi_status status; --- > napi_value this_arg; 623c754 < napi_value argv[3]; --- > napi_value argv[2]; 625c756 < argc = 3; --- > argc = 2; 629c760 < if (argc != 3) { --- > if (argc != 2) { 634,635c765,767 < req_num = napi.get_named_property(argv[0], "_req_point"); < req = napi.get_request_info(req_num); --- > req = napi.get_request_info(this_arg); > buf_type = napi.type_of(argv[0]); > buf_len = napi.get_value_uint32(argv[1]) + 1; 637c769,772 < buf_len = napi.get_value_uint32(argv[2]); --- > buf = nxt_unit_response_buf_alloc(req, buf_len); > if (buf == NULL) { > throw exception("Failed to allocate response buffer"); > } 639c774,775 < buf_type = napi.type_of(argv[1]); --- > if (buf_type == napi_string) { > /* TODO: will work only for utf8 content-type */ 640a777,791 > have_buf_len = napi.get_value_string_utf8(argv[0], buf->free, > buf_len); > > } else { > ptr = napi.get_buffer_info(argv[0], have_buf_len); > > memcpy(buf->free, ptr, have_buf_len); > } > > buf->free += have_buf_len; > > ret = nxt_unit_buf_send(buf); > if (ret != NXT_UNIT_OK) { > throw exception("Failed to send body buf"); > } 646c797,798 < buf_len++; --- > return this_arg; > } 648,650c800,822 < buf = nxt_unit_response_buf_alloc(req, buf_len); < if (buf == NULL) { < goto failed; --- > > napi_value > Unit::response_end(napi_env env, napi_callback_info info) > { > nxt_napi napi(env); > napi_value this_arg; > req_data_t *req_data; > nxt_unit_request_info_t *req; > > try { > this_arg = napi.get_cb_info(info); > > req = napi.get_request_info(this_arg); > > req_data = (req_data_t *) req->data; > > napi.remove_wrap(req_data->sock_ref); > napi.remove_wrap(req_data->resp_ref); > napi.remove_wrap(req_data->conn_ref); > > } catch (exception &e) { > napi.throw_error(e); > return nullptr; 653,654c825 < if (buf_type == napi_string) { < /* TODO: will work only for utf8 content-type */ --- > nxt_unit_request_done(req, NXT_UNIT_OK); 656,657c827,828 < status = napi_get_value_string_utf8(env, argv[1], buf->free, < buf_len, &have_buf_len); --- > return this_arg; > } 659,661d829 < } else { < status = napi_get_buffer_info(env, argv[1], (void **) &ptr, < &have_buf_len); 663c831,882 < memcpy(buf->free, ptr, have_buf_len); --- > napi_value > Unit::websocket_send_frame(napi_env env, napi_callback_info info) > { > int ret, iovec_len; > bool fin; > size_t buf_len; > uint32_t opcode, sc; > nxt_napi napi(env); > napi_value this_arg, frame, payload; > nxt_unit_request_info_t *req; > char status_code[2]; > struct iovec iov[2]; > > iovec_len = 0; > > try { > this_arg = napi.get_cb_info(info, frame); > > req = napi.get_request_info(this_arg); > > opcode = napi.get_value_uint32(napi.get_named_property(frame, > "opcode")); > if (opcode == NXT_WEBSOCKET_OP_CLOSE) { > sc = napi.get_value_uint32(napi.get_named_property(frame, > "closeStatus")); > status_code[0] = (sc >> 8) & 0xFF; > status_code[1] = sc & 0xFF; > > iov[iovec_len].iov_base = status_code; > iov[iovec_len].iov_len = 2; > iovec_len++; > } > > try { > fin = napi.get_value_bool(napi.get_named_property(frame, "fin")); > > } catch (exception &e) { > fin = true; > } > > payload = napi.get_named_property(frame, "binaryPayload"); > > if (napi.is_buffer(payload)) { > iov[iovec_len].iov_base = napi.get_buffer_info(payload, buf_len); > > } else { > buf_len = 0; > } > > } catch (exception &e) { > napi.throw_error(e); > return nullptr; 666,667c885,887 < if (status != napi_ok) { < goto failed; --- > if (buf_len > 0) { > iov[iovec_len].iov_len = buf_len; > iovec_len++; 670,672c890 < buf->free += have_buf_len; < < ret = nxt_unit_buf_send(buf); --- > ret = nxt_unit_websocket_sendv(req, opcode, fin ? 1 : 0, iov, iovec_len); 681c899 < napi.throw_error("Failed to write body"); --- > napi.throw_error("Failed to send frame"); 688c906 < Unit::response_end(napi_env env, napi_callback_info info) --- > Unit::websocket_set_sock(napi_env env, napi_callback_info info) 690d907 < size_t argc; 692c909,910 < napi_value resp, this_arg, req_num; --- > napi_value this_arg, sock; > req_data_t *req_data; 695,696d912 < argc = 1; < 698c914 < this_arg = napi.get_cb_info(info, argc, &resp); --- > this_arg = napi.get_cb_info(info, sock); 700,701c916 < req_num = napi.get_named_property(resp, "_req_point"); < req = napi.get_request_info(req_num); --- > req = napi.get_request_info(sock); 702a918,920 > req_data = (req_data_t *) req->data; > req_data->conn_ref = napi.wrap(this_arg, req, conn_destroy); > 708,709d925 < nxt_unit_request_done(req, NXT_UNIT_OK); < 711a928,960 > > > void > Unit::conn_destroy(napi_env env, void *nativeObject, void *finalize_hint) > { > nxt_unit_request_info_t *req; > > req = (nxt_unit_request_info_t *) nativeObject; > > nxt_unit_warn(NULL, "conn_destroy: %p", req); > } > > > void > Unit::sock_destroy(napi_env env, void *nativeObject, void *finalize_hint) > { > nxt_unit_request_info_t *req; > > req = (nxt_unit_request_info_t *) nativeObject; > > nxt_unit_warn(NULL, "sock_destroy: %p", req); > } > > > void > Unit::resp_destroy(napi_env env, void *nativeObject, void *finalize_hint) > { > nxt_unit_request_info_t *req; > > req = (nxt_unit_request_info_t *) nativeObject; > > nxt_unit_warn(NULL, "resp_destroy: %p", req); > }