summaryrefslogtreecommitdiff
path: root/src/trg-client.c
diff options
context:
space:
mode:
authorGravatar Alan Fitton <ajf@eth0.org.uk>2011-09-18 16:21:04 +0000
committerGravatar Alan Fitton <ajf@eth0.org.uk>2011-09-18 16:21:04 +0000
commit79cd86dbfd5b2ea0963c84b48088ec189acfc795 (patch)
tree535769200823fdaa1fec9795fe986668cb33bdee /src/trg-client.c
parent63763bb00502e3c235e478ec50e097904c774696 (diff)
Big changeset, may break stuff. Unfortunately you can't magically jump into the UI thread using gdk_threads_enter/leave() on Windows, the only way is to schedule a callback using g_idle_add. This required a lot of reworking. Good news, Windows support actually works now \o/
Diffstat (limited to 'src/trg-client.c')
-rw-r--r--src/trg-client.c136
1 files changed, 104 insertions, 32 deletions
diff --git a/src/trg-client.c b/src/trg-client.c
index 3dbcea1..6ddca81 100644
--- a/src/trg-client.c
+++ b/src/trg-client.c
@@ -17,9 +17,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include <stdlib.h>
#include <string.h>
@@ -33,9 +31,10 @@
#include <curl/curl.h>
#include <curl/easy.h>
+#include "json.h"
#include "trg-prefs.h"
+#include "protocol-constants.h"
#include "util.h"
-#include "dispatch.h"
#include "trg-client.h"
G_DEFINE_TYPE (TrgClient, trg_client, G_TYPE_OBJECT)
@@ -75,6 +74,9 @@ struct _TrgClientPrivate {
GMutex *configMutex;
};
+static void dispatch_async_threadfunc(trg_request *reqrsp,
+ TrgClient * client);
+
static void
trg_client_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
@@ -82,6 +84,7 @@ trg_client_get_property (GObject *object, guint property_id,
switch (property_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
}
}
@@ -92,6 +95,7 @@ trg_client_set_property (GObject *object, guint property_id,
switch (property_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
}
}
@@ -138,9 +142,11 @@ trg_client_new (void)
priv->updateMutex = g_mutex_new();
priv->configMutex = g_mutex_new();
- priv->pool = dispatch_init_pool(tc);
priv->tlsKey = g_private_new(NULL);
+ priv->pool = g_thread_pool_new((GFunc) dispatch_async_threadfunc, tc,
+ DISPATCH_POOL_SIZE, TRUE, NULL);
+
return tc;
}
@@ -441,24 +447,25 @@ void trg_client_set_minimised_interval(TrgClient *tc, guint interval)
/* formerly http.c */
-void http_response_free(trg_http_response *response)
+void trg_response_free(trg_response *response)
{
- g_free(response->data);
- response->data = NULL;
+ json_object_unref(response->obj);
+ g_free(response);
}
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;
+ trg_response *mem = (trg_response *) data;
- mem->data = realloc(mem->data, mem->size + realsize + 1);
- if (mem->data) {
- memcpy(&(mem->data[mem->size]), ptr, realsize);
+ mem->raw = realloc(mem->raw, mem->size + realsize + 1);
+ if (mem->raw) {
+ memcpy(&(mem->raw[mem->size]), ptr, realsize);
mem->size += realsize;
- mem->data[mem->size] = 0;
+ mem->raw[mem->size] = 0;
}
+
return realsize;
}
@@ -509,14 +516,11 @@ 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);
@@ -525,8 +529,9 @@ trg_tls *trg_tls_new(TrgClient *tc)
return tls;
}
-static trg_http_response *trg_http_perform_inner(TrgClient * tc,
- gchar * req,
+static int trg_http_perform_inner(TrgClient * tc,
+ gchar * reqstr,
+ trg_response *response,
gboolean recurse)
{
TrgClientPrivate *priv = TRG_CLIENT_GET_PRIVATE(tc);
@@ -556,16 +561,12 @@ static trg_http_response *trg_http_perform_inner(TrgClient * tc,
g_mutex_unlock(priv->configMutex);
- tls->response->size = 0;
- tls->response->status = -1;
-
- if (tls->response->data) {
- g_free(tls->response->data);
- tls->response->data = NULL;
- }
+ response->size = 0;
+ response->raw = NULL;
- curl_easy_setopt(tls->curl, CURLOPT_POSTFIELDS, req);
- tls->response->status = curl_easy_perform(tls->curl);
+ 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);
@@ -574,17 +575,88 @@ static trg_http_response *trg_http_perform_inner(TrgClient * tc,
curl_easy_getinfo(tls->curl, CURLINFO_RESPONSE_CODE, &httpCode);
- if (tls->response->status == CURLE_OK) {
+ if (response->status == CURLE_OK) {
if (httpCode == HTTP_CONFLICT && recurse == TRUE)
- return trg_http_perform_inner(tc, req, FALSE);
+ return trg_http_perform_inner(tc, reqstr, response, FALSE);
else if (httpCode != HTTP_OK)
- tls->response->status = (-httpCode) - 100;
+ response->status = (-httpCode) - 100;
}
- return tls->response;
+ return response->status;
}
-trg_http_response *trg_http_perform(TrgClient * tc, gchar * req)
+int trg_http_perform(TrgClient * tc, gchar * reqstr, trg_response *reqrsp)
{
- return trg_http_perform_inner(tc, req, TRUE);
+ return trg_http_perform_inner(tc, reqstr, reqrsp, TRUE);
+}
+
+/* formerly dispatch.c */
+
+trg_response *dispatch(TrgClient * client, JsonNode * req)
+{
+ trg_response *response = g_new0(trg_response, 1);
+ GError *decode_error = NULL;
+ gchar *serialized;
+ JsonNode *result;
+
+ serialized = trg_serialize(req);
+ json_node_free(req);
+#ifdef DEBUG
+ if (g_getenv("TRG_SHOW_OUTGOING"))
+ g_debug("=>(OUTgoing)=>: %s", serialized);
+#endif
+ trg_http_perform(client, serialized, response);
+ g_free(serialized);
+
+ if (response->status != CURLE_OK)
+ return response;
+
+ response->obj = trg_deserialize(response, &decode_error);
+ g_free(response->raw);
+ response->raw = NULL;
+
+ if (decode_error) {
+ g_error("JSON decoding error: %s", decode_error->message);
+ g_error_free(decode_error);
+ response->status = FAIL_JSON_DECODE;
+ return response;
+ }
+
+ result = json_object_get_member(response->obj, FIELD_RESULT);
+ if (!result || g_strcmp0(json_node_get_string(result), FIELD_SUCCESS))
+ response->status = FAIL_RESPONSE_UNSUCCESSFUL;
+
+ return response;
+}
+
+static void dispatch_async_threadfunc(trg_request *req,
+ TrgClient * client)
+{
+ trg_response *rsp = dispatch(client, req->node);
+ rsp->cb_data = req->cb_data;
+ if (req->callback)
+ g_idle_add(req->callback, rsp);
+ g_free(req);
+}
+
+gboolean dispatch_async(TrgClient * client, JsonNode * req,
+ GSourceFunc callback,
+ gpointer data)
+{
+ GError *error = NULL;
+ trg_request *trg_req = g_new(trg_request, 1);
+
+ trg_req->callback = callback;
+ trg_req->cb_data = data;
+ trg_req->node = req;
+
+ trg_client_thread_pool_push(client, trg_req, &error);
+ if (error) {
+ g_error("thread creation error: %s\n", error->message);
+ g_error_free(error);
+ g_free(req);
+ return FALSE;
+ } else {
+ return TRUE;
+ }
}