tAll code now uses the new metaserver at SourceForge - vaccinewars - be a docto… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 2eaeaade9e1413d2b357873738485f14ee86310e | |
parent 47ea05dc1f971516f22a9f5621f84bcf74657111 | |
Author: Ben Webb <[email protected]> | |
Date: Sat, 9 Jun 2001 23:16:52 +0000 | |
All code now uses the new metaserver at SourceForge | |
Diffstat: | |
M src/AIPlayer.c | 12 ++++++------ | |
M src/curses_client.c | 18 +++++++++--------- | |
M src/dopewars.c | 28 ++++++++++++++++------------ | |
M src/dopewars.h | 9 ++++++--- | |
M src/gtk_client.c | 17 +++++++++-------- | |
M src/message.c | 75 +++++++++++++++++++++--------… | |
M src/message.h | 5 +++-- | |
M src/serverside.c | 180 +++++++++++++++++++----------… | |
M src/serverside.h | 2 +- | |
9 files changed, 212 insertions(+), 134 deletions(-) | |
--- | |
diff --git a/src/AIPlayer.c b/src/AIPlayer.c | |
t@@ -54,7 +54,7 @@ void AIPlayerLoop() { | |
gchar *pt; | |
Player *AIPlay; | |
fd_set readfs,writefs; | |
- gboolean DataWaiting,QuitRequest; | |
+ gboolean DoneOK,QuitRequest; | |
int MaxSock; | |
AIPlay=g_new(Player,1); | |
t@@ -91,11 +91,7 @@ void AIPlayerLoop() { | |
printf("Error in select\n"); exit(1); | |
} | |
- if (!RespondToSelect(&AIPlay->NetBuf,&readfs,&writefs, | |
- NULL,&DataWaiting)) { | |
- g_print(_("Connection to server lost!\n")); | |
- break; | |
- } else if (DataWaiting) { | |
+ if (RespondToSelect(&AIPlay->NetBuf,&readfs,&writefs,NULL,&DoneOK)) { | |
QuitRequest=FALSE; | |
while ((pt=GetWaitingPlayerMessage(AIPlay))!=NULL) { | |
if (HandleAIMessage(pt,AIPlay)) { | |
t@@ -105,6 +101,10 @@ void AIPlayerLoop() { | |
} | |
if (QuitRequest) break; | |
} | |
+ if (!DoneOK) { | |
+ g_print(_("Connection to server lost!\n")); | |
+ break; | |
+ } | |
} | |
ShutdownNetwork(); | |
g_print(_("AI Player terminated OK.\n")); | |
diff --git a/src/curses_client.c b/src/curses_client.c | |
t@@ -1507,7 +1507,7 @@ static void Curses_DoGame(Player *Play) { | |
char HaveWorthless; | |
Player *tmp; | |
struct sigaction sact; | |
- gboolean DataWaiting; | |
+ gboolean DoneOK; | |
DisplayMode=DM_NONE; | |
QuitRequest=FALSE; | |
t@@ -1653,8 +1653,14 @@ static void Curses_DoGame(Player *Play) { | |
perror("bselect"); exit(1); | |
} | |
if (Client) { | |
- if (!RespondToSelect(&Play->NetBuf,&readfs,&writefs, | |
- NULL,&DataWaiting)) { | |
+ if (RespondToSelect(&Play->NetBuf,&readfs,&writefs,NULL,&DoneOK)) { | |
+ while ((pt=GetWaitingPlayerMessage(Play))!=NULL) { | |
+ HandleClientMessage(pt,Play); | |
+ g_free(pt); | |
+ } | |
+ if (QuitRequest) return; | |
+ } | |
+ if (!DoneOK) { | |
attrset(TextAttr); | |
clear_line(22); | |
mvaddstr(22,0,_("Connection to server lost! " | |
t@@ -1662,12 +1668,6 @@ static void Curses_DoGame(Player *Play) { | |
nice_wait(); | |
SwitchToSinglePlayer(Play); | |
print_status(Play,TRUE); | |
- } else if (DataWaiting) { | |
- while ((pt=GetWaitingPlayerMessage(Play))!=NULL) { | |
- HandleClientMessage(pt,Play); | |
- g_free(pt); | |
- } | |
- if (QuitRequest) return; | |
} | |
} | |
if (FD_ISSET(0,&readfs)) { | |
diff --git a/src/dopewars.c b/src/dopewars.c | |
t@@ -150,11 +150,11 @@ struct BITCH Bitch = { | |
50000,150000 | |
}; | |
-struct METASERVER MetaServer = { 0,0,0,NULL,NULL,NULL,NULL,NULL }; | |
+struct METASERVER MetaServer = { 0,NULL,0,NULL,0,NULL,NULL,NULL,NULL }; | |
struct METASERVER DefaultMetaServer = { | |
- 1,80,7802,"bellatrix.pcl.ox.ac.uk","/~ben/cgi-bin/server.pl","","", | |
- "dopewars server" | |
+ 1,"dopewars.sourceforge.net",80,"",8080,"/metaserver.php", | |
+ "","","dopewars server" | |
}; | |
int NumTurns=31; | |
t@@ -174,17 +174,20 @@ struct GLOBALS Globals[NUMGLOB] = { | |
{ &MetaServer.Active,NULL,NULL,NULL,"MetaServer.Active", | |
N_("Non-zero if server should report to a metaserver"), | |
NULL,NULL,0,"",NULL,NULL }, | |
- { &MetaServer.HttpPort,NULL,NULL,NULL,"MetaServer.HttpPort", | |
- N_("Port for metaserver communication (client)"), | |
+ { NULL,NULL,&MetaServer.Name,NULL,"MetaServer.Name", | |
+ N_("Metaserver name to report/get server details to/from"), | |
NULL,NULL,0,"",NULL,NULL }, | |
- { &MetaServer.UdpPort,NULL,NULL,NULL,"MetaServer.UdpPort", | |
- N_("Port for metaserver communication (server)"), | |
+ { &MetaServer.Port,NULL,NULL,NULL,"MetaServer.Port", | |
+ N_("Port for metaserver communication"), | |
NULL,NULL,0,"",NULL,NULL }, | |
- { NULL,NULL,&MetaServer.Name,NULL,"MetaServer.Name", | |
- N_("Metaserver name to report server details to"), | |
+ { NULL,NULL,&MetaServer.ProxyName,NULL,"MetaServer.ProxyName", | |
+ N_("Name of the proxy (if needed) for metaserver communication"), | |
+ NULL,NULL,0,"",NULL,NULL }, | |
+ { &MetaServer.ProxyPort,NULL,NULL,NULL,"MetaServer.ProxyPort", | |
+ N_("Port for communicating with the proxy server"), | |
NULL,NULL,0,"",NULL,NULL }, | |
{ NULL,NULL,&MetaServer.Path,NULL,"MetaServer.Path", | |
- N_("Path of the CGI script on the metaserver (client)"), | |
+ N_("Path of the script on the metaserver"), | |
NULL,NULL,0,"",NULL,NULL }, | |
{ NULL,NULL,&MetaServer.LocalName,NULL,"MetaServer.LocalName", | |
N_("Preferred hostname of your server machine"),NULL,NULL,0,"",NULL,NULL … | |
t@@ -1183,9 +1186,10 @@ void CopyNames(struct NAMES *dest,struct NAMES *src) { | |
void CopyMetaServer(struct METASERVER *dest,struct METASERVER *src) { | |
dest->Active=src->Active; | |
- dest->HttpPort=src->HttpPort; | |
- dest->UdpPort=src->UdpPort; | |
+ dest->Port=src->Port; | |
+ dest->ProxyPort=src->ProxyPort; | |
AssignName(&dest->Name,src->Name); | |
+ AssignName(&dest->ProxyName,src->ProxyName); | |
AssignName(&dest->Path,src->Path); | |
AssignName(&dest->LocalName,src->LocalName); | |
AssignName(&dest->Password,src->Password); | |
diff --git a/src/dopewars.h b/src/dopewars.h | |
t@@ -91,8 +91,11 @@ struct NAMES { | |
struct METASERVER { | |
int Active; | |
- int HttpPort,UdpPort; | |
- gchar *Name,*Path,*LocalName,*Password,*Comment; | |
+ gchar *Name; | |
+ int Port; | |
+ gchar *ProxyName; | |
+ int ProxyPort; | |
+ gchar *Path,*LocalName,*Password,*Comment; | |
}; | |
struct PRICES { | |
t@@ -329,7 +332,7 @@ typedef struct tag_serverdata { | |
char *Comment,*Version,*Update,*UpSince; | |
} ServerData; | |
-#define NUMGLOB 86 | |
+#define NUMGLOB 87 | |
struct GLOBALS { | |
int *IntVal; | |
price_t *PriceVal; | |
diff --git a/src/gtk_client.c b/src/gtk_client.c | |
t@@ -257,9 +257,15 @@ void ListInventory(GtkWidget *widget,gpointer data) { | |
void GetClientMessage(gpointer data,gint socket, | |
GdkInputCondition condition) { | |
gchar *pt; | |
- gboolean DataWaiting; | |
- if (!PlayerHandleNetwork(ClientData.Play,condition&GDK_INPUT_READ, | |
- condition&GDK_INPUT_WRITE,&DataWaiting)) { | |
+ gboolean DoneOK; | |
+ if (PlayerHandleNetwork(ClientData.Play,condition&GDK_INPUT_READ, | |
+ condition&GDK_INPUT_WRITE,&DoneOK)) { | |
+ while ((pt=GetWaitingPlayerMessage(ClientData.Play))!=NULL) { | |
+ HandleClientMessage(pt,ClientData.Play); | |
+ g_free(pt); | |
+ } | |
+ } | |
+ if (!DoneOK) { | |
if (Network) gdk_input_remove(ClientData.GdkInputTag); | |
if (InGame) { | |
/* The network connection to the server was dropped unexpectedly */ | |
t@@ -267,11 +273,6 @@ void GetClientMessage(gpointer data,gint socket, | |
"single player mode")); | |
SwitchToSinglePlayer(ClientData.Play); | |
} | |
- } else if (DataWaiting) { | |
- while ((pt=GetWaitingPlayerMessage(ClientData.Play))!=NULL) { | |
- HandleClientMessage(pt,ClientData.Play); | |
- g_free(pt); | |
- } | |
} | |
} | |
diff --git a/src/message.c b/src/message.c | |
t@@ -297,8 +297,14 @@ void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int … | |
NetBuf->fd=fd; | |
} | |
-static void MetaConnectError(gchar *Msg) { | |
- g_warning(_("Cannot connect to metaserver: %s"),Msg); | |
+gboolean IsNetworkBufferActive(NetworkBuffer *NetBuf) { | |
+/* Returns TRUE if the pointer is to a valid network buffer, and it's */ | |
+/* connected to an active socket. */ | |
+ return (NetBuf && NetBuf->fd>=0); | |
+} | |
+ | |
+static void ConnectError(gchar *Msg) { | |
+ g_warning(_("Cannot connect to remote host: %s"),Msg); | |
} | |
gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,gchar *RemoteHost, | |
t@@ -309,7 +315,7 @@ gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,g… | |
retval=StartConnect(&NetBuf->fd,RemoteHost,RemotePort,TRUE); | |
if (retval) { | |
- MetaConnectError(retval); return FALSE; | |
+ ConnectError(retval); return FALSE; | |
} else { | |
NetBuf->WaitConnect=TRUE; | |
return TRUE; | |
t@@ -358,7 +364,7 @@ static gboolean DoNetworkBufferStuff(NetworkBuffer *NetBuf… | |
retval=FinishConnect(NetBuf->fd); | |
if (retval) { | |
*WriteOK=FALSE; | |
- MetaConnectError(retval); | |
+ ConnectError(retval); | |
} else NetBuf->WaitConnect=FALSE; | |
} | |
return FALSE; | |
t@@ -370,37 +376,43 @@ static gboolean DoNetworkBufferStuff(NetworkBuffer *NetB… | |
if (ReadReady) { | |
*ReadOK=ReadDataFromWire(NetBuf); | |
- if (ReadOK) DataWaiting=TRUE; | |
+ if (NetBuf->ReadBuf.DataPresent>0) DataWaiting=TRUE; | |
} | |
return DataWaiting; | |
} | |
gboolean RespondToSelect(NetworkBuffer *NetBuf,fd_set *readfds, | |
fd_set *writefds,fd_set *errorfds, | |
- gboolean *DataWaiting) { | |
+ gboolean *DoneOK) { | |
/* Responds to a select() call by reading/writing data as necessary. */ | |
-/* If any data were read, DataWaiting is set TRUE. Returns TRUE unless */ | |
-/* a fatal error (i.e. the connection was broken) occurred. */ | |
+/* If any data were read, TRUE is returned. "DoneOK" is set TRUE */ | |
+/* unless a fatal error (i.e. the connection was broken) occurred. */ | |
gboolean ReadOK,WriteOK,ErrorOK; | |
- *DataWaiting=FALSE; | |
- if (!NetBuf || NetBuf->fd<=0) return TRUE; | |
- *DataWaiting=DoNetworkBufferStuff(NetBuf,FD_ISSET(NetBuf->fd,readfds), | |
+ gboolean DataWaiting=FALSE; | |
+ | |
+ *DoneOK=TRUE; | |
+ if (!NetBuf || NetBuf->fd<=0) return DataWaiting; | |
+ DataWaiting=DoNetworkBufferStuff(NetBuf,FD_ISSET(NetBuf->fd,readfds), | |
FD_ISSET(NetBuf->fd,writefds), | |
errorfds ? FD_ISSET(NetBuf->fd,errorfds) : FALSE, | |
&ReadOK,&WriteOK,&ErrorOK); | |
- return (WriteOK && ErrorOK && ReadOK); | |
+ *DoneOK=(WriteOK && ErrorOK && ReadOK); | |
+ return DataWaiting; | |
} | |
gboolean PlayerHandleNetwork(Player *Play,gboolean ReadReady, | |
- gboolean WriteReady,gboolean *DataWaiting) { | |
-/* Reads and writes player data from/to the network if it is ready. */ | |
-/* If any data were read, DataWaiting is set TRUE. Returns TRUE unless */ | |
-/* a fatal error (i.e. the connection was broken) occurred. */ | |
+ gboolean WriteReady,gboolean *DoneOK) { | |
+/* Reads and writes player data from/to the network if it is ready. */ | |
+/* If any data were read, TRUE is returned. "DoneOK" is set TRUE */ | |
+/* unless a fatal error (i.e. the connection was broken) occurred. */ | |
gboolean ReadOK,WriteOK,ErrorOK; | |
- *DataWaiting=FALSE; | |
- if (!Play || Play->NetBuf.fd<=0) return TRUE; | |
- *DataWaiting=DoNetworkBufferStuff(&Play->NetBuf,ReadReady,WriteReady,FALSE, | |
- &ReadOK,&WriteOK,&ErrorOK); | |
+ gboolean DataWaiting=FALSE; | |
+ | |
+ *DoneOK=TRUE; | |
+ if (!Play || Play->NetBuf.fd<=0) return DataWaiting; | |
+ | |
+ DataWaiting=DoNetworkBufferStuff(&Play->NetBuf,ReadReady,WriteReady,FALSE, | |
+ &ReadOK,&WriteOK,&ErrorOK); | |
/* If we've written out everything, then ask not to be notified of | |
socket write-ready status in future */ | |
t@@ -408,7 +420,9 @@ gboolean PlayerHandleNetwork(Player *Play,gboolean ReadRea… | |
SocketWriteTestPt) { | |
(*SocketWriteTestPt)(Play,FALSE); | |
} | |
- return (WriteOK && ErrorOK && ReadOK); | |
+ | |
+ *DoneOK=(WriteOK && ErrorOK && ReadOK); | |
+ return DataWaiting; | |
} | |
gchar *GetWaitingPlayerMessage(Player *Play) { | |
t@@ -1103,11 +1117,21 @@ char *OpenMetaServerConnection(int *HttpSock) { | |
N_("Metaserver not running HTTP or connection denied"); | |
struct sockaddr_in HttpAddr; | |
struct hostent *he; | |
+ gchar *MetaName; | |
+ int MetaPort; | |
+ | |
+/* If a proxy is defined, connect to that. Otherwise, connect to the | |
+ metaserver directly */ | |
+ if (MetaServer.ProxyName[0]) { | |
+ MetaName=MetaServer.ProxyName; MetaPort=MetaServer.ProxyPort; | |
+ } else { | |
+ MetaName=MetaServer.Name; MetaPort=MetaServer.Port; | |
+ } | |
- if ((he=gethostbyname(MetaServer.Name))==NULL) return NoHost; | |
+ if ((he=gethostbyname(MetaName))==NULL) return NoHost; | |
if ((*HttpSock=socket(AF_INET,SOCK_STREAM,0))==-1) return NoSocket; | |
HttpAddr.sin_family=AF_INET; | |
- HttpAddr.sin_port=htons(MetaServer.HttpPort); | |
+ HttpAddr.sin_port=htons(MetaPort); | |
HttpAddr.sin_addr=*((struct in_addr *)he->h_addr); | |
memset(HttpAddr.sin_zero,0,sizeof(HttpAddr.sin_zero)); | |
if (connect(*HttpSock,(struct sockaddr *)&HttpAddr, | |
t@@ -1139,8 +1163,9 @@ void ReadMetaServerData(int HttpSock) { | |
gboolean HeaderDone; | |
ClearServerList(); | |
- buf=g_strdup_printf("GET %s?output=text&getlist=%d HTTP/1.0\n\n", | |
- MetaServer.Path,METAVERSION); | |
+ buf=g_strdup_printf("GET %s?output=text&getlist=%d HTTP/1.1\n" | |
+ "Host: %s:%d\n\n",MetaServer.Path,METAVERSION, | |
+ MetaServer.Name,MetaServer.Port); | |
send(HttpSock,buf,strlen(buf),0); | |
g_free(buf); | |
HeaderDone=FALSE; | |
diff --git a/src/message.h b/src/message.h | |
t@@ -120,6 +120,7 @@ char *StartConnect(int *fd,gchar *RemoteHost,unsigned Remo… | |
char *FinishConnect(int fd); | |
void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator); | |
+gboolean IsNetworkBufferActive(NetworkBuffer *NetBuf); | |
void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int fd); | |
gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,gchar *RemoteHost, | |
unsigned RemotePort); | |
t@@ -128,9 +129,9 @@ void SetSelectForNetworkBuffer(NetworkBuffer *NetBuf,fd_se… | |
fd_set *writefds,fd_set *errorfds,int *MaxSock); | |
gboolean RespondToSelect(NetworkBuffer *NetBuf,fd_set *readfds, | |
fd_set *writefds,fd_set *errorfds, | |
- gboolean *DataWaiting); | |
+ gboolean *DoneOK); | |
gboolean PlayerHandleNetwork(Player *Play,gboolean ReadReady, | |
- gboolean WriteReady,gboolean *DataWaiting); | |
+ gboolean WriteReady,gboolean *DoneOK); | |
gboolean ReadPlayerDataFromWire(Player *Play); | |
void QueuePlayerMessageForSend(Player *Play,gchar *data); | |
gboolean WritePlayerDataToWire(Player *Play); | |
diff --git a/src/serverside.c b/src/serverside.c | |
t@@ -60,9 +60,9 @@ | |
#define METAUPDATETIME (10800) | |
/* Don't report players logging in/out to the metaserver more frequently */ | |
-/* than once every 5 minutes (so as not to overload the metaserver, or */ | |
-/* slow down our own server). */ | |
-#define METAMINTIME (300) | |
+/* than once every minute (so as not to overload the metaserver, or slow */ | |
+/* down our own server). */ | |
+#define METAMINTIME (60) | |
int TerminateRequest,ReregisterRequest; | |
t@@ -70,8 +70,9 @@ int MetaUpdateTimeout; | |
int MetaMinTimeout; | |
gboolean WantQuit=FALSE; | |
-/* Do we want to talk to the metaserver when the timeout expires? */ | |
-gboolean MetaPending=FALSE; | |
+/* Do we want to update the player details on the metaserver when the | |
+ timeout expires? */ | |
+gboolean MetaPlayerPending=FALSE; | |
GSList *FirstServer=NULL; | |
t@@ -128,55 +129,72 @@ int SendToMetaServer(char Up,int MetaSock,char *data, | |
return 1; | |
} | |
-void RegisterWithMetaServer(gboolean Up,gboolean SendData) { | |
+void RegisterWithMetaServer(gboolean Up,gboolean SendData, | |
+ gboolean RespectTimeout) { | |
/* Sends server details to the metaserver, if specified. If "Up" is */ | |
/* TRUE, informs the metaserver that the server is now accepting */ | |
/* connections - otherwise tells the metaserver that this server is */ | |
/* about to go down. If "SendData" is TRUE, then also sends game */ | |
-/* data (e.g. scores) to the metaserver. If networking is disabled, */ | |
-/* does nothing. */ | |
+/* data (e.g. scores) to the metaserver. If "RespectTimeout" is TRUE */ | |
+/* then the update is delayed if a previous update happened too */ | |
+/* recently. If networking is disabled, this function does nothing. */ | |
#if NETWORKING | |
struct HISCORE MultiScore[NUMHISCORE],AntiqueScore[NUMHISCORE]; | |
GString *text; | |
gchar *prstr; | |
+ gchar *MetaName; | |
+ int MetaPort; | |
int i; | |
- if (!MetaServer.Active || !NotifyMetaServer) return; | |
- if (MetaMinTimeout > time(NULL)) { | |
- MetaPending=TRUE; | |
+ if (!MetaServer.Active || !NotifyMetaServer || WantQuit) return; | |
+ | |
+ if (MetaMinTimeout > time(NULL) && RespectTimeout) { | |
+ g_print("Attempt to connect to metaserver too frequently - waiting for n… | |
+ MetaPlayerPending=TRUE; | |
return; | |
} | |
-/* If the previous connect hung for so long that it's still pending, then | |
+/* If the previous connect hung for so long that it's still active, then | |
break the connection before we start a new one */ | |
ShutdownNetworkBuffer(&MetaNetBuf); | |
- if (StartNetworkBufferConnect(&MetaNetBuf,"dopewars.sourceforge.net",80)) { | |
- g_print("Waiting for metaserver connect...\n"); | |
+/* If a proxy is defined, connect to that. Otherwise, connect to the | |
+ metaserver directly */ | |
+ if (MetaServer.ProxyName[0]) { | |
+ MetaName=MetaServer.ProxyName; MetaPort=MetaServer.ProxyPort; | |
+ } else { | |
+ MetaName=MetaServer.Name; MetaPort=MetaServer.Port; | |
} | |
- MetaPending=FALSE; | |
+ | |
+ if (StartNetworkBufferConnect(&MetaNetBuf,MetaName,MetaPort)) { | |
+ g_print("Waiting for metaserver connect to %s:%d...\n",MetaName,MetaPort… | |
+ } else return; | |
+ MetaPlayerPending=FALSE; | |
text=g_string_new(""); | |
- g_string_sprintf(text,"GET /metaserver.php?"); | |
+ g_string_sprintf(text,"GET %s?output=text&",MetaServer.Path); | |
- g_string_sprintfa(text,"port=%d&version=%s&players=%d&maxplay=%d&comment=%s… | |
- Port,VERSION,CountPlayers(FirstServer),MaxClients, | |
- MetaServer.Comment); | |
+ g_string_sprintfa(text,"up=%d&port=%d&version=%s&players=%d" | |
+ "&maxplay=%d&comment=%s", | |
+ Up ? 1 : 0,Port,VERSION,CountPlayers(FirstServer), | |
+ MaxClients,MetaServer.Comment); | |
- if (HighScoreRead(MultiScore,AntiqueScore)) { | |
- for (i=0;i<NUMHISCORE;i++) if (MultiScore[i].Name && MultiScore[i].Name[… | |
- g_string_sprintfa(text,"&nm[%d]=%s&dt[%d]=%s&st[%d]=%s&sc[%d]=%s", | |
- i,MultiScore[i].Name,i,MultiScore[i].Time, | |
- i,MultiScore[i].Dead ? "dead" : "alive", | |
- i,prstr=FormatPrice(MultiScore[i].Money)); | |
- g_free(prstr); | |
+ if (SendData && HighScoreRead(MultiScore,AntiqueScore)) { | |
+ for (i=0;i<NUMHISCORE;i++) { | |
+ if (MultiScore[i].Name && MultiScore[i].Name[0]) { | |
+ g_string_sprintfa(text,"&nm[%d]=%s&dt[%d]=%s&st[%d]=%s&sc[%d]=%s", | |
+ i,MultiScore[i].Name,i,MultiScore[i].Time, | |
+ i,MultiScore[i].Dead ? "dead" : "alive", | |
+ i,prstr=FormatPrice(MultiScore[i].Money)); | |
+ g_free(prstr); | |
+ } | |
} | |
} | |
g_string_sprintfa(text," HTTP/1.1"); | |
QueueMessageForSend(&MetaNetBuf,text->str); | |
- g_string_sprintf(text,"Host: dopewars.sourceforge.net\n"); | |
+ g_string_sprintf(text,"Host: %s:%d\n",MetaServer.Name,MetaServer.Port); | |
QueueMessageForSend(&MetaNetBuf,text->str); | |
g_string_free(text,TRUE); | |
t@@ -263,7 +281,7 @@ void HandleServerMessage(gchar *buf,Player *Play) { | |
if (pt!=Play && !IsCop(pt)) SendPlayerDetails(pt,Play,C_LIST… | |
} | |
SendServerMessage(NULL,C_NONE,C_ENDLIST,Play,NULL); | |
- RegisterWithMetaServer(TRUE,FALSE); | |
+ RegisterWithMetaServer(TRUE,FALSE,TRUE); | |
Play->ConnectTimeout=0; | |
if (Network) { | |
t@@ -442,7 +460,6 @@ void ClientLeftServer(Player *Play) { | |
void CleanUpServer() { | |
/* Closes down the server and frees up associated handles and memory */ | |
- if (Server) RegisterWithMetaServer(FALSE,FALSE); | |
while (FirstServer) { | |
FirstServer=RemovePlayer((Player *)FirstServer->data,FirstServer); | |
} | |
t@@ -664,10 +681,29 @@ void StartServer() { | |
} | |
#endif | |
- RegisterWithMetaServer(TRUE,TRUE); | |
+ RegisterWithMetaServer(TRUE,TRUE,FALSE); | |
} | |
-gboolean HandleServerCommand(char *string) { | |
+void RequestServerShutdown() { | |
+/* Begin the process of shutting down the server. In order to do this, */ | |
+/* we need to log out all of the currently connected players, and tell */ | |
+/* the metaserver that we're shutting down. We only shut down properly */ | |
+/* once all of these messages have been completely sent and */ | |
+/* acknowledged. (Of course, this can be overridden by a SIGINT or */ | |
+/* similar in the case of unresponsive players.) */ | |
+ RegisterWithMetaServer(FALSE,FALSE,FALSE); | |
+ BroadcastToClients(C_NONE,C_QUIT,NULL,NULL,NULL); | |
+ WantQuit=TRUE; | |
+} | |
+ | |
+gboolean IsServerShutdown() { | |
+/* Returns TRUE if the actions initiated by RequestServerShutdown() */ | |
+/* have been successfully completed, such that we can shut down the */ | |
+/* server properly now. */ | |
+ return (WantQuit && !FirstServer && !IsNetworkBufferActive(&MetaNetBuf)); | |
+} | |
+ | |
+void HandleServerCommand(char *string) { | |
GSList *list; | |
Player *tmp; | |
g_scanner_input_text(Scanner,string,strlen(string)); | |
t@@ -676,9 +712,7 @@ gboolean HandleServerCommand(char *string) { | |
strcmp(string,"?")==0) { | |
ServerHelp(); | |
} else if (strcasecmp(string,"quit")==0) { | |
- if (!FirstServer) return TRUE; | |
- WantQuit=TRUE; | |
- BroadcastToClients(C_NONE,C_QUIT,NULL,NULL,NULL); | |
+ RequestServerShutdown(); | |
} else if (strncasecmp(string,"msg:",4)==0) { | |
BroadcastToClients(C_NONE,C_MSG,string+4,NULL,NULL); | |
} else if (strcasecmp(string,"list")==0) { | |
t@@ -707,7 +741,6 @@ gboolean HandleServerCommand(char *string) { | |
g_warning(_("Unknown command - try \"help\" for help...")); | |
} | |
} | |
- return FALSE; | |
} | |
Player *HandleNewConnection() { | |
t@@ -736,7 +769,7 @@ void StopServer() { | |
RemovePidFile(); | |
} | |
-gboolean RemovePlayerFromServer(Player *Play,gboolean WantQuit) { | |
+void RemovePlayerFromServer(Player *Play,gboolean WantQuit) { | |
#ifdef GUI_SERVER | |
if (Play->InputTag) gdk_input_remove(Play->InputTag); | |
#endif | |
t@@ -747,10 +780,9 @@ gboolean RemovePlayerFromServer(Player *Play,gboolean Wan… | |
SetPlayerName(Play,NULL); | |
/* Report the new high scores (if any) and the new number of players | |
to the metaserver */ | |
- RegisterWithMetaServer(TRUE,TRUE); | |
+ RegisterWithMetaServer(TRUE,TRUE,TRUE); | |
} | |
FirstServer=RemovePlayer(Play,FirstServer); | |
- return (!FirstServer && WantQuit); | |
} | |
void ServerLoop() { | |
t@@ -765,7 +797,7 @@ void ServerLoop() { | |
struct timeval timeout; | |
int MinTimeout; | |
GString *LineBuf; | |
- gboolean EndOfLine,DataWaiting; | |
+ gboolean EndOfLine,DoneOK; | |
gchar *buf; | |
InitNetworkBuffer(&MetaNetBuf,'\n'); | |
t@@ -800,9 +832,13 @@ void ServerLoop() { | |
if (errno==EINTR) { | |
if (ReregisterRequest) { | |
ReregisterRequest=0; | |
- RegisterWithMetaServer(TRUE,TRUE); | |
+ RegisterWithMetaServer(TRUE,TRUE,FALSE); | |
continue; | |
- } else if (TerminateRequest) break; else continue; | |
+ } else if (TerminateRequest) { | |
+ RequestServerShutdown(); | |
+ if (IsServerShutdown()) break; | |
+ else continue; | |
+ } else continue; | |
} | |
perror("select"); bgetch(); break; | |
} | |
t@@ -810,41 +846,48 @@ void ServerLoop() { | |
if (FD_ISSET(0,&readfs)) { | |
if (ReadServerKey(LineBuf,&EndOfLine)==FALSE) { | |
if (isatty(0)) { | |
- break; | |
+ RequestServerShutdown(); | |
+ if (IsServerShutdown()) break; | |
} else { | |
g_message(_("Standard input closed.")); | |
InputClosed=TRUE; | |
} | |
} else if (EndOfLine) { | |
- if (HandleServerCommand(LineBuf->str)) break; | |
+ HandleServerCommand(LineBuf->str); | |
+ if (IsServerShutdown()) break; | |
g_string_truncate(LineBuf,0); | |
} | |
} | |
if (FD_ISSET(ListenSock,&readfs)) { | |
HandleNewConnection(); | |
} | |
- if (!RespondToSelect(&MetaNetBuf,&readfs,&writefs, | |
- &errorfs,&DataWaiting)) { | |
- g_warning("Metaserver connection closed"); | |
- ShutdownNetworkBuffer(&MetaNetBuf); | |
- } else if (DataWaiting) { | |
+ if (RespondToSelect(&MetaNetBuf,&readfs,&writefs,&errorfs,&DoneOK)) { | |
while ((buf=GetWaitingMessage(&MetaNetBuf))) { | |
g_print("Meta: %s\n",buf); | |
g_free(buf); | |
} | |
} | |
+ if (!DoneOK) { | |
+ g_print("Meta: (closed)\n"); | |
+ ShutdownNetworkBuffer(&MetaNetBuf); | |
+ if (IsServerShutdown()) break; | |
+ } | |
list=FirstServer; | |
while (list) { | |
nextlist=g_slist_next(list); | |
tmp=(Player *)list->data; | |
- if (tmp && !RespondToSelect(&tmp->NetBuf,&readfs,&writefs,&errorfs, | |
- &DataWaiting)) { | |
-/* The socket has been shut down, or the buffer was filled - remove player */ | |
- if (RemovePlayerFromServer(tmp,WantQuit)) break; | |
- tmp=NULL; | |
- } else if (tmp && DataWaiting) { | |
+ if (tmp) { | |
+ if (RespondToSelect(&tmp->NetBuf,&readfs,&writefs, | |
+ &errorfs,&DoneOK)) { | |
/* If any complete messages were read, process them */ | |
- HandleServerPlayer(tmp); | |
+ HandleServerPlayer(tmp); | |
+ } | |
+ if (!DoneOK) { | |
+/* The socket has been shut down, or the buffer was filled - remove player */ | |
+ RemovePlayerFromServer(tmp,WantQuit); | |
+ if (IsServerShutdown()) break; | |
+ tmp=NULL; | |
+ } | |
} | |
list=nextlist; | |
} | |
t@@ -914,30 +957,31 @@ static void GuiQuitServer() { | |
static void GuiDoCommand(GtkWidget *widget,gpointer data) { | |
gchar *text; | |
- gboolean retval; | |
text=gtk_editable_get_chars(GTK_EDITABLE(widget),0,-1); | |
gtk_editable_delete_text(GTK_EDITABLE(widget),0,-1); | |
- retval=HandleServerCommand(text); | |
+ HandleServerCommand(text); | |
g_free(text); | |
- if (retval) GuiQuitServer(); | |
+ if (IsServerShutdown()) GuiQuitServer(); | |
} | |
static void GuiHandleSocket(gpointer data,gint socket, | |
GdkInputCondition condition) { | |
Player *Play; | |
- gboolean DataWaiting; | |
+ gboolean DoneOK; | |
Play = (Player *)data; | |
/* Sanity check - is the player still around? */ | |
if (!g_slist_find(FirstServer,(gpointer)Play)) return; | |
- if (!PlayerHandleNetwork(Play,condition&GDK_INPUT_READ, | |
- condition&GDK_INPUT_WRITE,&DataWaiting)) { | |
- if (RemovePlayerFromServer(Play,WantQuit)) GuiQuitServer(); | |
- } else if (DataWaiting) { | |
+ if (PlayerHandleNetwork(Play,condition&GDK_INPUT_READ, | |
+ condition&GDK_INPUT_WRITE,&DoneOK)) { | |
HandleServerPlayer(Play); | |
GuiSetTimeouts(); /* We may have set some new timeouts */ | |
} | |
+ if (!DoneOK) { | |
+ RemovePlayerFromServer(Play,WantQuit); | |
+ if (IsServerShutdown()) GuiQuitServer(); | |
+ } | |
} | |
void SetSocketWriteTest(Player *Play,gboolean WriteTest) { | |
t@@ -964,7 +1008,8 @@ static gint GuiRequestDelete(GtkWidget *widget,GdkEvent *… | |
GuiQuitServer(); | |
} else { | |
TriedPoliteShutdown=TRUE; | |
- if (HandleServerCommand("quit")) GuiQuitServer(); | |
+ HandleServerCommand("quit"); | |
+ if (IsServerShutdown()) GuiQuitServer(); | |
} | |
return TRUE; /* Never allow automatic deletion - we handle it manually */ | |
} | |
t@@ -2384,13 +2429,12 @@ GSList *HandleTimeouts(GSList *First) { | |
time_t timenow; | |
timenow=time(NULL); | |
- if (MetaMinTimeout!=0 && MetaMinTimeout<=timenow) { | |
+ if (MetaMinTimeout<=timenow) { | |
MetaMinTimeout=0; | |
- if (MetaPending) RegisterWithMetaServer(TRUE,FALSE); | |
+ if (MetaPlayerPending) RegisterWithMetaServer(TRUE,TRUE,FALSE); | |
} | |
if (MetaUpdateTimeout!=0 && MetaUpdateTimeout<=timenow) { | |
- MetaUpdateTimeout=0; | |
- RegisterWithMetaServer(TRUE,FALSE); | |
+ RegisterWithMetaServer(TRUE,FALSE,FALSE); | |
} | |
list=First; | |
while (list) { | |
diff --git a/src/serverside.h b/src/serverside.h | |
t@@ -43,7 +43,7 @@ void BreakHandle(); | |
void ClientLeftServer(Player *Play); | |
void StartServer(); | |
void StopServer(); | |
-gboolean HandleServerCommand(char *string); | |
+void HandleServerCommand(char *string); | |
Player *HandleNewConnection(); | |
void ServerLoop(); | |
void HandleServerPlayer(Player *Play); |