tFirst attempt using libcurl to connect to metaserver - vaccinewars - be a doct… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 8b75b68f07617cbf489a17154c034c0e53353469 | |
parent e7209ec919eb016fb80517108c65feb26a3d5179 | |
Author: Ben Webb <[email protected]> | |
Date: Thu, 29 Oct 2020 00:48:46 -0700 | |
First attempt using libcurl to connect to metaserver | |
Diffstat: | |
M src/Makefile.am | 2 +- | |
M src/dopewars.c | 18 +++++------------- | |
M src/dopewars.h | 5 ++--- | |
M src/message.c | 4 ++-- | |
M src/serverside.c | 148 ++++++++++++++++++++++-------… | |
M src/serverside.h | 2 +- | |
6 files changed, 119 insertions(+), 60 deletions(-) | |
--- | |
diff --git a/src/Makefile.am b/src/Makefile.am | |
t@@ -21,7 +21,7 @@ CURSESPORTSUBDIR = cursesport | |
endif | |
SUBDIRS = $(GUISUBDIR) $(CURSESSUBDIR) $(GTKPORTSUBDIR) $(CURSESPORTSUBDIR) pl… | |
-dopewars_LDADD = @GUILIB@ @CURSESLIB@ @GTKPORTLIB@ @CURSESPORTLIB@ @GTK_LIBS@ … | |
+dopewars_LDADD = @GUILIB@ @CURSESLIB@ @GTKPORTLIB@ @CURSESPORTLIB@ @GTK_LIBS@ … | |
dopewars_DEPENDENCIES = @GUILIB@ @CURSESLIB@ @GTKPORTLIB@ @CURSESPORTLIB@ @WND… | |
bin_PROGRAMS = dopewars | |
diff --git a/src/dopewars.c b/src/dopewars.c | |
t@@ -210,12 +210,12 @@ struct BITCH Bitch = { | |
#ifdef NETWORKING | |
struct METASERVER MetaServer = { | |
- FALSE, NULL, 0, NULL, 0, NULL, NULL, NULL, | |
+ FALSE, NULL, NULL, 0, NULL, NULL, | |
NULL, FALSE, NULL, NULL, NULL, NULL | |
}; | |
struct METASERVER DefaultMetaServer = { | |
- TRUE, "dopewars.sourceforge.net", 80, "", 8080, "/metaserver.php", | |
+ TRUE, "https://dopewars.sourceforge.io/metaserver.php", "", 8080, | |
"", "", "dopewars server", FALSE, "", "", "", "" | |
}; | |
t@@ -277,21 +277,15 @@ struct GLOBALS Globals[] = { | |
{NULL, &MetaServer.Active, NULL, NULL, NULL, "MetaServer.Active", | |
N_("TRUE if server should report to a metaserver"), | |
NULL, NULL, 0, "", NULL, NULL, FALSE, 0, 0}, | |
- {NULL, NULL, NULL, &MetaServer.Name, NULL, "MetaServer.Name", | |
- N_("Metaserver name to report/get server details to/from"), | |
+ {NULL, NULL, NULL, &MetaServer.URL, NULL, "MetaServer.URL", | |
+ N_("Metaserver URL to report/get server details to/from"), | |
NULL, NULL, 0, "", NULL, NULL, FALSE, 0, 0}, | |
- {&MetaServer.Port, NULL, NULL, NULL, NULL, "MetaServer.Port", | |
- N_("Port for metaserver communication"), | |
- NULL, NULL, 0, "", NULL, NULL, FALSE, 0, 65535}, | |
{NULL, NULL, NULL, &MetaServer.ProxyName, NULL, "MetaServer.ProxyName", | |
N_("Name of a proxy for metaserver communication"), | |
NULL, NULL, 0, "", NULL, NULL, FALSE, 0, 0}, | |
{&MetaServer.ProxyPort, NULL, NULL, NULL, NULL, "MetaServer.ProxyPort", | |
N_("Port for communicating with the proxy server"), | |
NULL, NULL, 0, "", NULL, NULL, FALSE, 0, 65535}, | |
- {NULL, NULL, NULL, &MetaServer.Path, NULL, "MetaServer.Path", | |
- N_("Path of the script on the metaserver"), | |
- NULL, NULL, 0, "", NULL, NULL, FALSE, 0, 0}, | |
{NULL, NULL, NULL, &MetaServer.LocalName, NULL, "MetaServer.LocalName", | |
N_("Preferred hostname of your server machine"), NULL, NULL, 0, "", | |
NULL, NULL, FALSE, 0, 0}, | |
t@@ -1682,12 +1676,10 @@ void CopyNames(struct NAMES *dest, struct NAMES *src) | |
void CopyMetaServer(struct METASERVER *dest, struct METASERVER *src) | |
{ | |
dest->Active = src->Active; | |
- dest->Port = src->Port; | |
dest->ProxyPort = src->ProxyPort; | |
dest->UseSocks = src->UseSocks; | |
- AssignName(&dest->Name, src->Name); | |
+ AssignName(&dest->URL, src->URL); | |
AssignName(&dest->ProxyName, src->ProxyName); | |
- AssignName(&dest->Path, src->Path); | |
AssignName(&dest->LocalName, src->LocalName); | |
AssignName(&dest->Password, src->Password); | |
AssignName(&dest->Comment, src->Comment); | |
diff --git a/src/dopewars.h b/src/dopewars.h | |
t@@ -100,11 +100,10 @@ struct SOUNDS { | |
struct METASERVER { | |
gboolean Active; | |
- gchar *Name; | |
- unsigned Port; | |
+ gchar *URL; | |
gchar *ProxyName; | |
unsigned ProxyPort; | |
- gchar *Path, *LocalName, *Password, *Comment; | |
+ gchar *LocalName, *Password, *Comment; | |
gboolean UseSocks; | |
gchar *authuser, *authpassword, *proxyuser, *proxypassword; | |
}; | |
diff --git a/src/message.c b/src/message.c | |
t@@ -435,8 +435,8 @@ gboolean OpenMetaHttpConnection(HttpConnection **conn) | |
gboolean retval; | |
query = g_strdup_printf("%s?output=text&getlist=%d", | |
- MetaServer.Path, METAVERSION); | |
- retval = OpenHttpConnection(conn, MetaServer.Name, MetaServer.Port, | |
+ MetaServer.URL, METAVERSION); | |
+ retval = OpenHttpConnection(conn, MetaServer.URL, 80, | |
MetaServer.ProxyName, MetaServer.ProxyPort, | |
"", | |
UseSocks | |
diff --git a/src/serverside.c b/src/serverside.c | |
t@@ -28,6 +28,7 @@ | |
#include <string.h> | |
#include <sys/types.h> /* For size_t etc. */ | |
#include <sys/stat.h> | |
+#include <curl/curl.h> | |
#ifdef CYGWIN | |
#include <windows.h> /* For datatypes such as BOOL */ | |
t@@ -90,7 +91,7 @@ static char *attackquestiontr = N_("AE"); | |
int TerminateRequest, ReregisterRequest, RelogRequest; | |
int MetaUpdateTimeout; | |
-int MetaMinTimeout; | |
+long MetaMinTimeout; | |
gboolean WantQuit = FALSE; | |
#ifdef CYGWIN | |
t@@ -107,7 +108,38 @@ GSList *FirstServer = NULL; | |
static GScanner *Scanner; | |
/* Data waiting to be sent to/read from the metaserver */ | |
-HttpConnection *MetaConn = NULL; | |
+CURLM *MetaConnM = NULL; | |
+ | |
+struct _MetaServerConnection { | |
+ CURL *h; | |
+ gchar *data; | |
+ size_t data_size; | |
+ char Terminator; /* Character that separates messages */ | |
+ char StripChar; /* Char that should be removed | |
+ * from messages */ | |
+}; | |
+ | |
+struct _MetaServerConnection MetaConn; | |
+ | |
+static size_t MetaConnWriteFunc(void *contents, size_t size, size_t nmemb, voi… | |
+{ | |
+ size_t realsize = size * nmemb; | |
+ struct _MetaServerConnection *conn = (struct _MetaServerConnection *)userp; | |
+ | |
+ char *ptr = realloc(conn->data, conn->data_size + realsize + 1); | |
+ if(ptr == NULL) { | |
+ /* out of memory! */ | |
+ printf("not enough memory (realloc returned NULL)\n"); | |
+ return 0; | |
+ } | |
+ | |
+ conn->data = ptr; | |
+ memcpy(&(conn->data[conn->data_size]), contents, realsize); | |
+ conn->data_size += realsize; | |
+ conn->data[conn->data_size] = 0; | |
+ | |
+ return realsize; | |
+} | |
#endif | |
/* Handle to the high score file */ | |
t@@ -155,9 +187,9 @@ static void MetaSocketStatus(NetworkBuffer *NetBuf, | |
#endif | |
#ifdef NETWORKING | |
-static gboolean MetaConnectError(HttpConnection *conn) | |
+static gboolean MetaConnectError(CURL *conn) | |
{ | |
- GString *errstr; | |
+/*GString *errstr; | |
if (!IsHttpError(conn)) | |
return FALSE; | |
t@@ -165,7 +197,7 @@ static gboolean MetaConnectError(HttpConnection *conn) | |
g_string_assign_error(errstr, MetaConn->NetBuf.error); | |
dopelog(1, LF_SERVER, _("Failed to connect to metaserver at %s:%u (%s)"), | |
MetaServer.Name, MetaServer.Port, errstr->str); | |
- g_string_free(errstr, TRUE); | |
+ g_string_free(errstr, TRUE);*/ | |
return TRUE; | |
} | |
t@@ -227,7 +259,7 @@ void RegisterWithMetaServer(gboolean Up, gboolean SendData, | |
{ | |
#ifdef NETWORKING | |
struct HISCORE MultiScore[NUMHISCORE], AntiqueScore[NUMHISCORE]; | |
- GString *headers, *body; | |
+ GString *body; | |
gchar *prstr; | |
gboolean retval; | |
int i; | |
t@@ -246,10 +278,13 @@ void RegisterWithMetaServer(gboolean Up, gboolean SendDa… | |
/* If the previous connect hung for so long that it's still active, then | |
* break the connection before we start a new one */ | |
- if (MetaConn) | |
- CloseHttpConnection(MetaConn); | |
+ if (MetaConn.h) { | |
+ curl_multi_remove_handle(MetaConnM, MetaConn.h); | |
+ curl_easy_cleanup(MetaConn.h); | |
+ MetaConn.h = NULL; | |
+ free(MetaConn.data); | |
+ } | |
- headers = g_string_new(""); | |
body = g_string_new(""); | |
g_string_assign(body, "output=text&"); | |
t@@ -284,35 +319,36 @@ void RegisterWithMetaServer(gboolean Up, gboolean SendDa… | |
} | |
} | |
- g_string_printf(headers, | |
- "Content-Type: application/x-www-form-urlencoded\n" | |
- "Content-Length: %d", (int)strlen(body->str)); | |
- | |
- retval = OpenHttpConnection(&MetaConn, MetaServer.Name, MetaServer.Port, | |
- MetaServer.ProxyName, MetaServer.ProxyPort, | |
- BindAddress, | |
- UseSocks && MetaServer.UseSocks ? &Socks : NULL, | |
- "POST", MetaServer.Path, headers->str, | |
- body->str); | |
- g_string_free(headers, TRUE); | |
+ MetaConn.h = curl_easy_init(); | |
+ MetaConn.data = malloc(1); | |
+ MetaConn.Terminator = '\n'; | |
+ MetaConn.StripChar = '\r'; | |
+ MetaConn.data_size = 0; | |
+ if (MetaConn.h) { | |
+ int still_running; | |
+ curl_easy_setopt(MetaConn.h, CURLOPT_COPYPOSTFIELDS, body->str); | |
+ curl_easy_setopt(MetaConn.h, CURLOPT_URL, MetaServer.URL); | |
+ curl_easy_setopt(MetaConn.h, CURLOPT_WRITEFUNCTION, MetaConnWriteFunc); | |
+ curl_easy_setopt(MetaConn.h, CURLOPT_WRITEDATA, &MetaConn); | |
+ | |
+ curl_multi_add_handle(MetaConnM, MetaConn.h); | |
+ curl_multi_perform(MetaConnM, &still_running); | |
+ dopelog(2, LF_SERVER, _("Waiting for connect to metaserver at %s..."), | |
+ MetaServer.URL); | |
+ } | |
g_string_free(body, TRUE); | |
- if (retval) { | |
- dopelog(2, LF_SERVER, _("Waiting for connect to metaserver at %s:%u..."), | |
- MetaServer.Name, MetaServer.Port); | |
- } else { | |
- MetaConnectError(MetaConn); | |
+/* MetaConnectError(MetaConn); | |
CloseHttpConnection(MetaConn); | |
MetaConn = NULL; | |
- return; | |
- } | |
- SetHttpAuthFunc(MetaConn, ServerHttpAuth, NULL); | |
+ return;*/ | |
+/*SetHttpAuthFunc(MetaConn, ServerHttpAuth, NULL); | |
if (Socks.authuser && Socks.authuser[0] && | |
Socks.authpassword && Socks.authpassword[0]) { | |
SetNetworkBufferUserPasswdFunc(&MetaConn->NetBuf, ServerNetBufAuth, | |
NULL); | |
- } | |
+ }*/ | |
#ifdef GUI_SERVER | |
SetNetworkBufferCallBack(&MetaConn->NetBuf, MetaSocketStatus, NULL); | |
#endif | |
t@@ -952,7 +988,7 @@ void RequestServerShutdown(void) | |
*/ | |
gboolean IsServerShutdown(void) | |
{ | |
- return (WantQuit && !FirstServer && !MetaConn); | |
+ return (WantQuit && !FirstServer && !MetaConn.h); | |
} | |
static GPrintFunc StartServerReply(NetworkBuffer *netbuf) | |
t@@ -1182,6 +1218,9 @@ void ServerLoop(struct CMDLINE *cmdline) | |
InitConfiguration(cmdline); | |
+ curl_global_init(CURL_GLOBAL_DEFAULT); | |
+ MetaConnM = curl_multi_init(); | |
+ | |
if (!StartServer()) | |
return; | |
t@@ -1207,9 +1246,10 @@ void ServerLoop(struct CMDLINE *cmdline) | |
FD_ZERO(&readfs); | |
FD_ZERO(&writefs); | |
FD_ZERO(&errorfs); | |
+ curl_multi_fdset(MetaConnM, &readfs, &writefs, &errorfs, &topsock); | |
FD_SET(ListenSock, &readfs); | |
FD_SET(ListenSock, &errorfs); | |
- topsock = ListenSock + 1; | |
+ topsock = MAX(topsock + 1, ListenSock + 1); | |
#ifndef CYGWIN | |
if (localsock >= 0) { | |
FD_SET(localsock, &readfs); | |
t@@ -1223,10 +1263,6 @@ void ServerLoop(struct CMDLINE *cmdline) | |
&topsock); | |
} | |
#endif | |
- if (MetaConn) { | |
- SetSelectForNetworkBuffer(&MetaConn->NetBuf, &readfs, &writefs, | |
- &errorfs, &topsock); | |
- } | |
for (list = FirstServer; list; list = g_slist_next(list)) { | |
tmp = (Player *)list->data; | |
if (!IsCop(tmp)) { | |
t@@ -1311,8 +1347,11 @@ void ServerLoop(struct CMDLINE *cmdline) | |
if (IsServerShutdown()) | |
break; | |
#endif | |
- if (MetaConn) { | |
- if (RespondToSelect(&MetaConn->NetBuf, &readfs, &writefs, | |
+ if (MetaConn.h) { | |
+ int still_running; | |
+ curl_multi_perform(MetaConnM, &still_running); | |
+// dopelog(2, LF_SERVER, "MetaServer multi_perform: %d", still_running); | |
+/* if (RespondToSelect(&MetaConn->NetBuf, &readfs, &writefs, | |
&errorfs, &DoneOK)) { | |
while ((buf = ReadHttpResponse(MetaConn, &DoneOK))) { | |
gboolean ReadingBody = (MetaConn->Status == HS_READBODY); | |
t@@ -1331,6 +1370,30 @@ void ServerLoop(struct CMDLINE *cmdline) | |
MetaConn = NULL; | |
if (IsServerShutdown()) | |
break; | |
+ } */ | |
+ if (still_running == 0) { | |
+ char *ch = MetaConn.data; | |
+ while(ch && *ch) { | |
+ char *sep_pt = strchr(ch, MetaConn.Terminator); | |
+ if (sep_pt) { | |
+ *sep_pt = '\0'; | |
+ if (sep_pt > ch && sep_pt[-1] == MetaConn.StripChar) { | |
+ sep_pt[-1] = '\0'; | |
+ } | |
+ sep_pt++; | |
+ } | |
+ if (*ch) { | |
+ dopelog(2, LF_SERVER, "MetaServer: %s", ch); | |
+ } | |
+ ch = sep_pt; | |
+ } | |
+ dopelog(4, LF_SERVER, "MetaServer: (closed)\n"); | |
+ curl_multi_remove_handle(MetaConnM, MetaConn.h); | |
+ curl_easy_cleanup(MetaConn.h); | |
+ MetaConn.h = NULL; | |
+ free(MetaConn.data); | |
+ if (IsServerShutdown()) | |
+ break; | |
} | |
} | |
t@@ -1365,6 +1428,10 @@ void ServerLoop(struct CMDLINE *cmdline) | |
#endif | |
StopServer(); | |
g_string_free(LineBuf, TRUE); | |
+ | |
+ curl_multi_cleanup(MetaConnM); | |
+ | |
+ curl_global_cleanup(); | |
} | |
#ifdef GUI_SERVER | |
t@@ -3703,7 +3770,7 @@ void ClearFightTimeout(Player *Play) | |
* unless "mintime" is already smaller (as long as it's not -1, which | |
* means "uninitialized"). Returns 1 if the timeout has already expired. | |
*/ | |
-int AddTimeout(time_t timeout, time_t timenow, int *mintime) | |
+long AddTimeout(time_t timeout, time_t timenow, long *mintime) | |
{ | |
if (timeout == 0) | |
return 0; | |
t@@ -3721,14 +3788,15 @@ int AddTimeout(time_t timeout, time_t timenow, int *mi… | |
* an event has already expired, returns 0. If no events are pending, | |
* returns -1. "First" should point to a list of valid players. | |
*/ | |
-int GetMinimumTimeout(GSList *First) | |
+long GetMinimumTimeout(GSList *First) | |
{ | |
Player *Play; | |
GSList *list; | |
- int mintime = -1; | |
+ long mintime = -1; | |
time_t timenow; | |
timenow = time(NULL); | |
+ curl_multi_timeout(MetaConnM, &mintime); | |
if (AddTimeout(MetaMinTimeout, timenow, &mintime)) | |
return 0; | |
if (AddTimeout(MetaUpdateTimeout, timenow, &mintime)) | |
diff --git a/src/serverside.h b/src/serverside.h | |
t@@ -52,7 +52,7 @@ int LoseBitch(Player *Play, Inventory *Guns, Inventory *Drug… | |
void GainBitch(Player *Play); | |
void SetFightTimeout(Player *Play); | |
void ClearFightTimeout(Player *Play); | |
-int GetMinimumTimeout(GSList *First); | |
+long GetMinimumTimeout(GSList *First); | |
GSList *HandleTimeouts(GSList *First); | |
void ConvertHighScoreFile(const gchar *convertfile); | |
void OpenHighScoreFile(void); |