tNew callback code for alerting clients to socket read/write-ready status - vac… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit ce32bee1e9e077dbfb72701a7ac3b1867871fcf3 | |
parent a756e93c834008f86ef3bd1d41a7c943cea404e8 | |
Author: Ben Webb <[email protected]> | |
Date: Wed, 12 Sep 2001 18:04:06 +0000 | |
New callback code for alerting clients to socket read/write-ready status | |
Diffstat: | |
M src/curses_client.c | 1 - | |
M src/dopewars.h | 12 +++++++++--- | |
M src/gtk_client.c | 132 ++++++++++++++++++-----------… | |
M src/message.c | 109 +++++++++++++++++++++--------… | |
M src/message.h | 3 ++- | |
M src/serverside.c | 57 ++++++++++++++---------------… | |
6 files changed, 191 insertions(+), 123 deletions(-) | |
--- | |
diff --git a/src/curses_client.c b/src/curses_client.c | |
t@@ -1849,7 +1849,6 @@ void CursesLoop(void) { | |
/* Set up message handlers */ | |
ClientMessageHandlerPt = HandleClientMessage; | |
- SocketWriteTestPt = NULL; | |
/* Make the GLib log messages display nicely */ | |
g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING, | |
diff --git a/src/dopewars.h b/src/dopewars.h | |
t@@ -259,16 +259,23 @@ typedef struct tagConnBuf { | |
int DataPresent; /* number of bytes currently in "Data" */ | |
} ConnBuf; | |
+typedef struct _NetworkBuffer NetworkBuffer; | |
+ | |
+typedef void (*NBCallBack)(NetworkBuffer *NetBuf,gboolean Read,gboolean Write); | |
+ | |
/* Handles reading and writing messages from/to a network connection */ | |
-typedef struct tagNetworkBuffer { | |
+struct _NetworkBuffer { | |
int fd; /* File descriptor of the socket */ | |
gint InputTag; /* Identifier for gdk_input routines */ | |
+ NBCallBack CallBack; /* Function called when the socket read- or | |
+ write-able status changes */ | |
+ gpointer CallBackData; /* Data accessible to the callback function */ | |
char Terminator; /* Character that separates messages */ | |
char StripChar; /* Character that should be removed from messages */ | |
ConnBuf ReadBuf; /* New data, waiting for the application */ | |
ConnBuf WriteBuf; /* Data waiting to be written to the wire */ | |
gboolean WaitConnect; /* TRUE if a non-blocking connect is in progress */ | |
-} NetworkBuffer; | |
+}; | |
struct PLAYER_T { | |
guint ID; | |
t@@ -287,7 +294,6 @@ struct PLAYER_T { | |
Player *OnBehalfOf; | |
NetworkBuffer NetBuf; | |
Abilities Abil; | |
- gint InputTag; | |
GPtrArray *FightArray; /* If non-NULL, a list of players in a fight */ | |
Player *Attacking; /* The player that this player is attacking */ | |
gint CopIndex; /* if >0, then this player is a cop, described | |
diff --git a/src/gtk_client.c b/src/gtk_client.c | |
t@@ -68,7 +68,6 @@ struct ClientDataStruct { | |
struct InventoryWidgets Drug,Gun,InvenDrug,InvenGun; | |
GtkWidget *JetButton,*vbox,*PlayerList,*TalkList; | |
guint JetAccel; | |
- gint GdkInputTag; | |
}; | |
static struct ClientDataStruct ClientData; | |
t@@ -96,7 +95,9 @@ static void UpdateMenus(void); | |
#ifdef NETWORKING | |
static void GetClientMessage(gpointer data,gint socket, | |
GdkInputCondition condition); | |
-static void SetSocketWriteTest(Player *Play,gboolean WriteTest); | |
+static void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write); | |
+static void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read, | |
+ gboolean Write); | |
#endif | |
static void HandleClientMessage(char *buf,Player *Play); | |
t@@ -276,7 +277,6 @@ void GetClientMessage(gpointer data,gint socket, | |
} | |
} | |
if (!DoneOK) { | |
- if (Network) gdk_input_remove(ClientData.GdkInputTag); | |
if (InGame) { | |
/* The network connection to the server was dropped unexpectedly */ | |
g_warning(_("Connection to server lost - switching to " | |
t@@ -287,12 +287,14 @@ void GetClientMessage(gpointer data,gint socket, | |
} | |
} | |
-void SetSocketWriteTest(Player *Play,gboolean WriteTest) { | |
- if (Network) { | |
- if (ClientData.GdkInputTag) gdk_input_remove(ClientData.GdkInputTag); | |
- ClientData.GdkInputTag=gdk_input_add(Play->NetBuf.fd, | |
- GDK_INPUT_READ|(WriteTest ? GDK_INPUT_WRITE : 0), | |
- GetClientMessage,NULL); | |
+void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { | |
+ if (NetBuf->InputTag) gdk_input_remove(NetBuf->InputTag); | |
+ NetBuf->InputTag=0; | |
+ if (Read || Write) { | |
+ NetBuf->InputTag=gdk_input_add(NetBuf->fd, | |
+ (Read ? GDK_INPUT_READ : 0) | | |
+ (Write ? GDK_INPUT_WRITE : 0), | |
+ GetClientMessage,NULL); | |
} | |
} | |
#endif /* NETWORKING */ | |
t@@ -327,15 +329,15 @@ void HandleClientMessage(char *pt,Player *Play) { | |
case C_FIGHTPRINT: | |
DisplayFightMessage(Data); break; | |
case C_PUSH: | |
- if (Network) gdk_input_remove(ClientData.GdkInputTag); | |
/* The server admin has asked us to leave - so warn the user, and do so */ | |
+ ShutdownNetworkBuffer(&Play->NetBuf); | |
g_warning(_("You have been pushed from the server.")); | |
SwitchToSinglePlayer(Play); | |
UpdateMenus(); | |
break; | |
case C_QUIT: | |
- if (Network) gdk_input_remove(ClientData.GdkInputTag); | |
/* The server has sent us notice that it is shutting down */ | |
+ ShutdownNetworkBuffer(&Play->NetBuf); | |
g_warning(_("The server has terminated.")); | |
SwitchToSinglePlayer(Play); | |
UpdateMenus(); | |
t@@ -1544,7 +1546,10 @@ void StartGame(void) { | |
Play=ClientData.Play=g_new(Player,1); | |
FirstClient=AddPlayer(0,Play,FirstClient); | |
#ifdef NETWORKING | |
- BindNetworkBufferToSocket(&Play->NetBuf,ClientSock); | |
+ if (Network) { | |
+ BindNetworkBufferToSocket(&Play->NetBuf,ClientSock); | |
+ SetNetworkBufferCallBack(&Play->NetBuf,SocketStatus,NULL); | |
+ } | |
#endif | |
InitAbilities(Play); | |
SendAbilities(Play); | |
t@@ -1552,9 +1557,6 @@ void StartGame(void) { | |
SendNullClientMessage(Play,C_NONE,C_NAME,NULL,ClientData.PlayerName); | |
InGame=TRUE; | |
UpdateMenus(); | |
-#ifdef NETWORKING | |
- if (Network) SetSocketWriteTest(Play,TRUE); | |
-#endif | |
gtk_widget_show_all(ClientData.vbox); | |
UpdatePlayerLists(); | |
} | |
t@@ -1565,7 +1567,6 @@ void EndGame(void) { | |
gtk_editable_delete_text(GTK_EDITABLE(ClientData.messages),0,-1); | |
g_free(ClientData.PlayerName); | |
ClientData.PlayerName=g_strdup(GetPlayerName(ClientData.Play)); | |
- if (Network) gdk_input_remove(ClientData.GdkInputTag); | |
ShutdownNetwork(); | |
UpdatePlayerLists(); | |
CleanUpServer(); | |
t@@ -1735,10 +1736,6 @@ char GtkLoop(int *argc,char **argv[],gboolean ReturnOnF… | |
/* Set up message handlers */ | |
ClientMessageHandlerPt = HandleClientMessage; | |
- ClientData.GdkInputTag=0; | |
-#ifdef NETWORKING | |
- SocketWriteTestPt = SetSocketWriteTest; | |
-#endif | |
/* Have the GLib log messages pop up in a nice dialog box */ | |
g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING, | |
t@@ -1905,10 +1902,25 @@ _("\nFor information on the command line options, type… | |
struct StartGameStruct { | |
GtkWidget *dialog,*name,*hostname,*port,*antique,*status,*metaserv; | |
- gint ConnectTag,MetaTag; | |
+#ifdef NETWORKING | |
+ gint ConnectTag; | |
HttpConnection *MetaConn; | |
+#endif | |
}; | |
+static gboolean GetStartGamePlayerName(struct StartGameStruct *widgets, | |
+ gchar **PlayerName) { | |
+ g_free(*PlayerName); | |
+ *PlayerName = gtk_editable_get_chars(GTK_EDITABLE(widgets->name),0,-1); | |
+ if (*PlayerName && (*PlayerName)[0]) return TRUE; | |
+ else { | |
+ GtkMessageBox(widgets->dialog, | |
+ _("You can't start the game without giving a name first!"), | |
+ _("New Game"),MB_OK); | |
+ return FALSE; | |
+ } | |
+} | |
+ | |
#ifdef NETWORKING | |
static void FinishServerConnect(gpointer data,gint socket, | |
GdkInputCondition condition) { | |
t@@ -1954,15 +1966,13 @@ static void DoConnect(struct StartGameStruct *widgets)… | |
static void ConnectToServer(GtkWidget *widget,struct StartGameStruct *widgets)… | |
gchar *text; | |
+ | |
g_free(ServerName); | |
ServerName=gtk_editable_get_chars(GTK_EDITABLE(widgets->hostname),0,-1); | |
text=gtk_editable_get_chars(GTK_EDITABLE(widgets->port),0,-1); | |
- Port=atoi(text); | |
- g_free(text); | |
- g_free(ClientData.PlayerName); | |
- ClientData.PlayerName=gtk_editable_get_chars(GTK_EDITABLE(widgets->name), | |
- 0,-1); | |
- if (!ClientData.PlayerName || !ClientData.PlayerName[0]) return; | |
+ Port=atoi(text); g_free(text); | |
+ | |
+ if (!GetStartGamePlayerName(widgets,&ClientData.PlayerName)) return; | |
DoConnect(widgets); | |
} | |
t@@ -2015,27 +2025,29 @@ static void HandleMetaSock(gpointer data,gint socket, | |
} | |
if (!DoneOK) { | |
g_print("Metaserver communicated closed\n"); | |
- gdk_input_remove(widgets->MetaTag); | |
CloseHttpConnection(widgets->MetaConn); | |
- widgets->MetaTag=0; widgets->MetaConn=NULL; | |
+ widgets->MetaConn=NULL; | |
FillMetaServerList(widgets); | |
- } else if (condition&GDK_INPUT_WRITE && | |
- !widgets->MetaConn->NetBuf.WriteBuf.DataPresent) { | |
-/* If we've written out everything, no need to test for write-ready any more */ | |
- gdk_input_remove(widgets->MetaTag); | |
- widgets->MetaTag=gdk_input_add(widgets->MetaConn->NetBuf.fd, | |
- GDK_INPUT_READ, | |
- HandleMetaSock,(gpointer)widgets); | |
+ } | |
+} | |
+ | |
+void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { | |
+ if (NetBuf->InputTag) gdk_input_remove(NetBuf->InputTag); | |
+ NetBuf->InputTag=0; | |
+ if (Read || Write) { | |
+ NetBuf->InputTag=gdk_input_add(NetBuf->fd, | |
+ (Read ? GDK_INPUT_READ : 0) | | |
+ (Write ? GDK_INPUT_WRITE : 0), | |
+ HandleMetaSock,NetBuf->CallBackData); | |
} | |
} | |
static void UpdateMetaServerList(GtkWidget *widget, | |
struct StartGameStruct *widgets) { | |
GtkWidget *metaserv; | |
- if (widgets->MetaTag) { | |
- gdk_input_remove(widgets->MetaTag); | |
+ if (widgets->MetaConn) { | |
CloseHttpConnection(widgets->MetaConn); | |
- widgets->MetaTag=0; widgets->MetaConn=NULL; | |
+ widgets->MetaConn=NULL; | |
} | |
widgets->MetaConn = OpenMetaHttpConnection(); | |
t@@ -2044,9 +2056,8 @@ static void UpdateMetaServerList(GtkWidget *widget, | |
metaserv=widgets->metaserv; | |
gtk_clist_clear(GTK_CLIST(metaserv)); | |
ClearServerList(); | |
- widgets->MetaTag = gdk_input_add(widgets->MetaConn->NetBuf.fd, | |
- GDK_INPUT_READ|GDK_INPUT_WRITE, | |
- HandleMetaSock,(gpointer)widgets); | |
+ SetNetworkBufferCallBack(&widgets->MetaConn->NetBuf, | |
+ MetaSocketStatus,(gpointer)widgets); | |
} | |
} | |
t@@ -2064,10 +2075,8 @@ static void MetaServerConnect(GtkWidget *widget, | |
ThisServer=(ServerData *)gtk_clist_get_row_data(GTK_CLIST(clist),row); | |
AssignName(&ServerName,ThisServer->Name); | |
Port=ThisServer->Port; | |
- g_free(ClientData.PlayerName); | |
- ClientData.PlayerName=gtk_editable_get_chars(GTK_EDITABLE(widgets->name), | |
- 0,-1); | |
- if (!ClientData.PlayerName || !ClientData.PlayerName[0]) return; | |
+ | |
+ if (!GetStartGamePlayerName(widgets,&ClientData.PlayerName)) return; | |
DoConnect(widgets); | |
} | |
} | |
t@@ -2077,29 +2086,40 @@ static void StartSinglePlayer(GtkWidget *widget, | |
struct StartGameStruct *widgets) { | |
WantAntique= | |
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widgets->antique)); | |
- g_free(ClientData.PlayerName); | |
- ClientData.PlayerName=gtk_editable_get_chars(GTK_EDITABLE(widgets->name), | |
- 0,-1); | |
+ if (!GetStartGamePlayerName(widgets,&ClientData.PlayerName)) return; | |
StartGame(); | |
gtk_widget_destroy(widgets->dialog); | |
} | |
static void CloseNewGameDia(GtkWidget *widget, | |
struct StartGameStruct *widgets) { | |
+ g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING, | |
+ LogMessage,NULL); | |
#ifdef NETWORKING | |
if (widgets->ConnectTag) { | |
gdk_input_remove(widgets->ConnectTag); | |
CloseSocket(ClientSock); | |
widgets->ConnectTag=0; | |
} | |
- if (widgets->MetaTag) { | |
- gdk_input_remove(widgets->MetaTag); | |
+ if (widgets->MetaConn) { | |
CloseHttpConnection(widgets->MetaConn); | |
- widgets->MetaTag=0; widgets->MetaConn=NULL; | |
+ widgets->MetaConn=NULL; | |
} | |
#endif | |
} | |
+static void NewGameLogMessage(const gchar *log_domain,GLogLevelFlags log_level, | |
+ const gchar *message,gpointer user_data) { | |
+ struct StartGameStruct *widgets; | |
+ gchar *text; | |
+ | |
+ widgets = (struct StartGameStruct *)user_data; | |
+ | |
+ text=g_strdup_printf(_("Status: %s"),message); | |
+ gtk_label_set_text(GTK_LABEL(widgets->status),text); | |
+ g_free(text); | |
+} | |
+ | |
void NewGameDialog(void) { | |
GtkWidget *vbox,*vbox2,*hbox,*label,*entry,*notebook,*frame,*button; | |
GtkWidget *dialog; | |
t@@ -2117,10 +2137,11 @@ void NewGameDialog(void) { | |
server_titles[2]=_("Version"); | |
server_titles[3]=_("Players"); | |
server_titles[4]=_("Comment"); | |
-#endif /* NETWORKING */ | |
widgets.ConnectTag=0; | |
- widgets.MetaTag=0; widgets.MetaConn=NULL; | |
+ widgets.MetaConn=NULL; | |
+ | |
+#endif /* NETWORKING */ | |
widgets.dialog=dialog=gtk_window_new(GTK_WINDOW_DIALOG); | |
gtk_signal_connect(GTK_OBJECT(dialog),"destroy", | |
t@@ -2293,6 +2314,9 @@ void NewGameDialog(void) { | |
label=widgets.status=gtk_label_new(_("Status: Waiting for user input")); | |
gtk_box_pack_start(GTK_BOX(vbox),label,FALSE,FALSE,0); | |
+ g_log_set_handler(NULL,LogMask()|G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_WARNING, | |
+ NewGameLogMessage,(gpointer)&widgets); | |
+ | |
gtk_container_add(GTK_CONTAINER(widgets.dialog),vbox); | |
gtk_widget_grab_focus(widgets.name); | |
diff --git a/src/message.c b/src/message.c | |
t@@ -97,7 +97,6 @@ | |
GSList *FirstClient; | |
void (*ClientMessageHandlerPt) (char *,Player *) = NULL; | |
-void (*SocketWriteTestPt) (Player *,gboolean) = NULL; | |
void SendClientMessage(Player *From,AICode AI,MsgCode Code, | |
Player *To,char *Data) { | |
t@@ -148,7 +147,6 @@ void DoSendClientMessage(Player *From,AICode AI,MsgCode Co… | |
#if NETWORKING | |
} else { | |
QueuePlayerMessageForSend(BufOwn,text->str); | |
- if (SocketWriteTestPt) (*SocketWriteTestPt)(BufOwn,TRUE); | |
} | |
#endif /* NETWORKING */ | |
g_string_free(text,TRUE); | |
t@@ -192,7 +190,6 @@ void SendServerMessage(Player *From,AICode AI,MsgCode Code, | |
#if NETWORKING | |
} else { | |
QueuePlayerMessageForSend(To,text->str); | |
- if (SocketWriteTestPt) (*SocketWriteTestPt)(To,TRUE); | |
} | |
#endif | |
g_string_free(text,TRUE); | |
t@@ -277,12 +274,26 @@ gboolean HaveAbility(Player *Play,gint Type) { | |
} | |
#if NETWORKING | |
+static void NetBufCallBack(NetworkBuffer *NetBuf) { | |
+ if (NetBuf && NetBuf->CallBack) { | |
+ (*NetBuf->CallBack)(NetBuf,!NetBuf->WaitConnect, | |
+ NetBuf->WriteBuf.DataPresent || NetBuf->WaitConnect); | |
+ } | |
+} | |
+ | |
+static void NetBufCallBackStop(NetworkBuffer *NetBuf) { | |
+ if (NetBuf && NetBuf->CallBack) (*NetBuf->CallBack)(NetBuf,FALSE,FALSE); | |
+} | |
+ | |
void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator,char StripChar) { | |
/* Initialises the passed network buffer, ready for use. Messages sent */ | |
/* or received on the buffered connection will be terminated by the */ | |
/* given character, and if they end in "StripChar" it will be removed */ | |
/* before the messages are sent or received. */ | |
NetBuf->fd=-1; | |
+ NetBuf->InputTag=0; | |
+ NetBuf->CallBack=NULL; | |
+ NetBuf->CallBackData=NULL; | |
NetBuf->Terminator=Terminator; | |
NetBuf->StripChar=StripChar; | |
NetBuf->ReadBuf.Data=NetBuf->WriteBuf.Data=NULL; | |
t@@ -291,6 +302,14 @@ void InitNetworkBuffer(NetworkBuffer *NetBuf,char Termina… | |
NetBuf->WaitConnect=FALSE; | |
} | |
+void SetNetworkBufferCallBack(NetworkBuffer *NetBuf,NBCallBack CallBack, | |
+ gpointer CallBackData) { | |
+ NetBufCallBackStop(NetBuf); | |
+ NetBuf->CallBack=CallBack; | |
+ NetBuf->CallBackData=CallBackData; | |
+ NetBufCallBack(NetBuf); | |
+} | |
+ | |
void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int fd) { | |
/* Sets up the given network buffer to handle data being sent/received */ | |
/* through the given socket */ | |
t@@ -318,6 +337,10 @@ gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,… | |
ConnectError(retval); return FALSE; | |
} else { | |
NetBuf->WaitConnect=TRUE; | |
+ | |
+/* Notify the owner if necessary to check for the connection completing */ | |
+ NetBufCallBack(NetBuf); | |
+ | |
return TRUE; | |
} | |
} | |
t@@ -325,10 +348,14 @@ gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf… | |
void ShutdownNetworkBuffer(NetworkBuffer *NetBuf) { | |
/* Frees the network buffer's data structures (leaving it in the */ | |
/* 'initialised' state) and closes the accompanying socket. */ | |
- if (NetBuf->fd>0) CloseSocket(NetBuf->fd); | |
+ | |
+ NetBufCallBackStop(NetBuf); | |
+ | |
+ if (NetBuf->fd>=0) CloseSocket(NetBuf->fd); | |
g_free(NetBuf->ReadBuf.Data); | |
g_free(NetBuf->WriteBuf.Data); | |
+ | |
InitNetworkBuffer(NetBuf,NetBuf->Terminator,NetBuf->StripChar); | |
} | |
t@@ -355,29 +382,47 @@ static gboolean DoNetworkBufferStuff(NetworkBuffer *NetB… | |
/* various OK variables to TRUE if no errors occurred in the relevant */ | |
/* operations, and returns TRUE if data was read and is waiting for */ | |
/* processing. */ | |
- gboolean DataWaiting=FALSE; | |
+ gboolean DataWaiting=FALSE,ConnectDone=FALSE; | |
gchar *retval; | |
*ReadOK=*WriteOK=*ErrorOK=TRUE; | |
- if (NetBuf->WaitConnect) { | |
+ if (ErrorReady) *ErrorOK=FALSE; | |
+ else if (NetBuf->WaitConnect) { | |
if (WriteReady) { | |
retval=FinishConnect(NetBuf->fd); | |
+ ConnectDone=TRUE; | |
+ NetBuf->WaitConnect=FALSE; | |
+ | |
if (retval) { | |
*WriteOK=FALSE; | |
ConnectError(retval); | |
- } else NetBuf->WaitConnect=FALSE; | |
+ } | |
} | |
- return FALSE; | |
- } | |
- | |
- if (ErrorReady) *ErrorOK=FALSE; | |
+ } else { | |
+ if (WriteReady) *WriteOK=WriteDataToWire(NetBuf); | |
- if (WriteReady) *WriteOK=WriteDataToWire(NetBuf); | |
+ if (ReadReady) { | |
+ *ReadOK=ReadDataFromWire(NetBuf); | |
+ if (NetBuf->ReadBuf.DataPresent>0) DataWaiting=TRUE; | |
+ } | |
+ } | |
- if (ReadReady) { | |
- *ReadOK=ReadDataFromWire(NetBuf); | |
- if (NetBuf->ReadBuf.DataPresent>0) DataWaiting=TRUE; | |
+ if (!(*ErrorOK && *WriteOK && *ReadOK)) { | |
+/* We don't want to check the socket any more */ | |
+ NetBufCallBackStop(NetBuf); | |
+/* If there were errors, then the socket is now useless - so close it */ | |
+ CloseSocket(NetBuf->fd); | |
+ NetBuf->fd=-1; | |
+ } else if (ConnectDone) { | |
+/* If we just connected, then no need to listen for write-ready status | |
+ any more */ | |
+ NetBufCallBack(NetBuf); | |
+ } else if (WriteReady && NetBuf->WriteBuf.DataPresent==0) { | |
+/* If we wrote out everything, then tell the owner so that the socket no | |
+ longer needs to be checked for write-ready status */ | |
+ NetBufCallBack(NetBuf); | |
} | |
+ | |
return DataWaiting; | |
} | |
t@@ -426,13 +471,6 @@ gboolean PlayerHandleNetwork(Player *Play,gboolean ReadRe… | |
if (!Play) return DataWaiting; | |
DataWaiting=NetBufHandleNetwork(&Play->NetBuf,ReadReady,WriteReady,DoneOK); | |
-/* If we've written out everything, then ask not to be notified of | |
- socket write-ready status in future */ | |
- if (WriteReady && Play->NetBuf.WriteBuf.DataPresent==0 && | |
- SocketWriteTestPt) { | |
- (*SocketWriteTestPt)(Play,FALSE); | |
- } | |
- | |
return DataWaiting; | |
} | |
t@@ -547,6 +585,10 @@ void QueueMessageForSend(NetworkBuffer *NetBuf,gchar *dat… | |
memcpy(&conn->Data[conn->DataPresent],data,AddLength); | |
conn->DataPresent=NewLength; | |
conn->Data[NewLength-1]=NetBuf->Terminator; | |
+ | |
+/* If the buffer was empty before, we may need to tell the owner to check | |
+ the socket for write-ready status */ | |
+ if (NewLength==AddLength) NetBufCallBack(NetBuf); | |
} | |
gboolean WritePlayerDataToWire(Player *Play) { | |
t@@ -630,7 +672,9 @@ HttpConnection *OpenHttpConnection(gchar *HostName,unsigne… | |
g_string_sprintf(text,"User-Agent: dopewars/%s",VERSION); | |
QueueMessageForSend(&conn->NetBuf,text->str); | |
- QueueMessageForSend(&conn->NetBuf,"\n"); | |
+/* Insert a blank line between headers and body */ | |
+ QueueMessageForSend(&conn->NetBuf,""); | |
+ | |
if (conn->Body) QueueMessageForSend(&conn->NetBuf,conn->Body); | |
g_string_free(text,TRUE); | |
t@@ -1091,7 +1135,8 @@ char *StartConnect(int *fd,gchar *RemoteHost,unsigned Re… | |
} | |
*fd=socket(AF_INET,SOCK_STREAM,0); | |
if (*fd==SOCKET_ERROR) { | |
- return NoSocket; | |
+ return strerror(errno); | |
+/* return NoSocket;*/ | |
} | |
ClientAddr.sin_family=AF_INET; | |
t@@ -1108,7 +1153,8 @@ char *StartConnect(int *fd,gchar *RemoteHost,unsigned Re… | |
if (GetSocketError()==EINPROGRESS) return NULL; | |
#endif | |
CloseSocket(*fd); *fd=-1; | |
- return NoConnect; | |
+ return strerror(errno); | |
+/* return NoConnect;*/ | |
} else { | |
fcntl(*fd,F_SETFL,O_NONBLOCK); | |
} | |
t@@ -1130,10 +1176,12 @@ char *FinishConnect(int fd) { | |
optlen=sizeof(optval); | |
if (getsockopt(fd,SOL_SOCKET,SO_ERROR,&optval,&optlen)==-1) { | |
- return NoConnect; | |
+ return strerror(errno); | |
+/* return NoConnect;*/ | |
} | |
if (optval==0) return NULL; | |
- else return NoConnect; | |
+ else return strerror(optval); | |
+/* else return NoConnect;*/ | |
#endif /* CYGWIN */ | |
} | |
t@@ -1178,7 +1226,7 @@ void SwitchToSinglePlayer(Player *Play) { | |
FirstClient); | |
} | |
#ifdef NETWORKING | |
- CloseSocket(ClientSock); | |
+ ShutdownNetworkBuffer(&Play->NetBuf); | |
#endif | |
CleanUpServer(); | |
Network=Server=Client=FALSE; | |
t@@ -1197,11 +1245,6 @@ void ShutdownNetwork() { | |
while (FirstClient) { | |
FirstClient=RemovePlayer((Player *)FirstClient->data,FirstClient); | |
} | |
-#if NETWORKING | |
- if (Client) { | |
- CloseSocket(ClientSock); | |
- } | |
-#endif /* NETWORKING */ | |
Client=Network=Server=FALSE; | |
} | |
diff --git a/src/message.h b/src/message.h | |
t@@ -98,6 +98,8 @@ char *StartConnect(int *fd,gchar *RemoteHost,unsigned Remote… | |
char *FinishConnect(int fd); | |
void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator,char StripChar); | |
+void SetNetworkBufferCallBack(NetworkBuffer *NetBuf,NBCallBack CallBack, | |
+ gpointer CallBackData); | |
gboolean IsNetworkBufferActive(NetworkBuffer *NetBuf); | |
void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int fd); | |
gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,gchar *RemoteHost, | |
t@@ -138,7 +140,6 @@ gchar *bgets(int fd); | |
extern GSList *FirstClient; | |
extern void (*ClientMessageHandlerPt) (char *,Player *); | |
-extern void (*SocketWriteTestPt) (Player *,gboolean); | |
void AddURLEnc(GString *str,gchar *unenc); | |
void chomp(char *str); | |
diff --git a/src/serverside.c b/src/serverside.c | |
t@@ -90,11 +90,10 @@ GSList *FirstServer=NULL; | |
#ifdef NETWORKING | |
static GScanner *Scanner; | |
-#endif | |
/* Data waiting to be sent to/read from the metaserver */ | |
HttpConnection *MetaConn=NULL; | |
-gint MetaInputTag=0; | |
+#endif | |
/* Handle to the high score file */ | |
static FILE *ScoreFP=NULL; | |
t@@ -132,6 +131,8 @@ static int OfferObject(Player *To,gboolean ForceBitch); | |
#ifdef GUI_SERVER | |
static void GuiHandleMeta(gpointer data,gint socket, | |
GdkInputCondition condition); | |
+static void MetaSocketStatus(NetworkBuffer *NetBuf, | |
+ gboolean Read,gboolean Write); | |
#endif | |
void RegisterWithMetaServer(gboolean Up,gboolean SendData, | |
t@@ -161,10 +162,6 @@ void RegisterWithMetaServer(gboolean Up,gboolean SendData, | |
/* 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); | |
-#ifdef GUI_SERVER | |
- if (MetaInputTag) gdk_input_remove(MetaInputTag); | |
- MetaInputTag=0; | |
-#endif | |
headers=g_string_new(""); | |
body=g_string_new(""); | |
t@@ -208,7 +205,6 @@ void RegisterWithMetaServer(gboolean Up,gboolean SendData, | |
MetaConn=OpenHttpConnection(MetaServer.Name,MetaServer.Port, | |
MetaServer.ProxyName,MetaServer.ProxyPort, | |
"POST",MetaServer.Path,headers->str,body->str); | |
- g_print("Sending headers %s and body %s\n",headers->str,body->str); | |
g_string_free(headers,TRUE); | |
g_string_free(body,TRUE); | |
t@@ -217,9 +213,7 @@ void RegisterWithMetaServer(gboolean Up,gboolean SendData, | |
MetaServer.Name,MetaServer.Port); | |
} else return; | |
#ifdef GUI_SERVER | |
- MetaInputTag=gdk_input_add(MetaConn->NetBuf.fd, | |
- GDK_INPUT_READ|GDK_INPUT_WRITE, | |
- GuiHandleMeta,NULL); | |
+ SetNetworkBufferCallBack(&MetaConn->NetBuf,MetaSocketStatus,NULL); | |
#endif | |
MetaPlayerPending=FALSE; | |
t@@ -653,7 +647,6 @@ void StartServer() { | |
Network=TRUE; | |
FirstServer=NULL; | |
- SocketWriteTestPt=NULL; | |
ClientMessageHandlerPt=NULL; | |
ListenSock=socket(AF_INET,SOCK_STREAM,0); | |
if (ListenSock==SOCKET_ERROR) { | |
t@@ -800,9 +793,6 @@ void StopServer() { | |
} | |
void RemovePlayerFromServer(Player *Play) { | |
-#ifdef GUI_SERVER | |
- if (Play->InputTag) gdk_input_remove(Play->InputTag); | |
-#endif | |
if (!WantQuit && strlen(GetPlayerName(Play))>0) { | |
dopelog(2,_("%s leaves the server!"),GetPlayerName(Play)); | |
ClientLeftServer(Play); | |
t@@ -935,7 +925,7 @@ void ServerLoop() { | |
#ifdef GUI_SERVER | |
static GtkWidget *TextOutput; | |
static gint ListenTag=0; | |
-static void SetSocketWriteTest(Player *Play,gboolean WriteTest); | |
+static void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write); | |
static void GuiSetTimeouts(void); | |
static time_t NextTimeout=0; | |
static guint TimeoutTag=0; | |
t@@ -1021,15 +1011,7 @@ void GuiHandleMeta(gpointer data,gint socket,GdkInputCo… | |
if (!DoneOK) { | |
dopelog(4,"MetaServer: (closed)\n"); | |
CloseHttpConnection(MetaConn); MetaConn=NULL; | |
- gdk_input_remove(MetaInputTag); | |
- MetaInputTag=0; | |
if (IsServerShutdown()) GuiQuitServer(); | |
- } else if (condition&GDK_INPUT_WRITE && | |
- !MetaConn->NetBuf.WriteBuf.DataPresent) { | |
-/* If we've written out everything, no need to test for write-ready any more */ | |
- gdk_input_remove(MetaInputTag); | |
- MetaInputTag=gdk_input_add(MetaConn->NetBuf.fd, | |
- GDK_INPUT_READ,GuiHandleMeta,NULL); | |
} | |
} | |
t@@ -1053,11 +1035,26 @@ static void GuiHandleSocket(gpointer data,gint socket, | |
} | |
} | |
-void SetSocketWriteTest(Player *Play,gboolean WriteTest) { | |
- if (Play->InputTag) gdk_input_remove(Play->InputTag); | |
- Play->InputTag=gdk_input_add(Play->NetBuf.fd, | |
- GDK_INPUT_READ|(WriteTest ? GDK_INPUT_WRITE : 0), | |
- GuiHandleSocket,(gpointer)Play); | |
+void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { | |
+ if (NetBuf->InputTag) gdk_input_remove(NetBuf->InputTag); | |
+ NetBuf->InputTag=0; | |
+ if (Read || Write) { | |
+ NetBuf->InputTag=gdk_input_add(NetBuf->fd, | |
+ (Read ? GDK_INPUT_READ : 0) | | |
+ (Write ? GDK_INPUT_WRITE : 0), | |
+ GuiHandleSocket,NetBuf->CallBackData); | |
+ } | |
+} | |
+ | |
+void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { | |
+ if (NetBuf->InputTag) gdk_input_remove(NetBuf->InputTag); | |
+ NetBuf->InputTag=0; | |
+ if (Read || Write) { | |
+ NetBuf->InputTag=gdk_input_add(NetBuf->fd, | |
+ (Read ? GDK_INPUT_READ : 0) | | |
+ (Write ? GDK_INPUT_WRITE : 0), | |
+ GuiHandleMeta,NetBuf->CallBackData); | |
+ } | |
} | |
static void GuiNewConnect(gpointer data,gint socket, | |
t@@ -1065,8 +1062,7 @@ static void GuiNewConnect(gpointer data,gint socket, | |
Player *Play; | |
if (condition&GDK_INPUT_READ) { | |
Play=HandleNewConnection(); | |
- Play->InputTag=0; | |
- SetSocketWriteTest(Play,TRUE); | |
+ SetNetworkBufferCallBack(&Play->NetBuf,SocketStatus,(gpointer)Play); | |
} | |
} | |
t@@ -1121,7 +1117,6 @@ void GuiServerLoop() { | |
GuiServerLogMessage,NULL); | |
StartServer(); | |
- SocketWriteTestPt = SetSocketWriteTest; | |
ListenTag=gdk_input_add(ListenSock,GDK_INPUT_READ,GuiNewConnect,NULL); | |
gtk_main(); | |
} |