1802Salexander.borisov@nginx.com 2802Salexander.borisov@nginx.com /* 3802Salexander.borisov@nginx.com * Copyright (C) NGINX, Inc. 4802Salexander.borisov@nginx.com */ 5802Salexander.borisov@nginx.com 6802Salexander.borisov@nginx.com #include "unit.h" 7802Salexander.borisov@nginx.com 8828Salexander.borisov@nginx.com #include <unistd.h> 9828Salexander.borisov@nginx.com #include <fcntl.h> 10828Salexander.borisov@nginx.com 11828Salexander.borisov@nginx.com #include <uv.h> 12828Salexander.borisov@nginx.com 13802Salexander.borisov@nginx.com 14802Salexander.borisov@nginx.com napi_ref Unit::constructor_; 15802Salexander.borisov@nginx.com 16802Salexander.borisov@nginx.com 17*842Salexander.borisov@nginx.com struct nxt_nodejs_ctx_t { 18*842Salexander.borisov@nginx.com nxt_unit_port_id_t port_id; 19*842Salexander.borisov@nginx.com uv_poll_t poll; 20*842Salexander.borisov@nginx.com }; 21*842Salexander.borisov@nginx.com 22*842Salexander.borisov@nginx.com 23802Salexander.borisov@nginx.com Unit::Unit(napi_env env): 24802Salexander.borisov@nginx.com env_(env), 25802Salexander.borisov@nginx.com wrapper_(nullptr), 26802Salexander.borisov@nginx.com unit_ctx_(nullptr) 27802Salexander.borisov@nginx.com { 28802Salexander.borisov@nginx.com } 29802Salexander.borisov@nginx.com 30802Salexander.borisov@nginx.com 31802Salexander.borisov@nginx.com Unit::~Unit() 32802Salexander.borisov@nginx.com { 33802Salexander.borisov@nginx.com napi_delete_reference(env_, wrapper_); 34802Salexander.borisov@nginx.com } 35802Salexander.borisov@nginx.com 36802Salexander.borisov@nginx.com 37802Salexander.borisov@nginx.com napi_value 38802Salexander.borisov@nginx.com Unit::init(napi_env env, napi_value exports) 39802Salexander.borisov@nginx.com { 40802Salexander.borisov@nginx.com napi_value cons, fn; 41802Salexander.borisov@nginx.com napi_status status; 42802Salexander.borisov@nginx.com 43802Salexander.borisov@nginx.com napi_property_descriptor properties[] = { 44802Salexander.borisov@nginx.com { "createServer", 0, create_server, 0, 0, 0, napi_default, 0 }, 45828Salexander.borisov@nginx.com { "listen", 0, listen, 0, 0, 0, napi_default, 0 }, 46828Salexander.borisov@nginx.com { "_read", 0, _read, 0, 0, 0, napi_default, 0 } 47802Salexander.borisov@nginx.com }; 48802Salexander.borisov@nginx.com 49802Salexander.borisov@nginx.com status = napi_define_class(env, "Unit", NAPI_AUTO_LENGTH, create, nullptr, 50828Salexander.borisov@nginx.com 3, properties, &cons); 51802Salexander.borisov@nginx.com if (status != napi_ok) { 52802Salexander.borisov@nginx.com goto failed; 53802Salexander.borisov@nginx.com } 54802Salexander.borisov@nginx.com 55802Salexander.borisov@nginx.com status = napi_create_reference(env, cons, 1, &constructor_); 56802Salexander.borisov@nginx.com if (status != napi_ok) { 57802Salexander.borisov@nginx.com goto failed; 58802Salexander.borisov@nginx.com } 59802Salexander.borisov@nginx.com 60802Salexander.borisov@nginx.com status = napi_set_named_property(env, exports, "Unit", cons); 61802Salexander.borisov@nginx.com if (status != napi_ok) { 62802Salexander.borisov@nginx.com goto failed; 63802Salexander.borisov@nginx.com } 64802Salexander.borisov@nginx.com 65802Salexander.borisov@nginx.com status = napi_create_function(env, NULL, 0, response_send_headers, NULL, 66802Salexander.borisov@nginx.com &fn); 67802Salexander.borisov@nginx.com if (status != napi_ok) { 68802Salexander.borisov@nginx.com goto failed; 69802Salexander.borisov@nginx.com } 70802Salexander.borisov@nginx.com 71802Salexander.borisov@nginx.com status = napi_set_named_property(env, exports, 72802Salexander.borisov@nginx.com "unit_response_headers", fn); 73802Salexander.borisov@nginx.com if (status != napi_ok) { 74802Salexander.borisov@nginx.com goto failed; 75802Salexander.borisov@nginx.com } 76802Salexander.borisov@nginx.com 77802Salexander.borisov@nginx.com status = napi_create_function(env, NULL, 0, response_write, NULL, &fn); 78802Salexander.borisov@nginx.com if (status != napi_ok) { 79802Salexander.borisov@nginx.com goto failed; 80802Salexander.borisov@nginx.com } 81802Salexander.borisov@nginx.com 82802Salexander.borisov@nginx.com status = napi_set_named_property(env, exports, "unit_response_write", fn); 83802Salexander.borisov@nginx.com if (status != napi_ok) { 84802Salexander.borisov@nginx.com goto failed; 85802Salexander.borisov@nginx.com } 86802Salexander.borisov@nginx.com 87802Salexander.borisov@nginx.com status = napi_create_function(env, NULL, 0, response_end, NULL, &fn); 88802Salexander.borisov@nginx.com if (status != napi_ok) { 89802Salexander.borisov@nginx.com goto failed; 90802Salexander.borisov@nginx.com } 91802Salexander.borisov@nginx.com 92802Salexander.borisov@nginx.com status = napi_set_named_property(env, exports, "unit_response_end", fn); 93802Salexander.borisov@nginx.com if (status != napi_ok) { 94802Salexander.borisov@nginx.com goto failed; 95802Salexander.borisov@nginx.com } 96802Salexander.borisov@nginx.com 97802Salexander.borisov@nginx.com return exports; 98802Salexander.borisov@nginx.com 99802Salexander.borisov@nginx.com failed: 100802Salexander.borisov@nginx.com 101802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to define Unit class"); 102802Salexander.borisov@nginx.com 103802Salexander.borisov@nginx.com return nullptr; 104802Salexander.borisov@nginx.com } 105802Salexander.borisov@nginx.com 106802Salexander.borisov@nginx.com 107802Salexander.borisov@nginx.com void 108802Salexander.borisov@nginx.com Unit::destroy(napi_env env, void *nativeObject, void *finalize_hint) 109802Salexander.borisov@nginx.com { 110802Salexander.borisov@nginx.com Unit *obj = reinterpret_cast<Unit *>(nativeObject); 111802Salexander.borisov@nginx.com 112802Salexander.borisov@nginx.com delete obj; 113802Salexander.borisov@nginx.com } 114802Salexander.borisov@nginx.com 115802Salexander.borisov@nginx.com 116802Salexander.borisov@nginx.com napi_value 117802Salexander.borisov@nginx.com Unit::create(napi_env env, napi_callback_info info) 118802Salexander.borisov@nginx.com { 119802Salexander.borisov@nginx.com Unit *obj; 120841Salexander.borisov@nginx.com napi_ref ref; 121802Salexander.borisov@nginx.com napi_value target, cons, instance, jsthis; 122802Salexander.borisov@nginx.com napi_status status; 123802Salexander.borisov@nginx.com 124802Salexander.borisov@nginx.com status = napi_get_new_target(env, info, &target); 125802Salexander.borisov@nginx.com if (status != napi_ok) { 126802Salexander.borisov@nginx.com goto failed; 127802Salexander.borisov@nginx.com } 128802Salexander.borisov@nginx.com 129802Salexander.borisov@nginx.com if (target != nullptr) { 130802Salexander.borisov@nginx.com /* Invoked as constructor: `new Unit(...)` */ 131802Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, 132802Salexander.borisov@nginx.com nullptr); 133802Salexander.borisov@nginx.com if (status != napi_ok) { 134802Salexander.borisov@nginx.com goto failed; 135802Salexander.borisov@nginx.com } 136802Salexander.borisov@nginx.com 137802Salexander.borisov@nginx.com obj = new Unit(env); 138802Salexander.borisov@nginx.com 139802Salexander.borisov@nginx.com status = napi_wrap(env, jsthis, reinterpret_cast<void *>(obj), 140802Salexander.borisov@nginx.com destroy, nullptr, &obj->wrapper_); 141802Salexander.borisov@nginx.com if (status != napi_ok) { 142802Salexander.borisov@nginx.com goto failed; 143802Salexander.borisov@nginx.com } 144802Salexander.borisov@nginx.com 145841Salexander.borisov@nginx.com status = napi_create_reference(env, jsthis, 1, &ref); 146841Salexander.borisov@nginx.com if (status != napi_ok) { 147841Salexander.borisov@nginx.com goto failed; 148841Salexander.borisov@nginx.com } 149841Salexander.borisov@nginx.com 150802Salexander.borisov@nginx.com return jsthis; 151802Salexander.borisov@nginx.com } 152802Salexander.borisov@nginx.com 153802Salexander.borisov@nginx.com /* Invoked as plain function `Unit(...)`, turn into construct call. */ 154802Salexander.borisov@nginx.com status = napi_get_reference_value(env, constructor_, &cons); 155802Salexander.borisov@nginx.com if (status != napi_ok) { 156802Salexander.borisov@nginx.com goto failed; 157802Salexander.borisov@nginx.com } 158802Salexander.borisov@nginx.com 159802Salexander.borisov@nginx.com status = napi_new_instance(env, cons, 0, nullptr, &instance); 160802Salexander.borisov@nginx.com if (status != napi_ok) { 161802Salexander.borisov@nginx.com goto failed; 162802Salexander.borisov@nginx.com } 163802Salexander.borisov@nginx.com 164841Salexander.borisov@nginx.com status = napi_create_reference(env, instance, 1, &ref); 165841Salexander.borisov@nginx.com if (status != napi_ok) { 166841Salexander.borisov@nginx.com goto failed; 167841Salexander.borisov@nginx.com } 168841Salexander.borisov@nginx.com 169802Salexander.borisov@nginx.com return instance; 170802Salexander.borisov@nginx.com 171802Salexander.borisov@nginx.com failed: 172802Salexander.borisov@nginx.com 173802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to create Unit object"); 174802Salexander.borisov@nginx.com 175802Salexander.borisov@nginx.com return nullptr; 176802Salexander.borisov@nginx.com } 177802Salexander.borisov@nginx.com 178802Salexander.borisov@nginx.com 179802Salexander.borisov@nginx.com napi_value 180802Salexander.borisov@nginx.com Unit::create_server(napi_env env, napi_callback_info info) 181802Salexander.borisov@nginx.com { 182802Salexander.borisov@nginx.com Unit *obj; 183802Salexander.borisov@nginx.com size_t argc; 184828Salexander.borisov@nginx.com napi_value jsthis, argv; 185802Salexander.borisov@nginx.com napi_status status; 186802Salexander.borisov@nginx.com nxt_unit_init_t unit_init; 187802Salexander.borisov@nginx.com 188802Salexander.borisov@nginx.com argc = 1; 189802Salexander.borisov@nginx.com 190828Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, &argv, &jsthis, nullptr); 191802Salexander.borisov@nginx.com if (status != napi_ok) { 192802Salexander.borisov@nginx.com goto failed; 193802Salexander.borisov@nginx.com } 194802Salexander.borisov@nginx.com 195802Salexander.borisov@nginx.com status = napi_unwrap(env, jsthis, reinterpret_cast<void **>(&obj)); 196802Salexander.borisov@nginx.com if (status != napi_ok) { 197802Salexander.borisov@nginx.com goto failed; 198802Salexander.borisov@nginx.com } 199802Salexander.borisov@nginx.com 200802Salexander.borisov@nginx.com memset(&unit_init, 0, sizeof(nxt_unit_init_t)); 201802Salexander.borisov@nginx.com 202802Salexander.borisov@nginx.com unit_init.data = obj; 203802Salexander.borisov@nginx.com unit_init.callbacks.request_handler = request_handler; 204828Salexander.borisov@nginx.com unit_init.callbacks.add_port = add_port; 205828Salexander.borisov@nginx.com unit_init.callbacks.remove_port = remove_port; 206*842Salexander.borisov@nginx.com unit_init.callbacks.quit = quit; 207802Salexander.borisov@nginx.com 208802Salexander.borisov@nginx.com obj->unit_ctx_ = nxt_unit_init(&unit_init); 209802Salexander.borisov@nginx.com if (obj->unit_ctx_ == NULL) { 210802Salexander.borisov@nginx.com goto failed; 211802Salexander.borisov@nginx.com } 212802Salexander.borisov@nginx.com 213802Salexander.borisov@nginx.com return nullptr; 214802Salexander.borisov@nginx.com 215802Salexander.borisov@nginx.com failed: 216802Salexander.borisov@nginx.com 217802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to create Unit object"); 218802Salexander.borisov@nginx.com 219802Salexander.borisov@nginx.com return nullptr; 220802Salexander.borisov@nginx.com } 221802Salexander.borisov@nginx.com 222802Salexander.borisov@nginx.com 223802Salexander.borisov@nginx.com napi_value 224802Salexander.borisov@nginx.com Unit::listen(napi_env env, napi_callback_info info) 225802Salexander.borisov@nginx.com { 226828Salexander.borisov@nginx.com return nullptr; 227828Salexander.borisov@nginx.com } 228828Salexander.borisov@nginx.com 229802Salexander.borisov@nginx.com 230828Salexander.borisov@nginx.com napi_value 231828Salexander.borisov@nginx.com Unit::_read(napi_env env, napi_callback_info info) 232828Salexander.borisov@nginx.com { 233828Salexander.borisov@nginx.com Unit *obj; 234828Salexander.borisov@nginx.com void *data; 235828Salexander.borisov@nginx.com size_t argc; 236828Salexander.borisov@nginx.com int64_t req_pointer; 237828Salexander.borisov@nginx.com napi_value jsthis, buffer, argv; 238828Salexander.borisov@nginx.com napi_status status; 239828Salexander.borisov@nginx.com nxt_unit_request_info_t *req; 240828Salexander.borisov@nginx.com 241828Salexander.borisov@nginx.com argc = 1; 242828Salexander.borisov@nginx.com 243828Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, &argv, &jsthis, nullptr); 244802Salexander.borisov@nginx.com if (status != napi_ok) { 245828Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get arguments from js"); 246828Salexander.borisov@nginx.com return nullptr; 247802Salexander.borisov@nginx.com } 248802Salexander.borisov@nginx.com 249802Salexander.borisov@nginx.com status = napi_unwrap(env, jsthis, reinterpret_cast<void **>(&obj)); 250802Salexander.borisov@nginx.com if (status != napi_ok) { 251828Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get Unit object form js"); 252828Salexander.borisov@nginx.com return nullptr; 253802Salexander.borisov@nginx.com } 254802Salexander.borisov@nginx.com 255828Salexander.borisov@nginx.com status = napi_get_value_int64(env, argv, &req_pointer); 256828Salexander.borisov@nginx.com if (status != napi_ok) { 257828Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 258802Salexander.borisov@nginx.com return nullptr; 259802Salexander.borisov@nginx.com } 260802Salexander.borisov@nginx.com 261828Salexander.borisov@nginx.com req = (nxt_unit_request_info_t *) (uintptr_t) req_pointer; 262828Salexander.borisov@nginx.com 263828Salexander.borisov@nginx.com status = napi_create_buffer(env, (size_t) req->content_length, 264828Salexander.borisov@nginx.com &data, &buffer); 265828Salexander.borisov@nginx.com if (status != napi_ok) { 266828Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to create request buffer"); 267802Salexander.borisov@nginx.com return nullptr; 268802Salexander.borisov@nginx.com } 269802Salexander.borisov@nginx.com 270828Salexander.borisov@nginx.com nxt_unit_request_read(req, data, req->content_length); 271802Salexander.borisov@nginx.com 272828Salexander.borisov@nginx.com return buffer; 273802Salexander.borisov@nginx.com } 274802Salexander.borisov@nginx.com 275802Salexander.borisov@nginx.com 276802Salexander.borisov@nginx.com void 277802Salexander.borisov@nginx.com Unit::request_handler(nxt_unit_request_info_t *req) 278802Salexander.borisov@nginx.com { 279802Salexander.borisov@nginx.com Unit *obj; 280802Salexander.borisov@nginx.com napi_value socket, request, response; 281802Salexander.borisov@nginx.com napi_value global, server_obj; 282828Salexander.borisov@nginx.com napi_value run_events, events_res; 283802Salexander.borisov@nginx.com napi_status status; 284828Salexander.borisov@nginx.com napi_value events_args[3]; 285802Salexander.borisov@nginx.com 286802Salexander.borisov@nginx.com obj = reinterpret_cast<Unit *>(req->unit->data); 287802Salexander.borisov@nginx.com 288802Salexander.borisov@nginx.com napi_handle_scope scope; 289802Salexander.borisov@nginx.com status = napi_open_handle_scope(obj->env_, &scope); 290802Salexander.borisov@nginx.com if (status != napi_ok) { 291802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create handle scope"); 292802Salexander.borisov@nginx.com return; 293802Salexander.borisov@nginx.com } 294802Salexander.borisov@nginx.com 295802Salexander.borisov@nginx.com server_obj = obj->get_server_object(); 296802Salexander.borisov@nginx.com if (server_obj == nullptr) { 297802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to get server object"); 298802Salexander.borisov@nginx.com return; 299802Salexander.borisov@nginx.com } 300802Salexander.borisov@nginx.com 301802Salexander.borisov@nginx.com status = napi_get_global(obj->env_, &global); 302802Salexander.borisov@nginx.com if (status != napi_ok) { 303802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to get global variable"); 304802Salexander.borisov@nginx.com return; 305802Salexander.borisov@nginx.com } 306802Salexander.borisov@nginx.com 307802Salexander.borisov@nginx.com socket = obj->create_socket(server_obj, req); 308802Salexander.borisov@nginx.com if (socket == nullptr) { 309802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create socket object"); 310802Salexander.borisov@nginx.com return; 311802Salexander.borisov@nginx.com } 312802Salexander.borisov@nginx.com 313802Salexander.borisov@nginx.com request = obj->create_request(server_obj, socket); 314802Salexander.borisov@nginx.com if (request == nullptr) { 315802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create request object"); 316802Salexander.borisov@nginx.com return; 317802Salexander.borisov@nginx.com } 318802Salexander.borisov@nginx.com 319802Salexander.borisov@nginx.com response = obj->create_response(server_obj, socket, request, req, obj); 320802Salexander.borisov@nginx.com if (response == nullptr) { 321802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create response object"); 322802Salexander.borisov@nginx.com return; 323802Salexander.borisov@nginx.com } 324802Salexander.borisov@nginx.com 325802Salexander.borisov@nginx.com status = obj->create_headers(req, request); 326802Salexander.borisov@nginx.com if (status != napi_ok) { 327802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create headers"); 328802Salexander.borisov@nginx.com return; 329802Salexander.borisov@nginx.com } 330802Salexander.borisov@nginx.com 331828Salexander.borisov@nginx.com status = napi_get_named_property(obj->env_, server_obj, "run_events", 332828Salexander.borisov@nginx.com &run_events); 333828Salexander.borisov@nginx.com if (status != napi_ok) { 334828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to get" 335828Salexander.borisov@nginx.com " 'run_events' function"); 336828Salexander.borisov@nginx.com return; 337828Salexander.borisov@nginx.com } 338828Salexander.borisov@nginx.com 339828Salexander.borisov@nginx.com events_args[0] = server_obj; 340828Salexander.borisov@nginx.com events_args[1] = request; 341828Salexander.borisov@nginx.com events_args[2] = response; 342828Salexander.borisov@nginx.com 343828Salexander.borisov@nginx.com status = napi_call_function(obj->env_, server_obj, run_events, 3, 344828Salexander.borisov@nginx.com events_args, &events_res); 345828Salexander.borisov@nginx.com if (status != napi_ok) { 346828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to call" 347828Salexander.borisov@nginx.com " 'run_events' function"); 348828Salexander.borisov@nginx.com return; 349828Salexander.borisov@nginx.com } 350802Salexander.borisov@nginx.com 351802Salexander.borisov@nginx.com napi_close_handle_scope(obj->env_, scope); 352802Salexander.borisov@nginx.com } 353802Salexander.borisov@nginx.com 354802Salexander.borisov@nginx.com 355828Salexander.borisov@nginx.com void 356828Salexander.borisov@nginx.com nxt_uv_read_callback(uv_poll_t *handle, int status, int events) 357828Salexander.borisov@nginx.com { 358828Salexander.borisov@nginx.com nxt_unit_run_once((nxt_unit_ctx_t *) handle->data); 359828Salexander.borisov@nginx.com } 360828Salexander.borisov@nginx.com 361828Salexander.borisov@nginx.com 362828Salexander.borisov@nginx.com int 363828Salexander.borisov@nginx.com Unit::add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) 364828Salexander.borisov@nginx.com { 365*842Salexander.borisov@nginx.com int err; 366*842Salexander.borisov@nginx.com Unit *obj; 367*842Salexander.borisov@nginx.com uv_loop_t *loop; 368*842Salexander.borisov@nginx.com napi_status status; 369*842Salexander.borisov@nginx.com nxt_nodejs_ctx_t *node_ctx; 370828Salexander.borisov@nginx.com 371828Salexander.borisov@nginx.com if (port->in_fd != -1) { 372828Salexander.borisov@nginx.com obj = reinterpret_cast<Unit *>(ctx->unit->data); 373828Salexander.borisov@nginx.com 374828Salexander.borisov@nginx.com if (fcntl(port->in_fd, F_SETFL, O_NONBLOCK) == -1) { 375828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to upgrade read" 376828Salexander.borisov@nginx.com " file descriptor to O_NONBLOCK"); 377828Salexander.borisov@nginx.com return -1; 378828Salexander.borisov@nginx.com } 379828Salexander.borisov@nginx.com 380828Salexander.borisov@nginx.com status = napi_get_uv_event_loop(obj->env_, &loop); 381828Salexander.borisov@nginx.com if (status != napi_ok) { 382828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to get uv.loop"); 383828Salexander.borisov@nginx.com return NXT_UNIT_ERROR; 384828Salexander.borisov@nginx.com } 385828Salexander.borisov@nginx.com 386*842Salexander.borisov@nginx.com node_ctx = new nxt_nodejs_ctx_t; 387828Salexander.borisov@nginx.com 388*842Salexander.borisov@nginx.com err = uv_poll_init(loop, &node_ctx->poll, port->in_fd); 389828Salexander.borisov@nginx.com if (err < 0) { 390828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to init uv.poll"); 391828Salexander.borisov@nginx.com return NXT_UNIT_ERROR; 392828Salexander.borisov@nginx.com } 393828Salexander.borisov@nginx.com 394*842Salexander.borisov@nginx.com err = uv_poll_start(&node_ctx->poll, UV_READABLE, nxt_uv_read_callback); 395828Salexander.borisov@nginx.com if (err < 0) { 396828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to start uv.poll"); 397828Salexander.borisov@nginx.com return NXT_UNIT_ERROR; 398828Salexander.borisov@nginx.com } 399828Salexander.borisov@nginx.com 400*842Salexander.borisov@nginx.com ctx->data = node_ctx; 401*842Salexander.borisov@nginx.com 402*842Salexander.borisov@nginx.com node_ctx->port_id = port->id; 403*842Salexander.borisov@nginx.com node_ctx->poll.data = ctx; 404828Salexander.borisov@nginx.com } 405828Salexander.borisov@nginx.com 406828Salexander.borisov@nginx.com return nxt_unit_add_port(ctx, port); 407828Salexander.borisov@nginx.com } 408828Salexander.borisov@nginx.com 409828Salexander.borisov@nginx.com 410*842Salexander.borisov@nginx.com inline bool 411*842Salexander.borisov@nginx.com operator == (const nxt_unit_port_id_t &p1, const nxt_unit_port_id_t &p2) 412*842Salexander.borisov@nginx.com { 413*842Salexander.borisov@nginx.com return p1.pid == p2.pid && p1.id == p2.id; 414*842Salexander.borisov@nginx.com } 415*842Salexander.borisov@nginx.com 416*842Salexander.borisov@nginx.com 417828Salexander.borisov@nginx.com void 418828Salexander.borisov@nginx.com Unit::remove_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id) 419828Salexander.borisov@nginx.com { 420*842Salexander.borisov@nginx.com nxt_nodejs_ctx_t *node_ctx; 421*842Salexander.borisov@nginx.com 422*842Salexander.borisov@nginx.com if (ctx->data != NULL) { 423*842Salexander.borisov@nginx.com node_ctx = (nxt_nodejs_ctx_t *) ctx->data; 424828Salexander.borisov@nginx.com 425*842Salexander.borisov@nginx.com if (node_ctx->port_id == *port_id) { 426*842Salexander.borisov@nginx.com uv_poll_stop(&node_ctx->poll); 427828Salexander.borisov@nginx.com 428*842Salexander.borisov@nginx.com delete node_ctx; 429828Salexander.borisov@nginx.com 430*842Salexander.borisov@nginx.com ctx->data = NULL; 431*842Salexander.borisov@nginx.com } 432828Salexander.borisov@nginx.com } 433828Salexander.borisov@nginx.com 434828Salexander.borisov@nginx.com nxt_unit_remove_port(ctx, port_id); 435828Salexander.borisov@nginx.com } 436828Salexander.borisov@nginx.com 437828Salexander.borisov@nginx.com 438*842Salexander.borisov@nginx.com void 439*842Salexander.borisov@nginx.com Unit::quit(nxt_unit_ctx_t *ctx) 440*842Salexander.borisov@nginx.com { 441*842Salexander.borisov@nginx.com nxt_unit_done(ctx); 442*842Salexander.borisov@nginx.com } 443*842Salexander.borisov@nginx.com 444*842Salexander.borisov@nginx.com 445802Salexander.borisov@nginx.com napi_value 446802Salexander.borisov@nginx.com Unit::get_server_object() 447802Salexander.borisov@nginx.com { 448802Salexander.borisov@nginx.com napi_value unit_obj, server_obj; 449802Salexander.borisov@nginx.com napi_status status; 450802Salexander.borisov@nginx.com 451802Salexander.borisov@nginx.com status = napi_get_reference_value(env_, wrapper_, &unit_obj); 452802Salexander.borisov@nginx.com if (status != napi_ok) { 453802Salexander.borisov@nginx.com return nullptr; 454802Salexander.borisov@nginx.com } 455802Salexander.borisov@nginx.com 456802Salexander.borisov@nginx.com status = napi_get_named_property(env_, unit_obj, "server", &server_obj); 457802Salexander.borisov@nginx.com if (status != napi_ok) { 458802Salexander.borisov@nginx.com return nullptr; 459802Salexander.borisov@nginx.com } 460802Salexander.borisov@nginx.com 461802Salexander.borisov@nginx.com return server_obj; 462802Salexander.borisov@nginx.com } 463802Salexander.borisov@nginx.com 464802Salexander.borisov@nginx.com 465802Salexander.borisov@nginx.com napi_status 466802Salexander.borisov@nginx.com Unit::create_headers(nxt_unit_request_info_t *req, napi_value request) 467802Salexander.borisov@nginx.com { 468802Salexander.borisov@nginx.com uint32_t i; 469802Salexander.borisov@nginx.com const char *p; 470802Salexander.borisov@nginx.com napi_value headers, raw_headers, str; 471802Salexander.borisov@nginx.com napi_status status; 472802Salexander.borisov@nginx.com nxt_unit_field_t *f; 473802Salexander.borisov@nginx.com nxt_unit_request_t *r; 474802Salexander.borisov@nginx.com 475802Salexander.borisov@nginx.com r = req->request; 476802Salexander.borisov@nginx.com 477802Salexander.borisov@nginx.com status = napi_create_object(env_, &headers); 478802Salexander.borisov@nginx.com if (status != napi_ok) { 479802Salexander.borisov@nginx.com return status; 480802Salexander.borisov@nginx.com } 481802Salexander.borisov@nginx.com 482802Salexander.borisov@nginx.com status = napi_create_array_with_length(env_, r->fields_count * 2, 483802Salexander.borisov@nginx.com &raw_headers); 484802Salexander.borisov@nginx.com if (status != napi_ok) { 485802Salexander.borisov@nginx.com return status; 486802Salexander.borisov@nginx.com } 487802Salexander.borisov@nginx.com 488802Salexander.borisov@nginx.com for (i = 0; i < r->fields_count; i++) { 489802Salexander.borisov@nginx.com f = r->fields + i; 490802Salexander.borisov@nginx.com 491802Salexander.borisov@nginx.com status = this->append_header(f, headers, raw_headers, i); 492802Salexander.borisov@nginx.com if (status != napi_ok) { 493802Salexander.borisov@nginx.com return status; 494802Salexander.borisov@nginx.com } 495802Salexander.borisov@nginx.com } 496802Salexander.borisov@nginx.com 497802Salexander.borisov@nginx.com status = napi_set_named_property(env_, request, "headers", headers); 498802Salexander.borisov@nginx.com if (status != napi_ok) { 499802Salexander.borisov@nginx.com return status; 500802Salexander.borisov@nginx.com } 501802Salexander.borisov@nginx.com 502830Szelenkov@nginx.com status = napi_set_named_property(env_, request, "rawHeaders", raw_headers); 503802Salexander.borisov@nginx.com if (status != napi_ok) { 504802Salexander.borisov@nginx.com return status; 505802Salexander.borisov@nginx.com } 506802Salexander.borisov@nginx.com 507802Salexander.borisov@nginx.com p = (const char *) nxt_unit_sptr_get(&r->version); 508802Salexander.borisov@nginx.com 509802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, p, r->version_length, &str); 510802Salexander.borisov@nginx.com if (status != napi_ok) { 511802Salexander.borisov@nginx.com return status; 512802Salexander.borisov@nginx.com } 513802Salexander.borisov@nginx.com 514802Salexander.borisov@nginx.com status = napi_set_named_property(env_, request, "httpVersion", str); 515802Salexander.borisov@nginx.com if (status != napi_ok) { 516802Salexander.borisov@nginx.com return status; 517802Salexander.borisov@nginx.com } 518802Salexander.borisov@nginx.com 519802Salexander.borisov@nginx.com p = (const char *) nxt_unit_sptr_get(&r->method); 520802Salexander.borisov@nginx.com 521802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, p, r->method_length, &str); 522802Salexander.borisov@nginx.com if (status != napi_ok) { 523802Salexander.borisov@nginx.com return status; 524802Salexander.borisov@nginx.com } 525802Salexander.borisov@nginx.com 526802Salexander.borisov@nginx.com status = napi_set_named_property(env_, request, "method", str); 527802Salexander.borisov@nginx.com if (status != napi_ok) { 528802Salexander.borisov@nginx.com return status; 529802Salexander.borisov@nginx.com } 530802Salexander.borisov@nginx.com 531802Salexander.borisov@nginx.com p = (const char *) nxt_unit_sptr_get(&r->target); 532802Salexander.borisov@nginx.com 533802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, p, r->target_length, &str); 534802Salexander.borisov@nginx.com if (status != napi_ok) { 535802Salexander.borisov@nginx.com return status; 536802Salexander.borisov@nginx.com } 537802Salexander.borisov@nginx.com 538802Salexander.borisov@nginx.com status = napi_set_named_property(env_, request, "url", str); 539802Salexander.borisov@nginx.com if (status != napi_ok) { 540802Salexander.borisov@nginx.com return status; 541802Salexander.borisov@nginx.com } 542802Salexander.borisov@nginx.com 543802Salexander.borisov@nginx.com return napi_ok; 544802Salexander.borisov@nginx.com } 545802Salexander.borisov@nginx.com 546802Salexander.borisov@nginx.com 547802Salexander.borisov@nginx.com inline napi_status 548802Salexander.borisov@nginx.com Unit::append_header(nxt_unit_field_t *f, napi_value headers, 549802Salexander.borisov@nginx.com napi_value raw_headers, uint32_t idx) 550802Salexander.borisov@nginx.com { 551802Salexander.borisov@nginx.com const char *name, *value; 552802Salexander.borisov@nginx.com napi_value str, vstr; 553802Salexander.borisov@nginx.com napi_status status; 554802Salexander.borisov@nginx.com 555802Salexander.borisov@nginx.com value = (const char *) nxt_unit_sptr_get(&f->value); 556802Salexander.borisov@nginx.com 557802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, value, f->value_length, &vstr); 558802Salexander.borisov@nginx.com if (status != napi_ok) { 559802Salexander.borisov@nginx.com return status; 560802Salexander.borisov@nginx.com } 561802Salexander.borisov@nginx.com 562802Salexander.borisov@nginx.com name = (const char *) nxt_unit_sptr_get(&f->name); 563802Salexander.borisov@nginx.com 564802Salexander.borisov@nginx.com status = napi_set_named_property(env_, headers, name, vstr); 565802Salexander.borisov@nginx.com if (status != napi_ok) { 566802Salexander.borisov@nginx.com return status; 567802Salexander.borisov@nginx.com } 568802Salexander.borisov@nginx.com 569802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, name, f->name_length, &str); 570802Salexander.borisov@nginx.com if (status != napi_ok) { 571802Salexander.borisov@nginx.com return status; 572802Salexander.borisov@nginx.com } 573802Salexander.borisov@nginx.com 574802Salexander.borisov@nginx.com status = napi_set_element(env_, raw_headers, idx * 2, str); 575802Salexander.borisov@nginx.com if (status != napi_ok) { 576802Salexander.borisov@nginx.com return status; 577802Salexander.borisov@nginx.com } 578802Salexander.borisov@nginx.com 579802Salexander.borisov@nginx.com status = napi_set_element(env_, raw_headers, idx * 2 + 1, vstr); 580802Salexander.borisov@nginx.com if (status != napi_ok) { 581802Salexander.borisov@nginx.com return status; 582802Salexander.borisov@nginx.com } 583802Salexander.borisov@nginx.com 584802Salexander.borisov@nginx.com return napi_ok; 585802Salexander.borisov@nginx.com } 586802Salexander.borisov@nginx.com 587802Salexander.borisov@nginx.com 588802Salexander.borisov@nginx.com napi_value 589802Salexander.borisov@nginx.com Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req) 590802Salexander.borisov@nginx.com { 591828Salexander.borisov@nginx.com napi_value constructor, return_val, req_pointer; 592802Salexander.borisov@nginx.com napi_status status; 593802Salexander.borisov@nginx.com 594802Salexander.borisov@nginx.com status = napi_get_named_property(env_, server_obj, "socket", 595802Salexander.borisov@nginx.com &constructor); 596802Salexander.borisov@nginx.com if (status != napi_ok) { 597802Salexander.borisov@nginx.com return nullptr; 598802Salexander.borisov@nginx.com } 599802Salexander.borisov@nginx.com 600802Salexander.borisov@nginx.com status = napi_new_instance(env_, constructor, 0, NULL, &return_val); 601802Salexander.borisov@nginx.com if (status != napi_ok) { 602802Salexander.borisov@nginx.com return nullptr; 603802Salexander.borisov@nginx.com } 604802Salexander.borisov@nginx.com 605828Salexander.borisov@nginx.com status = napi_create_int64(env_, (uintptr_t) req, &req_pointer); 606828Salexander.borisov@nginx.com if (status != napi_ok) { 607828Salexander.borisov@nginx.com return nullptr; 608828Salexander.borisov@nginx.com } 609828Salexander.borisov@nginx.com 610828Salexander.borisov@nginx.com status = napi_set_named_property(env_, return_val, "req_pointer", 611828Salexander.borisov@nginx.com req_pointer); 612828Salexander.borisov@nginx.com if (status != napi_ok) { 613828Salexander.borisov@nginx.com return nullptr; 614828Salexander.borisov@nginx.com } 615828Salexander.borisov@nginx.com 616802Salexander.borisov@nginx.com return return_val; 617802Salexander.borisov@nginx.com } 618802Salexander.borisov@nginx.com 619802Salexander.borisov@nginx.com 620802Salexander.borisov@nginx.com napi_value 621802Salexander.borisov@nginx.com Unit::create_request(napi_value server_obj, napi_value socket) 622802Salexander.borisov@nginx.com { 623802Salexander.borisov@nginx.com napi_value constructor, return_val; 624802Salexander.borisov@nginx.com napi_status status; 625802Salexander.borisov@nginx.com 626802Salexander.borisov@nginx.com status = napi_get_named_property(env_, server_obj, "request", 627802Salexander.borisov@nginx.com &constructor); 628802Salexander.borisov@nginx.com if (status != napi_ok) { 629802Salexander.borisov@nginx.com return nullptr; 630802Salexander.borisov@nginx.com } 631802Salexander.borisov@nginx.com 632802Salexander.borisov@nginx.com status = napi_new_instance(env_, constructor, 1, &server_obj, 633802Salexander.borisov@nginx.com &return_val); 634802Salexander.borisov@nginx.com if (status != napi_ok) { 635802Salexander.borisov@nginx.com return nullptr; 636802Salexander.borisov@nginx.com } 637802Salexander.borisov@nginx.com 638802Salexander.borisov@nginx.com status = napi_set_named_property(env_, return_val, "socket", socket); 639802Salexander.borisov@nginx.com if (status != napi_ok) { 640802Salexander.borisov@nginx.com return nullptr; 641802Salexander.borisov@nginx.com } 642802Salexander.borisov@nginx.com 643802Salexander.borisov@nginx.com return return_val; 644802Salexander.borisov@nginx.com } 645802Salexander.borisov@nginx.com 646802Salexander.borisov@nginx.com 647802Salexander.borisov@nginx.com napi_value 648802Salexander.borisov@nginx.com Unit::create_response(napi_value server_obj, napi_value socket, 649802Salexander.borisov@nginx.com napi_value request, nxt_unit_request_info_t *req, 650802Salexander.borisov@nginx.com Unit *obj) 651802Salexander.borisov@nginx.com { 652802Salexander.borisov@nginx.com napi_value constructor, return_val, req_num; 653802Salexander.borisov@nginx.com napi_status status; 654802Salexander.borisov@nginx.com 655802Salexander.borisov@nginx.com status = napi_get_named_property(env_, server_obj, "response", 656802Salexander.borisov@nginx.com &constructor); 657802Salexander.borisov@nginx.com if (status != napi_ok) { 658802Salexander.borisov@nginx.com return nullptr; 659802Salexander.borisov@nginx.com } 660802Salexander.borisov@nginx.com 661802Salexander.borisov@nginx.com status = napi_new_instance(env_, constructor, 1, &request, &return_val); 662802Salexander.borisov@nginx.com if (status != napi_ok) { 663802Salexander.borisov@nginx.com return nullptr; 664802Salexander.borisov@nginx.com } 665802Salexander.borisov@nginx.com 666802Salexander.borisov@nginx.com status = napi_set_named_property(env_, return_val, "socket", socket); 667802Salexander.borisov@nginx.com if (status != napi_ok) { 668802Salexander.borisov@nginx.com return nullptr; 669802Salexander.borisov@nginx.com } 670802Salexander.borisov@nginx.com 671802Salexander.borisov@nginx.com status = napi_create_int64(env_, (int64_t) (uintptr_t) req, &req_num); 672802Salexander.borisov@nginx.com if (status != napi_ok) { 673802Salexander.borisov@nginx.com return nullptr; 674802Salexander.borisov@nginx.com } 675802Salexander.borisov@nginx.com 676802Salexander.borisov@nginx.com status = napi_set_named_property(env_, return_val, "_req_point", req_num); 677802Salexander.borisov@nginx.com if (status != napi_ok) { 678802Salexander.borisov@nginx.com return nullptr; 679802Salexander.borisov@nginx.com } 680802Salexander.borisov@nginx.com 681802Salexander.borisov@nginx.com return return_val; 682802Salexander.borisov@nginx.com } 683802Salexander.borisov@nginx.com 684802Salexander.borisov@nginx.com 685802Salexander.borisov@nginx.com napi_value 686802Salexander.borisov@nginx.com Unit::response_send_headers(napi_env env, napi_callback_info info) 687802Salexander.borisov@nginx.com { 688802Salexander.borisov@nginx.com int ret; 689802Salexander.borisov@nginx.com char *ptr, *name_ptr; 690802Salexander.borisov@nginx.com bool is_array; 691802Salexander.borisov@nginx.com size_t argc, name_len, value_len; 692802Salexander.borisov@nginx.com int64_t req_p; 693802Salexander.borisov@nginx.com uint32_t status_code, header_len, keys_len, array_len; 694802Salexander.borisov@nginx.com uint32_t keys_count, i, j; 695802Salexander.borisov@nginx.com uint16_t hash; 696802Salexander.borisov@nginx.com napi_value this_arg, headers, keys, name, value, array_val; 697802Salexander.borisov@nginx.com napi_value req_num; 698802Salexander.borisov@nginx.com napi_status status; 699802Salexander.borisov@nginx.com nxt_unit_field_t *f; 700802Salexander.borisov@nginx.com nxt_unit_request_info_t *req; 701802Salexander.borisov@nginx.com napi_value argv[5]; 702802Salexander.borisov@nginx.com 703802Salexander.borisov@nginx.com argc = 5; 704802Salexander.borisov@nginx.com 705802Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, argv, &this_arg, NULL); 706802Salexander.borisov@nginx.com if (status != napi_ok) { 707802Salexander.borisov@nginx.com return nullptr; 708802Salexander.borisov@nginx.com } 709802Salexander.borisov@nginx.com 710802Salexander.borisov@nginx.com if (argc != 5) { 711802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Wrong args count. Need three: " 712802Salexander.borisov@nginx.com "statusCode, headers, headers count, headers length"); 713802Salexander.borisov@nginx.com return nullptr; 714802Salexander.borisov@nginx.com } 715802Salexander.borisov@nginx.com 716802Salexander.borisov@nginx.com status = napi_get_named_property(env, argv[0], "_req_point", &req_num); 717802Salexander.borisov@nginx.com if (status != napi_ok) { 718802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 719802Salexander.borisov@nginx.com return nullptr; 720802Salexander.borisov@nginx.com } 721802Salexander.borisov@nginx.com 722802Salexander.borisov@nginx.com status = napi_get_value_int64(env, req_num, &req_p); 723802Salexander.borisov@nginx.com if (status != napi_ok) { 724802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 725802Salexander.borisov@nginx.com return nullptr; 726802Salexander.borisov@nginx.com } 727802Salexander.borisov@nginx.com 728802Salexander.borisov@nginx.com req = (nxt_unit_request_info_t *) (uintptr_t) req_p; 729802Salexander.borisov@nginx.com 730802Salexander.borisov@nginx.com status = napi_get_value_uint32(env, argv[1], &status_code); 731802Salexander.borisov@nginx.com if (status != napi_ok) { 732802Salexander.borisov@nginx.com goto failed; 733802Salexander.borisov@nginx.com } 734802Salexander.borisov@nginx.com 735802Salexander.borisov@nginx.com status = napi_get_value_uint32(env, argv[3], &keys_count); 736802Salexander.borisov@nginx.com if (status != napi_ok) { 737802Salexander.borisov@nginx.com goto failed; 738802Salexander.borisov@nginx.com } 739802Salexander.borisov@nginx.com 740802Salexander.borisov@nginx.com status = napi_get_value_uint32(env, argv[4], &header_len); 741802Salexander.borisov@nginx.com if (status != napi_ok) { 742802Salexander.borisov@nginx.com goto failed; 743802Salexander.borisov@nginx.com } 744802Salexander.borisov@nginx.com 745802Salexander.borisov@nginx.com /* Need to reserve extra byte for C-string 0-termination. */ 746802Salexander.borisov@nginx.com header_len++; 747802Salexander.borisov@nginx.com 748802Salexander.borisov@nginx.com headers = argv[2]; 749802Salexander.borisov@nginx.com 750802Salexander.borisov@nginx.com ret = nxt_unit_response_init(req, status_code, keys_count, header_len); 751802Salexander.borisov@nginx.com if (ret != NXT_UNIT_OK) { 752802Salexander.borisov@nginx.com goto failed; 753802Salexander.borisov@nginx.com } 754802Salexander.borisov@nginx.com 755802Salexander.borisov@nginx.com status = napi_get_property_names(env, headers, &keys); 756802Salexander.borisov@nginx.com if (status != napi_ok) { 757802Salexander.borisov@nginx.com goto failed; 758802Salexander.borisov@nginx.com } 759802Salexander.borisov@nginx.com 760802Salexander.borisov@nginx.com status = napi_get_array_length(env, keys, &keys_len); 761802Salexander.borisov@nginx.com if (status != napi_ok) { 762802Salexander.borisov@nginx.com goto failed; 763802Salexander.borisov@nginx.com } 764802Salexander.borisov@nginx.com 765802Salexander.borisov@nginx.com ptr = req->response_buf->free; 766802Salexander.borisov@nginx.com 767802Salexander.borisov@nginx.com for (i = 0; i < keys_len; i++) { 768802Salexander.borisov@nginx.com status = napi_get_element(env, keys, i, &name); 769802Salexander.borisov@nginx.com if (status != napi_ok) { 770802Salexander.borisov@nginx.com goto failed; 771802Salexander.borisov@nginx.com } 772802Salexander.borisov@nginx.com 773802Salexander.borisov@nginx.com status = napi_get_property(env, headers, name, &value); 774802Salexander.borisov@nginx.com if (status != napi_ok) { 775802Salexander.borisov@nginx.com goto failed; 776802Salexander.borisov@nginx.com } 777802Salexander.borisov@nginx.com 778802Salexander.borisov@nginx.com status = napi_get_value_string_latin1(env, name, ptr, header_len, 779802Salexander.borisov@nginx.com &name_len); 780802Salexander.borisov@nginx.com if (status != napi_ok) { 781802Salexander.borisov@nginx.com goto failed; 782802Salexander.borisov@nginx.com } 783802Salexander.borisov@nginx.com 784802Salexander.borisov@nginx.com name_ptr = ptr; 785802Salexander.borisov@nginx.com 786802Salexander.borisov@nginx.com ptr += name_len; 787802Salexander.borisov@nginx.com header_len -= name_len; 788802Salexander.borisov@nginx.com 789802Salexander.borisov@nginx.com hash = nxt_unit_field_hash(name_ptr, name_len); 790802Salexander.borisov@nginx.com 791802Salexander.borisov@nginx.com status = napi_is_array(env, value, &is_array); 792802Salexander.borisov@nginx.com if (status != napi_ok) { 793802Salexander.borisov@nginx.com goto failed; 794802Salexander.borisov@nginx.com } 795802Salexander.borisov@nginx.com 796802Salexander.borisov@nginx.com if (is_array) { 797802Salexander.borisov@nginx.com status = napi_get_array_length(env, value, &array_len); 798802Salexander.borisov@nginx.com if (status != napi_ok) { 799802Salexander.borisov@nginx.com goto failed; 800802Salexander.borisov@nginx.com } 801802Salexander.borisov@nginx.com 802802Salexander.borisov@nginx.com for (j = 0; j < array_len; j++) { 803802Salexander.borisov@nginx.com status = napi_get_element(env, value, j, &array_val); 804802Salexander.borisov@nginx.com if (status != napi_ok) { 805802Salexander.borisov@nginx.com goto failed; 806802Salexander.borisov@nginx.com } 807802Salexander.borisov@nginx.com 808802Salexander.borisov@nginx.com status = napi_get_value_string_latin1(env, array_val, ptr, 809802Salexander.borisov@nginx.com header_len, 810802Salexander.borisov@nginx.com &value_len); 811802Salexander.borisov@nginx.com if (status != napi_ok) { 812802Salexander.borisov@nginx.com goto failed; 813802Salexander.borisov@nginx.com } 814802Salexander.borisov@nginx.com 815802Salexander.borisov@nginx.com f = req->response->fields + req->response->fields_count; 816802Salexander.borisov@nginx.com f->skip = 0; 817802Salexander.borisov@nginx.com 818802Salexander.borisov@nginx.com nxt_unit_sptr_set(&f->name, name_ptr); 819802Salexander.borisov@nginx.com 820802Salexander.borisov@nginx.com f->name_length = name_len; 821802Salexander.borisov@nginx.com f->hash = hash; 822802Salexander.borisov@nginx.com 823802Salexander.borisov@nginx.com nxt_unit_sptr_set(&f->value, ptr); 824802Salexander.borisov@nginx.com f->value_length = (uint32_t) value_len; 825802Salexander.borisov@nginx.com 826802Salexander.borisov@nginx.com ptr += value_len; 827802Salexander.borisov@nginx.com header_len -= value_len; 828802Salexander.borisov@nginx.com 829802Salexander.borisov@nginx.com req->response->fields_count++; 830802Salexander.borisov@nginx.com } 831802Salexander.borisov@nginx.com 832802Salexander.borisov@nginx.com } else { 833802Salexander.borisov@nginx.com status = napi_get_value_string_latin1(env, value, ptr, header_len, 834802Salexander.borisov@nginx.com &value_len); 835802Salexander.borisov@nginx.com if (status != napi_ok) { 836802Salexander.borisov@nginx.com goto failed; 837802Salexander.borisov@nginx.com } 838802Salexander.borisov@nginx.com 839802Salexander.borisov@nginx.com f = req->response->fields + req->response->fields_count; 840802Salexander.borisov@nginx.com f->skip = 0; 841802Salexander.borisov@nginx.com 842802Salexander.borisov@nginx.com nxt_unit_sptr_set(&f->name, name_ptr); 843802Salexander.borisov@nginx.com 844802Salexander.borisov@nginx.com f->name_length = name_len; 845802Salexander.borisov@nginx.com f->hash = hash; 846802Salexander.borisov@nginx.com 847802Salexander.borisov@nginx.com nxt_unit_sptr_set(&f->value, ptr); 848802Salexander.borisov@nginx.com f->value_length = (uint32_t) value_len; 849802Salexander.borisov@nginx.com 850802Salexander.borisov@nginx.com ptr += value_len; 851802Salexander.borisov@nginx.com header_len -= value_len; 852802Salexander.borisov@nginx.com 853802Salexander.borisov@nginx.com req->response->fields_count++; 854802Salexander.borisov@nginx.com } 855802Salexander.borisov@nginx.com } 856802Salexander.borisov@nginx.com 857802Salexander.borisov@nginx.com req->response_buf->free = ptr; 858802Salexander.borisov@nginx.com 859802Salexander.borisov@nginx.com ret = nxt_unit_response_send(req); 860802Salexander.borisov@nginx.com if (ret != NXT_UNIT_OK) { 861802Salexander.borisov@nginx.com goto failed; 862802Salexander.borisov@nginx.com } 863802Salexander.borisov@nginx.com 864802Salexander.borisov@nginx.com return this_arg; 865802Salexander.borisov@nginx.com 866802Salexander.borisov@nginx.com failed: 867802Salexander.borisov@nginx.com 868802Salexander.borisov@nginx.com req->response->fields_count = 0; 869802Salexander.borisov@nginx.com 870802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to write headers"); 871802Salexander.borisov@nginx.com 872802Salexander.borisov@nginx.com return nullptr; 873802Salexander.borisov@nginx.com } 874802Salexander.borisov@nginx.com 875802Salexander.borisov@nginx.com 876802Salexander.borisov@nginx.com napi_value 877802Salexander.borisov@nginx.com Unit::response_write(napi_env env, napi_callback_info info) 878802Salexander.borisov@nginx.com { 879802Salexander.borisov@nginx.com int ret; 880802Salexander.borisov@nginx.com char *ptr; 881802Salexander.borisov@nginx.com size_t argc, have_buf_len; 882802Salexander.borisov@nginx.com int64_t req_p; 883802Salexander.borisov@nginx.com uint32_t buf_len; 884802Salexander.borisov@nginx.com napi_value this_arg, req_num; 885802Salexander.borisov@nginx.com napi_status status; 886802Salexander.borisov@nginx.com nxt_unit_buf_t *buf; 887802Salexander.borisov@nginx.com napi_valuetype buf_type; 888802Salexander.borisov@nginx.com nxt_unit_request_info_t *req; 889802Salexander.borisov@nginx.com napi_value argv[3]; 890802Salexander.borisov@nginx.com 891802Salexander.borisov@nginx.com argc = 3; 892802Salexander.borisov@nginx.com 893802Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, argv, &this_arg, NULL); 894802Salexander.borisov@nginx.com if (status != napi_ok) { 895802Salexander.borisov@nginx.com goto failed; 896802Salexander.borisov@nginx.com } 897802Salexander.borisov@nginx.com 898802Salexander.borisov@nginx.com if (argc != 3) { 899802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Wrong args count. Need two: " 900802Salexander.borisov@nginx.com "chunk, chunk length"); 901802Salexander.borisov@nginx.com return nullptr; 902802Salexander.borisov@nginx.com } 903802Salexander.borisov@nginx.com 904802Salexander.borisov@nginx.com status = napi_get_named_property(env, argv[0], "_req_point", &req_num); 905802Salexander.borisov@nginx.com if (status != napi_ok) { 906802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 907802Salexander.borisov@nginx.com return nullptr; 908802Salexander.borisov@nginx.com } 909802Salexander.borisov@nginx.com 910802Salexander.borisov@nginx.com status = napi_get_value_int64(env, req_num, &req_p); 911802Salexander.borisov@nginx.com if (status != napi_ok) { 912802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 913802Salexander.borisov@nginx.com return nullptr; 914802Salexander.borisov@nginx.com } 915802Salexander.borisov@nginx.com 916802Salexander.borisov@nginx.com req = (nxt_unit_request_info_t *) (uintptr_t) req_p; 917802Salexander.borisov@nginx.com 918802Salexander.borisov@nginx.com status = napi_get_value_uint32(env, argv[2], &buf_len); 919802Salexander.borisov@nginx.com if (status != napi_ok) { 920802Salexander.borisov@nginx.com goto failed; 921802Salexander.borisov@nginx.com } 922802Salexander.borisov@nginx.com 923802Salexander.borisov@nginx.com status = napi_typeof(env, argv[1], &buf_type); 924802Salexander.borisov@nginx.com if (status != napi_ok) { 925802Salexander.borisov@nginx.com goto failed; 926802Salexander.borisov@nginx.com } 927802Salexander.borisov@nginx.com 928802Salexander.borisov@nginx.com buf_len++; 929802Salexander.borisov@nginx.com 930802Salexander.borisov@nginx.com buf = nxt_unit_response_buf_alloc(req, buf_len); 931802Salexander.borisov@nginx.com if (buf == NULL) { 932802Salexander.borisov@nginx.com goto failed; 933802Salexander.borisov@nginx.com } 934802Salexander.borisov@nginx.com 935802Salexander.borisov@nginx.com if (buf_type == napi_string) { 936802Salexander.borisov@nginx.com /* TODO: will work only for utf8 content-type */ 937802Salexander.borisov@nginx.com 938802Salexander.borisov@nginx.com status = napi_get_value_string_utf8(env, argv[1], buf->free, 939802Salexander.borisov@nginx.com buf_len, &have_buf_len); 940802Salexander.borisov@nginx.com 941802Salexander.borisov@nginx.com } else { 942802Salexander.borisov@nginx.com status = napi_get_buffer_info(env, argv[1], (void **) &ptr, 943802Salexander.borisov@nginx.com &have_buf_len); 944802Salexander.borisov@nginx.com 945802Salexander.borisov@nginx.com memcpy(buf->free, ptr, have_buf_len); 946802Salexander.borisov@nginx.com } 947802Salexander.borisov@nginx.com 948802Salexander.borisov@nginx.com if (status != napi_ok) { 949802Salexander.borisov@nginx.com goto failed; 950802Salexander.borisov@nginx.com } 951802Salexander.borisov@nginx.com 952802Salexander.borisov@nginx.com buf->free += have_buf_len; 953802Salexander.borisov@nginx.com 954802Salexander.borisov@nginx.com ret = nxt_unit_buf_send(buf); 955802Salexander.borisov@nginx.com if (ret != NXT_UNIT_OK) { 956802Salexander.borisov@nginx.com goto failed; 957802Salexander.borisov@nginx.com } 958802Salexander.borisov@nginx.com 959802Salexander.borisov@nginx.com return this_arg; 960802Salexander.borisov@nginx.com 961802Salexander.borisov@nginx.com failed: 962802Salexander.borisov@nginx.com 963802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to write body"); 964802Salexander.borisov@nginx.com 965802Salexander.borisov@nginx.com return nullptr; 966802Salexander.borisov@nginx.com } 967802Salexander.borisov@nginx.com 968802Salexander.borisov@nginx.com 969802Salexander.borisov@nginx.com napi_value 970802Salexander.borisov@nginx.com Unit::response_end(napi_env env, napi_callback_info info) 971802Salexander.borisov@nginx.com { 972802Salexander.borisov@nginx.com size_t argc; 973802Salexander.borisov@nginx.com int64_t req_p; 974802Salexander.borisov@nginx.com napi_value resp, this_arg, req_num; 975802Salexander.borisov@nginx.com napi_status status; 976802Salexander.borisov@nginx.com nxt_unit_request_info_t *req; 977802Salexander.borisov@nginx.com 978802Salexander.borisov@nginx.com argc = 1; 979802Salexander.borisov@nginx.com 980802Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, &resp, &this_arg, NULL); 981802Salexander.borisov@nginx.com if (status != napi_ok) { 982802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to finalize sending body"); 983802Salexander.borisov@nginx.com return nullptr; 984802Salexander.borisov@nginx.com } 985802Salexander.borisov@nginx.com 986802Salexander.borisov@nginx.com status = napi_get_named_property(env, resp, "_req_point", &req_num); 987802Salexander.borisov@nginx.com if (status != napi_ok) { 988802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 989802Salexander.borisov@nginx.com return nullptr; 990802Salexander.borisov@nginx.com } 991802Salexander.borisov@nginx.com 992802Salexander.borisov@nginx.com status = napi_get_value_int64(env, req_num, &req_p); 993802Salexander.borisov@nginx.com if (status != napi_ok) { 994802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 995802Salexander.borisov@nginx.com return nullptr; 996802Salexander.borisov@nginx.com } 997802Salexander.borisov@nginx.com 998802Salexander.borisov@nginx.com req = (nxt_unit_request_info_t *) (uintptr_t) req_p; 999802Salexander.borisov@nginx.com 1000802Salexander.borisov@nginx.com nxt_unit_request_done(req, NXT_UNIT_OK); 1001802Salexander.borisov@nginx.com 1002802Salexander.borisov@nginx.com return this_arg; 1003802Salexander.borisov@nginx.com } 1004