napi_value aws_napi_http_connection_manager_new()

in source/http_connection_manager.c [56:208]


napi_value aws_napi_http_connection_manager_new(napi_env env, napi_callback_info info) {

    napi_value result = NULL;

    napi_value node_args[9];
    size_t num_args = AWS_ARRAY_SIZE(node_args);
    napi_value *arg = &node_args[0];
    AWS_NAPI_CALL(env, napi_get_cb_info(env, info, &num_args, node_args, NULL, NULL), {
        napi_throw_error(env, NULL, "Unable to get callback info");
        return NULL;
    });
    if (num_args != AWS_ARRAY_SIZE(node_args)) {
        napi_throw_error(env, NULL, "http_connection_manager_new takes exactly 8 arguments");
        return NULL;
    }

    struct aws_allocator *allocator = aws_napi_get_allocator();
    struct aws_http_connection_manager_options options;
    AWS_ZERO_STRUCT(options);
    struct aws_byte_buf host_buf;
    AWS_ZERO_STRUCT(host_buf);
    struct aws_tls_connection_options tls_connection_options;
    AWS_ZERO_STRUCT(tls_connection_options);

    napi_value node_bootstrap = *arg++;
    struct client_bootstrap_binding *client_bootstrap_binding = NULL;
    napi_get_value_external(env, node_bootstrap, (void **)&client_bootstrap_binding);
    if (client_bootstrap_binding != NULL) {
        options.bootstrap = aws_napi_get_client_bootstrap(client_bootstrap_binding);
    } else {
        options.bootstrap = aws_napi_get_default_client_bootstrap();
    }

    napi_value node_host = *arg++;
    if (aws_byte_buf_init_from_napi(&host_buf, env, node_host)) {
        napi_throw_type_error(env, NULL, "host must be a string");
        return NULL;
    }
    options.host = aws_byte_cursor_from_buf(&host_buf);

    struct http_connection_manager_binding *binding =
        aws_mem_calloc(allocator, 1, sizeof(struct http_connection_manager_binding));
    AWS_FATAL_ASSERT(binding);

    binding->allocator = allocator;
    binding->env = env;

    napi_value node_port = *arg++;
    uint32_t port = 0;
    if (napi_get_value_uint32(env, node_port, &port) || port > UINT16_MAX) {
        napi_throw_type_error(env, NULL, "port must be a number between 0 and 65535");
        goto cleanup;
    }
    options.port = (uint16_t)port;

    napi_value node_max_conns = *arg++;
    uint32_t max_connections = 0;
    AWS_NAPI_CALL(env, napi_get_value_uint32(env, node_max_conns, &max_connections), {
        napi_throw_type_error(env, NULL, "max_connections must be a number");
        goto cleanup;
    });
    options.max_connections = (size_t)max_connections;

    napi_value node_window_size = *arg++;
    uint32_t window_size = 16 * 1024;
    AWS_NAPI_CALL(env, napi_get_value_uint32(env, node_window_size, &window_size), {
        napi_throw_type_error(env, NULL, "initial_window_size must be a number");
        goto cleanup;
    });
    options.initial_window_size = (size_t)window_size;

    napi_value node_socket_options = *arg++;
    const struct aws_socket_options *socket_options = NULL;
    if (!aws_napi_is_null_or_undefined(env, node_socket_options)) {
        AWS_NAPI_CALL(env, napi_get_value_external(env, node_socket_options, (void **)&socket_options), {
            napi_throw_type_error(env, NULL, "socket_options must be undefined or a valid SocketOptions");
            goto cleanup;
        });
    }
    options.socket_options = socket_options;

    napi_value node_tls_opts = *arg++;
    struct aws_tls_connection_options *tls_opts = NULL;
    if (!aws_napi_is_null_or_undefined(env, node_tls_opts)) {
        AWS_NAPI_CALL(env, napi_get_value_external(env, node_tls_opts, (void **)&tls_opts), {
            napi_throw_type_error(env, NULL, "tls_opts must be undefined or a valid TlsConnectionOptions");
            goto cleanup;
        });
    }
    options.tls_connection_options = tls_opts;

    napi_value node_proxy_options = *arg++;
    struct aws_http_proxy_options *proxy_options = NULL;
    if (!aws_napi_is_null_or_undefined(env, node_proxy_options)) {
        struct http_proxy_options_binding *proxy_binding = NULL;
        AWS_NAPI_CALL(env, napi_get_value_external(env, node_proxy_options, (void **)&proxy_binding), {
            napi_throw_type_error(env, NULL, "tls_opts must be undefined or a valid TlsConnectionOptions");
            goto cleanup;
        });
        proxy_options = aws_napi_get_http_proxy_options(proxy_binding);
    }
    /* proxy_options are copied internally, no need to go nuts on copies */
    options.proxy_options = proxy_options;

    napi_value node_on_shutdown = *arg++;
    if (!aws_napi_is_null_or_undefined(env, node_on_shutdown)) {
        AWS_NAPI_CALL(
            env,
            aws_napi_create_threadsafe_function(
                env,
                node_on_shutdown,
                "aws_http_connection_manager_on_shutdown",
                s_http_connection_manager_shutdown_call,
                binding,
                &binding->on_shutdown),
            {
                napi_throw_type_error(env, NULL, "on_shutdown must be a valid callback or undefined");
                goto cleanup;
            });
    }

    options.shutdown_complete_callback = s_http_connection_manager_shutdown_complete;
    options.shutdown_complete_user_data = binding;
    binding->manager = aws_http_connection_manager_new(allocator, &options);
    if (!binding->manager) {
        aws_napi_throw_last_error(env);
        goto cleanup;
    }

    napi_value node_external = NULL;
    AWS_NAPI_CALL(env, napi_create_external(env, binding, s_http_connection_manager_finalize, NULL, &node_external), {
        napi_throw_error(env, NULL, "Unable to create node external");
        goto external_failed;
    });
    AWS_NAPI_CALL(env, napi_create_reference(env, node_external, 1, &binding->node_external), {
        napi_throw_error(env, NULL, "Unable to create reference to node external");
        goto external_failed;
    });

    /* success, set the return value */
    result = node_external;
    goto done;

external_failed:
    aws_http_connection_manager_release(binding->manager);

cleanup:
done:
    aws_tls_connection_options_clean_up(&tls_connection_options);
    aws_byte_buf_clean_up(&host_buf);

    return result;
}