static int
trg_http_perform_inner(TrgClient * tc, gchar * reqstr,
                       trg_response * response, gboolean recurse)
{
    TrgClientPrivate *priv = tc->priv;
    TrgPrefs *prefs = trg_client_get_prefs(tc);
    gpointer threadLocalStorage = g_private_get(priv->tlsKey);
    trg_tls *tls;
    long httpCode = 0;
    gchar *session_id;
    struct curl_slist *headers = NULL;

    if (!threadLocalStorage) {
        tls = trg_tls_new(tc);
        g_private_set(priv->tlsKey, tls);
    } else {
        tls = (trg_tls *) threadLocalStorage;
    }

    g_mutex_lock(priv->configMutex);

    if (priv->configSerial > tls->serial)
        trg_tls_update(tc, tls, priv->configSerial);

    session_id = trg_client_get_session_id(tc);
    if (session_id) {
        headers = curl_slist_append(NULL, session_id);
        curl_easy_setopt(tls->curl, CURLOPT_HTTPHEADER, headers);
    }

    curl_easy_setopt(tls->curl, CURLOPT_TIMEOUT,
                     (long) trg_prefs_get_int(prefs, TRG_PREFS_KEY_TIMEOUT,
                                              TRG_PREFS_CONNECTION));

    g_mutex_unlock(priv->configMutex);

    response->size = 0;
    response->raw = NULL;

    curl_easy_setopt(tls->curl, CURLOPT_POSTFIELDS, reqstr);
    curl_easy_setopt(tls->curl, CURLOPT_WRITEDATA, (void *) response);
    response->status = curl_easy_perform(tls->curl);

    if (session_id) {
        g_free(session_id);
        curl_slist_free_all(headers);
    }

    curl_easy_getinfo(tls->curl, CURLINFO_RESPONSE_CODE, &httpCode);

    if (response->status == CURLE_OK) {
        if (httpCode == HTTP_CONFLICT && recurse == TRUE)
            return trg_http_perform_inner(tc, reqstr, response, FALSE);
        else if (httpCode != HTTP_OK)
            response->status = (-httpCode) - 100;
    }

    return response->status;
}
void trg_prefs_load(TrgPrefs * p)
{
    TrgPrefsPrivate *priv = p->priv;
    JsonParser *parser = json_parser_new();
    JsonNode *root;
    guint n_profiles;
    JsonArray *profiles;

    gboolean parsed = json_parser_load_from_file(parser, priv->file, NULL);

    if (!parsed) {
        trg_prefs_empty_init(p);
        g_object_unref(parser);
        return;
    }

    root = json_parser_get_root(parser);
    if (root) {
        priv->user = json_node_copy(root);
        priv->userObj = json_node_get_object(priv->user);
    }

    g_object_unref(parser);

    if (!root) {
        trg_prefs_empty_init(p);
        return;
    }

    if (!json_object_has_member(priv->userObj, TRG_PREFS_KEY_PROFILES)) {
        profiles = json_array_new();
        json_object_set_array_member(priv->userObj, TRG_PREFS_KEY_PROFILES,
                                     profiles);
    } else {
        profiles = json_object_get_array_member(priv->userObj,
                                                TRG_PREFS_KEY_PROFILES);
    }

    n_profiles = json_array_get_length(profiles);

    if (n_profiles < 1) {
        priv->profile = trg_prefs_new_profile_object();
        json_array_add_object_element(profiles, priv->profile);
        trg_prefs_set_int(p, TRG_PREFS_KEY_PROFILE_ID, 0,
                          TRG_PREFS_GLOBAL);
    } else {
        gint profile_id = trg_prefs_get_int(p, TRG_PREFS_KEY_PROFILE_ID,
                                            TRG_PREFS_GLOBAL);
        if (profile_id >= n_profiles)
            trg_prefs_set_int(p, TRG_PREFS_KEY_PROFILE_ID, profile_id = 0,
                              TRG_PREFS_GLOBAL);

        priv->profile =
            json_array_get_object_element(profiles, profile_id);
    }
}
static CURL* get_curl(TrgClient *tc, guint http_class)
{
	TrgClientPrivate *priv = tc->priv;
	TrgPrefs *prefs = trg_client_get_prefs(tc);
	trg_tls *tls = get_tls(tc);
	CURL *curl = tls->curl;

    g_mutex_lock(&priv->configMutex);

    if (priv->configSerial > tls->serial || http_class != priv->http_class) {
    	gchar *proxy;

        curl_easy_reset(curl);

        curl_easy_setopt(curl, CURLOPT_USERAGENT, PACKAGE_NAME);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
                         &http_receive_callback);
#ifdef DEBUG
        if (g_getenv("TRG_CURL_VERBOSE") != NULL)
        	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
#endif

        if (http_class == HTTP_CLASS_TRANSMISSION) {
        	curl_easy_setopt(curl, CURLOPT_WRITEHEADER, (void *) tc);
        	curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &header_callback);
            curl_easy_setopt(curl, CURLOPT_PASSWORD,
                             trg_client_get_password(tc));
            curl_easy_setopt(curl, CURLOPT_USERNAME,
                             trg_client_get_username(tc));
            curl_easy_setopt(curl, CURLOPT_URL, trg_client_get_url(tc));
        }

    #ifndef CURL_NO_SSL
        if (trg_client_get_ssl(tc) && !trg_client_get_ssl_validate(tc)) {

            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
            curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
        }
    #endif

        proxy = trg_client_get_proxy(tc);
        if (proxy) {
            curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
            curl_easy_setopt(curl, CURLOPT_PROXY, proxy);
        }

        tls->serial = priv->configSerial;
        priv->http_class = http_class;
    }

    if (http_class == HTTP_CLASS_TRANSMISSION)
    	curl_easy_setopt(curl, CURLOPT_URL, trg_client_get_url(tc));

	curl_easy_setopt(curl, CURLOPT_TIMEOUT,
					 (long) trg_prefs_get_int(prefs, TRG_PREFS_KEY_TIMEOUT,
											  TRG_PREFS_CONNECTION));

    g_mutex_unlock(&priv->configMutex);

    /* Headers are set on each use, then freed, so make sure invalid headers aren't still around. */
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL);

    return curl;

}
int trg_client_populate_with_settings(TrgClient * tc)
{
    TrgClientPrivate *priv = tc->priv;
    TrgPrefs *prefs = priv->prefs;

    gint port;
    gchar *host, *path;
#ifdef HAVE_LIBPROXY
    pxProxyFactory *pf = NULL;
#endif

    g_mutex_lock(&priv->configMutex);

    trg_prefs_set_connection(prefs, trg_prefs_get_profile(prefs));

    g_free(priv->url);
    priv->url = NULL;

    g_free(priv->username);
    priv->username = NULL;

    g_free(priv->password);
    priv->password = NULL;

    port =
        trg_prefs_get_int(prefs, TRG_PREFS_KEY_PORT, TRG_PREFS_CONNECTION);

    host = trg_prefs_get_string(prefs, TRG_PREFS_KEY_HOSTNAME,
                                TRG_PREFS_CONNECTION);
    path = trg_prefs_get_string(prefs, TRG_PREFS_KEY_RPC_URL_PATH, TRG_PREFS_CONNECTION);

    if (!host || strlen(host) < 1) {
        g_free(host);
        g_mutex_unlock(&priv->configMutex);
        return TRG_NO_HOSTNAME_SET;
    }
#ifndef CURL_NO_SSL
    priv->ssl = trg_prefs_get_bool(prefs, TRG_PREFS_KEY_SSL,
                                   TRG_PREFS_CONNECTION);
    priv->ssl_validate = trg_prefs_get_bool(prefs, TRG_PREFS_KEY_SSL_VALIDATE,
                                   TRG_PREFS_CONNECTION);

#else
    priv->ssl = FALSE;
#endif


    priv->url = g_strdup_printf("%s://%s:%d%s",
                                priv->ssl ? HTTPS_URI_PREFIX :
                                HTTP_URI_PREFIX, host, port, path);
    g_free(host);
    g_free(path);

    priv->username = trg_prefs_get_string(prefs, TRG_PREFS_KEY_USERNAME,
                                          TRG_PREFS_CONNECTION);

    priv->password = trg_prefs_get_string(prefs, TRG_PREFS_KEY_PASSWORD,
                                          TRG_PREFS_CONNECTION);

    g_free(priv->proxy);
    priv->proxy = NULL;

#ifdef HAVE_LIBPROXY
    if ((pf = px_proxy_factory_new())) {
        char **proxies = px_proxy_factory_get_proxies(pf, priv->url);
        int i;

        for (i = 0; proxies[i]; i++) {
            if (g_str_has_prefix(proxies[i], HTTP_URI_PREFIX)
                || g_str_has_prefix(proxies[i], HTTPS_URI_PREFIX)) {
                g_free(priv->proxy);
                priv->proxy = proxies[i];
            } else {
                g_free(proxies[i]);
            }
        }

        g_free(proxies);
        px_proxy_factory_free(pf);
    }
#endif

    priv->configSerial++;
    g_mutex_unlock(&priv->configMutex);
    return 0;
}