tNew callback code for alerting clients to socket read/write-ready status - vaccinewars - be a doctor and try to vaccinate the world
(HTM) git clone git://src.adamsgaard.dk/vaccinewars
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit ce32bee1e9e077dbfb72701a7ac3b1867871fcf3
(DIR) parent a756e93c834008f86ef3bd1d41a7c943cea404e8
(HTM) Author: Ben Webb <ben@salilab.org>
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(-)
---
(DIR) 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,
(DIR) 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
(DIR) 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 ReturnOnFail) {
/* 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 dopewars -h at your\n"
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);
(DIR) 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 Code,
#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 Terminator,char StripChar) {
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,gchar *RemoteHost,
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,gchar *RemoteHost,
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 *NetBuf,gboolean ReadReady,
/* 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 ReadReady,
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 *data) {
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,unsigned Port,
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 RemotePort,
}
*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 RemotePort,
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;
}
(DIR) diff --git a/src/message.h b/src/message.h
t@@ -98,6 +98,8 @@ char *StartConnect(int *fd,gchar *RemoteHost,unsigned RemotePort,
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);
(DIR) 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,GdkInputCondition condition) {
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();
}