mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-08 20:46:12 +01:00
implement sendViaWeb for linux
Fixed the crash that was forcing synchronous sends (and so seriously slowing down my test script) by using http instead of https. That's due to limitations in ssl/curl interaction I can look at if necessary.
This commit is contained in:
parent
ee26816420
commit
2997f32ad0
2 changed files with 83 additions and 117 deletions
|
@ -37,20 +37,9 @@
|
||||||
#include "mqttcon.h"
|
#include "mqttcon.h"
|
||||||
|
|
||||||
|
|
||||||
/* Define ACK_IN_BACKGROUND and you'll crash inside curl_easy_perform(). No
|
|
||||||
idea why, and no time to debug it now.
|
|
||||||
*/
|
|
||||||
// #define ACK_IN_BACKGROUND
|
|
||||||
|
|
||||||
typedef struct _LinDUtilCtxt {
|
typedef struct _LinDUtilCtxt {
|
||||||
XW_DUtilCtxt super;
|
XW_DUtilCtxt super;
|
||||||
|
|
||||||
#ifdef ACK_IN_BACKGROUND
|
|
||||||
pthread_t ackThread;
|
|
||||||
pthread_mutex_t ackMutex;
|
|
||||||
pthread_cond_t ackCondVar;
|
|
||||||
GList* ackList;
|
|
||||||
#endif
|
|
||||||
} LinDUtilCtxt;
|
} LinDUtilCtxt;
|
||||||
|
|
||||||
static XP_U32 linux_dutil_getCurSeconds( XW_DUtilCtxt* duc, XWEnv xwe );
|
static XP_U32 linux_dutil_getCurSeconds( XW_DUtilCtxt* duc, XWEnv xwe );
|
||||||
|
@ -202,124 +191,100 @@ linux_dutil_onGameGoneReceived( XW_DUtilCtxt* duc, XWEnv XP_UNUSED(xwe),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* typedef struct _AckData { */
|
typedef struct _SendViaData {
|
||||||
/* XW_DUtilCtxt* duc; */
|
LinDUtilCtxt* lduc;
|
||||||
/* XP_U8* msg; */
|
char* pstr;
|
||||||
/* XP_U16 len; */
|
char* api;
|
||||||
/* gchar* topic; */
|
} SendViaData;
|
||||||
/* XP_U32 gameID; */
|
|
||||||
/* } AckData; */
|
|
||||||
|
|
||||||
/* static void */
|
typedef struct _FetchData {
|
||||||
/* sendViaCurl( LinDUtilCtxt* lduc, AckData* adp ) */
|
char* payload;
|
||||||
/* { */
|
size_t size;
|
||||||
/* LaunchParams* params = (LaunchParams*)lduc->super.closure; */
|
} FetchData;
|
||||||
|
|
||||||
/* CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT); */
|
static size_t
|
||||||
/* XP_ASSERT(res == CURLE_OK); */
|
curl_callback( void *contents, size_t size, size_t nmemb, void *userp )
|
||||||
/* CURL* curl = curl_easy_init(); */
|
|
||||||
|
|
||||||
/* char url[128]; */
|
|
||||||
/* snprintf( url, sizeof(url), "https://%s/xw4/api/v1/ack", */
|
|
||||||
/* params->connInfo.mqtt.hostName ); */
|
|
||||||
/* curl_easy_setopt( curl, CURLOPT_URL, url ); */
|
|
||||||
|
|
||||||
/* gchar* sum = g_compute_checksum_for_data( G_CHECKSUM_MD5, adp->msg, adp->len ); */
|
|
||||||
/* gchar* json */
|
|
||||||
/* = g_strdup_printf("{\"topic\": \"%s\", \"gid\": %u, \"sum\": \"%s\"}", */
|
|
||||||
/* adp->topic, adp->gameID, sum ); */
|
|
||||||
/* // XP_LOGFF( "json: %s", json ); */
|
|
||||||
/* g_free( sum ); */
|
|
||||||
/* curl_easy_setopt( curl, CURLOPT_POSTFIELDS, json ); */
|
|
||||||
/* curl_easy_setopt( curl, CURLOPT_POSTFIELDSIZE, -1L ); */
|
|
||||||
|
|
||||||
/* struct curl_slist *headers = NULL; */
|
|
||||||
/* headers = curl_slist_append(headers, "Expect:"); */
|
|
||||||
/* headers = curl_slist_append(headers, "Content-Type: application/json"); */
|
|
||||||
/* curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); */
|
|
||||||
|
|
||||||
/* res = curl_easy_perform(curl); */
|
|
||||||
/* XP_Bool success = res == CURLE_OK; */
|
|
||||||
/* /\* XP_LOGFF( "curl_easy_perform() => %d", res ); *\/ */
|
|
||||||
/* if ( ! success ) { */
|
|
||||||
/* XP_LOGFF( "curl_easy_perform() failed: %s", curl_easy_strerror(res)); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
/* curl_slist_free_all( headers ); */
|
|
||||||
/* curl_easy_cleanup( curl ); */
|
|
||||||
/* curl_global_cleanup(); */
|
|
||||||
/* g_free( json ); */
|
|
||||||
|
|
||||||
/* /\* g_idle_add( nuke_ack_data, ad ); *\/ */
|
|
||||||
/* g_free( adp->topic ); */
|
|
||||||
/* g_free( adp->msg ); */
|
|
||||||
/* g_free( adp ); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
#ifdef ACK_IN_BACKGROUND
|
|
||||||
static void*
|
|
||||||
sendAckThreadProc( void* arg )
|
|
||||||
{
|
{
|
||||||
LOG_FUNC();
|
size_t realsize = size * nmemb;
|
||||||
LinDUtilCtxt* lduc = (LinDUtilCtxt*)arg;
|
FetchData* fdp = (FetchData*)userp;
|
||||||
|
XP_LOGFF( "(realsize: %zu)", realsize );
|
||||||
|
|
||||||
for ( ; ; ) {
|
fdp->payload = (char *) realloc(fdp->payload, fdp->size + realsize + 1);
|
||||||
XP_LOGFF( "top of loop" );
|
memcpy(&(fdp->payload[fdp->size]), contents, realsize);
|
||||||
pthread_mutex_lock( &lduc->ackMutex );
|
fdp->size += realsize;
|
||||||
while ( 0 == g_list_length(lduc->ackList) ) {
|
fdp->payload[fdp->size] = 0;
|
||||||
pthread_cond_wait( &lduc->ackCondVar, &lduc->ackMutex );
|
return realsize;
|
||||||
}
|
}
|
||||||
GList* head = lduc->ackList;
|
|
||||||
lduc->ackList = g_list_remove_link( lduc->ackList, lduc->ackList );
|
|
||||||
AckData* adp = (AckData*)head->data;
|
|
||||||
g_list_free( head );
|
|
||||||
pthread_mutex_unlock( &lduc->ackMutex );
|
|
||||||
|
|
||||||
sendViaCurl( lduc, adp );
|
static void*
|
||||||
XP_LOGFF( "bottom of loop" );
|
sendViaThreadProc( void* arg )
|
||||||
|
{
|
||||||
|
SendViaData* svdp = (SendViaData*)arg;
|
||||||
|
|
||||||
|
const LaunchParams* params = (LaunchParams*)svdp->lduc->super.closure;
|
||||||
|
|
||||||
|
XP_LOGFF( "(api: %s, json: %s)", svdp->api, svdp->pstr );
|
||||||
|
|
||||||
|
CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT); /* ok to call multiple times */
|
||||||
|
XP_ASSERT(res == CURLE_OK);
|
||||||
|
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
|
||||||
|
char url[128];
|
||||||
|
/* Don't use https. Doing so triggers a race condition/crash in openssl as
|
||||||
|
called by curl. See https://curl.se/libcurl/c/threaded-ssl.html (which
|
||||||
|
has a fix to allow using https, but I'm to lazy to work it out now.) */
|
||||||
|
const char* proto = "http";
|
||||||
|
snprintf( url, sizeof(url), "%s://%s/xw4/api/v1/%s", proto,
|
||||||
|
params->connInfo.mqtt.hostName, svdp->api );
|
||||||
|
curl_easy_setopt( curl, CURLOPT_URL, url );
|
||||||
|
|
||||||
|
curl_easy_setopt( curl, CURLOPT_POSTFIELDS, svdp->pstr );
|
||||||
|
curl_easy_setopt( curl, CURLOPT_POSTFIELDSIZE, -1L );
|
||||||
|
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
headers = curl_slist_append(headers, "Expect:");
|
||||||
|
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
|
FetchData fd = {0};
|
||||||
|
|
||||||
|
curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, curl_callback );
|
||||||
|
curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void *) &fd );
|
||||||
|
|
||||||
|
res = curl_easy_perform( curl );
|
||||||
|
if ( res != CURLE_OK ) {
|
||||||
|
XP_LOGFF( "curl_easy_perform() failed: %s", curl_easy_strerror(res));
|
||||||
|
} else {
|
||||||
|
XP_LOGFF( "got buffer: %s", fd.payload );
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_RETURN_VOID();
|
curl_slist_free_all( headers );
|
||||||
|
curl_easy_cleanup( curl );
|
||||||
|
|
||||||
|
free( svdp->pstr );
|
||||||
|
free( svdp->api );
|
||||||
|
free( svdp );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* static void */
|
|
||||||
/* linux_dutil_ackMQTTMsg( XW_DUtilCtxt* duc, XWEnv XP_UNUSED(xwe), */
|
|
||||||
/* const XP_UCHAR* topic, XP_U32 gameID, */
|
|
||||||
/* const MQTTDevID* XP_UNUSED(senderID), */
|
|
||||||
/* const XP_U8* msg, XP_U16 len ) */
|
|
||||||
/* { */
|
|
||||||
/* AckData ad = { */
|
|
||||||
/* .duc = duc, */
|
|
||||||
/* .topic = g_strdup( topic ), */
|
|
||||||
/* .gameID = gameID, */
|
|
||||||
/* .len = len, */
|
|
||||||
/* .msg = g_memdup2( msg, len ), */
|
|
||||||
/* }; */
|
|
||||||
/* AckData* adp = g_memdup2( &ad, sizeof(ad) ); */
|
|
||||||
|
|
||||||
/* LinDUtilCtxt* lduc = (LinDUtilCtxt*)duc; */
|
|
||||||
/* #ifdef ACK_IN_BACKGROUND */
|
|
||||||
/* pthread_mutex_lock( &lduc->ackMutex ); */
|
|
||||||
/* lduc->ackList = g_list_append( lduc->ackList, adp ); */
|
|
||||||
/* pthread_cond_signal( &lduc->ackCondVar ); */
|
|
||||||
/* pthread_mutex_unlock( &lduc->ackMutex ); */
|
|
||||||
/* #else */
|
|
||||||
/* sendViaCurl( lduc, adp ); */
|
|
||||||
/* #endif */
|
|
||||||
/* /\* LOG_RETURN_VOID(); *\/ */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
linux_dutil_sendViaWeb( XW_DUtilCtxt* duc, XWEnv xwe, const XP_UCHAR* api,
|
linux_dutil_sendViaWeb( XW_DUtilCtxt* duc, XWEnv XP_UNUSED(xwe),
|
||||||
const cJSON* params )
|
const XP_UCHAR* api, const cJSON* json )
|
||||||
{
|
{
|
||||||
XP_USE(duc);
|
LinDUtilCtxt* lduc = (LinDUtilCtxt*)duc;
|
||||||
XP_USE(xwe);
|
|
||||||
char* pstr = cJSON_PrintUnformatted( params );
|
SendViaData svd = {
|
||||||
XP_LOGFF( "(api: %s, params: %s)", api, pstr );
|
.lduc = lduc,
|
||||||
free( pstr );
|
.pstr = cJSON_PrintUnformatted( json ),
|
||||||
|
.api = g_strdup(api),
|
||||||
|
};
|
||||||
|
SendViaData* svdp = malloc( sizeof(*svdp) );
|
||||||
|
*svdp = svd;
|
||||||
|
|
||||||
|
pthread_t thrd;
|
||||||
|
(void)pthread_create( &thrd, NULL, sendViaThreadProc, svdp );
|
||||||
|
pthread_detach( thrd );
|
||||||
}
|
}
|
||||||
|
|
||||||
XW_DUtilCtxt*
|
XW_DUtilCtxt*
|
||||||
|
|
|
@ -199,6 +199,7 @@ mkJsonParams( CURL* curl, va_list ap )
|
||||||
static XP_Bool
|
static XP_Bool
|
||||||
runWitCurl( RelayTask* task, const gchar* proc, ...)
|
runWitCurl( RelayTask* task, const gchar* proc, ...)
|
||||||
{
|
{
|
||||||
|
XP_ASSERT(0); /* should no longer be getting called */
|
||||||
CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT);
|
CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
XP_ASSERT(res == CURLE_OK);
|
XP_ASSERT(res == CURLE_OK);
|
||||||
CURL* curl = curl_easy_init();
|
CURL* curl = curl_easy_init();
|
||||||
|
|
Loading…
Add table
Reference in a new issue