Use native libpurple HTTP functions
This commit is contained in:
@@ -16,7 +16,7 @@ Debian 9:
|
|||||||
- cd vendor && tar -xvzf deltachat-core-0.41.0.tar.gz && cd deltachat-core-0.41.0 && mkdir builddir && cd builddir && meson && ninja && ninja install && cd ../../..
|
- cd vendor && tar -xvzf deltachat-core-0.41.0.tar.gz && cd deltachat-core-0.41.0 && mkdir builddir && cd builddir && meson && ninja && ninja install && cd ../../..
|
||||||
- cp /usr/local/lib/x86_64-linux-gnu/libdeltachat.so libdeltachat.so
|
- cp /usr/local/lib/x86_64-linux-gnu/libdeltachat.so libdeltachat.so
|
||||||
# purple-plugin-delta
|
# purple-plugin-delta
|
||||||
- apt install --no-install-recommends -t stretch-backports -yy libpurple-dev libcurl4-openssl-dev libglib2.0-dev
|
- apt install --no-install-recommends -t stretch-backports -yy libpurple-dev libglib2.0-dev
|
||||||
- make
|
- make
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
|
4
Makefile
4
Makefile
@@ -11,11 +11,11 @@ $(LIB_TARGET): *.c *.h Makefile
|
|||||||
-std=c11 \
|
-std=c11 \
|
||||||
-shared \
|
-shared \
|
||||||
-fpic \
|
-fpic \
|
||||||
$(shell $(PKG_CONFIG) --cflags purple libcurl deltachat) \
|
$(shell $(PKG_CONFIG) --cflags purple deltachat) \
|
||||||
-o $(LIB_TARGET) \
|
-o $(LIB_TARGET) \
|
||||||
*.c \
|
*.c \
|
||||||
-shared \
|
-shared \
|
||||||
$(shell $(PKG_CONFIG) --libs purple libcurl deltachat) \
|
$(shell $(PKG_CONFIG) --libs purple deltachat) \
|
||||||
|
|
||||||
install:
|
install:
|
||||||
install -D $(LIB_TARGET) $(LIB_DEST)
|
install -D $(LIB_TARGET) $(LIB_DEST)
|
||||||
|
@@ -19,7 +19,7 @@ you'll need to build and install it according to
|
|||||||
Now, you'll need some other build dependencies:
|
Now, you'll need some other build dependencies:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt install build-essential libpurple-dev libcurl4-openssl-dev libglib2.0-dev
|
sudo apt install build-essential libpurple-dev libglib2.0-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, run `make` to create a `libdelta.so` file.
|
Finally, run `make` to create a `libdelta.so` file.
|
||||||
|
@@ -5,9 +5,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <curl/easy.h>
|
|
||||||
|
|
||||||
#include "delta-connection.h"
|
#include "delta-connection.h"
|
||||||
#include "libdelta.h"
|
#include "libdelta.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -76,78 +73,6 @@ _transpose_config(dc_context_t *mailbox, PurpleAccount *acct)
|
|||||||
dc_set_config(mailbox, PLUGIN_ACCOUNT_OPT_SMTP_SERVER_PORT, smtp_port);
|
dc_set_config(mailbox, PLUGIN_ACCOUNT_OPT_SMTP_SERVER_PORT, smtp_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This and WriteMemoryCallback are "borrowed" from https://curl.haxx.se/libcurl/c/getinmemory.html
|
|
||||||
struct MemoryStruct {
|
|
||||||
char *memory;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
static size_t
|
|
||||||
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
|
||||||
{
|
|
||||||
size_t realsize = size * nmemb;
|
|
||||||
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
|
|
||||||
|
|
||||||
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
|
|
||||||
if(mem->memory == NULL) {
|
|
||||||
printf("not enough memory (realloc returned NULL)\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&(mem->memory[mem->size]), contents, realsize);
|
|
||||||
mem->size += realsize;
|
|
||||||
mem->memory[mem->size] = 0;
|
|
||||||
|
|
||||||
return realsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t
|
|
||||||
_http_get(const char *url)
|
|
||||||
{
|
|
||||||
long status = 0;
|
|
||||||
uintptr_t out = 0;
|
|
||||||
CURL *curl = curl_easy_init();
|
|
||||||
CURLcode res;
|
|
||||||
|
|
||||||
if (curl == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MemoryStruct chunk;
|
|
||||||
chunk.memory = malloc(1); /* will be grown as needed by the realloc above */
|
|
||||||
chunk.size = 0; /* no data at this point */
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
|
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
|
||||||
if (res != CURLE_OK) {
|
|
||||||
printf("Failed to GET %s: %s\n", url, curl_easy_strerror(res));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status);
|
|
||||||
if (res != CURLE_OK) {
|
|
||||||
printf("Failed to read response code for %s: %s\n", url, curl_easy_strerror(res));
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status < 200 || status > 299) {
|
|
||||||
printf("Non-success HTTP response code for %s: %lu\n", url, status);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
out = (uintptr_t)chunk.memory;
|
|
||||||
|
|
||||||
err:
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
|
|
||||||
// Don't free chunk.memory - that will be done by deltachat-core
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DeltaConnectionData *conn;
|
DeltaConnectionData *conn;
|
||||||
|
|
||||||
@@ -156,6 +81,11 @@ typedef struct {
|
|||||||
|
|
||||||
// Used by delta_process_connection_state
|
// Used by delta_process_connection_state
|
||||||
int connection_state;
|
int connection_state;
|
||||||
|
|
||||||
|
// Used by delta_process_http_get
|
||||||
|
char *http_url;
|
||||||
|
char *http_response;
|
||||||
|
pthread_cond_t *http_wait;
|
||||||
} ProcessRequest;
|
} ProcessRequest;
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@@ -218,8 +148,71 @@ delta_process_fresh_messages(void *data)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not call any libpurple functions in here, as it is not thread-safe and
|
void
|
||||||
// events may be dispatched from any delta thread. Use
|
delta_process_http_get_cb(
|
||||||
|
PurpleUtilFetchUrlData *url_data,
|
||||||
|
gpointer user_data,
|
||||||
|
const gchar *url_text,
|
||||||
|
gsize len,
|
||||||
|
const gchar *error_message
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UNUSED(url_data);
|
||||||
|
|
||||||
|
ProcessRequest *pr = (ProcessRequest *)user_data;
|
||||||
|
g_assert(pr != NULL);
|
||||||
|
g_assert(pr->http_wait != NULL);
|
||||||
|
|
||||||
|
if (len == 0) {
|
||||||
|
printf("Failed to GET %s: %s\n", pr->http_url, error_message);
|
||||||
|
pr->http_response = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr->http_response = g_malloc(len);
|
||||||
|
g_assert(pr->http_response != NULL);
|
||||||
|
|
||||||
|
strncpy(pr->http_response, url_text, len);
|
||||||
|
|
||||||
|
out:
|
||||||
|
pthread_cond_broadcast(pr->http_wait);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
delta_process_http_get(void *data)
|
||||||
|
{
|
||||||
|
ProcessRequest *pr = (ProcessRequest *)data;
|
||||||
|
g_assert(pr != NULL);
|
||||||
|
g_assert(pr->http_url != NULL);
|
||||||
|
|
||||||
|
purple_util_fetch_url(
|
||||||
|
pr->http_url,
|
||||||
|
TRUE,
|
||||||
|
NULL,
|
||||||
|
TRUE,
|
||||||
|
delta_process_http_get_cb,
|
||||||
|
data
|
||||||
|
);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessRequest *
|
||||||
|
delta_build_process_request(DeltaConnectionData *conn)
|
||||||
|
{
|
||||||
|
g_assert(conn != NULL);
|
||||||
|
|
||||||
|
ProcessRequest *pr = g_malloc(sizeof(ProcessRequest));
|
||||||
|
g_assert(pr != NULL);
|
||||||
|
|
||||||
|
pr->conn = conn;
|
||||||
|
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not call any libpurple or delta functions in here, as it is not
|
||||||
|
// thread-safe and events may be dispatched from any delta thread. Use
|
||||||
// purple_timeout_add(0, callback, data) to run on the main thread instead
|
// purple_timeout_add(0, callback, data) to run on the main thread instead
|
||||||
uintptr_t
|
uintptr_t
|
||||||
my_delta_handler(dc_context_t* mailbox, int event, uintptr_t data1, uintptr_t data2)
|
my_delta_handler(dc_context_t* mailbox, int event, uintptr_t data1, uintptr_t data2)
|
||||||
@@ -227,8 +220,10 @@ my_delta_handler(dc_context_t* mailbox, int event, uintptr_t data1, uintptr_t da
|
|||||||
DeltaConnectionData *conn = (DeltaConnectionData *)dc_get_userdata(mailbox);
|
DeltaConnectionData *conn = (DeltaConnectionData *)dc_get_userdata(mailbox);
|
||||||
g_assert(conn != NULL);
|
g_assert(conn != NULL);
|
||||||
|
|
||||||
ProcessRequest *pr;
|
ProcessRequest *pr = NULL;
|
||||||
uintptr_t out = 0;
|
uintptr_t out = 0;
|
||||||
|
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||||
|
|
||||||
printf("my_delta_handler(mailbox, %d, %lu, %lu)\n", event, data1, data2);
|
printf("my_delta_handler(mailbox, %d, %lu, %lu)\n", event, data1, data2);
|
||||||
|
|
||||||
@@ -248,20 +243,14 @@ my_delta_handler(dc_context_t* mailbox, int event, uintptr_t data1, uintptr_t da
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DC_EVENT_MSGS_CHANGED:
|
case DC_EVENT_MSGS_CHANGED:
|
||||||
pr = g_malloc(sizeof(ProcessRequest));
|
pr = delta_build_process_request(conn);
|
||||||
g_assert(pr != NULL);
|
|
||||||
|
|
||||||
pr->conn = conn;
|
|
||||||
purple_timeout_add(0, delta_process_fresh_messages, pr);
|
purple_timeout_add(0, delta_process_fresh_messages, pr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DC_EVENT_INCOMING_MSG:
|
case DC_EVENT_INCOMING_MSG:
|
||||||
// data1 is chat_id, which we don't seem to need yet.
|
// data1 is chat_id, which we don't seem to need yet.
|
||||||
// TODO: It may be needed for group chats
|
// TODO: It may be needed for group chats
|
||||||
pr = g_malloc(sizeof(ProcessRequest));
|
pr = delta_build_process_request(conn);
|
||||||
g_assert(pr != NULL);
|
|
||||||
|
|
||||||
pr->conn = conn;
|
|
||||||
pr->msg_id = (uint32_t)data2;
|
pr->msg_id = (uint32_t)data2;
|
||||||
purple_timeout_add(0, delta_process_incoming_message, pr);
|
purple_timeout_add(0, delta_process_incoming_message, pr);
|
||||||
break;
|
break;
|
||||||
@@ -276,16 +265,34 @@ my_delta_handler(dc_context_t* mailbox, int event, uintptr_t data1, uintptr_t da
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DC_EVENT_CONFIGURE_PROGRESS:
|
case DC_EVENT_CONFIGURE_PROGRESS:
|
||||||
pr = g_malloc(sizeof(ProcessRequest));
|
pr = delta_build_process_request(conn);
|
||||||
g_assert(pr != NULL);
|
|
||||||
|
|
||||||
pr->conn = conn;
|
|
||||||
pr->connection_state = (int)data1;
|
pr->connection_state = (int)data1;
|
||||||
purple_timeout_add(0, delta_process_connection_state, pr);
|
purple_timeout_add(0, delta_process_connection_state, pr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DC_EVENT_HTTP_GET:
|
case DC_EVENT_HTTP_GET:
|
||||||
printf("HTTP GET requested: %s\n", (char *)data1);
|
printf("HTTP GET requested: %s\n", (char *)data1);
|
||||||
out = _http_get((char *)data1);
|
|
||||||
|
pthread_mutex_lock(&mutex);
|
||||||
|
|
||||||
|
pr = delta_build_process_request(conn);
|
||||||
|
g_assert(pr != NULL);
|
||||||
|
|
||||||
|
pr->http_url = (char *)data1;
|
||||||
|
pr->http_wait = &cond;
|
||||||
|
|
||||||
|
purple_timeout_add(0, delta_process_http_get, pr);
|
||||||
|
|
||||||
|
// Wait patiently for the HTTP GET to complete
|
||||||
|
pthread_cond_wait(pr->http_wait, &mutex);
|
||||||
|
out = (uintptr_t)pr->http_response;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
|
pthread_cond_destroy(&cond);
|
||||||
|
pthread_mutex_destroy(&mutex);
|
||||||
|
free(pr);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DC_EVENT_IS_OFFLINE:
|
case DC_EVENT_IS_OFFLINE:
|
||||||
if ( conn->pc == NULL || !PURPLE_CONNECTION_IS_CONNECTED(conn->pc) ) {
|
if ( conn->pc == NULL || !PURPLE_CONNECTION_IS_CONNECTED(conn->pc) ) {
|
||||||
|
Reference in New Issue
Block a user