From be569c0953fcd777ae00ae41feb9c673e4df2f23 Mon Sep 17 00:00:00 2001 From: Alan Fitton Date: Sun, 11 Sep 2011 10:27:06 +0000 Subject: use thread local storage to keep one curl client per thread (by default 3) in the thread pool --- src/Makefile.am | 3 +- src/dispatch.c | 14 ++-- src/dispatch.h | 2 +- src/http.c | 158 --------------------------------------- src/http.h | 43 ----------- src/json.c | 5 +- src/json.h | 4 +- src/main.c | 1 - src/protocol-constants.h | 5 ++ src/torrent.c | 6 +- src/trg-client.c | 172 ++++++++++++++++++++++++++++++++++++++++++- src/trg-client.h | 33 +++++++++ src/trg-general-panel.c | 4 +- src/trg-main-window.c | 40 ++++++---- src/trg-trackers-tree-view.c | 1 + 15 files changed, 253 insertions(+), 238 deletions(-) delete mode 100644 src/http.c delete mode 100644 src/http.h diff --git a/src/Makefile.am b/src/Makefile.am index 3339143..49da641 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,14 +26,13 @@ transmission_remote_gtk_SOURCES = main.c \ requests.c \ base64.c \ json.c \ - http.c \ - dispatch.c \ trg-main-window.c \ util.c \ trg-about-window.c \ torrent.c \ tpeer.c \ tfile.c \ + dispatch.c \ session-get.c \ trg-client.c \ trg-preferences-dialog.c \ diff --git a/src/dispatch.c b/src/dispatch.c index e6181a1..e92cb34 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -24,8 +24,8 @@ #include "config.h" #include "dispatch.h" -#include "http.h" #include "json.h" +#include "protocol-constants.h" static void dispatch_async_threadfunc(struct DispatchAsyncData *task, TrgClient * client); @@ -33,7 +33,7 @@ static void dispatch_async_threadfunc(struct DispatchAsyncData *task, JsonObject *dispatch(TrgClient * client, JsonNode * req, int *status) { gchar *serialized; - struct http_response *response; + trg_http_response *response; JsonObject *deserialized; JsonNode *result; GError *decode_error = NULL; @@ -42,7 +42,7 @@ JsonObject *dispatch(TrgClient * client, JsonNode * req, int *status) json_node_free(req); #ifdef DEBUG if (g_getenv("TRG_SHOW_OUTGOING")) - g_debug("=>(outgoing)=>\n%s\n", serialized); + g_debug("=>(outgoing)=>\n%s", serialized); #endif response = trg_http_perform(client, serialized); g_free(serialized); @@ -59,16 +59,16 @@ JsonObject *dispatch(TrgClient * client, JsonNode * req, int *status) http_response_free(response); if (decode_error) { - g_printf("JSON decoding error: %s\n", decode_error->message); + g_error("JSON decoding error: %s", decode_error->message); g_error_free(decode_error); if (status) *status = FAIL_JSON_DECODE; return NULL; } - result = json_object_get_member(deserialized, "result"); + result = json_object_get_member(deserialized, FIELD_RESULT); if (status - && (!result || g_strcmp0(json_node_get_string(result), "success"))) + && (!result || g_strcmp0(json_node_get_string(result), FIELD_SUCCESS))) *status = FAIL_RESPONSE_UNSUCCESSFUL; return deserialized; @@ -87,7 +87,7 @@ static void dispatch_async_threadfunc(struct DispatchAsyncData *task, GThreadPool *dispatch_init_pool(TrgClient * client) { return g_thread_pool_new((GFunc) dispatch_async_threadfunc, client, - DISPATCH_POOL_SIZE, FALSE, NULL); + DISPATCH_POOL_SIZE, TRUE, NULL); } gboolean dispatch_async(TrgClient * client, JsonNode * req, diff --git a/src/dispatch.h b/src/dispatch.h index 6734f33..0e7225f 100644 --- a/src/dispatch.h +++ b/src/dispatch.h @@ -25,7 +25,7 @@ #define FAIL_JSON_DECODE -2 #define FAIL_RESPONSE_UNSUCCESSFUL -3 -#define DISPATCH_POOL_SIZE 4 +#define DISPATCH_POOL_SIZE 3 struct DispatchAsyncData { gpointer *data; diff --git a/src/http.c b/src/http.c deleted file mode 100644 index ddbe413..0000000 --- a/src/http.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * transmission-remote-gtk - A GTK RPC client to Transmission - * Copyright (C) 2011 Alan Fitton - - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include - -#include -#include - -#include -#include - -#include "trg-client.h" -#include "http.h" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -static struct http_response *trg_http_perform_inner(TrgClient * client, - gchar * req, - gboolean recurse); - -static size_t http_receive_callback(void *ptr, size_t size, size_t nmemb, - void *data); - -static size_t header_callback(void *ptr, size_t size, size_t nmemb, - void *data); - -void http_response_free(struct http_response *response) -{ - if (response->data != NULL) - g_free(response->data); - - g_free(response); -} - -static struct http_response *trg_http_perform_inner(TrgClient * tc, - gchar * req, - gboolean recurse) -{ - CURL *handle; - long httpCode; - struct http_response *response; - struct curl_slist *headers = NULL; - gchar *proxy, *session_id; - - response = g_new(struct http_response, 1); - response->size = 0; - response->status = -1; - response->data = NULL; - - handle = curl_easy_init(); - - curl_easy_setopt(handle, CURLOPT_USERAGENT, PACKAGE_NAME); - curl_easy_setopt(handle, CURLOPT_PASSWORD, trg_client_get_password(tc)); - curl_easy_setopt(handle, CURLOPT_USERNAME, trg_client_get_username(tc)); - curl_easy_setopt(handle, CURLOPT_URL, trg_client_get_url(tc)); - curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, - &http_receive_callback); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *) response); - curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, &header_callback); - curl_easy_setopt(handle, CURLOPT_WRITEHEADER, (void *) tc); - curl_easy_setopt(handle, CURLOPT_POSTFIELDS, req); - - - if (trg_client_get_ssl(tc)) - curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0); - - proxy = trg_client_get_proxy(tc); - if (proxy) { - curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - curl_easy_setopt(handle, CURLOPT_PROXY, proxy); - } - - session_id = trg_client_get_session_id(tc); - if (session_id) { - headers = curl_slist_append(headers, session_id); - curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); - } - - response->status = curl_easy_perform(handle); - - curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &httpCode); - curl_easy_cleanup(handle); - - if (headers) - curl_slist_free_all(headers); - - if (response->status == CURLE_OK) { - if (httpCode == HTTP_CONFLICT && recurse == TRUE) { - http_response_free(response); - return trg_http_perform_inner(tc, req, FALSE); - } else if (httpCode != HTTP_OK) { - response->status = (-httpCode) - 100; - } - } - - return response; -} - -struct http_response *trg_http_perform(TrgClient * tc, gchar * req) -{ - return trg_http_perform_inner(tc, req, TRUE); -} - -static size_t -http_receive_callback(void *ptr, size_t size, size_t nmemb, void *data) -{ - size_t realsize = size * nmemb; - struct http_response *mem = (struct http_response *) data; - - mem->data = realloc(mem->data, mem->size + realsize + 1); - if (mem->data) { - memcpy(&(mem->data[mem->size]), ptr, realsize); - mem->size += realsize; - mem->data[mem->size] = 0; - } - return realsize; -} - -static size_t header_callback(void *ptr, size_t size, size_t nmemb, - void *data) -{ - char *header = (char *) (ptr); - TrgClient *tc = TRG_CLIENT(data); - gchar *session_id; - - if (g_str_has_prefix(header, "X-Transmission-Session-Id: ")) { - char *nl; - - session_id = g_strdup(header); - nl = strrchr(session_id, '\r'); - if (nl) - *nl = '\0'; - - trg_client_set_session_id(tc, session_id); - } - - return (nmemb * size); -} diff --git a/src/http.h b/src/http.h deleted file mode 100644 index 6fe9783..0000000 --- a/src/http.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * transmission-remote-gtk - A GTK RPC client to Transmission - * Copyright (C) 2011 Alan Fitton - - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef HTTP_H_ -#define HTTP_H_ - -#include - -#include -#include -#include - -#include "trg-client.h" - -#define HTTP_OK 200 -#define HTTP_CONFLICT 409 - -struct http_response { - int status; - char *data; - int size; -}; - -void http_response_free(struct http_response *response); -struct http_response *trg_http_perform(TrgClient * client, gchar * req); - -#endif /* HTTP_H_ */ diff --git a/src/json.c b/src/json.c index 47ca27b..6d74b24 100644 --- a/src/json.c +++ b/src/json.c @@ -26,7 +26,6 @@ #include "protocol-constants.h" #include "requests.h" #include "dispatch.h" -#include "http.h" #include "json.h" gchar *trg_serialize(JsonNode * req) @@ -44,7 +43,7 @@ gchar *trg_serialize(JsonNode * req) return response; } -JsonObject *trg_deserialize(struct http_response * response, +JsonObject *trg_deserialize(trg_http_response * response, GError ** error) { JsonParser *parser; @@ -58,7 +57,7 @@ JsonObject *trg_deserialize(struct http_response * response, root = json_parser_get_root(parser); #ifdef DEBUG if (g_getenv("TRG_SHOW_INCOMING") != NULL) { - g_debug("<=(incoming)<=:\n%s\n", response->data); + g_debug("<=(incoming)<=:\n%s", response->data); } else if (g_getenv("TRG_SHOW_INCOMING_PRETTY") != NULL) { JsonGenerator *pg; gsize len; diff --git a/src/json.h b/src/json.h index 1234784..a71e130 100644 --- a/src/json.h +++ b/src/json.h @@ -23,10 +23,10 @@ #include #include -#include "http.h" +#include "trg-client.h" gchar *trg_serialize(JsonNode * req); -JsonObject *trg_deserialize(struct http_response *response, +JsonObject *trg_deserialize(trg_http_response *response, GError ** error); JsonObject *get_arguments(JsonObject * req); JsonObject *node_get_arguments(JsonNode * req); diff --git a/src/main.c b/src/main.c index fb54202..3530b8c 100644 --- a/src/main.c +++ b/src/main.c @@ -34,7 +34,6 @@ #include #endif -#include "http.h" #include "trg-main-window.h" #include "trg-client.h" diff --git a/src/protocol-constants.h b/src/protocol-constants.h index 01fd99e..ccc91c4 100644 --- a/src/protocol-constants.h +++ b/src/protocol-constants.h @@ -25,6 +25,11 @@ #define PARAM_METHOD "method" #define FIELD_ID "id" +/* top level */ + +#define FIELD_RESULT "result" +#define FIELD_SUCCESS "success" + /* torrents */ #define FIELD_RECENTLY_ACTIVE "recently-active" diff --git a/src/torrent.c b/src/torrent.c index 85b351b..73fa66a 100644 --- a/src/torrent.c +++ b/src/torrent.c @@ -315,9 +315,11 @@ gchar *torrent_get_status_string(gint64 rpcv, gint64 value) gboolean torrent_has_tracker(JsonObject * t, GRegex * rx, gchar * search) { - GList *trackers = json_array_get_elements(torrent_get_tracker_stats(t)); - gboolean ret = FALSE; + GList *trackers; GList *li; + gboolean ret = FALSE; + + trackers = json_array_get_elements(torrent_get_tracker_stats(t)); for (li = trackers; li; li = g_list_next(li)) { JsonObject *tracker = json_node_get_object((JsonNode *) li->data); diff --git a/src/trg-client.c b/src/trg-client.c index 44943ea..6810278 100644 --- a/src/trg-client.c +++ b/src/trg-client.c @@ -21,6 +21,7 @@ #include "config.h" #endif +#include #include #include #include @@ -29,6 +30,9 @@ #include #endif +#include +#include + #include "trg-prefs.h" #include "util.h" #include "dispatch.h" @@ -66,6 +70,9 @@ struct _TrgClientPrivate { GThreadPool *pool; GMutex *updateMutex; TrgPrefs *prefs; + GPrivate *tlsKey; + gint configSerial; + GMutex *configMutex; }; static void @@ -130,10 +137,10 @@ trg_client_new (void) trg_prefs_load(prefs); priv->updateMutex = g_mutex_new(); - priv->activeOnlyUpdate = - trg_prefs_get_bool(prefs, - TRG_PREFS_KEY_UPDATE_ACTIVE_ONLY, TRG_PREFS_PROFILE); + priv->configMutex = g_mutex_new(); + priv->configSerial = 0; priv->pool = dispatch_init_pool(tc); + priv->tlsKey = g_private_new(NULL); return tc; } @@ -181,6 +188,8 @@ int trg_client_populate_with_settings(TrgClient * tc) pxProxyFactory *pf = NULL; #endif + g_mutex_lock(priv->configMutex); + g_free(priv->url); priv->url = NULL; @@ -227,6 +236,10 @@ int trg_client_populate_with_settings(TrgClient * tc) g_free(priv->proxy); priv->proxy = NULL; + priv->activeOnlyUpdate = + trg_prefs_get_bool(prefs, + TRG_PREFS_KEY_UPDATE_ACTIVE_ONLY, TRG_PREFS_PROFILE); + #ifdef HAVE_LIBPROXY if ((pf = px_proxy_factory_new())) { char **proxies = px_proxy_factory_get_proxies(pf, priv->url); @@ -246,6 +259,8 @@ int trg_client_populate_with_settings(TrgClient * tc) } #endif + priv->configSerial++; + g_mutex_unlock(priv->configMutex); return 0; } @@ -270,17 +285,21 @@ gchar *trg_client_get_url(TrgClient *tc) gchar *trg_client_get_session_id(TrgClient *tc) { TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); - return priv->session_id; + return priv->session_id ? g_strdup(priv->session_id) : NULL; } void trg_client_set_session_id(TrgClient *tc, gchar *session_id) { TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); + g_mutex_lock(priv->configMutex); + if (priv->session_id) g_free(priv->session_id); priv->session_id = session_id; + + g_mutex_unlock(priv->configMutex); } void trg_client_status_change(TrgClient *tc, gboolean connected) @@ -411,3 +430,148 @@ void trg_client_set_minimised_interval(TrgClient *tc, guint interval) TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc); priv->min_interval = interval; } + +/* formerly http.c */ + +void http_response_free(trg_http_response *response) +{ + g_free(response->data); + response->data = NULL; +} + +static size_t +http_receive_callback(void *ptr, size_t size, size_t nmemb, void *data) +{ + size_t realsize = size * nmemb; + trg_http_response *mem = (trg_http_response *) data; + + mem->data = realloc(mem->data, mem->size + realsize + 1); + if (mem->data) { + memcpy(&(mem->data[mem->size]), ptr, realsize); + mem->size += realsize; + mem->data[mem->size] = 0; + } + return realsize; +} + +static size_t header_callback(void *ptr, size_t size, size_t nmemb, + void *data) +{ + char *header = (char *) (ptr); + TrgClient *tc = TRG_CLIENT(data); + gchar *session_id; + + if (g_str_has_prefix(header, X_TRANSMISSION_SESSION_ID_HEADER_PREFIX)) { + char *nl; + + session_id = g_strdup(header); + nl = strrchr(session_id, '\r'); + if (nl) + *nl = '\0'; + + trg_client_set_session_id(tc, session_id); + } + + return (nmemb * size); +} + +static void trg_tls_update(TrgClient *tc, trg_tls *tls, gint serial) +{ + gchar *proxy; + + curl_easy_setopt(tls->curl, CURLOPT_PASSWORD, trg_client_get_password(tc)); + curl_easy_setopt(tls->curl, CURLOPT_USERNAME, trg_client_get_username(tc)); + curl_easy_setopt(tls->curl, CURLOPT_URL, trg_client_get_url(tc)); + + if (trg_client_get_ssl(tc)) + curl_easy_setopt(tls->curl, CURLOPT_SSL_VERIFYPEER, 0); + + proxy = trg_client_get_proxy(tc); + if (proxy) { + curl_easy_setopt(tls->curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + curl_easy_setopt(tls->curl, CURLOPT_PROXY, proxy); + } + + tls->serial = serial; +} + +trg_tls *trg_tls_new(TrgClient *tc) +{ + trg_tls *tls = g_new0(trg_tls, 1); + + tls->response = g_new0(trg_http_response, 1); + + tls->curl = curl_easy_init(); + curl_easy_setopt(tls->curl, CURLOPT_USERAGENT, PACKAGE_NAME); + curl_easy_setopt(tls->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(tls->curl, CURLOPT_WRITEFUNCTION, + &http_receive_callback); + curl_easy_setopt(tls->curl, CURLOPT_WRITEDATA, (void *)tls->response); + curl_easy_setopt(tls->curl, CURLOPT_HEADERFUNCTION, &header_callback); + curl_easy_setopt(tls->curl, CURLOPT_WRITEHEADER, (void *) tc); + + tls->serial = -1; + + return tls; +} + +static trg_http_response *trg_http_perform_inner(TrgClient * tc, + gchar * req, + gboolean recurse) +{ + TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(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); + } + + g_mutex_unlock(priv->configMutex); + + tls->response->size = 0; + tls->response->status = -1; + g_free(tls->response->data); + tls->response->data = NULL; + + curl_easy_setopt(tls->curl, CURLOPT_POSTFIELDS, req); + tls->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 (tls->response->status == CURLE_OK) { + if (httpCode == HTTP_CONFLICT && recurse == TRUE) + return trg_http_perform_inner(tc, req, FALSE); + else if (httpCode != HTTP_OK) + tls->response->status = (-httpCode) - 100; + } + + return tls->response; +} + +trg_http_response *trg_http_perform(TrgClient * tc, gchar * req) +{ + return trg_http_perform_inner(tc, req, TRUE); +} diff --git a/src/trg-client.h b/src/trg-client.h index 67d026b..78a674d 100644 --- a/src/trg-client.h +++ b/src/trg-client.h @@ -16,12 +16,14 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + /* trg-client.h */ #ifndef _TRG_CLIENT_H_ #define _TRG_CLIENT_H_ #define TRANSMISSION_MIN_SUPPORTED 2.0 +#define X_TRANSMISSION_SESSION_ID_HEADER_PREFIX "X-Transmission-Session-Id: " #define TRG_MAX_RETRIES 3 #define TORRENT_GET_MODE_FIRST 0 @@ -32,12 +34,24 @@ #define TRG_NO_HOSTNAME_SET -2 #define SESSION_UPDATE_DIVISOR 10 +#include +#include + #include #include #include "trg-prefs.h" #include "session-get.h" +#define HTTP_OK 200 +#define HTTP_CONFLICT 409 + +typedef struct { + int status; + char *data; + int size; +} trg_http_response; + G_BEGIN_DECLS #define TRG_TYPE_CLIENT trg_client_get_type() @@ -67,6 +81,25 @@ typedef struct { } TrgClientClass; +/* Thread local storage (TLS). + * CURL clients can't be used concurrently. + * So create one instance for each thread in the thread pool. + */ +typedef struct { + /* Use a serial to figure out when there's been a configuration change + * by comparing with priv->serial. + * We lock updating (and checking for updates) with priv->configMutex + */ + int serial; + CURL *curl; + trg_http_response *response; +} trg_tls; + +/* stuff that used to be in http.h */ +void http_response_free(trg_http_response *response); +trg_http_response *trg_http_perform(TrgClient * client, gchar * req); +/* end http.h*/ + GType trg_client_get_type (void); TrgClient* trg_client_new (void); diff --git a/src/trg-general-panel.c b/src/trg-general-panel.c index 0cdff84..0c7742e 100644 --- a/src/trg-general-panel.c +++ b/src/trg-general-panel.c @@ -190,9 +190,9 @@ void trg_general_panel_update(TrgGeneralPanel * panel, JsonObject * t, TORRENT_COLUMN_SEEDS, &seeders, TORRENT_COLUMN_LEECHERS, &leechers, -1); - snprintf(buf, sizeof(buf), "%d", seeders); + snprintf(buf, sizeof(buf), "%d", seeders >= 0 ? seeders : 0); gtk_label_set_text(GTK_LABEL(priv->gen_seeders_label), buf); - snprintf(buf, sizeof(buf), "%d", leechers); + snprintf(buf, sizeof(buf), "%d", leechers >= 0 ? leechers : 0); gtk_label_set_text(GTK_LABEL(priv->gen_leechers_label), buf); } diff --git a/src/trg-main-window.c b/src/trg-main-window.c index 48e7c4b..972ba2d 100644 --- a/src/trg-main-window.c +++ b/src/trg-main-window.c @@ -36,7 +36,6 @@ #include "dispatch.h" #include "trg-client.h" -#include "http.h" #include "json.h" #include "util.h" #include "requests.h" @@ -737,6 +736,7 @@ static void on_session_get(JsonObject * response, int status, gpointer data) { TrgMainWindowPrivate *priv = TRG_MAIN_WINDOW_GET_PRIVATE(data); TrgClient *client = priv->client; JsonObject *newSession; + gboolean isConnected = trg_client_is_connected(client); gdk_threads_enter(); @@ -748,7 +748,7 @@ static void on_session_get(JsonObject * response, int status, gpointer data) { newSession = get_arguments(response); - if (!trg_client_is_connected(client)) { + if (!isConnected) { float version; if (session_get_version(newSession, &version)) { if (version < TRANSMISSION_MIN_SUPPORTED) { @@ -765,21 +765,31 @@ static void on_session_get(JsonObject * response, int status, gpointer data) { gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); g_free(msg); - goto out; + gdk_threads_leave(); + response_unref(response); + return; } } trg_status_bar_connect(priv->statusBar, newSession); trg_main_window_conn_changed(win, TRUE); - dispatch_async(client, torrent_get(-1), on_torrent_get_first, data); } trg_client_set_session(client, newSession); - trg_trackers_tree_view_new_connection(priv->trackersTreeView, client); + + if (!isConnected) + trg_trackers_tree_view_new_connection(priv->trackersTreeView, client); + + gdk_threads_leave(); json_object_ref(newSession); - out: gdk_threads_leave(); response_unref(response); + + if (!isConnected) { + int firstStatus; + JsonObject *firstResponse = dispatch(client, torrent_get(-1), &firstStatus); + on_torrent_get_first(firstResponse, firstStatus, data); + } } /* @@ -792,10 +802,7 @@ static void on_torrent_get(JsonObject * response, int mode, int status, TrgClient *client = priv->client; trg_torrent_model_update_stats stats; - - guint interval = - gtk_widget_get_visible(GTK_WIDGET(data)) ? trg_client_get_interval( - client) : trg_client_get_minimised_interval(client); + guint interval; /* Disconnected between request and response callback */ if (!trg_client_is_connected(client)) { @@ -806,6 +813,9 @@ static void on_torrent_get(JsonObject * response, int mode, int status, trg_client_updatelock(client); gdk_threads_enter(); + interval = gtk_widget_get_visible(GTK_WIDGET(data)) ? trg_client_get_interval( + client) : trg_client_get_minimised_interval(client); + if (status != CURLE_OK) { if (trg_client_inc_failcount(client) >= TRG_MAX_RETRIES) { trg_main_window_conn_changed(TRG_MAIN_WINDOW(data), FALSE); @@ -923,9 +933,13 @@ static gboolean trg_torrent_tree_view_visible_func(GtkTreeModel * model, } else if (criteria & FILTER_FLAG_DIR) { gchar *text = trg_state_selector_get_selected_text( priv->stateSelector); - JsonObject *json = NULL; - gtk_tree_model_get(model, iter, TORRENT_COLUMN_JSON, &json, -1); - if (g_strcmp0(text, torrent_get_download_dir(json))) + gchar *dd; + int cmp; + gtk_tree_model_get(model, iter, TORRENT_COLUMN_DOWNLOADDIR, &dd, -1); + cmp = g_strcmp0(text, dd); + g_free(dd); + g_free(text); + if (cmp) return FALSE; } else if (!(flags & criteria)) { return FALSE; diff --git a/src/trg-trackers-tree-view.c b/src/trg-trackers-tree-view.c index 4919bcf..7f385ba 100644 --- a/src/trg-trackers-tree-view.c +++ b/src/trg-trackers-tree-view.c @@ -73,6 +73,7 @@ void trg_trackers_tree_view_new_connection(TrgTrackersTreeView * tv, { TrgTrackersTreeViewPrivate *priv = TRG_TRACKERS_TREE_VIEW_GET_PRIVATE(tv); + gboolean editable = is_tracker_edit_supported(tc); g_object_set(priv->announceRenderer, "editable", editable, NULL); -- cgit v1.2.3