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 17802Salexander.borisov@nginx.com Unit::Unit(napi_env env): 18802Salexander.borisov@nginx.com env_(env), 19802Salexander.borisov@nginx.com wrapper_(nullptr), 20802Salexander.borisov@nginx.com unit_ctx_(nullptr) 21802Salexander.borisov@nginx.com { 22802Salexander.borisov@nginx.com } 23802Salexander.borisov@nginx.com 24802Salexander.borisov@nginx.com 25802Salexander.borisov@nginx.com Unit::~Unit() 26802Salexander.borisov@nginx.com { 27802Salexander.borisov@nginx.com napi_delete_reference(env_, wrapper_); 28802Salexander.borisov@nginx.com } 29802Salexander.borisov@nginx.com 30802Salexander.borisov@nginx.com 31802Salexander.borisov@nginx.com napi_value 32802Salexander.borisov@nginx.com Unit::init(napi_env env, napi_value exports) 33802Salexander.borisov@nginx.com { 34802Salexander.borisov@nginx.com napi_value cons, fn; 35802Salexander.borisov@nginx.com napi_status status; 36802Salexander.borisov@nginx.com 37802Salexander.borisov@nginx.com napi_property_descriptor properties[] = { 38802Salexander.borisov@nginx.com { "createServer", 0, create_server, 0, 0, 0, napi_default, 0 }, 39828Salexander.borisov@nginx.com { "listen", 0, listen, 0, 0, 0, napi_default, 0 }, 40828Salexander.borisov@nginx.com { "_read", 0, _read, 0, 0, 0, napi_default, 0 } 41802Salexander.borisov@nginx.com }; 42802Salexander.borisov@nginx.com 43802Salexander.borisov@nginx.com status = napi_define_class(env, "Unit", NAPI_AUTO_LENGTH, create, nullptr, 44828Salexander.borisov@nginx.com 3, properties, &cons); 45802Salexander.borisov@nginx.com if (status != napi_ok) { 46802Salexander.borisov@nginx.com goto failed; 47802Salexander.borisov@nginx.com } 48802Salexander.borisov@nginx.com 49802Salexander.borisov@nginx.com status = napi_create_reference(env, cons, 1, &constructor_); 50802Salexander.borisov@nginx.com if (status != napi_ok) { 51802Salexander.borisov@nginx.com goto failed; 52802Salexander.borisov@nginx.com } 53802Salexander.borisov@nginx.com 54802Salexander.borisov@nginx.com status = napi_set_named_property(env, exports, "Unit", cons); 55802Salexander.borisov@nginx.com if (status != napi_ok) { 56802Salexander.borisov@nginx.com goto failed; 57802Salexander.borisov@nginx.com } 58802Salexander.borisov@nginx.com 59802Salexander.borisov@nginx.com status = napi_create_function(env, NULL, 0, response_send_headers, NULL, 60802Salexander.borisov@nginx.com &fn); 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_set_named_property(env, exports, 66802Salexander.borisov@nginx.com "unit_response_headers", 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_create_function(env, NULL, 0, response_write, NULL, &fn); 72802Salexander.borisov@nginx.com if (status != napi_ok) { 73802Salexander.borisov@nginx.com goto failed; 74802Salexander.borisov@nginx.com } 75802Salexander.borisov@nginx.com 76802Salexander.borisov@nginx.com status = napi_set_named_property(env, exports, "unit_response_write", fn); 77802Salexander.borisov@nginx.com if (status != napi_ok) { 78802Salexander.borisov@nginx.com goto failed; 79802Salexander.borisov@nginx.com } 80802Salexander.borisov@nginx.com 81802Salexander.borisov@nginx.com status = napi_create_function(env, NULL, 0, response_end, NULL, &fn); 82802Salexander.borisov@nginx.com if (status != napi_ok) { 83802Salexander.borisov@nginx.com goto failed; 84802Salexander.borisov@nginx.com } 85802Salexander.borisov@nginx.com 86802Salexander.borisov@nginx.com status = napi_set_named_property(env, exports, "unit_response_end", fn); 87802Salexander.borisov@nginx.com if (status != napi_ok) { 88802Salexander.borisov@nginx.com goto failed; 89802Salexander.borisov@nginx.com } 90802Salexander.borisov@nginx.com 91802Salexander.borisov@nginx.com return exports; 92802Salexander.borisov@nginx.com 93802Salexander.borisov@nginx.com failed: 94802Salexander.borisov@nginx.com 95802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to define Unit class"); 96802Salexander.borisov@nginx.com 97802Salexander.borisov@nginx.com return nullptr; 98802Salexander.borisov@nginx.com } 99802Salexander.borisov@nginx.com 100802Salexander.borisov@nginx.com 101802Salexander.borisov@nginx.com void 102802Salexander.borisov@nginx.com Unit::destroy(napi_env env, void *nativeObject, void *finalize_hint) 103802Salexander.borisov@nginx.com { 104802Salexander.borisov@nginx.com Unit *obj = reinterpret_cast<Unit *>(nativeObject); 105802Salexander.borisov@nginx.com 106802Salexander.borisov@nginx.com delete obj; 107802Salexander.borisov@nginx.com } 108802Salexander.borisov@nginx.com 109802Salexander.borisov@nginx.com 110802Salexander.borisov@nginx.com napi_value 111802Salexander.borisov@nginx.com Unit::create(napi_env env, napi_callback_info info) 112802Salexander.borisov@nginx.com { 113802Salexander.borisov@nginx.com Unit *obj; 114*841Salexander.borisov@nginx.com napi_ref ref; 115802Salexander.borisov@nginx.com napi_value target, cons, instance, jsthis; 116802Salexander.borisov@nginx.com napi_status status; 117802Salexander.borisov@nginx.com 118802Salexander.borisov@nginx.com status = napi_get_new_target(env, info, &target); 119802Salexander.borisov@nginx.com if (status != napi_ok) { 120802Salexander.borisov@nginx.com goto failed; 121802Salexander.borisov@nginx.com } 122802Salexander.borisov@nginx.com 123802Salexander.borisov@nginx.com if (target != nullptr) { 124802Salexander.borisov@nginx.com /* Invoked as constructor: `new Unit(...)` */ 125802Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, nullptr, nullptr, &jsthis, 126802Salexander.borisov@nginx.com nullptr); 127802Salexander.borisov@nginx.com if (status != napi_ok) { 128802Salexander.borisov@nginx.com goto failed; 129802Salexander.borisov@nginx.com } 130802Salexander.borisov@nginx.com 131802Salexander.borisov@nginx.com obj = new Unit(env); 132802Salexander.borisov@nginx.com 133802Salexander.borisov@nginx.com status = napi_wrap(env, jsthis, reinterpret_cast<void *>(obj), 134802Salexander.borisov@nginx.com destroy, nullptr, &obj->wrapper_); 135802Salexander.borisov@nginx.com if (status != napi_ok) { 136802Salexander.borisov@nginx.com goto failed; 137802Salexander.borisov@nginx.com } 138802Salexander.borisov@nginx.com 139*841Salexander.borisov@nginx.com status = napi_create_reference(env, jsthis, 1, &ref); 140*841Salexander.borisov@nginx.com if (status != napi_ok) { 141*841Salexander.borisov@nginx.com goto failed; 142*841Salexander.borisov@nginx.com } 143*841Salexander.borisov@nginx.com 144802Salexander.borisov@nginx.com return jsthis; 145802Salexander.borisov@nginx.com } 146802Salexander.borisov@nginx.com 147802Salexander.borisov@nginx.com /* Invoked as plain function `Unit(...)`, turn into construct call. */ 148802Salexander.borisov@nginx.com status = napi_get_reference_value(env, constructor_, &cons); 149802Salexander.borisov@nginx.com if (status != napi_ok) { 150802Salexander.borisov@nginx.com goto failed; 151802Salexander.borisov@nginx.com } 152802Salexander.borisov@nginx.com 153802Salexander.borisov@nginx.com status = napi_new_instance(env, cons, 0, nullptr, &instance); 154802Salexander.borisov@nginx.com if (status != napi_ok) { 155802Salexander.borisov@nginx.com goto failed; 156802Salexander.borisov@nginx.com } 157802Salexander.borisov@nginx.com 158*841Salexander.borisov@nginx.com status = napi_create_reference(env, instance, 1, &ref); 159*841Salexander.borisov@nginx.com if (status != napi_ok) { 160*841Salexander.borisov@nginx.com goto failed; 161*841Salexander.borisov@nginx.com } 162*841Salexander.borisov@nginx.com 163802Salexander.borisov@nginx.com return instance; 164802Salexander.borisov@nginx.com 165802Salexander.borisov@nginx.com failed: 166802Salexander.borisov@nginx.com 167802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to create Unit object"); 168802Salexander.borisov@nginx.com 169802Salexander.borisov@nginx.com return nullptr; 170802Salexander.borisov@nginx.com } 171802Salexander.borisov@nginx.com 172802Salexander.borisov@nginx.com 173802Salexander.borisov@nginx.com napi_value 174802Salexander.borisov@nginx.com Unit::create_server(napi_env env, napi_callback_info info) 175802Salexander.borisov@nginx.com { 176802Salexander.borisov@nginx.com Unit *obj; 177802Salexander.borisov@nginx.com size_t argc; 178828Salexander.borisov@nginx.com napi_value jsthis, argv; 179802Salexander.borisov@nginx.com napi_status status; 180802Salexander.borisov@nginx.com nxt_unit_init_t unit_init; 181802Salexander.borisov@nginx.com 182802Salexander.borisov@nginx.com argc = 1; 183802Salexander.borisov@nginx.com 184828Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, &argv, &jsthis, nullptr); 185802Salexander.borisov@nginx.com if (status != napi_ok) { 186802Salexander.borisov@nginx.com goto failed; 187802Salexander.borisov@nginx.com } 188802Salexander.borisov@nginx.com 189802Salexander.borisov@nginx.com status = napi_unwrap(env, jsthis, reinterpret_cast<void **>(&obj)); 190802Salexander.borisov@nginx.com if (status != napi_ok) { 191802Salexander.borisov@nginx.com goto failed; 192802Salexander.borisov@nginx.com } 193802Salexander.borisov@nginx.com 194802Salexander.borisov@nginx.com memset(&unit_init, 0, sizeof(nxt_unit_init_t)); 195802Salexander.borisov@nginx.com 196802Salexander.borisov@nginx.com unit_init.data = obj; 197802Salexander.borisov@nginx.com unit_init.callbacks.request_handler = request_handler; 198828Salexander.borisov@nginx.com unit_init.callbacks.add_port = add_port; 199828Salexander.borisov@nginx.com unit_init.callbacks.remove_port = remove_port; 200802Salexander.borisov@nginx.com 201802Salexander.borisov@nginx.com obj->unit_ctx_ = nxt_unit_init(&unit_init); 202802Salexander.borisov@nginx.com if (obj->unit_ctx_ == NULL) { 203802Salexander.borisov@nginx.com goto failed; 204802Salexander.borisov@nginx.com } 205802Salexander.borisov@nginx.com 206802Salexander.borisov@nginx.com return nullptr; 207802Salexander.borisov@nginx.com 208802Salexander.borisov@nginx.com failed: 209802Salexander.borisov@nginx.com 210802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to create Unit object"); 211802Salexander.borisov@nginx.com 212802Salexander.borisov@nginx.com return nullptr; 213802Salexander.borisov@nginx.com } 214802Salexander.borisov@nginx.com 215802Salexander.borisov@nginx.com 216802Salexander.borisov@nginx.com napi_value 217802Salexander.borisov@nginx.com Unit::listen(napi_env env, napi_callback_info info) 218802Salexander.borisov@nginx.com { 219828Salexander.borisov@nginx.com return nullptr; 220828Salexander.borisov@nginx.com } 221828Salexander.borisov@nginx.com 222802Salexander.borisov@nginx.com 223828Salexander.borisov@nginx.com napi_value 224828Salexander.borisov@nginx.com Unit::_read(napi_env env, napi_callback_info info) 225828Salexander.borisov@nginx.com { 226828Salexander.borisov@nginx.com Unit *obj; 227828Salexander.borisov@nginx.com void *data; 228828Salexander.borisov@nginx.com size_t argc; 229828Salexander.borisov@nginx.com int64_t req_pointer; 230828Salexander.borisov@nginx.com napi_value jsthis, buffer, argv; 231828Salexander.borisov@nginx.com napi_status status; 232828Salexander.borisov@nginx.com nxt_unit_request_info_t *req; 233828Salexander.borisov@nginx.com 234828Salexander.borisov@nginx.com argc = 1; 235828Salexander.borisov@nginx.com 236828Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, &argv, &jsthis, nullptr); 237802Salexander.borisov@nginx.com if (status != napi_ok) { 238828Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get arguments from js"); 239828Salexander.borisov@nginx.com return nullptr; 240802Salexander.borisov@nginx.com } 241802Salexander.borisov@nginx.com 242802Salexander.borisov@nginx.com status = napi_unwrap(env, jsthis, reinterpret_cast<void **>(&obj)); 243802Salexander.borisov@nginx.com if (status != napi_ok) { 244828Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get Unit object form js"); 245828Salexander.borisov@nginx.com return nullptr; 246802Salexander.borisov@nginx.com } 247802Salexander.borisov@nginx.com 248828Salexander.borisov@nginx.com status = napi_get_value_int64(env, argv, &req_pointer); 249828Salexander.borisov@nginx.com if (status != napi_ok) { 250828Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 251802Salexander.borisov@nginx.com return nullptr; 252802Salexander.borisov@nginx.com } 253802Salexander.borisov@nginx.com 254828Salexander.borisov@nginx.com req = (nxt_unit_request_info_t *) (uintptr_t) req_pointer; 255828Salexander.borisov@nginx.com 256828Salexander.borisov@nginx.com status = napi_create_buffer(env, (size_t) req->content_length, 257828Salexander.borisov@nginx.com &data, &buffer); 258828Salexander.borisov@nginx.com if (status != napi_ok) { 259828Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to create request buffer"); 260802Salexander.borisov@nginx.com return nullptr; 261802Salexander.borisov@nginx.com } 262802Salexander.borisov@nginx.com 263828Salexander.borisov@nginx.com nxt_unit_request_read(req, data, req->content_length); 264802Salexander.borisov@nginx.com 265828Salexander.borisov@nginx.com return buffer; 266802Salexander.borisov@nginx.com } 267802Salexander.borisov@nginx.com 268802Salexander.borisov@nginx.com 269802Salexander.borisov@nginx.com void 270802Salexander.borisov@nginx.com Unit::request_handler(nxt_unit_request_info_t *req) 271802Salexander.borisov@nginx.com { 272802Salexander.borisov@nginx.com Unit *obj; 273802Salexander.borisov@nginx.com napi_value socket, request, response; 274802Salexander.borisov@nginx.com napi_value global, server_obj; 275828Salexander.borisov@nginx.com napi_value run_events, events_res; 276802Salexander.borisov@nginx.com napi_status status; 277828Salexander.borisov@nginx.com napi_value events_args[3]; 278802Salexander.borisov@nginx.com 279802Salexander.borisov@nginx.com obj = reinterpret_cast<Unit *>(req->unit->data); 280802Salexander.borisov@nginx.com 281802Salexander.borisov@nginx.com napi_handle_scope scope; 282802Salexander.borisov@nginx.com status = napi_open_handle_scope(obj->env_, &scope); 283802Salexander.borisov@nginx.com if (status != napi_ok) { 284802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create handle scope"); 285802Salexander.borisov@nginx.com return; 286802Salexander.borisov@nginx.com } 287802Salexander.borisov@nginx.com 288802Salexander.borisov@nginx.com server_obj = obj->get_server_object(); 289802Salexander.borisov@nginx.com if (server_obj == nullptr) { 290802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to get server object"); 291802Salexander.borisov@nginx.com return; 292802Salexander.borisov@nginx.com } 293802Salexander.borisov@nginx.com 294802Salexander.borisov@nginx.com status = napi_get_global(obj->env_, &global); 295802Salexander.borisov@nginx.com if (status != napi_ok) { 296802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to get global variable"); 297802Salexander.borisov@nginx.com return; 298802Salexander.borisov@nginx.com } 299802Salexander.borisov@nginx.com 300802Salexander.borisov@nginx.com socket = obj->create_socket(server_obj, req); 301802Salexander.borisov@nginx.com if (socket == nullptr) { 302802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create socket object"); 303802Salexander.borisov@nginx.com return; 304802Salexander.borisov@nginx.com } 305802Salexander.borisov@nginx.com 306802Salexander.borisov@nginx.com request = obj->create_request(server_obj, socket); 307802Salexander.borisov@nginx.com if (request == nullptr) { 308802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create request object"); 309802Salexander.borisov@nginx.com return; 310802Salexander.borisov@nginx.com } 311802Salexander.borisov@nginx.com 312802Salexander.borisov@nginx.com response = obj->create_response(server_obj, socket, request, req, obj); 313802Salexander.borisov@nginx.com if (response == nullptr) { 314802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create response object"); 315802Salexander.borisov@nginx.com return; 316802Salexander.borisov@nginx.com } 317802Salexander.borisov@nginx.com 318802Salexander.borisov@nginx.com status = obj->create_headers(req, request); 319802Salexander.borisov@nginx.com if (status != napi_ok) { 320802Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to create headers"); 321802Salexander.borisov@nginx.com return; 322802Salexander.borisov@nginx.com } 323802Salexander.borisov@nginx.com 324828Salexander.borisov@nginx.com status = napi_get_named_property(obj->env_, server_obj, "run_events", 325828Salexander.borisov@nginx.com &run_events); 326828Salexander.borisov@nginx.com if (status != napi_ok) { 327828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to get" 328828Salexander.borisov@nginx.com " 'run_events' function"); 329828Salexander.borisov@nginx.com return; 330828Salexander.borisov@nginx.com } 331828Salexander.borisov@nginx.com 332828Salexander.borisov@nginx.com events_args[0] = server_obj; 333828Salexander.borisov@nginx.com events_args[1] = request; 334828Salexander.borisov@nginx.com events_args[2] = response; 335828Salexander.borisov@nginx.com 336828Salexander.borisov@nginx.com status = napi_call_function(obj->env_, server_obj, run_events, 3, 337828Salexander.borisov@nginx.com events_args, &events_res); 338828Salexander.borisov@nginx.com if (status != napi_ok) { 339828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to call" 340828Salexander.borisov@nginx.com " 'run_events' function"); 341828Salexander.borisov@nginx.com return; 342828Salexander.borisov@nginx.com } 343802Salexander.borisov@nginx.com 344802Salexander.borisov@nginx.com napi_close_handle_scope(obj->env_, scope); 345802Salexander.borisov@nginx.com } 346802Salexander.borisov@nginx.com 347802Salexander.borisov@nginx.com 348828Salexander.borisov@nginx.com void 349828Salexander.borisov@nginx.com nxt_uv_read_callback(uv_poll_t *handle, int status, int events) 350828Salexander.borisov@nginx.com { 351828Salexander.borisov@nginx.com nxt_unit_run_once((nxt_unit_ctx_t *) handle->data); 352828Salexander.borisov@nginx.com } 353828Salexander.borisov@nginx.com 354828Salexander.borisov@nginx.com 355828Salexander.borisov@nginx.com int 356828Salexander.borisov@nginx.com Unit::add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port) 357828Salexander.borisov@nginx.com { 358828Salexander.borisov@nginx.com int err; 359828Salexander.borisov@nginx.com Unit *obj; 360828Salexander.borisov@nginx.com uv_loop_t *loop; 361828Salexander.borisov@nginx.com uv_poll_t *uv_handle; 362828Salexander.borisov@nginx.com napi_status status; 363828Salexander.borisov@nginx.com 364828Salexander.borisov@nginx.com if (port->in_fd != -1) { 365828Salexander.borisov@nginx.com obj = reinterpret_cast<Unit *>(ctx->unit->data); 366828Salexander.borisov@nginx.com 367828Salexander.borisov@nginx.com if (fcntl(port->in_fd, F_SETFL, O_NONBLOCK) == -1) { 368828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to upgrade read" 369828Salexander.borisov@nginx.com " file descriptor to O_NONBLOCK"); 370828Salexander.borisov@nginx.com return -1; 371828Salexander.borisov@nginx.com } 372828Salexander.borisov@nginx.com 373828Salexander.borisov@nginx.com status = napi_get_uv_event_loop(obj->env_, &loop); 374828Salexander.borisov@nginx.com if (status != napi_ok) { 375828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to get uv.loop"); 376828Salexander.borisov@nginx.com return NXT_UNIT_ERROR; 377828Salexander.borisov@nginx.com } 378828Salexander.borisov@nginx.com 379828Salexander.borisov@nginx.com uv_handle = new uv_poll_t; 380828Salexander.borisov@nginx.com 381828Salexander.borisov@nginx.com err = uv_poll_init(loop, uv_handle, port->in_fd); 382828Salexander.borisov@nginx.com if (err < 0) { 383828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to init uv.poll"); 384828Salexander.borisov@nginx.com return NXT_UNIT_ERROR; 385828Salexander.borisov@nginx.com } 386828Salexander.borisov@nginx.com 387828Salexander.borisov@nginx.com err = uv_poll_start(uv_handle, UV_READABLE, nxt_uv_read_callback); 388828Salexander.borisov@nginx.com if (err < 0) { 389828Salexander.borisov@nginx.com napi_throw_error(obj->env_, NULL, "Failed to start uv.poll"); 390828Salexander.borisov@nginx.com return NXT_UNIT_ERROR; 391828Salexander.borisov@nginx.com } 392828Salexander.borisov@nginx.com 393828Salexander.borisov@nginx.com port->data = uv_handle; 394828Salexander.borisov@nginx.com uv_handle->data = ctx; 395828Salexander.borisov@nginx.com } 396828Salexander.borisov@nginx.com 397828Salexander.borisov@nginx.com return nxt_unit_add_port(ctx, port); 398828Salexander.borisov@nginx.com } 399828Salexander.borisov@nginx.com 400828Salexander.borisov@nginx.com 401828Salexander.borisov@nginx.com void 402828Salexander.borisov@nginx.com Unit::remove_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id) 403828Salexander.borisov@nginx.com { 404828Salexander.borisov@nginx.com nxt_unit_port_t *port; 405828Salexander.borisov@nginx.com 406828Salexander.borisov@nginx.com port = nxt_unit_find_port(ctx, port_id); 407828Salexander.borisov@nginx.com if (port == NULL) { 408828Salexander.borisov@nginx.com return; 409828Salexander.borisov@nginx.com } 410828Salexander.borisov@nginx.com 411828Salexander.borisov@nginx.com if (port->in_fd != -1 && port->data != NULL) { 412828Salexander.borisov@nginx.com uv_poll_stop((uv_poll_t *) port->data); 413828Salexander.borisov@nginx.com 414828Salexander.borisov@nginx.com delete (uv_poll_t *) port->data; 415828Salexander.borisov@nginx.com } 416828Salexander.borisov@nginx.com 417828Salexander.borisov@nginx.com nxt_unit_remove_port(ctx, port_id); 418828Salexander.borisov@nginx.com } 419828Salexander.borisov@nginx.com 420828Salexander.borisov@nginx.com 421802Salexander.borisov@nginx.com napi_value 422802Salexander.borisov@nginx.com Unit::get_server_object() 423802Salexander.borisov@nginx.com { 424802Salexander.borisov@nginx.com napi_value unit_obj, server_obj; 425802Salexander.borisov@nginx.com napi_status status; 426802Salexander.borisov@nginx.com 427802Salexander.borisov@nginx.com status = napi_get_reference_value(env_, wrapper_, &unit_obj); 428802Salexander.borisov@nginx.com if (status != napi_ok) { 429802Salexander.borisov@nginx.com return nullptr; 430802Salexander.borisov@nginx.com } 431802Salexander.borisov@nginx.com 432802Salexander.borisov@nginx.com status = napi_get_named_property(env_, unit_obj, "server", &server_obj); 433802Salexander.borisov@nginx.com if (status != napi_ok) { 434802Salexander.borisov@nginx.com return nullptr; 435802Salexander.borisov@nginx.com } 436802Salexander.borisov@nginx.com 437802Salexander.borisov@nginx.com return server_obj; 438802Salexander.borisov@nginx.com } 439802Salexander.borisov@nginx.com 440802Salexander.borisov@nginx.com 441802Salexander.borisov@nginx.com napi_status 442802Salexander.borisov@nginx.com Unit::create_headers(nxt_unit_request_info_t *req, napi_value request) 443802Salexander.borisov@nginx.com { 444802Salexander.borisov@nginx.com uint32_t i; 445802Salexander.borisov@nginx.com const char *p; 446802Salexander.borisov@nginx.com napi_value headers, raw_headers, str; 447802Salexander.borisov@nginx.com napi_status status; 448802Salexander.borisov@nginx.com nxt_unit_field_t *f; 449802Salexander.borisov@nginx.com nxt_unit_request_t *r; 450802Salexander.borisov@nginx.com 451802Salexander.borisov@nginx.com r = req->request; 452802Salexander.borisov@nginx.com 453802Salexander.borisov@nginx.com status = napi_create_object(env_, &headers); 454802Salexander.borisov@nginx.com if (status != napi_ok) { 455802Salexander.borisov@nginx.com return status; 456802Salexander.borisov@nginx.com } 457802Salexander.borisov@nginx.com 458802Salexander.borisov@nginx.com status = napi_create_array_with_length(env_, r->fields_count * 2, 459802Salexander.borisov@nginx.com &raw_headers); 460802Salexander.borisov@nginx.com if (status != napi_ok) { 461802Salexander.borisov@nginx.com return status; 462802Salexander.borisov@nginx.com } 463802Salexander.borisov@nginx.com 464802Salexander.borisov@nginx.com for (i = 0; i < r->fields_count; i++) { 465802Salexander.borisov@nginx.com f = r->fields + i; 466802Salexander.borisov@nginx.com 467802Salexander.borisov@nginx.com status = this->append_header(f, headers, raw_headers, i); 468802Salexander.borisov@nginx.com if (status != napi_ok) { 469802Salexander.borisov@nginx.com return status; 470802Salexander.borisov@nginx.com } 471802Salexander.borisov@nginx.com } 472802Salexander.borisov@nginx.com 473802Salexander.borisov@nginx.com status = napi_set_named_property(env_, request, "headers", headers); 474802Salexander.borisov@nginx.com if (status != napi_ok) { 475802Salexander.borisov@nginx.com return status; 476802Salexander.borisov@nginx.com } 477802Salexander.borisov@nginx.com 478830Szelenkov@nginx.com status = napi_set_named_property(env_, request, "rawHeaders", raw_headers); 479802Salexander.borisov@nginx.com if (status != napi_ok) { 480802Salexander.borisov@nginx.com return status; 481802Salexander.borisov@nginx.com } 482802Salexander.borisov@nginx.com 483802Salexander.borisov@nginx.com p = (const char *) nxt_unit_sptr_get(&r->version); 484802Salexander.borisov@nginx.com 485802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, p, r->version_length, &str); 486802Salexander.borisov@nginx.com if (status != napi_ok) { 487802Salexander.borisov@nginx.com return status; 488802Salexander.borisov@nginx.com } 489802Salexander.borisov@nginx.com 490802Salexander.borisov@nginx.com status = napi_set_named_property(env_, request, "httpVersion", str); 491802Salexander.borisov@nginx.com if (status != napi_ok) { 492802Salexander.borisov@nginx.com return status; 493802Salexander.borisov@nginx.com } 494802Salexander.borisov@nginx.com 495802Salexander.borisov@nginx.com p = (const char *) nxt_unit_sptr_get(&r->method); 496802Salexander.borisov@nginx.com 497802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, p, r->method_length, &str); 498802Salexander.borisov@nginx.com if (status != napi_ok) { 499802Salexander.borisov@nginx.com return status; 500802Salexander.borisov@nginx.com } 501802Salexander.borisov@nginx.com 502802Salexander.borisov@nginx.com status = napi_set_named_property(env_, request, "method", str); 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->target); 508802Salexander.borisov@nginx.com 509802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, p, r->target_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, "url", 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 return napi_ok; 520802Salexander.borisov@nginx.com } 521802Salexander.borisov@nginx.com 522802Salexander.borisov@nginx.com 523802Salexander.borisov@nginx.com inline napi_status 524802Salexander.borisov@nginx.com Unit::append_header(nxt_unit_field_t *f, napi_value headers, 525802Salexander.borisov@nginx.com napi_value raw_headers, uint32_t idx) 526802Salexander.borisov@nginx.com { 527802Salexander.borisov@nginx.com const char *name, *value; 528802Salexander.borisov@nginx.com napi_value str, vstr; 529802Salexander.borisov@nginx.com napi_status status; 530802Salexander.borisov@nginx.com 531802Salexander.borisov@nginx.com value = (const char *) nxt_unit_sptr_get(&f->value); 532802Salexander.borisov@nginx.com 533802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, value, f->value_length, &vstr); 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 name = (const char *) nxt_unit_sptr_get(&f->name); 539802Salexander.borisov@nginx.com 540802Salexander.borisov@nginx.com status = napi_set_named_property(env_, headers, name, vstr); 541802Salexander.borisov@nginx.com if (status != napi_ok) { 542802Salexander.borisov@nginx.com return status; 543802Salexander.borisov@nginx.com } 544802Salexander.borisov@nginx.com 545802Salexander.borisov@nginx.com status = napi_create_string_latin1(env_, name, f->name_length, &str); 546802Salexander.borisov@nginx.com if (status != napi_ok) { 547802Salexander.borisov@nginx.com return status; 548802Salexander.borisov@nginx.com } 549802Salexander.borisov@nginx.com 550802Salexander.borisov@nginx.com status = napi_set_element(env_, raw_headers, idx * 2, str); 551802Salexander.borisov@nginx.com if (status != napi_ok) { 552802Salexander.borisov@nginx.com return status; 553802Salexander.borisov@nginx.com } 554802Salexander.borisov@nginx.com 555802Salexander.borisov@nginx.com status = napi_set_element(env_, raw_headers, idx * 2 + 1, vstr); 556802Salexander.borisov@nginx.com if (status != napi_ok) { 557802Salexander.borisov@nginx.com return status; 558802Salexander.borisov@nginx.com } 559802Salexander.borisov@nginx.com 560802Salexander.borisov@nginx.com return napi_ok; 561802Salexander.borisov@nginx.com } 562802Salexander.borisov@nginx.com 563802Salexander.borisov@nginx.com 564802Salexander.borisov@nginx.com napi_value 565802Salexander.borisov@nginx.com Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req) 566802Salexander.borisov@nginx.com { 567828Salexander.borisov@nginx.com napi_value constructor, return_val, req_pointer; 568802Salexander.borisov@nginx.com napi_status status; 569802Salexander.borisov@nginx.com 570802Salexander.borisov@nginx.com status = napi_get_named_property(env_, server_obj, "socket", 571802Salexander.borisov@nginx.com &constructor); 572802Salexander.borisov@nginx.com if (status != napi_ok) { 573802Salexander.borisov@nginx.com return nullptr; 574802Salexander.borisov@nginx.com } 575802Salexander.borisov@nginx.com 576802Salexander.borisov@nginx.com status = napi_new_instance(env_, constructor, 0, NULL, &return_val); 577802Salexander.borisov@nginx.com if (status != napi_ok) { 578802Salexander.borisov@nginx.com return nullptr; 579802Salexander.borisov@nginx.com } 580802Salexander.borisov@nginx.com 581828Salexander.borisov@nginx.com status = napi_create_int64(env_, (uintptr_t) req, &req_pointer); 582828Salexander.borisov@nginx.com if (status != napi_ok) { 583828Salexander.borisov@nginx.com return nullptr; 584828Salexander.borisov@nginx.com } 585828Salexander.borisov@nginx.com 586828Salexander.borisov@nginx.com status = napi_set_named_property(env_, return_val, "req_pointer", 587828Salexander.borisov@nginx.com req_pointer); 588828Salexander.borisov@nginx.com if (status != napi_ok) { 589828Salexander.borisov@nginx.com return nullptr; 590828Salexander.borisov@nginx.com } 591828Salexander.borisov@nginx.com 592802Salexander.borisov@nginx.com return return_val; 593802Salexander.borisov@nginx.com } 594802Salexander.borisov@nginx.com 595802Salexander.borisov@nginx.com 596802Salexander.borisov@nginx.com napi_value 597802Salexander.borisov@nginx.com Unit::create_request(napi_value server_obj, napi_value socket) 598802Salexander.borisov@nginx.com { 599802Salexander.borisov@nginx.com napi_value constructor, return_val; 600802Salexander.borisov@nginx.com napi_status status; 601802Salexander.borisov@nginx.com 602802Salexander.borisov@nginx.com status = napi_get_named_property(env_, server_obj, "request", 603802Salexander.borisov@nginx.com &constructor); 604802Salexander.borisov@nginx.com if (status != napi_ok) { 605802Salexander.borisov@nginx.com return nullptr; 606802Salexander.borisov@nginx.com } 607802Salexander.borisov@nginx.com 608802Salexander.borisov@nginx.com status = napi_new_instance(env_, constructor, 1, &server_obj, 609802Salexander.borisov@nginx.com &return_val); 610802Salexander.borisov@nginx.com if (status != napi_ok) { 611802Salexander.borisov@nginx.com return nullptr; 612802Salexander.borisov@nginx.com } 613802Salexander.borisov@nginx.com 614802Salexander.borisov@nginx.com status = napi_set_named_property(env_, return_val, "socket", socket); 615802Salexander.borisov@nginx.com if (status != napi_ok) { 616802Salexander.borisov@nginx.com return nullptr; 617802Salexander.borisov@nginx.com } 618802Salexander.borisov@nginx.com 619802Salexander.borisov@nginx.com return return_val; 620802Salexander.borisov@nginx.com } 621802Salexander.borisov@nginx.com 622802Salexander.borisov@nginx.com 623802Salexander.borisov@nginx.com napi_value 624802Salexander.borisov@nginx.com Unit::create_response(napi_value server_obj, napi_value socket, 625802Salexander.borisov@nginx.com napi_value request, nxt_unit_request_info_t *req, 626802Salexander.borisov@nginx.com Unit *obj) 627802Salexander.borisov@nginx.com { 628802Salexander.borisov@nginx.com napi_value constructor, return_val, req_num; 629802Salexander.borisov@nginx.com napi_status status; 630802Salexander.borisov@nginx.com 631802Salexander.borisov@nginx.com status = napi_get_named_property(env_, server_obj, "response", 632802Salexander.borisov@nginx.com &constructor); 633802Salexander.borisov@nginx.com if (status != napi_ok) { 634802Salexander.borisov@nginx.com return nullptr; 635802Salexander.borisov@nginx.com } 636802Salexander.borisov@nginx.com 637802Salexander.borisov@nginx.com status = napi_new_instance(env_, constructor, 1, &request, &return_val); 638802Salexander.borisov@nginx.com if (status != napi_ok) { 639802Salexander.borisov@nginx.com return nullptr; 640802Salexander.borisov@nginx.com } 641802Salexander.borisov@nginx.com 642802Salexander.borisov@nginx.com status = napi_set_named_property(env_, return_val, "socket", socket); 643802Salexander.borisov@nginx.com if (status != napi_ok) { 644802Salexander.borisov@nginx.com return nullptr; 645802Salexander.borisov@nginx.com } 646802Salexander.borisov@nginx.com 647802Salexander.borisov@nginx.com status = napi_create_int64(env_, (int64_t) (uintptr_t) req, &req_num); 648802Salexander.borisov@nginx.com if (status != napi_ok) { 649802Salexander.borisov@nginx.com return nullptr; 650802Salexander.borisov@nginx.com } 651802Salexander.borisov@nginx.com 652802Salexander.borisov@nginx.com status = napi_set_named_property(env_, return_val, "_req_point", req_num); 653802Salexander.borisov@nginx.com if (status != napi_ok) { 654802Salexander.borisov@nginx.com return nullptr; 655802Salexander.borisov@nginx.com } 656802Salexander.borisov@nginx.com 657802Salexander.borisov@nginx.com return return_val; 658802Salexander.borisov@nginx.com } 659802Salexander.borisov@nginx.com 660802Salexander.borisov@nginx.com 661802Salexander.borisov@nginx.com napi_value 662802Salexander.borisov@nginx.com Unit::response_send_headers(napi_env env, napi_callback_info info) 663802Salexander.borisov@nginx.com { 664802Salexander.borisov@nginx.com int ret; 665802Salexander.borisov@nginx.com char *ptr, *name_ptr; 666802Salexander.borisov@nginx.com bool is_array; 667802Salexander.borisov@nginx.com size_t argc, name_len, value_len; 668802Salexander.borisov@nginx.com int64_t req_p; 669802Salexander.borisov@nginx.com uint32_t status_code, header_len, keys_len, array_len; 670802Salexander.borisov@nginx.com uint32_t keys_count, i, j; 671802Salexander.borisov@nginx.com uint16_t hash; 672802Salexander.borisov@nginx.com napi_value this_arg, headers, keys, name, value, array_val; 673802Salexander.borisov@nginx.com napi_value req_num; 674802Salexander.borisov@nginx.com napi_status status; 675802Salexander.borisov@nginx.com nxt_unit_field_t *f; 676802Salexander.borisov@nginx.com nxt_unit_request_info_t *req; 677802Salexander.borisov@nginx.com napi_value argv[5]; 678802Salexander.borisov@nginx.com 679802Salexander.borisov@nginx.com argc = 5; 680802Salexander.borisov@nginx.com 681802Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, argv, &this_arg, NULL); 682802Salexander.borisov@nginx.com if (status != napi_ok) { 683802Salexander.borisov@nginx.com return nullptr; 684802Salexander.borisov@nginx.com } 685802Salexander.borisov@nginx.com 686802Salexander.borisov@nginx.com if (argc != 5) { 687802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Wrong args count. Need three: " 688802Salexander.borisov@nginx.com "statusCode, headers, headers count, headers length"); 689802Salexander.borisov@nginx.com return nullptr; 690802Salexander.borisov@nginx.com } 691802Salexander.borisov@nginx.com 692802Salexander.borisov@nginx.com status = napi_get_named_property(env, argv[0], "_req_point", &req_num); 693802Salexander.borisov@nginx.com if (status != napi_ok) { 694802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 695802Salexander.borisov@nginx.com return nullptr; 696802Salexander.borisov@nginx.com } 697802Salexander.borisov@nginx.com 698802Salexander.borisov@nginx.com status = napi_get_value_int64(env, req_num, &req_p); 699802Salexander.borisov@nginx.com if (status != napi_ok) { 700802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 701802Salexander.borisov@nginx.com return nullptr; 702802Salexander.borisov@nginx.com } 703802Salexander.borisov@nginx.com 704802Salexander.borisov@nginx.com req = (nxt_unit_request_info_t *) (uintptr_t) req_p; 705802Salexander.borisov@nginx.com 706802Salexander.borisov@nginx.com status = napi_get_value_uint32(env, argv[1], &status_code); 707802Salexander.borisov@nginx.com if (status != napi_ok) { 708802Salexander.borisov@nginx.com goto failed; 709802Salexander.borisov@nginx.com } 710802Salexander.borisov@nginx.com 711802Salexander.borisov@nginx.com status = napi_get_value_uint32(env, argv[3], &keys_count); 712802Salexander.borisov@nginx.com if (status != napi_ok) { 713802Salexander.borisov@nginx.com goto failed; 714802Salexander.borisov@nginx.com } 715802Salexander.borisov@nginx.com 716802Salexander.borisov@nginx.com status = napi_get_value_uint32(env, argv[4], &header_len); 717802Salexander.borisov@nginx.com if (status != napi_ok) { 718802Salexander.borisov@nginx.com goto failed; 719802Salexander.borisov@nginx.com } 720802Salexander.borisov@nginx.com 721802Salexander.borisov@nginx.com /* Need to reserve extra byte for C-string 0-termination. */ 722802Salexander.borisov@nginx.com header_len++; 723802Salexander.borisov@nginx.com 724802Salexander.borisov@nginx.com headers = argv[2]; 725802Salexander.borisov@nginx.com 726802Salexander.borisov@nginx.com ret = nxt_unit_response_init(req, status_code, keys_count, header_len); 727802Salexander.borisov@nginx.com if (ret != NXT_UNIT_OK) { 728802Salexander.borisov@nginx.com goto failed; 729802Salexander.borisov@nginx.com } 730802Salexander.borisov@nginx.com 731802Salexander.borisov@nginx.com status = napi_get_property_names(env, headers, &keys); 732802Salexander.borisov@nginx.com if (status != napi_ok) { 733802Salexander.borisov@nginx.com goto failed; 734802Salexander.borisov@nginx.com } 735802Salexander.borisov@nginx.com 736802Salexander.borisov@nginx.com status = napi_get_array_length(env, keys, &keys_len); 737802Salexander.borisov@nginx.com if (status != napi_ok) { 738802Salexander.borisov@nginx.com goto failed; 739802Salexander.borisov@nginx.com } 740802Salexander.borisov@nginx.com 741802Salexander.borisov@nginx.com ptr = req->response_buf->free; 742802Salexander.borisov@nginx.com 743802Salexander.borisov@nginx.com for (i = 0; i < keys_len; i++) { 744802Salexander.borisov@nginx.com status = napi_get_element(env, keys, i, &name); 745802Salexander.borisov@nginx.com if (status != napi_ok) { 746802Salexander.borisov@nginx.com goto failed; 747802Salexander.borisov@nginx.com } 748802Salexander.borisov@nginx.com 749802Salexander.borisov@nginx.com status = napi_get_property(env, headers, name, &value); 750802Salexander.borisov@nginx.com if (status != napi_ok) { 751802Salexander.borisov@nginx.com goto failed; 752802Salexander.borisov@nginx.com } 753802Salexander.borisov@nginx.com 754802Salexander.borisov@nginx.com status = napi_get_value_string_latin1(env, name, ptr, header_len, 755802Salexander.borisov@nginx.com &name_len); 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 name_ptr = ptr; 761802Salexander.borisov@nginx.com 762802Salexander.borisov@nginx.com ptr += name_len; 763802Salexander.borisov@nginx.com header_len -= name_len; 764802Salexander.borisov@nginx.com 765802Salexander.borisov@nginx.com hash = nxt_unit_field_hash(name_ptr, name_len); 766802Salexander.borisov@nginx.com 767802Salexander.borisov@nginx.com status = napi_is_array(env, value, &is_array); 768802Salexander.borisov@nginx.com if (status != napi_ok) { 769802Salexander.borisov@nginx.com goto failed; 770802Salexander.borisov@nginx.com } 771802Salexander.borisov@nginx.com 772802Salexander.borisov@nginx.com if (is_array) { 773802Salexander.borisov@nginx.com status = napi_get_array_length(env, value, &array_len); 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 for (j = 0; j < array_len; j++) { 779802Salexander.borisov@nginx.com status = napi_get_element(env, value, j, &array_val); 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 status = napi_get_value_string_latin1(env, array_val, ptr, 785802Salexander.borisov@nginx.com header_len, 786802Salexander.borisov@nginx.com &value_len); 787802Salexander.borisov@nginx.com if (status != napi_ok) { 788802Salexander.borisov@nginx.com goto failed; 789802Salexander.borisov@nginx.com } 790802Salexander.borisov@nginx.com 791802Salexander.borisov@nginx.com f = req->response->fields + req->response->fields_count; 792802Salexander.borisov@nginx.com f->skip = 0; 793802Salexander.borisov@nginx.com 794802Salexander.borisov@nginx.com nxt_unit_sptr_set(&f->name, name_ptr); 795802Salexander.borisov@nginx.com 796802Salexander.borisov@nginx.com f->name_length = name_len; 797802Salexander.borisov@nginx.com f->hash = hash; 798802Salexander.borisov@nginx.com 799802Salexander.borisov@nginx.com nxt_unit_sptr_set(&f->value, ptr); 800802Salexander.borisov@nginx.com f->value_length = (uint32_t) value_len; 801802Salexander.borisov@nginx.com 802802Salexander.borisov@nginx.com ptr += value_len; 803802Salexander.borisov@nginx.com header_len -= value_len; 804802Salexander.borisov@nginx.com 805802Salexander.borisov@nginx.com req->response->fields_count++; 806802Salexander.borisov@nginx.com } 807802Salexander.borisov@nginx.com 808802Salexander.borisov@nginx.com } else { 809802Salexander.borisov@nginx.com status = napi_get_value_string_latin1(env, value, ptr, 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 833802Salexander.borisov@nginx.com req->response_buf->free = ptr; 834802Salexander.borisov@nginx.com 835802Salexander.borisov@nginx.com ret = nxt_unit_response_send(req); 836802Salexander.borisov@nginx.com if (ret != NXT_UNIT_OK) { 837802Salexander.borisov@nginx.com goto failed; 838802Salexander.borisov@nginx.com } 839802Salexander.borisov@nginx.com 840802Salexander.borisov@nginx.com return this_arg; 841802Salexander.borisov@nginx.com 842802Salexander.borisov@nginx.com failed: 843802Salexander.borisov@nginx.com 844802Salexander.borisov@nginx.com req->response->fields_count = 0; 845802Salexander.borisov@nginx.com 846802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to write headers"); 847802Salexander.borisov@nginx.com 848802Salexander.borisov@nginx.com return nullptr; 849802Salexander.borisov@nginx.com } 850802Salexander.borisov@nginx.com 851802Salexander.borisov@nginx.com 852802Salexander.borisov@nginx.com napi_value 853802Salexander.borisov@nginx.com Unit::response_write(napi_env env, napi_callback_info info) 854802Salexander.borisov@nginx.com { 855802Salexander.borisov@nginx.com int ret; 856802Salexander.borisov@nginx.com char *ptr; 857802Salexander.borisov@nginx.com size_t argc, have_buf_len; 858802Salexander.borisov@nginx.com int64_t req_p; 859802Salexander.borisov@nginx.com uint32_t buf_len; 860802Salexander.borisov@nginx.com napi_value this_arg, req_num; 861802Salexander.borisov@nginx.com napi_status status; 862802Salexander.borisov@nginx.com nxt_unit_buf_t *buf; 863802Salexander.borisov@nginx.com napi_valuetype buf_type; 864802Salexander.borisov@nginx.com nxt_unit_request_info_t *req; 865802Salexander.borisov@nginx.com napi_value argv[3]; 866802Salexander.borisov@nginx.com 867802Salexander.borisov@nginx.com argc = 3; 868802Salexander.borisov@nginx.com 869802Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, argv, &this_arg, NULL); 870802Salexander.borisov@nginx.com if (status != napi_ok) { 871802Salexander.borisov@nginx.com goto failed; 872802Salexander.borisov@nginx.com } 873802Salexander.borisov@nginx.com 874802Salexander.borisov@nginx.com if (argc != 3) { 875802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Wrong args count. Need two: " 876802Salexander.borisov@nginx.com "chunk, chunk length"); 877802Salexander.borisov@nginx.com return nullptr; 878802Salexander.borisov@nginx.com } 879802Salexander.borisov@nginx.com 880802Salexander.borisov@nginx.com status = napi_get_named_property(env, argv[0], "_req_point", &req_num); 881802Salexander.borisov@nginx.com if (status != napi_ok) { 882802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 883802Salexander.borisov@nginx.com return nullptr; 884802Salexander.borisov@nginx.com } 885802Salexander.borisov@nginx.com 886802Salexander.borisov@nginx.com status = napi_get_value_int64(env, req_num, &req_p); 887802Salexander.borisov@nginx.com if (status != napi_ok) { 888802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 889802Salexander.borisov@nginx.com return nullptr; 890802Salexander.borisov@nginx.com } 891802Salexander.borisov@nginx.com 892802Salexander.borisov@nginx.com req = (nxt_unit_request_info_t *) (uintptr_t) req_p; 893802Salexander.borisov@nginx.com 894802Salexander.borisov@nginx.com status = napi_get_value_uint32(env, argv[2], &buf_len); 895802Salexander.borisov@nginx.com if (status != napi_ok) { 896802Salexander.borisov@nginx.com goto failed; 897802Salexander.borisov@nginx.com } 898802Salexander.borisov@nginx.com 899802Salexander.borisov@nginx.com status = napi_typeof(env, argv[1], &buf_type); 900802Salexander.borisov@nginx.com if (status != napi_ok) { 901802Salexander.borisov@nginx.com goto failed; 902802Salexander.borisov@nginx.com } 903802Salexander.borisov@nginx.com 904802Salexander.borisov@nginx.com buf_len++; 905802Salexander.borisov@nginx.com 906802Salexander.borisov@nginx.com buf = nxt_unit_response_buf_alloc(req, buf_len); 907802Salexander.borisov@nginx.com if (buf == NULL) { 908802Salexander.borisov@nginx.com goto failed; 909802Salexander.borisov@nginx.com } 910802Salexander.borisov@nginx.com 911802Salexander.borisov@nginx.com if (buf_type == napi_string) { 912802Salexander.borisov@nginx.com /* TODO: will work only for utf8 content-type */ 913802Salexander.borisov@nginx.com 914802Salexander.borisov@nginx.com status = napi_get_value_string_utf8(env, argv[1], buf->free, 915802Salexander.borisov@nginx.com buf_len, &have_buf_len); 916802Salexander.borisov@nginx.com 917802Salexander.borisov@nginx.com } else { 918802Salexander.borisov@nginx.com status = napi_get_buffer_info(env, argv[1], (void **) &ptr, 919802Salexander.borisov@nginx.com &have_buf_len); 920802Salexander.borisov@nginx.com 921802Salexander.borisov@nginx.com memcpy(buf->free, ptr, have_buf_len); 922802Salexander.borisov@nginx.com } 923802Salexander.borisov@nginx.com 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->free += have_buf_len; 929802Salexander.borisov@nginx.com 930802Salexander.borisov@nginx.com ret = nxt_unit_buf_send(buf); 931802Salexander.borisov@nginx.com if (ret != NXT_UNIT_OK) { 932802Salexander.borisov@nginx.com goto failed; 933802Salexander.borisov@nginx.com } 934802Salexander.borisov@nginx.com 935802Salexander.borisov@nginx.com return this_arg; 936802Salexander.borisov@nginx.com 937802Salexander.borisov@nginx.com failed: 938802Salexander.borisov@nginx.com 939802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to write body"); 940802Salexander.borisov@nginx.com 941802Salexander.borisov@nginx.com return nullptr; 942802Salexander.borisov@nginx.com } 943802Salexander.borisov@nginx.com 944802Salexander.borisov@nginx.com 945802Salexander.borisov@nginx.com napi_value 946802Salexander.borisov@nginx.com Unit::response_end(napi_env env, napi_callback_info info) 947802Salexander.borisov@nginx.com { 948802Salexander.borisov@nginx.com size_t argc; 949802Salexander.borisov@nginx.com int64_t req_p; 950802Salexander.borisov@nginx.com napi_value resp, this_arg, req_num; 951802Salexander.borisov@nginx.com napi_status status; 952802Salexander.borisov@nginx.com nxt_unit_request_info_t *req; 953802Salexander.borisov@nginx.com 954802Salexander.borisov@nginx.com argc = 1; 955802Salexander.borisov@nginx.com 956802Salexander.borisov@nginx.com status = napi_get_cb_info(env, info, &argc, &resp, &this_arg, NULL); 957802Salexander.borisov@nginx.com if (status != napi_ok) { 958802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to finalize sending body"); 959802Salexander.borisov@nginx.com return nullptr; 960802Salexander.borisov@nginx.com } 961802Salexander.borisov@nginx.com 962802Salexander.borisov@nginx.com status = napi_get_named_property(env, resp, "_req_point", &req_num); 963802Salexander.borisov@nginx.com if (status != napi_ok) { 964802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 965802Salexander.borisov@nginx.com return nullptr; 966802Salexander.borisov@nginx.com } 967802Salexander.borisov@nginx.com 968802Salexander.borisov@nginx.com status = napi_get_value_int64(env, req_num, &req_p); 969802Salexander.borisov@nginx.com if (status != napi_ok) { 970802Salexander.borisov@nginx.com napi_throw_error(env, NULL, "Failed to get request pointer"); 971802Salexander.borisov@nginx.com return nullptr; 972802Salexander.borisov@nginx.com } 973802Salexander.borisov@nginx.com 974802Salexander.borisov@nginx.com req = (nxt_unit_request_info_t *) (uintptr_t) req_p; 975802Salexander.borisov@nginx.com 976802Salexander.borisov@nginx.com nxt_unit_request_done(req, NXT_UNIT_OK); 977802Salexander.borisov@nginx.com 978802Salexander.borisov@nginx.com return this_arg; 979802Salexander.borisov@nginx.com } 980