static void shutdown_http(clconfig_provider *provider)
{
    http_provider *http = (http_provider *)provider;

    reset_stream_state(http);

    lcb_string_release(&http->stream.chunk);
    lcb_string_release(&http->stream.input);
    lcb_string_release(&http->stream.header);

    lcb_connection_close(&http->connection);
    lcb_connection_cleanup(&http->connection);

    if (http->current_config) {
        lcb_clconfig_decref(http->current_config);
    }
    if (http->disconn_timer) {
        lcb_timer_destroy(NULL, http->disconn_timer);
    }
    if (http->io_timer) {
        lcb_timer_destroy(NULL, http->io_timer);
    }
    if (http->as_schederr) {
        lcb_timer_destroy(NULL, http->as_schederr);
    }
    if (http->nodes) {
        hostlist_destroy(http->nodes);
    }
    free(http);
}
static lcb_error_t connect_next(http_provider *http)
{
    char *errinfo = NULL;
    lcb_error_t err;
    lcb_conn_params params;
    lcb_connection_t conn = &http->connection;

    close_current(http);
    reset_stream_state(http);
    params.handler = connect_done_handler;
    params.timeout = PROVIDER_SETTING(&http->base, config_node_timeout);

    lcb_log(LOGARGS(http, TRACE),
            "Starting HTTP Configuration Provider %p", http);

    err = lcb_connection_cycle_nodes(conn, http->nodes, &params, &errinfo);

    if (err == LCB_SUCCESS) {
        err = setup_request_header(http);
    } else {
        lcb_log(LOGARGS(http, ERROR),
                "%p: Couldn't schedule connection (0x%x)", http, err);
    }

    return err;
}
static void delayed_disconn(lcb_timer_t tm, lcb_t instance, const void *cookie)
{
    http_provider *http = (http_provider *)cookie;
    lcb_log(LOGARGS(http, DEBUG), "Stopping HTTP provider %p", http);

    /** closes the connection and cleans up the timer */
    close_current(http);
    lcb_timer_disarm(http->io_timer);
    reset_stream_state(http);

    (void)tm;
    (void)instance;
}
static lcb_error_t start_connection(lcb_t instance)
{
    lcb_error_t rc;
    char *ptr;
    lcb_connection_result_t connres;
    lcb_connection_t conn = &instance->bootstrap.via.http.connection;

    /**
     * First, close the connection, if there's an open socket from a previous
     * one.
     */
    lcb_connection_close(conn);
    reset_stream_state(instance);

    conn->on_connect_complete = connect_done_handler;
    conn->evinfo.handler = config_v0_handler;
    conn->completion.read = config_v1_read_handler;
    conn->completion.write = config_v1_write_handler;
    conn->completion.error = config_v1_error_handler;
    conn->on_timeout = lcb_bootstrap_timeout_handler;
    conn->timeout.usec = instance->config.bootstrap_timeout;
    rc = lcb_init_next_host(instance, 8091);
    if (rc != LCB_SUCCESS) {
        return rc;
    }
    instance->last_error = LCB_SUCCESS;

    /* We need to fix the host part... */
    ptr = strstr(instance->bootstrap.via.http.uri, LCB_LAST_HTTP_HEADER);
    lcb_assert(ptr);
    ptr += strlen(LCB_LAST_HTTP_HEADER);
    sprintf(ptr, "Host: %s:%s\r\n\r\n", conn->host, conn->port);
    connres = lcb_connection_start(conn, 1);
    if (connres == LCB_CONN_ERROR) {
        lcb_connection_close(conn);
        return lcb_error_handler(instance, LCB_CONNECT_ERROR,
                                 "Couldn't schedule connection");
    }

    if (instance->config.syncmode == LCB_SYNCHRONOUS) {
        lcb_wait(instance);
    }

    return instance->last_error;
}
void http_cleanup(lcb_t instance)
{
    reset_stream_state(instance);
    free(instance->bootstrap.via.http.uri);
    lcb_connection_cleanup(&instance->bootstrap.via.http.connection);
}