xref: /unit/src/nodejs/unit-http/unit.cpp (revision 2623:15a457cb829e)
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 
131132Smax.romanov@nginx.com #include <nxt_unit_websocket.h>
141132Smax.romanov@nginx.com 
15802Salexander.borisov@nginx.com 
16802Salexander.borisov@nginx.com napi_ref Unit::constructor_;
17802Salexander.borisov@nginx.com 
18802Salexander.borisov@nginx.com 
191543Smax.romanov@nginx.com struct port_data_t {
201767Smax.romanov@nginx.com     port_data_t(nxt_unit_ctx_t *c, nxt_unit_port_t *p);
211767Smax.romanov@nginx.com 
221767Smax.romanov@nginx.com     void process_port_msg();
231767Smax.romanov@nginx.com     void stop();
241767Smax.romanov@nginx.com 
251767Smax.romanov@nginx.com     template<typename T>
261767Smax.romanov@nginx.com     static port_data_t *get(T *handle);
271767Smax.romanov@nginx.com 
281767Smax.romanov@nginx.com     static void read_callback(uv_poll_t *handle, int status, int events);
291767Smax.romanov@nginx.com     static void timer_callback(uv_timer_t *handle);
301767Smax.romanov@nginx.com     static void delete_data(uv_handle_t* handle);
311767Smax.romanov@nginx.com 
321767Smax.romanov@nginx.com     nxt_unit_ctx_t   *ctx;
331767Smax.romanov@nginx.com     nxt_unit_port_t  *port;
341767Smax.romanov@nginx.com     uv_poll_t        poll;
351767Smax.romanov@nginx.com     uv_timer_t       timer;
361767Smax.romanov@nginx.com     int              ref_count;
371767Smax.romanov@nginx.com     bool             scheduled;
381767Smax.romanov@nginx.com     bool             stopped;
39842Salexander.borisov@nginx.com };
40842Salexander.borisov@nginx.com 
41842Salexander.borisov@nginx.com 
421132Smax.romanov@nginx.com struct req_data_t {
431132Smax.romanov@nginx.com     napi_ref  sock_ref;
441766Smax.romanov@nginx.com     napi_ref  req_ref;
451132Smax.romanov@nginx.com     napi_ref  resp_ref;
461132Smax.romanov@nginx.com     napi_ref  conn_ref;
471132Smax.romanov@nginx.com };
481132Smax.romanov@nginx.com 
491132Smax.romanov@nginx.com 
port_data_t(nxt_unit_ctx_t * c,nxt_unit_port_t * p)501767Smax.romanov@nginx.com port_data_t::port_data_t(nxt_unit_ctx_t *c, nxt_unit_port_t *p) :
511767Smax.romanov@nginx.com     ctx(c), port(p), ref_count(0), scheduled(false), stopped(false)
521767Smax.romanov@nginx.com {
531767Smax.romanov@nginx.com     timer.type = UV_UNKNOWN_HANDLE;
541767Smax.romanov@nginx.com }
551767Smax.romanov@nginx.com 
561767Smax.romanov@nginx.com 
571767Smax.romanov@nginx.com void
process_port_msg()581767Smax.romanov@nginx.com port_data_t::process_port_msg()
591767Smax.romanov@nginx.com {
601767Smax.romanov@nginx.com     int  rc, err;
611767Smax.romanov@nginx.com 
621767Smax.romanov@nginx.com     rc = nxt_unit_process_port_msg(ctx, port);
631767Smax.romanov@nginx.com 
641767Smax.romanov@nginx.com     if (rc != NXT_UNIT_OK) {
651767Smax.romanov@nginx.com         return;
661767Smax.romanov@nginx.com     }
671767Smax.romanov@nginx.com 
681767Smax.romanov@nginx.com     if (timer.type == UV_UNKNOWN_HANDLE) {
691767Smax.romanov@nginx.com         err = uv_timer_init(poll.loop, &timer);
701767Smax.romanov@nginx.com         if (err < 0) {
711767Smax.romanov@nginx.com             nxt_unit_warn(ctx, "Failed to init uv.poll");
721767Smax.romanov@nginx.com             return;
731767Smax.romanov@nginx.com         }
741767Smax.romanov@nginx.com 
751767Smax.romanov@nginx.com         ref_count++;
761767Smax.romanov@nginx.com         timer.data = this;
771767Smax.romanov@nginx.com     }
781767Smax.romanov@nginx.com 
791767Smax.romanov@nginx.com     if (!scheduled && !stopped) {
801767Smax.romanov@nginx.com         uv_timer_start(&timer, timer_callback, 0, 0);
811767Smax.romanov@nginx.com 
821767Smax.romanov@nginx.com         scheduled = true;
831767Smax.romanov@nginx.com     }
841767Smax.romanov@nginx.com }
851767Smax.romanov@nginx.com 
861767Smax.romanov@nginx.com 
871767Smax.romanov@nginx.com void
stop()881767Smax.romanov@nginx.com port_data_t::stop()
891767Smax.romanov@nginx.com {
901767Smax.romanov@nginx.com     stopped = true;
911767Smax.romanov@nginx.com 
921767Smax.romanov@nginx.com     uv_poll_stop(&poll);
931767Smax.romanov@nginx.com 
941767Smax.romanov@nginx.com     uv_close((uv_handle_t *) &poll, delete_data);
951767Smax.romanov@nginx.com 
961767Smax.romanov@nginx.com     if (timer.type == UV_UNKNOWN_HANDLE) {
971767Smax.romanov@nginx.com         return;
981767Smax.romanov@nginx.com     }
991767Smax.romanov@nginx.com 
1001767Smax.romanov@nginx.com     uv_timer_stop(&timer);
1011767Smax.romanov@nginx.com 
1021767Smax.romanov@nginx.com     uv_close((uv_handle_t *) &timer, delete_data);
1031767Smax.romanov@nginx.com }
1041767Smax.romanov@nginx.com 
1051767Smax.romanov@nginx.com 
1061767Smax.romanov@nginx.com template<typename T>
1071767Smax.romanov@nginx.com port_data_t *
get(T * handle)1081767Smax.romanov@nginx.com port_data_t::get(T *handle)
1091767Smax.romanov@nginx.com {
1101767Smax.romanov@nginx.com     return (port_data_t *) handle->data;
1111767Smax.romanov@nginx.com }
1121767Smax.romanov@nginx.com 
1131767Smax.romanov@nginx.com 
1141767Smax.romanov@nginx.com void
read_callback(uv_poll_t * handle,int status,int events)1151767Smax.romanov@nginx.com port_data_t::read_callback(uv_poll_t *handle, int status, int events)
1161767Smax.romanov@nginx.com {
1171767Smax.romanov@nginx.com     get(handle)->process_port_msg();
1181767Smax.romanov@nginx.com }
1191767Smax.romanov@nginx.com 
1201767Smax.romanov@nginx.com 
1211767Smax.romanov@nginx.com void
timer_callback(uv_timer_t * handle)1221767Smax.romanov@nginx.com port_data_t::timer_callback(uv_timer_t *handle)
1231767Smax.romanov@nginx.com {
1241767Smax.romanov@nginx.com     port_data_t  *data;
1251767Smax.romanov@nginx.com 
1261767Smax.romanov@nginx.com     data = get(handle);
1271767Smax.romanov@nginx.com 
1281767Smax.romanov@nginx.com     data->scheduled = false;
1291767Smax.romanov@nginx.com     if (data->stopped) {
1301767Smax.romanov@nginx.com         return;
1311767Smax.romanov@nginx.com     }
1321767Smax.romanov@nginx.com 
1331767Smax.romanov@nginx.com     data->process_port_msg();
1341767Smax.romanov@nginx.com }
1351767Smax.romanov@nginx.com 
1361767Smax.romanov@nginx.com 
1371767Smax.romanov@nginx.com void
delete_data(uv_handle_t * handle)1381767Smax.romanov@nginx.com port_data_t::delete_data(uv_handle_t* handle)
1391767Smax.romanov@nginx.com {
1401767Smax.romanov@nginx.com     port_data_t  *data;
1411767Smax.romanov@nginx.com 
1421767Smax.romanov@nginx.com     data = get(handle);
1431767Smax.romanov@nginx.com 
1441767Smax.romanov@nginx.com     if (--data->ref_count <= 0) {
1451767Smax.romanov@nginx.com         delete data;
1461767Smax.romanov@nginx.com     }
1471767Smax.romanov@nginx.com }
1481767Smax.romanov@nginx.com 
1491767Smax.romanov@nginx.com 
Unit(napi_env env,napi_value jsthis)1501020Smax.romanov@nginx.com Unit::Unit(napi_env env, napi_value jsthis):
1511020Smax.romanov@nginx.com     nxt_napi(env),
1521020Smax.romanov@nginx.com     wrapper_(wrap(jsthis, this, destroy)),
153802Salexander.borisov@nginx.com     unit_ctx_(nullptr)
154802Salexander.borisov@nginx.com {
1551132Smax.romanov@nginx.com     nxt_unit_debug(NULL, "Unit::Unit()");
156802Salexander.borisov@nginx.com }
157802Salexander.borisov@nginx.com 
158802Salexander.borisov@nginx.com 
~Unit()159802Salexander.borisov@nginx.com Unit::~Unit()
160802Salexander.borisov@nginx.com {
1611020Smax.romanov@nginx.com     delete_reference(wrapper_);
1621132Smax.romanov@nginx.com 
1631132Smax.romanov@nginx.com     nxt_unit_debug(NULL, "Unit::~Unit()");
164802Salexander.borisov@nginx.com }
165802Salexander.borisov@nginx.com 
166802Salexander.borisov@nginx.com 
167802Salexander.borisov@nginx.com napi_value
init(napi_env env,napi_value exports)168802Salexander.borisov@nginx.com Unit::init(napi_env env, napi_value exports)
169802Salexander.borisov@nginx.com {
1701020Smax.romanov@nginx.com     nxt_napi    napi(env);
1711132Smax.romanov@nginx.com     napi_value  ctor;
172802Salexander.borisov@nginx.com 
1731132Smax.romanov@nginx.com     napi_property_descriptor  unit_props[] = {
174802Salexander.borisov@nginx.com         { "createServer", 0, create_server, 0, 0, 0, napi_default, 0 },
175828Salexander.borisov@nginx.com         { "listen", 0, listen, 0, 0, 0, napi_default, 0 },
176802Salexander.borisov@nginx.com     };
177802Salexander.borisov@nginx.com 
1781020Smax.romanov@nginx.com     try {
1791132Smax.romanov@nginx.com         ctor = napi.define_class("Unit", create, 2, unit_props);
1801132Smax.romanov@nginx.com         constructor_ = napi.create_reference(ctor);
181802Salexander.borisov@nginx.com 
1821132Smax.romanov@nginx.com         napi.set_named_property(exports, "Unit", ctor);
1831766Smax.romanov@nginx.com         napi.set_named_property(exports, "request_read", request_read);
1841132Smax.romanov@nginx.com         napi.set_named_property(exports, "response_send_headers",
1851020Smax.romanov@nginx.com                                 response_send_headers);
1861132Smax.romanov@nginx.com         napi.set_named_property(exports, "response_write", response_write);
1871132Smax.romanov@nginx.com         napi.set_named_property(exports, "response_end", response_end);
1881132Smax.romanov@nginx.com         napi.set_named_property(exports, "websocket_send_frame",
1891132Smax.romanov@nginx.com                                 websocket_send_frame);
1901132Smax.romanov@nginx.com         napi.set_named_property(exports, "websocket_set_sock",
1911132Smax.romanov@nginx.com                                 websocket_set_sock);
1921322Smax.romanov@nginx.com         napi.set_named_property(exports, "buf_min", nxt_unit_buf_min());
1931322Smax.romanov@nginx.com         napi.set_named_property(exports, "buf_max", nxt_unit_buf_max());
194802Salexander.borisov@nginx.com 
1951020Smax.romanov@nginx.com     } catch (exception &e) {
1961020Smax.romanov@nginx.com         napi.throw_error(e);
1971020Smax.romanov@nginx.com         return nullptr;
198802Salexander.borisov@nginx.com     }
199802Salexander.borisov@nginx.com 
200802Salexander.borisov@nginx.com     return exports;
201802Salexander.borisov@nginx.com }
202802Salexander.borisov@nginx.com 
203802Salexander.borisov@nginx.com 
204802Salexander.borisov@nginx.com void
destroy(napi_env env,void * nativeObject,void * finalize_hint)205802Salexander.borisov@nginx.com Unit::destroy(napi_env env, void *nativeObject, void *finalize_hint)
206802Salexander.borisov@nginx.com {
207802Salexander.borisov@nginx.com     Unit  *obj = reinterpret_cast<Unit *>(nativeObject);
208802Salexander.borisov@nginx.com 
209802Salexander.borisov@nginx.com     delete obj;
210802Salexander.borisov@nginx.com }
211802Salexander.borisov@nginx.com 
212802Salexander.borisov@nginx.com 
213802Salexander.borisov@nginx.com napi_value
create(napi_env env,napi_callback_info info)214802Salexander.borisov@nginx.com Unit::create(napi_env env, napi_callback_info info)
215802Salexander.borisov@nginx.com {
2161020Smax.romanov@nginx.com     nxt_napi    napi(env);
2171132Smax.romanov@nginx.com     napi_value  target, ctor, instance, jsthis;
2181020Smax.romanov@nginx.com 
2191020Smax.romanov@nginx.com     try {
2201020Smax.romanov@nginx.com         target = napi.get_new_target(info);
221802Salexander.borisov@nginx.com 
2221020Smax.romanov@nginx.com         if (target != nullptr) {
2231020Smax.romanov@nginx.com             /* Invoked as constructor: `new Unit(...)`. */
2241020Smax.romanov@nginx.com             jsthis = napi.get_cb_info(info);
225802Salexander.borisov@nginx.com 
2261023Smax.romanov@nginx.com             new Unit(env, jsthis);
2271023Smax.romanov@nginx.com             napi.create_reference(jsthis);
2281020Smax.romanov@nginx.com 
2291020Smax.romanov@nginx.com             return jsthis;
230802Salexander.borisov@nginx.com         }
231802Salexander.borisov@nginx.com 
2321020Smax.romanov@nginx.com         /* Invoked as plain function `Unit(...)`, turn into construct call. */
2331132Smax.romanov@nginx.com         ctor = napi.get_reference_value(constructor_);
2341132Smax.romanov@nginx.com         instance = napi.new_instance(ctor);
2351023Smax.romanov@nginx.com         napi.create_reference(instance);
236841Salexander.borisov@nginx.com 
2371020Smax.romanov@nginx.com     } catch (exception &e) {
2381020Smax.romanov@nginx.com         napi.throw_error(e);
2391020Smax.romanov@nginx.com         return nullptr;
240841Salexander.borisov@nginx.com     }
241841Salexander.borisov@nginx.com 
242802Salexander.borisov@nginx.com     return instance;
243802Salexander.borisov@nginx.com }
244802Salexander.borisov@nginx.com 
245802Salexander.borisov@nginx.com 
246802Salexander.borisov@nginx.com napi_value
create_server(napi_env env,napi_callback_info info)247802Salexander.borisov@nginx.com Unit::create_server(napi_env env, napi_callback_info info)
248802Salexander.borisov@nginx.com {
249802Salexander.borisov@nginx.com     Unit             *obj;
250802Salexander.borisov@nginx.com     size_t           argc;
2511020Smax.romanov@nginx.com     nxt_napi         napi(env);
252828Salexander.borisov@nginx.com     napi_value       jsthis, argv;
253802Salexander.borisov@nginx.com     nxt_unit_init_t  unit_init;
254802Salexander.borisov@nginx.com 
255802Salexander.borisov@nginx.com     argc = 1;
256802Salexander.borisov@nginx.com 
2571020Smax.romanov@nginx.com     try {
2581020Smax.romanov@nginx.com         jsthis = napi.get_cb_info(info, argc, &argv);
2591020Smax.romanov@nginx.com         obj = (Unit *) napi.unwrap(jsthis);
260802Salexander.borisov@nginx.com 
2611020Smax.romanov@nginx.com     } catch (exception &e) {
2621020Smax.romanov@nginx.com         napi.throw_error(e);
2631020Smax.romanov@nginx.com         return nullptr;
264802Salexander.borisov@nginx.com     }
265802Salexander.borisov@nginx.com 
266802Salexander.borisov@nginx.com     memset(&unit_init, 0, sizeof(nxt_unit_init_t));
267802Salexander.borisov@nginx.com 
268802Salexander.borisov@nginx.com     unit_init.data = obj;
2691132Smax.romanov@nginx.com     unit_init.callbacks.request_handler   = request_handler_cb;
2701132Smax.romanov@nginx.com     unit_init.callbacks.websocket_handler = websocket_handler_cb;
2711132Smax.romanov@nginx.com     unit_init.callbacks.close_handler     = close_handler_cb;
2721322Smax.romanov@nginx.com     unit_init.callbacks.shm_ack_handler   = shm_ack_handler_cb;
2731132Smax.romanov@nginx.com     unit_init.callbacks.add_port          = add_port;
2741132Smax.romanov@nginx.com     unit_init.callbacks.remove_port       = remove_port;
2751132Smax.romanov@nginx.com     unit_init.callbacks.quit              = quit_cb;
2761132Smax.romanov@nginx.com 
2771132Smax.romanov@nginx.com     unit_init.request_data_size = sizeof(req_data_t);
278802Salexander.borisov@nginx.com 
279802Salexander.borisov@nginx.com     obj->unit_ctx_ = nxt_unit_init(&unit_init);
280802Salexander.borisov@nginx.com     if (obj->unit_ctx_ == NULL) {
281802Salexander.borisov@nginx.com         goto failed;
282802Salexander.borisov@nginx.com     }
283802Salexander.borisov@nginx.com 
284802Salexander.borisov@nginx.com     return nullptr;
285802Salexander.borisov@nginx.com 
286802Salexander.borisov@nginx.com failed:
287802Salexander.borisov@nginx.com 
288802Salexander.borisov@nginx.com     napi_throw_error(env, NULL, "Failed to create Unit object");
289802Salexander.borisov@nginx.com 
290802Salexander.borisov@nginx.com     return nullptr;
291802Salexander.borisov@nginx.com }
292802Salexander.borisov@nginx.com 
293802Salexander.borisov@nginx.com 
294802Salexander.borisov@nginx.com napi_value
listen(napi_env env,napi_callback_info info)295802Salexander.borisov@nginx.com Unit::listen(napi_env env, napi_callback_info info)
296802Salexander.borisov@nginx.com {
297828Salexander.borisov@nginx.com     return nullptr;
298828Salexander.borisov@nginx.com }
299828Salexander.borisov@nginx.com 
300802Salexander.borisov@nginx.com 
3011132Smax.romanov@nginx.com void
request_handler_cb(nxt_unit_request_info_t * req)3021132Smax.romanov@nginx.com Unit::request_handler_cb(nxt_unit_request_info_t *req)
303828Salexander.borisov@nginx.com {
3041132Smax.romanov@nginx.com     Unit  *obj;
305828Salexander.borisov@nginx.com 
3061132Smax.romanov@nginx.com     obj = reinterpret_cast<Unit *>(req->unit->data);
307802Salexander.borisov@nginx.com 
3081132Smax.romanov@nginx.com     obj->request_handler(req);
309802Salexander.borisov@nginx.com }
310802Salexander.borisov@nginx.com 
311802Salexander.borisov@nginx.com 
312802Salexander.borisov@nginx.com void
request_handler(nxt_unit_request_info_t * req)313802Salexander.borisov@nginx.com Unit::request_handler(nxt_unit_request_info_t *req)
314802Salexander.borisov@nginx.com {
3151132Smax.romanov@nginx.com     napi_value  socket, request, response, server_obj, emit_request;
316802Salexander.borisov@nginx.com 
3171132Smax.romanov@nginx.com     memset(req->data, 0, sizeof(req_data_t));
318802Salexander.borisov@nginx.com 
3191020Smax.romanov@nginx.com     try {
3201132Smax.romanov@nginx.com         nxt_handle_scope  scope(env());
321802Salexander.borisov@nginx.com 
3221132Smax.romanov@nginx.com         server_obj = get_server_object();
323802Salexander.borisov@nginx.com 
3241132Smax.romanov@nginx.com         socket = create_socket(server_obj, req);
3251766Smax.romanov@nginx.com         request = create_request(server_obj, socket, req);
3261132Smax.romanov@nginx.com         response = create_response(server_obj, request, req);
327828Salexander.borisov@nginx.com 
3281132Smax.romanov@nginx.com         create_headers(req, request);
329871Salexander.borisov@nginx.com 
3301132Smax.romanov@nginx.com         emit_request = get_named_property(server_obj, "emit_request");
3311132Smax.romanov@nginx.com 
3321132Smax.romanov@nginx.com         nxt_async_context   async_context(env(), "request_handler");
3331020Smax.romanov@nginx.com         nxt_callback_scope  async_scope(async_context);
334876Salexander.borisov@nginx.com 
3351132Smax.romanov@nginx.com         make_callback(async_context, server_obj, emit_request, request,
3361132Smax.romanov@nginx.com                       response);
337871Salexander.borisov@nginx.com 
3381020Smax.romanov@nginx.com     } catch (exception &e) {
3391132Smax.romanov@nginx.com         nxt_unit_req_warn(req, "request_handler: %s", e.str);
340871Salexander.borisov@nginx.com     }
341802Salexander.borisov@nginx.com }
342802Salexander.borisov@nginx.com 
343802Salexander.borisov@nginx.com 
344828Salexander.borisov@nginx.com void
websocket_handler_cb(nxt_unit_websocket_frame_t * ws)3451132Smax.romanov@nginx.com Unit::websocket_handler_cb(nxt_unit_websocket_frame_t *ws)
3461132Smax.romanov@nginx.com {
3471132Smax.romanov@nginx.com     Unit  *obj;
3481132Smax.romanov@nginx.com 
3491132Smax.romanov@nginx.com     obj = reinterpret_cast<Unit *>(ws->req->unit->data);
3501132Smax.romanov@nginx.com 
3511132Smax.romanov@nginx.com     obj->websocket_handler(ws);
3521132Smax.romanov@nginx.com }
3531132Smax.romanov@nginx.com 
3541132Smax.romanov@nginx.com 
3551132Smax.romanov@nginx.com void
websocket_handler(nxt_unit_websocket_frame_t * ws)3561132Smax.romanov@nginx.com Unit::websocket_handler(nxt_unit_websocket_frame_t *ws)
3571132Smax.romanov@nginx.com {
3581132Smax.romanov@nginx.com     napi_value  frame, server_obj, process_frame, conn;
3591132Smax.romanov@nginx.com     req_data_t  *req_data;
3601132Smax.romanov@nginx.com 
3611132Smax.romanov@nginx.com     req_data = (req_data_t *) ws->req->data;
3621132Smax.romanov@nginx.com 
3631132Smax.romanov@nginx.com     try {
3641132Smax.romanov@nginx.com         nxt_handle_scope  scope(env());
3651132Smax.romanov@nginx.com 
3661132Smax.romanov@nginx.com         server_obj = get_server_object();
3671132Smax.romanov@nginx.com 
3681132Smax.romanov@nginx.com         frame = create_websocket_frame(server_obj, ws);
3691132Smax.romanov@nginx.com 
3701132Smax.romanov@nginx.com         conn = get_reference_value(req_data->conn_ref);
3711132Smax.romanov@nginx.com 
3721132Smax.romanov@nginx.com         process_frame = get_named_property(conn, "processFrame");
3731132Smax.romanov@nginx.com 
3741132Smax.romanov@nginx.com         nxt_async_context   async_context(env(), "websocket_handler");
3751132Smax.romanov@nginx.com         nxt_callback_scope  async_scope(async_context);
3761132Smax.romanov@nginx.com 
3771132Smax.romanov@nginx.com         make_callback(async_context, conn, process_frame, frame);
3781132Smax.romanov@nginx.com 
3791132Smax.romanov@nginx.com     } catch (exception &e) {
3801132Smax.romanov@nginx.com         nxt_unit_req_warn(ws->req, "websocket_handler: %s", e.str);
3811132Smax.romanov@nginx.com     }
3821132Smax.romanov@nginx.com 
3831132Smax.romanov@nginx.com     nxt_unit_websocket_done(ws);
3841132Smax.romanov@nginx.com }
3851132Smax.romanov@nginx.com 
3861132Smax.romanov@nginx.com 
3871132Smax.romanov@nginx.com void
close_handler_cb(nxt_unit_request_info_t * req)3881132Smax.romanov@nginx.com Unit::close_handler_cb(nxt_unit_request_info_t *req)
3891132Smax.romanov@nginx.com {
3901132Smax.romanov@nginx.com     Unit  *obj;
3911132Smax.romanov@nginx.com 
3921132Smax.romanov@nginx.com     obj = reinterpret_cast<Unit *>(req->unit->data);
3931132Smax.romanov@nginx.com 
3941132Smax.romanov@nginx.com     obj->close_handler(req);
3951132Smax.romanov@nginx.com }
3961132Smax.romanov@nginx.com 
3971132Smax.romanov@nginx.com 
3981132Smax.romanov@nginx.com void
close_handler(nxt_unit_request_info_t * req)3991132Smax.romanov@nginx.com Unit::close_handler(nxt_unit_request_info_t *req)
4001132Smax.romanov@nginx.com {
4011132Smax.romanov@nginx.com     napi_value  conn_handle_close, conn;
4021132Smax.romanov@nginx.com     req_data_t  *req_data;
4031132Smax.romanov@nginx.com 
4041132Smax.romanov@nginx.com     req_data = (req_data_t *) req->data;
4051132Smax.romanov@nginx.com 
4061132Smax.romanov@nginx.com     try {
4071132Smax.romanov@nginx.com         nxt_handle_scope  scope(env());
4081132Smax.romanov@nginx.com 
4091132Smax.romanov@nginx.com         conn = get_reference_value(req_data->conn_ref);
4101132Smax.romanov@nginx.com 
4111132Smax.romanov@nginx.com         conn_handle_close = get_named_property(conn, "handleSocketClose");
4121132Smax.romanov@nginx.com 
4131132Smax.romanov@nginx.com         nxt_async_context   async_context(env(), "close_handler");
4141132Smax.romanov@nginx.com         nxt_callback_scope  async_scope(async_context);
4151132Smax.romanov@nginx.com 
4161132Smax.romanov@nginx.com         make_callback(async_context, conn, conn_handle_close,
4171132Smax.romanov@nginx.com                       nxt_napi::create(0));
4181132Smax.romanov@nginx.com 
4191132Smax.romanov@nginx.com         remove_wrap(req_data->sock_ref);
4201766Smax.romanov@nginx.com         remove_wrap(req_data->req_ref);
4211132Smax.romanov@nginx.com         remove_wrap(req_data->resp_ref);
4221132Smax.romanov@nginx.com         remove_wrap(req_data->conn_ref);
4231132Smax.romanov@nginx.com 
4241132Smax.romanov@nginx.com     } catch (exception &e) {
4251132Smax.romanov@nginx.com         nxt_unit_req_warn(req, "close_handler: %s", e.str);
4261132Smax.romanov@nginx.com 
4271715Smax.romanov@nginx.com         nxt_unit_request_done(req, NXT_UNIT_ERROR);
4281715Smax.romanov@nginx.com 
4291132Smax.romanov@nginx.com         return;
4301132Smax.romanov@nginx.com     }
4311132Smax.romanov@nginx.com 
4321132Smax.romanov@nginx.com     nxt_unit_request_done(req, NXT_UNIT_OK);
4331132Smax.romanov@nginx.com }
4341132Smax.romanov@nginx.com 
4351132Smax.romanov@nginx.com 
4361322Smax.romanov@nginx.com void
shm_ack_handler_cb(nxt_unit_ctx_t * ctx)4371322Smax.romanov@nginx.com Unit::shm_ack_handler_cb(nxt_unit_ctx_t *ctx)
4381322Smax.romanov@nginx.com {
4391322Smax.romanov@nginx.com     Unit  *obj;
4401322Smax.romanov@nginx.com 
4411322Smax.romanov@nginx.com     obj = reinterpret_cast<Unit *>(ctx->unit->data);
4421322Smax.romanov@nginx.com 
4431322Smax.romanov@nginx.com     obj->shm_ack_handler(ctx);
4441322Smax.romanov@nginx.com }
4451322Smax.romanov@nginx.com 
4461322Smax.romanov@nginx.com 
4471322Smax.romanov@nginx.com void
shm_ack_handler(nxt_unit_ctx_t * ctx)4481322Smax.romanov@nginx.com Unit::shm_ack_handler(nxt_unit_ctx_t *ctx)
4491322Smax.romanov@nginx.com {
4501322Smax.romanov@nginx.com     napi_value  server_obj, emit_drain;
4511322Smax.romanov@nginx.com 
4521322Smax.romanov@nginx.com     try {
4531322Smax.romanov@nginx.com         nxt_handle_scope  scope(env());
4541322Smax.romanov@nginx.com 
4551322Smax.romanov@nginx.com         server_obj = get_server_object();
4561322Smax.romanov@nginx.com 
4571322Smax.romanov@nginx.com         emit_drain = get_named_property(server_obj, "emit_drain");
4581322Smax.romanov@nginx.com 
4591322Smax.romanov@nginx.com         nxt_async_context   async_context(env(), "shm_ack_handler");
4601322Smax.romanov@nginx.com         nxt_callback_scope  async_scope(async_context);
4611322Smax.romanov@nginx.com 
4621322Smax.romanov@nginx.com         make_callback(async_context, server_obj, emit_drain);
4631322Smax.romanov@nginx.com 
4641322Smax.romanov@nginx.com     } catch (exception &e) {
4651322Smax.romanov@nginx.com         nxt_unit_warn(ctx, "shm_ack_handler: %s", e.str);
4661322Smax.romanov@nginx.com     }
4671322Smax.romanov@nginx.com }
4681322Smax.romanov@nginx.com 
4691322Smax.romanov@nginx.com 
470828Salexander.borisov@nginx.com int
add_port(nxt_unit_ctx_t * ctx,nxt_unit_port_t * port)471828Salexander.borisov@nginx.com Unit::add_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port)
472828Salexander.borisov@nginx.com {
4731767Smax.romanov@nginx.com     int          err;
4741767Smax.romanov@nginx.com     Unit         *obj;
4751767Smax.romanov@nginx.com     uv_loop_t    *loop;
4761767Smax.romanov@nginx.com     port_data_t  *data;
4771767Smax.romanov@nginx.com     napi_status  status;
478828Salexander.borisov@nginx.com 
479828Salexander.borisov@nginx.com     if (port->in_fd != -1) {
480828Salexander.borisov@nginx.com         if (fcntl(port->in_fd, F_SETFL, O_NONBLOCK) == -1) {
4811132Smax.romanov@nginx.com             nxt_unit_warn(ctx, "fcntl(%d, O_NONBLOCK) failed: %s (%d)",
4821132Smax.romanov@nginx.com                           port->in_fd, strerror(errno), errno);
483828Salexander.borisov@nginx.com             return -1;
484828Salexander.borisov@nginx.com         }
485828Salexander.borisov@nginx.com 
4861767Smax.romanov@nginx.com         obj = reinterpret_cast<Unit *>(ctx->unit->data);
4871767Smax.romanov@nginx.com 
4881020Smax.romanov@nginx.com         status = napi_get_uv_event_loop(obj->env(), &loop);
489828Salexander.borisov@nginx.com         if (status != napi_ok) {
4901132Smax.romanov@nginx.com             nxt_unit_warn(ctx, "Failed to get uv.loop");
491828Salexander.borisov@nginx.com             return NXT_UNIT_ERROR;
492828Salexander.borisov@nginx.com         }
493828Salexander.borisov@nginx.com 
4941767Smax.romanov@nginx.com         data = new port_data_t(ctx, port);
495828Salexander.borisov@nginx.com 
4961543Smax.romanov@nginx.com         err = uv_poll_init(loop, &data->poll, port->in_fd);
497828Salexander.borisov@nginx.com         if (err < 0) {
4981132Smax.romanov@nginx.com             nxt_unit_warn(ctx, "Failed to init uv.poll");
4991767Smax.romanov@nginx.com             delete data;
500828Salexander.borisov@nginx.com             return NXT_UNIT_ERROR;
501828Salexander.borisov@nginx.com         }
502828Salexander.borisov@nginx.com 
5031767Smax.romanov@nginx.com         err = uv_poll_start(&data->poll, UV_READABLE,
5041767Smax.romanov@nginx.com                             port_data_t::read_callback);
505828Salexander.borisov@nginx.com         if (err < 0) {
5061132Smax.romanov@nginx.com             nxt_unit_warn(ctx, "Failed to start uv.poll");
5071767Smax.romanov@nginx.com             delete data;
508828Salexander.borisov@nginx.com             return NXT_UNIT_ERROR;
509828Salexander.borisov@nginx.com         }
510828Salexander.borisov@nginx.com 
5111543Smax.romanov@nginx.com         port->data = data;
512842Salexander.borisov@nginx.com 
5131767Smax.romanov@nginx.com         data->ref_count++;
5141547Smax.romanov@nginx.com         data->poll.data = data;
515828Salexander.borisov@nginx.com     }
516828Salexander.borisov@nginx.com 
5171543Smax.romanov@nginx.com     return NXT_UNIT_OK;
518828Salexander.borisov@nginx.com }
519828Salexander.borisov@nginx.com 
520828Salexander.borisov@nginx.com 
521828Salexander.borisov@nginx.com void
remove_port(nxt_unit_t * unit,nxt_unit_ctx_t * ctx,nxt_unit_port_t * port)5221980Smax.romanov@nginx.com Unit::remove_port(nxt_unit_t *unit, nxt_unit_ctx_t *ctx, nxt_unit_port_t *port)
523828Salexander.borisov@nginx.com {
5241543Smax.romanov@nginx.com     port_data_t  *data;
525828Salexander.borisov@nginx.com 
5261980Smax.romanov@nginx.com     if (port->data != NULL && ctx != NULL) {
5271543Smax.romanov@nginx.com         data = (port_data_t *) port->data;
528828Salexander.borisov@nginx.com 
5291767Smax.romanov@nginx.com         data->stop();
530828Salexander.borisov@nginx.com     }
531828Salexander.borisov@nginx.com }
532828Salexander.borisov@nginx.com 
533828Salexander.borisov@nginx.com 
534842Salexander.borisov@nginx.com void
quit_cb(nxt_unit_ctx_t * ctx)5351132Smax.romanov@nginx.com Unit::quit_cb(nxt_unit_ctx_t *ctx)
536842Salexander.borisov@nginx.com {
5371132Smax.romanov@nginx.com     Unit  *obj;
5381021Smax.romanov@nginx.com 
5391021Smax.romanov@nginx.com     obj = reinterpret_cast<Unit *>(ctx->unit->data);
5401021Smax.romanov@nginx.com 
5411132Smax.romanov@nginx.com     obj->quit(ctx);
5421132Smax.romanov@nginx.com }
5431132Smax.romanov@nginx.com 
5441132Smax.romanov@nginx.com 
5451132Smax.romanov@nginx.com void
quit(nxt_unit_ctx_t * ctx)5461132Smax.romanov@nginx.com Unit::quit(nxt_unit_ctx_t *ctx)
5471132Smax.romanov@nginx.com {
5481132Smax.romanov@nginx.com     napi_value  server_obj, emit_close;
5491021Smax.romanov@nginx.com 
5501132Smax.romanov@nginx.com     try {
5511132Smax.romanov@nginx.com         nxt_handle_scope  scope(env());
5521021Smax.romanov@nginx.com 
5531132Smax.romanov@nginx.com         server_obj = get_server_object();
5541021Smax.romanov@nginx.com 
5551132Smax.romanov@nginx.com         emit_close = get_named_property(server_obj, "emit_close");
5561132Smax.romanov@nginx.com 
5571132Smax.romanov@nginx.com         nxt_async_context   async_context(env(), "unit_quit");
5581021Smax.romanov@nginx.com         nxt_callback_scope  async_scope(async_context);
5591021Smax.romanov@nginx.com 
5601132Smax.romanov@nginx.com         make_callback(async_context, server_obj, emit_close);
5611021Smax.romanov@nginx.com 
5621021Smax.romanov@nginx.com     } catch (exception &e) {
5631132Smax.romanov@nginx.com         nxt_unit_debug(ctx, "quit: %s", e.str);
5641021Smax.romanov@nginx.com     }
5651021Smax.romanov@nginx.com 
566842Salexander.borisov@nginx.com     nxt_unit_done(ctx);
567842Salexander.borisov@nginx.com }
568842Salexander.borisov@nginx.com 
569842Salexander.borisov@nginx.com 
570802Salexander.borisov@nginx.com napi_value
get_server_object()571802Salexander.borisov@nginx.com Unit::get_server_object()
572802Salexander.borisov@nginx.com {
5731020Smax.romanov@nginx.com     napi_value  unit_obj;
574802Salexander.borisov@nginx.com 
5751020Smax.romanov@nginx.com     unit_obj = get_reference_value(wrapper_);
576802Salexander.borisov@nginx.com 
5771020Smax.romanov@nginx.com     return get_named_property(unit_obj, "server");
578802Salexander.borisov@nginx.com }
579802Salexander.borisov@nginx.com 
580802Salexander.borisov@nginx.com 
5811020Smax.romanov@nginx.com void
create_headers(nxt_unit_request_info_t * req,napi_value request)582802Salexander.borisov@nginx.com Unit::create_headers(nxt_unit_request_info_t *req, napi_value request)
583802Salexander.borisov@nginx.com {
584*2623Szelenkov@nginx.com     char                *p;
585802Salexander.borisov@nginx.com     uint32_t            i;
5861766Smax.romanov@nginx.com     napi_value          headers, raw_headers;
587802Salexander.borisov@nginx.com     napi_status         status;
588802Salexander.borisov@nginx.com     nxt_unit_request_t  *r;
589802Salexander.borisov@nginx.com 
590802Salexander.borisov@nginx.com     r = req->request;
591802Salexander.borisov@nginx.com 
5921020Smax.romanov@nginx.com     headers = create_object();
593802Salexander.borisov@nginx.com 
5941020Smax.romanov@nginx.com     status = napi_create_array_with_length(env(), r->fields_count * 2,
595802Salexander.borisov@nginx.com                                            &raw_headers);
596802Salexander.borisov@nginx.com     if (status != napi_ok) {
5971020Smax.romanov@nginx.com         throw exception("Failed to create array");
598802Salexander.borisov@nginx.com     }
599802Salexander.borisov@nginx.com 
600802Salexander.borisov@nginx.com     for (i = 0; i < r->fields_count; i++) {
6011020Smax.romanov@nginx.com         append_header(r->fields + i, headers, raw_headers, i);
602802Salexander.borisov@nginx.com     }
603802Salexander.borisov@nginx.com 
6041020Smax.romanov@nginx.com     set_named_property(request, "headers", headers);
6051020Smax.romanov@nginx.com     set_named_property(request, "rawHeaders", raw_headers);
606*2623Szelenkov@nginx.com 
607*2623Szelenkov@nginx.com     // trim the "HTTP/" protocol prefix
608*2623Szelenkov@nginx.com     p = (char *) nxt_unit_sptr_get(&r->version);
609*2623Szelenkov@nginx.com     p += 5;
610*2623Szelenkov@nginx.com 
611*2623Szelenkov@nginx.com     set_named_property(request, "httpVersion", create_string_latin1(p, 3));
6121020Smax.romanov@nginx.com     set_named_property(request, "method", r->method, r->method_length);
6131020Smax.romanov@nginx.com     set_named_property(request, "url", r->target, r->target_length);
6141132Smax.romanov@nginx.com 
6151132Smax.romanov@nginx.com     set_named_property(request, "_websocket_handshake", r->websocket_handshake);
616802Salexander.borisov@nginx.com }
617802Salexander.borisov@nginx.com 
618802Salexander.borisov@nginx.com 
6191038Smax.romanov@nginx.com inline char
lowcase(char c)6201038Smax.romanov@nginx.com lowcase(char c)
6211038Smax.romanov@nginx.com {
6221038Smax.romanov@nginx.com     return (c >= 'A' && c <= 'Z') ? (c | 0x20) : c;
6231038Smax.romanov@nginx.com }
6241038Smax.romanov@nginx.com 
6251038Smax.romanov@nginx.com 
6261020Smax.romanov@nginx.com inline void
append_header(nxt_unit_field_t * f,napi_value headers,napi_value raw_headers,uint32_t idx)627802Salexander.borisov@nginx.com Unit::append_header(nxt_unit_field_t *f, napi_value headers,
6281020Smax.romanov@nginx.com     napi_value raw_headers, uint32_t idx)
629802Salexander.borisov@nginx.com {
6301038Smax.romanov@nginx.com     char        *name;
6311038Smax.romanov@nginx.com     uint8_t     i;
6321038Smax.romanov@nginx.com     napi_value  str, vstr;
6331038Smax.romanov@nginx.com 
6341038Smax.romanov@nginx.com     name = (char *) nxt_unit_sptr_get(&f->name);
635802Salexander.borisov@nginx.com 
6361038Smax.romanov@nginx.com     str = create_string_latin1(name, f->name_length);
6371038Smax.romanov@nginx.com 
6381038Smax.romanov@nginx.com     for (i = 0; i < f->name_length; i++) {
6391038Smax.romanov@nginx.com         name[i] = lowcase(name[i]);
6401038Smax.romanov@nginx.com     }
641802Salexander.borisov@nginx.com 
6421020Smax.romanov@nginx.com     vstr = set_named_property(headers, name, f->value, f->value_length);
643802Salexander.borisov@nginx.com 
6441020Smax.romanov@nginx.com     set_element(raw_headers, idx * 2, str);
6451020Smax.romanov@nginx.com     set_element(raw_headers, idx * 2 + 1, vstr);
646802Salexander.borisov@nginx.com }
647802Salexander.borisov@nginx.com 
648802Salexander.borisov@nginx.com 
649802Salexander.borisov@nginx.com napi_value
create_socket(napi_value server_obj,nxt_unit_request_info_t * req)650802Salexander.borisov@nginx.com Unit::create_socket(napi_value server_obj, nxt_unit_request_info_t *req)
651802Salexander.borisov@nginx.com {
6521022Smax.romanov@nginx.com     napi_value          constructor, res;
6531132Smax.romanov@nginx.com     req_data_t          *req_data;
6541022Smax.romanov@nginx.com     nxt_unit_request_t  *r;
6551022Smax.romanov@nginx.com 
6561022Smax.romanov@nginx.com     r = req->request;
657802Salexander.borisov@nginx.com 
6581132Smax.romanov@nginx.com     constructor = get_named_property(server_obj, "Socket");
659802Salexander.borisov@nginx.com 
6601022Smax.romanov@nginx.com     res = new_instance(constructor);
661802Salexander.borisov@nginx.com 
6621132Smax.romanov@nginx.com     req_data = (req_data_t *) req->data;
6631132Smax.romanov@nginx.com     req_data->sock_ref = wrap(res, req, sock_destroy);
6641132Smax.romanov@nginx.com 
6651022Smax.romanov@nginx.com     set_named_property(res, "remoteAddress", r->remote, r->remote_length);
6662208Sa.clayton@nginx.com     set_named_property(res, "localAddress", r->local_addr,
6672208Sa.clayton@nginx.com                        r->local_addr_length);
668828Salexander.borisov@nginx.com 
6691022Smax.romanov@nginx.com     return res;
670802Salexander.borisov@nginx.com }
671802Salexander.borisov@nginx.com 
672802Salexander.borisov@nginx.com 
673802Salexander.borisov@nginx.com napi_value
create_request(napi_value server_obj,napi_value socket,nxt_unit_request_info_t * req)6741766Smax.romanov@nginx.com Unit::create_request(napi_value server_obj, napi_value socket,
6751766Smax.romanov@nginx.com     nxt_unit_request_info_t *req)
676802Salexander.borisov@nginx.com {
6771766Smax.romanov@nginx.com     napi_value  constructor, res;
6781766Smax.romanov@nginx.com     req_data_t  *req_data;
6791132Smax.romanov@nginx.com 
6801132Smax.romanov@nginx.com     constructor = get_named_property(server_obj, "ServerRequest");
681802Salexander.borisov@nginx.com 
6821766Smax.romanov@nginx.com     res = new_instance(constructor, server_obj, socket);
6831766Smax.romanov@nginx.com 
6841766Smax.romanov@nginx.com     req_data = (req_data_t *) req->data;
6851766Smax.romanov@nginx.com     req_data->req_ref = wrap(res, req, req_destroy);
6861766Smax.romanov@nginx.com 
6871766Smax.romanov@nginx.com     return res;
6881132Smax.romanov@nginx.com }
6891132Smax.romanov@nginx.com 
690802Salexander.borisov@nginx.com 
6911132Smax.romanov@nginx.com napi_value
create_response(napi_value server_obj,napi_value request,nxt_unit_request_info_t * req)6921132Smax.romanov@nginx.com Unit::create_response(napi_value server_obj, napi_value request,
6931132Smax.romanov@nginx.com     nxt_unit_request_info_t *req)
6941132Smax.romanov@nginx.com {
6951132Smax.romanov@nginx.com     napi_value  constructor, res;
6961132Smax.romanov@nginx.com     req_data_t  *req_data;
697802Salexander.borisov@nginx.com 
6981132Smax.romanov@nginx.com     constructor = get_named_property(server_obj, "ServerResponse");
6991132Smax.romanov@nginx.com 
7001132Smax.romanov@nginx.com     res = new_instance(constructor, request);
701802Salexander.borisov@nginx.com 
7021132Smax.romanov@nginx.com     req_data = (req_data_t *) req->data;
7031132Smax.romanov@nginx.com     req_data->resp_ref = wrap(res, req, resp_destroy);
7041132Smax.romanov@nginx.com 
7051132Smax.romanov@nginx.com     return res;
706802Salexander.borisov@nginx.com }
707802Salexander.borisov@nginx.com 
708802Salexander.borisov@nginx.com 
709802Salexander.borisov@nginx.com napi_value
create_websocket_frame(napi_value server_obj,nxt_unit_websocket_frame_t * ws)7101132Smax.romanov@nginx.com Unit::create_websocket_frame(napi_value server_obj,
7111132Smax.romanov@nginx.com                              nxt_unit_websocket_frame_t *ws)
712802Salexander.borisov@nginx.com {
7131132Smax.romanov@nginx.com     void        *data;
7141132Smax.romanov@nginx.com     napi_value  constructor, res, buffer;
7151132Smax.romanov@nginx.com     uint8_t     sc[2];
7161132Smax.romanov@nginx.com 
7171132Smax.romanov@nginx.com     constructor = get_named_property(server_obj, "WebSocketFrame");
718802Salexander.borisov@nginx.com 
7191132Smax.romanov@nginx.com     res = new_instance(constructor);
7201132Smax.romanov@nginx.com 
7211132Smax.romanov@nginx.com     set_named_property(res, "fin", (bool) ws->header->fin);
7221132Smax.romanov@nginx.com     set_named_property(res, "opcode", ws->header->opcode);
7231132Smax.romanov@nginx.com     set_named_property(res, "length", (int64_t) ws->payload_len);
724802Salexander.borisov@nginx.com 
7251132Smax.romanov@nginx.com     if (ws->header->opcode == NXT_WEBSOCKET_OP_CLOSE) {
7261132Smax.romanov@nginx.com         if (ws->payload_len >= 2) {
7271132Smax.romanov@nginx.com             nxt_unit_websocket_read(ws, sc, 2);
7281132Smax.romanov@nginx.com 
7291132Smax.romanov@nginx.com             set_named_property(res, "closeStatus",
7301132Smax.romanov@nginx.com                                (((uint16_t) sc[0]) << 8) | sc[1]);
731802Salexander.borisov@nginx.com 
7321132Smax.romanov@nginx.com         } else {
7331132Smax.romanov@nginx.com             set_named_property(res, "closeStatus", -1);
7341132Smax.romanov@nginx.com         }
7351132Smax.romanov@nginx.com     }
736802Salexander.borisov@nginx.com 
7371132Smax.romanov@nginx.com     buffer = create_buffer((size_t) ws->content_length, &data);
7381132Smax.romanov@nginx.com     nxt_unit_websocket_read(ws, data, ws->content_length);
7391132Smax.romanov@nginx.com 
7401132Smax.romanov@nginx.com     set_named_property(res, "binaryPayload", buffer);
7411132Smax.romanov@nginx.com 
7421132Smax.romanov@nginx.com     return res;
743802Salexander.borisov@nginx.com }
744802Salexander.borisov@nginx.com 
745802Salexander.borisov@nginx.com 
746802Salexander.borisov@nginx.com napi_value
request_read(napi_env env,napi_callback_info info)7471766Smax.romanov@nginx.com Unit::request_read(napi_env env, napi_callback_info info)
7481766Smax.romanov@nginx.com {
7491766Smax.romanov@nginx.com     void                     *data;
7501766Smax.romanov@nginx.com     uint32_t                 wm;
7511766Smax.romanov@nginx.com     nxt_napi                 napi(env);
7521766Smax.romanov@nginx.com     napi_value               this_arg, argv, buffer;
7531766Smax.romanov@nginx.com     nxt_unit_request_info_t  *req;
7541766Smax.romanov@nginx.com 
7551766Smax.romanov@nginx.com     try {
7561766Smax.romanov@nginx.com         this_arg = napi.get_cb_info(info, argv);
7571766Smax.romanov@nginx.com 
7581766Smax.romanov@nginx.com         try {
7591766Smax.romanov@nginx.com             req = napi.get_request_info(this_arg);
7601766Smax.romanov@nginx.com 
7611766Smax.romanov@nginx.com         } catch (exception &e) {
7621766Smax.romanov@nginx.com             return nullptr;
7631766Smax.romanov@nginx.com         }
7641766Smax.romanov@nginx.com 
7651766Smax.romanov@nginx.com         if (req->content_length == 0) {
7661766Smax.romanov@nginx.com             return nullptr;
7671766Smax.romanov@nginx.com         }
7681766Smax.romanov@nginx.com 
7691766Smax.romanov@nginx.com         wm = napi.get_value_uint32(argv);
7701766Smax.romanov@nginx.com 
7711766Smax.romanov@nginx.com         if (wm > req->content_length) {
7721766Smax.romanov@nginx.com             wm = req->content_length;
7731766Smax.romanov@nginx.com         }
7741766Smax.romanov@nginx.com 
7751766Smax.romanov@nginx.com         buffer = napi.create_buffer((size_t) wm, &data);
7761766Smax.romanov@nginx.com         nxt_unit_request_read(req, data, wm);
7771766Smax.romanov@nginx.com 
7781766Smax.romanov@nginx.com     } catch (exception &e) {
7791766Smax.romanov@nginx.com         napi.throw_error(e);
7801766Smax.romanov@nginx.com         return nullptr;
7811766Smax.romanov@nginx.com     }
7821766Smax.romanov@nginx.com 
7831766Smax.romanov@nginx.com     return buffer;
7841766Smax.romanov@nginx.com }
7851766Smax.romanov@nginx.com 
7861766Smax.romanov@nginx.com 
7871766Smax.romanov@nginx.com napi_value
response_send_headers(napi_env env,napi_callback_info info)788802Salexander.borisov@nginx.com Unit::response_send_headers(napi_env env, napi_callback_info info)
789802Salexander.borisov@nginx.com {
790802Salexander.borisov@nginx.com     int                      ret;
791802Salexander.borisov@nginx.com     char                     *ptr, *name_ptr;
792802Salexander.borisov@nginx.com     bool                     is_array;
793802Salexander.borisov@nginx.com     size_t                   argc, name_len, value_len;
794802Salexander.borisov@nginx.com     uint32_t                 status_code, header_len, keys_len, array_len;
795802Salexander.borisov@nginx.com     uint32_t                 keys_count, i, j;
796802Salexander.borisov@nginx.com     uint16_t                 hash;
7971020Smax.romanov@nginx.com     nxt_napi                 napi(env);
798802Salexander.borisov@nginx.com     napi_value               this_arg, headers, keys, name, value, array_val;
7991132Smax.romanov@nginx.com     napi_value               array_entry;
800843Salexander.borisov@nginx.com     napi_valuetype           val_type;
801802Salexander.borisov@nginx.com     nxt_unit_field_t         *f;
802802Salexander.borisov@nginx.com     nxt_unit_request_info_t  *req;
8031132Smax.romanov@nginx.com     napi_value               argv[4];
804802Salexander.borisov@nginx.com 
8051132Smax.romanov@nginx.com     argc = 4;
806802Salexander.borisov@nginx.com 
8071020Smax.romanov@nginx.com     try {
8081020Smax.romanov@nginx.com         this_arg = napi.get_cb_info(info, argc, argv);
8091132Smax.romanov@nginx.com         if (argc != 4) {
8101020Smax.romanov@nginx.com             napi.throw_error("Wrong args count. Expected: "
8111020Smax.romanov@nginx.com                              "statusCode, headers, headers count, "
8121020Smax.romanov@nginx.com                              "headers length");
8131020Smax.romanov@nginx.com             return nullptr;
8141020Smax.romanov@nginx.com         }
815802Salexander.borisov@nginx.com 
8161132Smax.romanov@nginx.com         req = napi.get_request_info(this_arg);
8171132Smax.romanov@nginx.com         status_code = napi.get_value_uint32(argv[0]);
8181132Smax.romanov@nginx.com         keys_count = napi.get_value_uint32(argv[2]);
8191132Smax.romanov@nginx.com         header_len = napi.get_value_uint32(argv[3]);
820802Salexander.borisov@nginx.com 
8211132Smax.romanov@nginx.com         headers = argv[1];
822802Salexander.borisov@nginx.com 
8231020Smax.romanov@nginx.com         ret = nxt_unit_response_init(req, status_code, keys_count, header_len);
8241020Smax.romanov@nginx.com         if (ret != NXT_UNIT_OK) {
8251020Smax.romanov@nginx.com             napi.throw_error("Failed to create response");
8261020Smax.romanov@nginx.com             return nullptr;
827802Salexander.borisov@nginx.com         }
828802Salexander.borisov@nginx.com 
8291257Smax.romanov@nginx.com         /*
8301257Smax.romanov@nginx.com          * Each name and value are 0-terminated by libunit.
8311257Smax.romanov@nginx.com          * Need to add extra 2 bytes for each header.
8321257Smax.romanov@nginx.com          */
8331257Smax.romanov@nginx.com         header_len += keys_count * 2;
8341257Smax.romanov@nginx.com 
8351020Smax.romanov@nginx.com         keys = napi.get_property_names(headers);
8361020Smax.romanov@nginx.com         keys_len = napi.get_array_length(keys);
8371020Smax.romanov@nginx.com 
8381020Smax.romanov@nginx.com         ptr = req->response_buf->free;
839875Salexander.borisov@nginx.com 
8401020Smax.romanov@nginx.com         for (i = 0; i < keys_len; i++) {
8411020Smax.romanov@nginx.com             name = napi.get_element(keys, i);
8421020Smax.romanov@nginx.com 
8431020Smax.romanov@nginx.com             array_entry = napi.get_property(headers, name);
8441020Smax.romanov@nginx.com 
8451020Smax.romanov@nginx.com             name = napi.get_element(array_entry, 0);
8461020Smax.romanov@nginx.com             value = napi.get_element(array_entry, 1);
847875Salexander.borisov@nginx.com 
8481020Smax.romanov@nginx.com             name_len = napi.get_value_string_latin1(name, ptr, header_len);
8491020Smax.romanov@nginx.com             name_ptr = ptr;
8501020Smax.romanov@nginx.com 
8511257Smax.romanov@nginx.com             ptr += name_len + 1;
8521257Smax.romanov@nginx.com             header_len -= name_len + 1;
853802Salexander.borisov@nginx.com 
8541020Smax.romanov@nginx.com             hash = nxt_unit_field_hash(name_ptr, name_len);
8551020Smax.romanov@nginx.com 
8561020Smax.romanov@nginx.com             is_array = napi.is_array(value);
8571020Smax.romanov@nginx.com 
8581020Smax.romanov@nginx.com             if (is_array) {
8591020Smax.romanov@nginx.com                 array_len = napi.get_array_length(value);
860802Salexander.borisov@nginx.com 
8611020Smax.romanov@nginx.com                 for (j = 0; j < array_len; j++) {
8621020Smax.romanov@nginx.com                     array_val = napi.get_element(value, j);
8631020Smax.romanov@nginx.com 
8641020Smax.romanov@nginx.com                     val_type = napi.type_of(array_val);
865802Salexander.borisov@nginx.com 
8661020Smax.romanov@nginx.com                     if (val_type != napi_string) {
8671020Smax.romanov@nginx.com                         array_val = napi.coerce_to_string(array_val);
8681020Smax.romanov@nginx.com                     }
869802Salexander.borisov@nginx.com 
8701020Smax.romanov@nginx.com                     value_len = napi.get_value_string_latin1(array_val, ptr,
8711020Smax.romanov@nginx.com                                                              header_len);
872802Salexander.borisov@nginx.com 
8731020Smax.romanov@nginx.com                     f = req->response->fields + req->response->fields_count;
8741020Smax.romanov@nginx.com                     f->skip = 0;
8751020Smax.romanov@nginx.com 
8761020Smax.romanov@nginx.com                     nxt_unit_sptr_set(&f->name, name_ptr);
8771020Smax.romanov@nginx.com 
8781020Smax.romanov@nginx.com                     f->name_length = name_len;
8791020Smax.romanov@nginx.com                     f->hash = hash;
880802Salexander.borisov@nginx.com 
8811020Smax.romanov@nginx.com                     nxt_unit_sptr_set(&f->value, ptr);
8821020Smax.romanov@nginx.com                     f->value_length = (uint32_t) value_len;
883802Salexander.borisov@nginx.com 
8841257Smax.romanov@nginx.com                     ptr += value_len + 1;
8851257Smax.romanov@nginx.com                     header_len -= value_len + 1;
8861020Smax.romanov@nginx.com 
8871020Smax.romanov@nginx.com                     req->response->fields_count++;
888802Salexander.borisov@nginx.com                 }
889802Salexander.borisov@nginx.com 
8901020Smax.romanov@nginx.com             } else {
8911020Smax.romanov@nginx.com                 val_type = napi.type_of(value);
892843Salexander.borisov@nginx.com 
893843Salexander.borisov@nginx.com                 if (val_type != napi_string) {
8941020Smax.romanov@nginx.com                     value = napi.coerce_to_string(value);
895843Salexander.borisov@nginx.com                 }
896843Salexander.borisov@nginx.com 
8971020Smax.romanov@nginx.com                 value_len = napi.get_value_string_latin1(value, ptr, header_len);
898802Salexander.borisov@nginx.com 
899802Salexander.borisov@nginx.com                 f = req->response->fields + req->response->fields_count;
900802Salexander.borisov@nginx.com                 f->skip = 0;
901802Salexander.borisov@nginx.com 
902802Salexander.borisov@nginx.com                 nxt_unit_sptr_set(&f->name, name_ptr);
903802Salexander.borisov@nginx.com 
904802Salexander.borisov@nginx.com                 f->name_length = name_len;
905802Salexander.borisov@nginx.com                 f->hash = hash;
906802Salexander.borisov@nginx.com 
907802Salexander.borisov@nginx.com                 nxt_unit_sptr_set(&f->value, ptr);
908802Salexander.borisov@nginx.com                 f->value_length = (uint32_t) value_len;
909802Salexander.borisov@nginx.com 
9101257Smax.romanov@nginx.com                 ptr += value_len + 1;
9111257Smax.romanov@nginx.com                 header_len -= value_len + 1;
912802Salexander.borisov@nginx.com 
913802Salexander.borisov@nginx.com                 req->response->fields_count++;
914802Salexander.borisov@nginx.com             }
9151020Smax.romanov@nginx.com         }
916843Salexander.borisov@nginx.com 
9171020Smax.romanov@nginx.com     } catch (exception &e) {
9181020Smax.romanov@nginx.com         napi.throw_error(e);
9191020Smax.romanov@nginx.com         return nullptr;
920802Salexander.borisov@nginx.com     }
921802Salexander.borisov@nginx.com 
922802Salexander.borisov@nginx.com     req->response_buf->free = ptr;
923802Salexander.borisov@nginx.com 
924802Salexander.borisov@nginx.com     ret = nxt_unit_response_send(req);
925802Salexander.borisov@nginx.com     if (ret != NXT_UNIT_OK) {
9261020Smax.romanov@nginx.com         napi.throw_error("Failed to send response");
9271020Smax.romanov@nginx.com         return nullptr;
928802Salexander.borisov@nginx.com     }
929802Salexander.borisov@nginx.com 
930802Salexander.borisov@nginx.com     return this_arg;
931802Salexander.borisov@nginx.com }
932802Salexander.borisov@nginx.com 
933802Salexander.borisov@nginx.com 
934802Salexander.borisov@nginx.com napi_value
response_write(napi_env env,napi_callback_info info)935802Salexander.borisov@nginx.com Unit::response_write(napi_env env, napi_callback_info info)
936802Salexander.borisov@nginx.com {
937802Salexander.borisov@nginx.com     int                      ret;
9381132Smax.romanov@nginx.com     void                     *ptr;
939802Salexander.borisov@nginx.com     size_t                   argc, have_buf_len;
9401322Smax.romanov@nginx.com     ssize_t                  res_len;
9411322Smax.romanov@nginx.com     uint32_t                 buf_start, buf_len;
9421020Smax.romanov@nginx.com     nxt_napi                 napi(env);
9431132Smax.romanov@nginx.com     napi_value               this_arg;
944802Salexander.borisov@nginx.com     nxt_unit_buf_t           *buf;
945802Salexander.borisov@nginx.com     napi_valuetype           buf_type;
946802Salexander.borisov@nginx.com     nxt_unit_request_info_t  *req;
9471322Smax.romanov@nginx.com     napi_value               argv[3];
948802Salexander.borisov@nginx.com 
9491322Smax.romanov@nginx.com     argc = 3;
950802Salexander.borisov@nginx.com 
9511020Smax.romanov@nginx.com     try {
9521020Smax.romanov@nginx.com         this_arg = napi.get_cb_info(info, argc, argv);
9531322Smax.romanov@nginx.com         if (argc != 3) {
9541020Smax.romanov@nginx.com             throw exception("Wrong args count. Expected: "
9551322Smax.romanov@nginx.com                             "chunk, start, length");
9561020Smax.romanov@nginx.com         }
957802Salexander.borisov@nginx.com 
9581132Smax.romanov@nginx.com         req = napi.get_request_info(this_arg);
9591132Smax.romanov@nginx.com         buf_type = napi.type_of(argv[0]);
9601322Smax.romanov@nginx.com         buf_start = napi.get_value_uint32(argv[1]);
9611322Smax.romanov@nginx.com         buf_len = napi.get_value_uint32(argv[2]) + 1;
9621132Smax.romanov@nginx.com 
9631132Smax.romanov@nginx.com         if (buf_type == napi_string) {
9641132Smax.romanov@nginx.com             /* TODO: will work only for utf8 content-type */
965802Salexander.borisov@nginx.com 
9661322Smax.romanov@nginx.com             if (req->response_buf != NULL
9671373Smax.romanov@nginx.com                 && req->response_buf->end >= req->response_buf->free + buf_len)
9681322Smax.romanov@nginx.com             {
9691322Smax.romanov@nginx.com                 buf = req->response_buf;
9701322Smax.romanov@nginx.com 
9711322Smax.romanov@nginx.com             } else {
9721322Smax.romanov@nginx.com                 buf = nxt_unit_response_buf_alloc(req, buf_len);
9731322Smax.romanov@nginx.com                 if (buf == NULL) {
9741322Smax.romanov@nginx.com                     throw exception("Failed to allocate response buffer");
9751322Smax.romanov@nginx.com                 }
9761322Smax.romanov@nginx.com             }
9771322Smax.romanov@nginx.com 
9781132Smax.romanov@nginx.com             have_buf_len = napi.get_value_string_utf8(argv[0], buf->free,
9791132Smax.romanov@nginx.com                                                       buf_len);
9801132Smax.romanov@nginx.com 
9811322Smax.romanov@nginx.com             buf->free += have_buf_len;
9821322Smax.romanov@nginx.com 
9831322Smax.romanov@nginx.com             ret = nxt_unit_buf_send(buf);
9841322Smax.romanov@nginx.com             if (ret == NXT_UNIT_OK) {
9851322Smax.romanov@nginx.com                 res_len = have_buf_len;
9861322Smax.romanov@nginx.com             }
9871322Smax.romanov@nginx.com 
9881132Smax.romanov@nginx.com         } else {
9891132Smax.romanov@nginx.com             ptr = napi.get_buffer_info(argv[0], have_buf_len);
990802Salexander.borisov@nginx.com 
9911322Smax.romanov@nginx.com             if (buf_start > 0) {
9921322Smax.romanov@nginx.com                 ptr = ((uint8_t *) ptr) + buf_start;
9931322Smax.romanov@nginx.com                 have_buf_len -= buf_start;
9941322Smax.romanov@nginx.com             }
9951322Smax.romanov@nginx.com 
9961322Smax.romanov@nginx.com             res_len = nxt_unit_response_write_nb(req, ptr, have_buf_len, 0);
9971322Smax.romanov@nginx.com 
9981342Smax.romanov@nginx.com             ret = res_len < 0 ? -res_len : (int) NXT_UNIT_OK;
9991132Smax.romanov@nginx.com         }
10001132Smax.romanov@nginx.com 
10011132Smax.romanov@nginx.com         if (ret != NXT_UNIT_OK) {
10021132Smax.romanov@nginx.com             throw exception("Failed to send body buf");
10031132Smax.romanov@nginx.com         }
10041020Smax.romanov@nginx.com     } catch (exception &e) {
10051020Smax.romanov@nginx.com         napi.throw_error(e);
10061020Smax.romanov@nginx.com         return nullptr;
1007802Salexander.borisov@nginx.com     }
1008802Salexander.borisov@nginx.com 
10091322Smax.romanov@nginx.com     return napi.create((int64_t) res_len);
1010802Salexander.borisov@nginx.com }
1011802Salexander.borisov@nginx.com 
1012802Salexander.borisov@nginx.com 
1013802Salexander.borisov@nginx.com napi_value
response_end(napi_env env,napi_callback_info info)1014802Salexander.borisov@nginx.com Unit::response_end(napi_env env, napi_callback_info info)
1015802Salexander.borisov@nginx.com {
10161020Smax.romanov@nginx.com     nxt_napi                 napi(env);
10171132Smax.romanov@nginx.com     napi_value               this_arg;
10181132Smax.romanov@nginx.com     req_data_t               *req_data;
1019802Salexander.borisov@nginx.com     nxt_unit_request_info_t  *req;
1020802Salexander.borisov@nginx.com 
10211132Smax.romanov@nginx.com     try {
10221132Smax.romanov@nginx.com         this_arg = napi.get_cb_info(info);
10231132Smax.romanov@nginx.com 
10241132Smax.romanov@nginx.com         req = napi.get_request_info(this_arg);
1025802Salexander.borisov@nginx.com 
10261132Smax.romanov@nginx.com         req_data = (req_data_t *) req->data;
10271020Smax.romanov@nginx.com 
10281132Smax.romanov@nginx.com         napi.remove_wrap(req_data->sock_ref);
10291766Smax.romanov@nginx.com         napi.remove_wrap(req_data->req_ref);
10301132Smax.romanov@nginx.com         napi.remove_wrap(req_data->resp_ref);
10311132Smax.romanov@nginx.com         napi.remove_wrap(req_data->conn_ref);
10321020Smax.romanov@nginx.com 
10331020Smax.romanov@nginx.com     } catch (exception &e) {
10341020Smax.romanov@nginx.com         napi.throw_error(e);
1035802Salexander.borisov@nginx.com         return nullptr;
1036802Salexander.borisov@nginx.com     }
1037802Salexander.borisov@nginx.com 
1038802Salexander.borisov@nginx.com     nxt_unit_request_done(req, NXT_UNIT_OK);
1039802Salexander.borisov@nginx.com 
1040802Salexander.borisov@nginx.com     return this_arg;
1041802Salexander.borisov@nginx.com }
10421132Smax.romanov@nginx.com 
10431132Smax.romanov@nginx.com 
10441132Smax.romanov@nginx.com napi_value
websocket_send_frame(napi_env env,napi_callback_info info)10451132Smax.romanov@nginx.com Unit::websocket_send_frame(napi_env env, napi_callback_info info)
10461132Smax.romanov@nginx.com {
10471132Smax.romanov@nginx.com     int                      ret, iovec_len;
10481132Smax.romanov@nginx.com     bool                     fin;
10491132Smax.romanov@nginx.com     size_t                   buf_len;
10501132Smax.romanov@nginx.com     uint32_t                 opcode, sc;
10511132Smax.romanov@nginx.com     nxt_napi                 napi(env);
10521132Smax.romanov@nginx.com     napi_value               this_arg, frame, payload;
10531132Smax.romanov@nginx.com     nxt_unit_request_info_t  *req;
10541132Smax.romanov@nginx.com     char                     status_code[2];
10551132Smax.romanov@nginx.com     struct iovec             iov[2];
10561132Smax.romanov@nginx.com 
10571132Smax.romanov@nginx.com     iovec_len = 0;
10581132Smax.romanov@nginx.com 
10591132Smax.romanov@nginx.com     try {
10601132Smax.romanov@nginx.com         this_arg = napi.get_cb_info(info, frame);
10611132Smax.romanov@nginx.com 
10621132Smax.romanov@nginx.com         req = napi.get_request_info(this_arg);
10631132Smax.romanov@nginx.com 
10641132Smax.romanov@nginx.com         opcode = napi.get_value_uint32(napi.get_named_property(frame,
10651132Smax.romanov@nginx.com                                                                "opcode"));
10661132Smax.romanov@nginx.com         if (opcode == NXT_WEBSOCKET_OP_CLOSE) {
10671132Smax.romanov@nginx.com             sc = napi.get_value_uint32(napi.get_named_property(frame,
10681132Smax.romanov@nginx.com                                                                "closeStatus"));
10691132Smax.romanov@nginx.com             status_code[0] = (sc >> 8) & 0xFF;
10701132Smax.romanov@nginx.com             status_code[1] = sc & 0xFF;
10711132Smax.romanov@nginx.com 
10721132Smax.romanov@nginx.com             iov[iovec_len].iov_base = status_code;
10731132Smax.romanov@nginx.com             iov[iovec_len].iov_len = 2;
10741132Smax.romanov@nginx.com             iovec_len++;
10751132Smax.romanov@nginx.com         }
10761132Smax.romanov@nginx.com 
10771132Smax.romanov@nginx.com         try {
10781132Smax.romanov@nginx.com             fin = napi.get_value_bool(napi.get_named_property(frame, "fin"));
10791132Smax.romanov@nginx.com 
10801132Smax.romanov@nginx.com         } catch (exception &e) {
10811132Smax.romanov@nginx.com             fin = true;
10821132Smax.romanov@nginx.com         }
10831132Smax.romanov@nginx.com 
10841132Smax.romanov@nginx.com         payload = napi.get_named_property(frame, "binaryPayload");
10851132Smax.romanov@nginx.com 
10861132Smax.romanov@nginx.com         if (napi.is_buffer(payload)) {
10871132Smax.romanov@nginx.com             iov[iovec_len].iov_base = napi.get_buffer_info(payload, buf_len);
10881132Smax.romanov@nginx.com 
10891132Smax.romanov@nginx.com         } else {
10901132Smax.romanov@nginx.com             buf_len = 0;
10911132Smax.romanov@nginx.com         }
10921132Smax.romanov@nginx.com 
10931132Smax.romanov@nginx.com     } catch (exception &e) {
10941132Smax.romanov@nginx.com         napi.throw_error(e);
10951132Smax.romanov@nginx.com         return nullptr;
10961132Smax.romanov@nginx.com     }
10971132Smax.romanov@nginx.com 
10981132Smax.romanov@nginx.com     if (buf_len > 0) {
10991132Smax.romanov@nginx.com         iov[iovec_len].iov_len = buf_len;
11001132Smax.romanov@nginx.com         iovec_len++;
11011132Smax.romanov@nginx.com     }
11021132Smax.romanov@nginx.com 
11031132Smax.romanov@nginx.com     ret = nxt_unit_websocket_sendv(req, opcode, fin ? 1 : 0, iov, iovec_len);
11041132Smax.romanov@nginx.com     if (ret != NXT_UNIT_OK) {
11051132Smax.romanov@nginx.com         goto failed;
11061132Smax.romanov@nginx.com     }
11071132Smax.romanov@nginx.com 
11081132Smax.romanov@nginx.com     return this_arg;
11091132Smax.romanov@nginx.com 
11101132Smax.romanov@nginx.com failed:
11111132Smax.romanov@nginx.com 
11121132Smax.romanov@nginx.com     napi.throw_error("Failed to send frame");
11131132Smax.romanov@nginx.com 
11141132Smax.romanov@nginx.com     return nullptr;
11151132Smax.romanov@nginx.com }
11161132Smax.romanov@nginx.com 
11171132Smax.romanov@nginx.com 
11181132Smax.romanov@nginx.com napi_value
websocket_set_sock(napi_env env,napi_callback_info info)11191132Smax.romanov@nginx.com Unit::websocket_set_sock(napi_env env, napi_callback_info info)
11201132Smax.romanov@nginx.com {
11211132Smax.romanov@nginx.com     nxt_napi                 napi(env);
11221132Smax.romanov@nginx.com     napi_value               this_arg, sock;
11231132Smax.romanov@nginx.com     req_data_t               *req_data;
11241132Smax.romanov@nginx.com     nxt_unit_request_info_t  *req;
11251132Smax.romanov@nginx.com 
11261132Smax.romanov@nginx.com     try {
11271132Smax.romanov@nginx.com         this_arg = napi.get_cb_info(info, sock);
11281132Smax.romanov@nginx.com 
11291132Smax.romanov@nginx.com         req = napi.get_request_info(sock);
11301132Smax.romanov@nginx.com 
11311132Smax.romanov@nginx.com         req_data = (req_data_t *) req->data;
11321132Smax.romanov@nginx.com         req_data->conn_ref = napi.wrap(this_arg, req, conn_destroy);
11331132Smax.romanov@nginx.com 
11341132Smax.romanov@nginx.com     } catch (exception &e) {
11351132Smax.romanov@nginx.com         napi.throw_error(e);
11361132Smax.romanov@nginx.com         return nullptr;
11371132Smax.romanov@nginx.com     }
11381132Smax.romanov@nginx.com 
11391132Smax.romanov@nginx.com     return this_arg;
11401132Smax.romanov@nginx.com }
11411132Smax.romanov@nginx.com 
11421132Smax.romanov@nginx.com 
11431132Smax.romanov@nginx.com void
conn_destroy(napi_env env,void * r,void * finalize_hint)11441729Smax.romanov@nginx.com Unit::conn_destroy(napi_env env, void *r, void *finalize_hint)
11451132Smax.romanov@nginx.com {
11461731Smax.romanov@nginx.com     nxt_unit_req_debug(NULL, "conn_destroy: %p", r);
11471132Smax.romanov@nginx.com }
11481132Smax.romanov@nginx.com 
11491132Smax.romanov@nginx.com 
11501132Smax.romanov@nginx.com void
sock_destroy(napi_env env,void * r,void * finalize_hint)11511729Smax.romanov@nginx.com Unit::sock_destroy(napi_env env, void *r, void *finalize_hint)
11521132Smax.romanov@nginx.com {
11531731Smax.romanov@nginx.com     nxt_unit_req_debug(NULL, "sock_destroy: %p", r);
11541132Smax.romanov@nginx.com }
11551132Smax.romanov@nginx.com 
11561132Smax.romanov@nginx.com 
11571132Smax.romanov@nginx.com void
req_destroy(napi_env env,void * r,void * finalize_hint)11581766Smax.romanov@nginx.com Unit::req_destroy(napi_env env, void *r, void *finalize_hint)
11591766Smax.romanov@nginx.com {
11601766Smax.romanov@nginx.com     nxt_unit_req_debug(NULL, "req_destroy: %p", r);
11611766Smax.romanov@nginx.com }
11621766Smax.romanov@nginx.com 
11631766Smax.romanov@nginx.com 
11641766Smax.romanov@nginx.com void
resp_destroy(napi_env env,void * r,void * finalize_hint)11651729Smax.romanov@nginx.com Unit::resp_destroy(napi_env env, void *r, void *finalize_hint)
11661132Smax.romanov@nginx.com {
11671731Smax.romanov@nginx.com     nxt_unit_req_debug(NULL, "resp_destroy: %p", r);
11681132Smax.romanov@nginx.com }
1169