Introduction
Introduction Statistics Contact Development Disclaimer Help
tNon-blocking network handling abstracted out into NetworkBuffer datatype - vac…
git clone git://src.adamsgaard.dk/vaccinewars
Log
Files
Refs
README
LICENSE
---
commit 7d0b10dce7f72780b488b3df2800347731565a73
parent e694fa9cbc3214dbf38465474571e2d9209f7d23
Author: Ben Webb <[email protected]>
Date: Tue, 5 Jun 2001 02:45:07 +0000
Non-blocking network handling abstracted out into NetworkBuffer datatype
Diffstat:
M TODO | 9 ++-------
M src/AIPlayer.c | 32 +++++++++++++++--------------…
M src/curses_client.c | 31 +++++++++++++----------------…
M src/dopewars.c | 17 +++++++----------
M src/dopewars.h | 11 +++++++++--
M src/gtk_client.c | 36 +++++++++++++----------------…
M src/message.c | 170 +++++++++++++++++++++++++----…
M src/message.h | 24 ++++++++++++++++++++----
M src/serverside.c | 61 ++++++++++-------------------…
9 files changed, 240 insertions(+), 151 deletions(-)
---
diff --git a/TODO b/TODO
t@@ -1,13 +1,8 @@
-DONE - Tidy up display of high scores in GUI client
-- Revamp player-player fighting; use same system for fighting the cops and
- for fighting other players (perhaps the cops can intervene in fights);
- add SWAT teams, soldiers, etc. as dealers get more and more guns
-- Increase cops' toughness - they should kill a bitch in 50-70% of encounters
- (and damage should be cumulative)
+- Fix problem with dialogs popping up while menus are open
+- Fix problem with Jet dialog during fights
- Increase difficulty of escaping from another player - impose penalty on
running (lose drugs, free shot, destination revealed)
- Alliances/cartels - several players share cash
-- Graphical mode server? (would avoid select() problems under Win32)
- Introduce minimum/maximum players options - AI players automatically
spawned/killed to "fill the gaps" when humans leave/enter
- "Deal" option when meeting players?
diff --git a/src/AIPlayer.c b/src/AIPlayer.c
t@@ -54,7 +54,8 @@ void AIPlayerLoop() {
gchar *pt;
Player *AIPlay;
fd_set readfs,writefs;
- gboolean ReadOK,QuitRequest;
+ gboolean DataWaiting,QuitRequest;
+ int MaxSock;
AIPlay=g_new(Player,1);
FirstClient=AddPlayer(0,AIPlay,FirstClient);
t@@ -67,7 +68,7 @@ void AIPlayerLoop() {
"AI Player terminating abnormally."),_(pt));
return;
}
- AIPlay->fd=ClientSock;
+ BindNetworkBufferToSocket(&AIPlay->NetBuf,ClientSock);
InitAbilities(AIPlay);
SendAbilities(AIPlay);
t@@ -81,31 +82,28 @@ void AIPlayerLoop() {
while (1) {
FD_ZERO(&readfs);
FD_ZERO(&writefs);
- FD_SET(ClientSock,&readfs);
- if (AIPlay->WriteBuf.DataPresent) FD_SET(ClientSock,&writefs);
- if (bselect(ClientSock+1,&readfs,&writefs,NULL,NULL)==-1) {
+ MaxSock=0;
+
+ SetSelectForNetworkBuffer(&AIPlay->NetBuf,&readfs,&writefs,NULL,&MaxSock…
+
+ if (bselect(MaxSock,&readfs,&writefs,NULL,NULL)==-1) {
if (errno==EINTR) continue;
printf("Error in select\n"); exit(1);
}
- if (FD_ISSET(ClientSock,&writefs)) {
- WriteConnectionBufferToWire(AIPlay);
- }
- if (FD_ISSET(ClientSock,&readfs)) {
- QuitRequest=FALSE;
- ReadOK=ReadConnectionBufferFromWire(AIPlay);
- while ((pt=ReadFromConnectionBuffer(AIPlay))!=NULL) {
+ if (!RespondToSelect(&AIPlay->NetBuf,&readfs,&writefs,
+ NULL,&DataWaiting)) {
+ g_print(_("Connection to server lost!\n"));
+ break;
+ } else if (DataWaiting) {
+ QuitRequest=FALSE;
+ while ((pt=GetWaitingPlayerMessage(AIPlay))!=NULL) {
if (HandleAIMessage(pt,AIPlay)) {
QuitRequest=TRUE;
break;
}
}
if (QuitRequest) break;
-
- if (!ReadOK) {
- g_print(_("Connection to server lost!\n"));
- break;
- }
}
}
ShutdownNetwork();
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 ReadOK;
+ gboolean DataWaiting;
DisplayMode=DM_NONE;
QuitRequest=FALSE;
t@@ -1535,7 +1535,7 @@ static void Curses_DoGame(Player *Play) {
#if NETWORKING
if (WantNetwork) {
if (!ConnectToServer(Play)) { end_curses(); exit(1); }
- Play->fd=ClientSock;
+ BindNetworkBufferToSocket(&Play->NetBuf,ClientSock);
}
#endif /* NETWORKING */
print_status(Play,TRUE);
t@@ -1642,9 +1642,8 @@ static void Curses_DoGame(Player *Play) {
FD_ZERO(&writefs);
FD_SET(0,&readfs); MaxSock=1;
if (Client) {
- FD_SET(Play->fd,&readfs);
- if (Play->WriteBuf.DataPresent) FD_SET(Play->fd,&writefs);
- MaxSock=ClientSock+2;
+ SetSelectForNetworkBuffer(&Play->NetBuf,&readfs,&writefs,
+ NULL,&MaxSock);
}
if (bselect(MaxSock,&readfs,&writefs,NULL,NULL)==-1) {
if (errno==EINTR) {
t@@ -1653,16 +1652,9 @@ static void Curses_DoGame(Player *Play) {
}
perror("bselect"); exit(1);
}
- if (Client && FD_ISSET(Play->fd,&readfs)) {
- ReadOK=ReadConnectionBufferFromWire(Play);
-
- while ((pt=ReadFromConnectionBuffer(Play))!=NULL) {
- HandleClientMessage(pt,Play);
- g_free(pt);
- }
- if (QuitRequest) return;
-
- if (!ReadOK) {
+ if (Client) {
+ if (!RespondToSelect(&Play->NetBuf,&readfs,&writefs,
+ NULL,&DataWaiting)) {
attrset(TextAttr);
clear_line(22);
mvaddstr(22,0,_("Connection to server lost! "
t@@ -1670,11 +1662,14 @@ 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 (Client && FD_ISSET(Play->fd,&writefs)) {
- WriteConnectionBufferToWire(Play);
- }
if (FD_ISSET(0,&readfs)) {
#elif HAVE_SELECT
FD_ZERO(&readfs);
diff --git a/src/dopewars.c b/src/dopewars.c
t@@ -600,7 +600,6 @@ GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First) {
list=g_slist_next(list);
}
}
- NewPlayer->fd=-1;
NewPlayer->Name=NULL;
SetPlayerName(NewPlayer,NULL);
NewPlayer->IsAt=0;
t@@ -619,11 +618,11 @@ GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First…
NewPlayer->Health=100;
NewPlayer->CoatSize=100;
NewPlayer->Flags=0;
- NewPlayer->ReadBuf.Data=NewPlayer->WriteBuf.Data=NULL;
- NewPlayer->ReadBuf.Length=NewPlayer->WriteBuf.Length=0;
- NewPlayer->ReadBuf.DataPresent=NewPlayer->WriteBuf.DataPresent=0;
+#if NETWORKING
+ InitNetworkBuffer(&NewPlayer->NetBuf,'\n');
+ if (Server) BindNetworkBufferToSocket(&NewPlayer->NetBuf,fd);
+#endif
InitAbilities(NewPlayer);
- if (Server) NewPlayer->fd=fd;
NewPlayer->FightArray=NULL;
NewPlayer->Attacking=NULL;
return g_slist_append(First,(gpointer)NewPlayer);
t@@ -643,13 +642,11 @@ GSList *RemovePlayer(Player *Play,GSList *First) {
g_assert(First);
First=g_slist_remove(First,(gpointer)Play);
- if (Server && !IsCop(Play) && Play->fd>=0) {
- CloseSocket(Play->fd);
- }
+#if NETWORKING
+ if (!IsCop(Play)) ShutdownNetworkBuffer(&Play->NetBuf);
+#endif
ClearList(&(Play->SpyList));
ClearList(&(Play->TipList));
- g_free(Play->ReadBuf.Data);
- g_free(Play->WriteBuf.Data);
g_free(Play->Name);
g_free(Play);
return First;
diff --git a/src/dopewars.h b/src/dopewars.h
t@@ -277,6 +277,14 @@ typedef struct tagConnBuf {
int DataPresent; /* number of bytes currently in "Data" */
} ConnBuf;
+/* Handles reading and writing messages from/to a network connection */
+typedef struct tagNetworkBuffer {
+ int fd; /* File descriptor of the socket */
+ char Terminator; /* Character that separates messages */
+ ConnBuf ReadBuf; /* New data, waiting for the application */
+ ConnBuf WriteBuf; /* Data waiting to be written to the wire */
+} NetworkBuffer;
+
struct PLAYER_T {
guint ID;
int Turn;
t@@ -287,13 +295,12 @@ struct PLAYER_T {
char Flags;
gchar *Name;
Inventory *Guns,*Drugs,Bitches;
- int fd;
int EventNum,ResyncNum;
time_t FightTimeout,IdleTimeout,ConnectTimeout;
price_t DocPrice;
DopeList SpyList,TipList;
Player *OnBehalfOf;
- ConnBuf ReadBuf,WriteBuf;
+ NetworkBuffer NetBuf;
Abilities Abil;
gint InputTag;
GPtrArray *FightArray; /* If non-NULL, a list of players in a fight */
diff --git a/src/gtk_client.c b/src/gtk_client.c
t@@ -257,26 +257,20 @@ void ListInventory(GtkWidget *widget,gpointer data) {
void GetClientMessage(gpointer data,gint socket,
GdkInputCondition condition) {
gchar *pt;
- gboolean ReadOK;
- if (condition&GDK_INPUT_WRITE) {
- WriteConnectionBufferToWire(ClientData.Play);
- if (ClientData.Play->WriteBuf.DataPresent==0) {
- SetSocketWriteTest(ClientData.Play,FALSE);
- }
- }
- if (condition&GDK_INPUT_READ) {
- ReadOK=ReadConnectionBufferFromWire(ClientData.Play);
- while ((pt=ReadFromConnectionBuffer(ClientData.Play))!=NULL) {
- HandleClientMessage(pt,ClientData.Play); g_free(pt);
- }
- if (!ReadOK) {
- if (Network) gdk_input_remove(ClientData.GdkInputTag);
- if (InGame) {
+ gboolean DataWaiting;
+ if (!PlayerHandleNetwork(ClientData.Play,condition&GDK_INPUT_READ,
+ condition&GDK_INPUT_WRITE,&DataWaiting)) {
+ 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 "
- "single player mode"));
- SwitchToSinglePlayer(ClientData.Play);
- }
+ g_warning(_("Connection to server lost - switching to "
+ "single player mode"));
+ SwitchToSinglePlayer(ClientData.Play);
+ }
+ } else if (DataWaiting) {
+ while ((pt=GetWaitingPlayerMessage(ClientData.Play))!=NULL) {
+ HandleClientMessage(pt,ClientData.Play);
+ g_free(pt);
}
}
}
t@@ -284,7 +278,7 @@ 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->fd,
+ ClientData.GdkInputTag=gdk_input_add(Play->NetBuf.fd,
GDK_INPUT_READ|(WriteTest ? GDK_INPUT_WRITE : 0),
GetClientMessage,NULL);
}
t@@ -1513,7 +1507,7 @@ void StartGame() {
Player *Play;
Play=ClientData.Play=g_new(Player,1);
FirstClient=AddPlayer(0,Play,FirstClient);
- Play->fd=ClientSock;
+ BindNetworkBufferToSocket(&Play->NetBuf,ClientSock);
InitAbilities(Play);
SendAbilities(Play);
SetPlayerName(Play,ClientData.PlayerName);
diff --git a/src/message.c b/src/message.c
t@@ -147,7 +147,7 @@ void DoSendClientMessage(Player *From,char AICode,char Cod…
HandleServerMessage(text->str,ServerFrom);
#if NETWORKING
} else {
- WriteToConnectionBuffer(BufOwn,text->str);
+ QueuePlayerMessageForSend(BufOwn,text->str);
if (SocketWriteTestPt) (*SocketWriteTestPt)(BufOwn,TRUE);
}
#endif /* NETWORKING */
t@@ -193,7 +193,7 @@ void SendServerMessage(Player *From,char AICode,char Code,
}
#if NETWORKING
} else {
- WriteToConnectionBuffer(To,text->str);
+ QueuePlayerMessageForSend(To,text->str);
if (SocketWriteTestPt) (*SocketWriteTestPt)(To,TRUE);
}
#endif
t@@ -279,19 +279,117 @@ gboolean HaveAbility(Player *Play,gint Type) {
}
#if NETWORKING
-gchar *ReadFromConnectionBuffer(Player *Play) {
-/* Reads a newline-terminated message from "Play"'s read buffer. The message */
-/* is removed from the buffer, and returned as a null-terminated string (the */
-/* terminating newline is removed). If no complete message is waiting, NULL */
-/* is returned. The string is dynamically allocated, and must be g_free'd by */
-/* the caller. */
+void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator) {
+/* Initialises the passed network buffer, ready for use. Messages sent */
+/* or received on the buffered connection will be terminated by the */
+/* given character. */
+ NetBuf->fd=-1;
+ NetBuf->Terminator=Terminator;
+ NetBuf->ReadBuf.Data=NetBuf->WriteBuf.Data=NULL;
+ NetBuf->ReadBuf.Length=NetBuf->WriteBuf.Length=0;
+ NetBuf->ReadBuf.DataPresent=NetBuf->WriteBuf.DataPresent=0;
+}
+
+void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int fd) {
+/* Sets up the given network buffer to handle data being sent/received */
+/* through the given socket */
+ NetBuf->fd=fd;
+}
+
+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);
+
+ g_free(NetBuf->ReadBuf.Data);
+ g_free(NetBuf->WriteBuf.Data);
+ InitNetworkBuffer(NetBuf,NetBuf->Terminator);
+}
+
+void SetSelectForNetworkBuffer(NetworkBuffer *NetBuf,fd_set *readfds,
+ fd_set *writefds,fd_set *errorfds,int *MaxSock)…
+/* Updates the sets of read and write file descriptors to monitor */
+/* input to/output from the given network buffer. MaxSock is updated */
+/* with the highest-numbered file descriptor (plus 1) for use in a */
+/* later select() call. */
+ if (!NetBuf || NetBuf->fd<=0) return;
+ FD_SET(NetBuf->fd,readfds);
+ if (errorfds) FD_SET(NetBuf->fd,errorfds);
+ if (NetBuf->fd >= *MaxSock) *MaxSock=NetBuf->fd+1;
+ if (NetBuf->WriteBuf.DataPresent) FD_SET(NetBuf->fd,writefds);
+}
+
+static gboolean DoNetworkBufferStuff(NetworkBuffer *NetBuf,gboolean ReadReady,
+ gboolean WriteReady,gboolean ErrorReady,
+ gboolean *ReadOK,gboolean *WriteOK,
+ gboolean *ErrorOK) {
+/* Reads and writes data if the network connection is ready. Sets the */
+/* 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;
+ *ReadOK=*WriteOK=*ErrorOK=TRUE;
+
+ if (ErrorReady) *ErrorOK=FALSE;
+
+ if (WriteReady) *WriteOK=WriteDataToWire(NetBuf);
+
+ if (ReadReady) {
+ *ReadOK=ReadDataFromWire(NetBuf);
+ if (ReadOK) DataWaiting=TRUE;
+ }
+ return DataWaiting;
+}
+
+gboolean RespondToSelect(NetworkBuffer *NetBuf,fd_set *readfds,
+ fd_set *writefds,fd_set *errorfds,
+ gboolean *DataWaiting) {
+/* 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. */
+ gboolean ReadOK,WriteOK,ErrorOK;
+ *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);
+}
+
+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 ReadOK,WriteOK,ErrorOK;
+ *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 */
+ if (WriteReady && Play->NetBuf.WriteBuf.DataPresent==0 &&
+ SocketWriteTestPt) {
+ (*SocketWriteTestPt)(Play,FALSE);
+ }
+ return (WriteOK && ErrorOK && ReadOK);
+}
+
+gchar *GetWaitingPlayerMessage(Player *Play) {
+ return GetWaitingMessage(&Play->NetBuf);
+}
+
+gchar *GetWaitingMessage(NetworkBuffer *NetBuf) {
+/* Reads a complete (terminated) message from the network buffer. The */
+/* message is removed from the buffer, and returned as a null-terminated */
+/* string (the network terminator is removed). If no complete message is */
+/* waiting, NULL is returned. The string is dynamically allocated, and */
+/* so must be g_free'd by the caller. */
ConnBuf *conn;
int MessageLen;
char *SepPt;
gchar *NewMessage;
- conn=&Play->ReadBuf;
+ conn=&NetBuf->ReadBuf;
if (!conn->Data || !conn->DataPresent) return NULL;
- SepPt=memchr(conn->Data,'\n',conn->DataPresent);
+ SepPt=memchr(conn->Data,NetBuf->Terminator,conn->DataPresent);
if (!SepPt) return NULL;
*SepPt='\0';
MessageLen=SepPt-conn->Data+1;
t@@ -305,13 +403,17 @@ gchar *ReadFromConnectionBuffer(Player *Play) {
return NewMessage;
}
-gboolean ReadConnectionBufferFromWire(Player *Play) {
-/* Reads any waiting data on the TCP/IP connection for player "Play" into */
-/* the player's read buffer. Returns FALSE if the connection was closed, */
-/* or if the read buffer's maximum size was reached. */
+gboolean ReadPlayerDataFromWire(Player *Play) {
+ return ReadDataFromWire(&Play->NetBuf);
+}
+
+gboolean ReadDataFromWire(NetworkBuffer *NetBuf) {
+/* Reads any waiting data on the given network buffer's TCP/IP connection */
+/* into the read buffer. Returns FALSE if the connection was closed, or */
+/* if the read buffer's maximum size was reached. */
ConnBuf *conn;
int CurrentPosition,BytesRead;
- conn=&Play->ReadBuf;
+ conn=&NetBuf->ReadBuf;
CurrentPosition=conn->DataPresent;
while(1) {
if (CurrentPosition>=conn->Length) {
t@@ -322,7 +424,7 @@ gboolean ReadConnectionBufferFromWire(Player *Play) {
if (conn->Length>MAXREADBUF) conn->Length=MAXREADBUF;
conn->Data=g_realloc(conn->Data,conn->Length);
}
- BytesRead=recv(Play->fd,&conn->Data[CurrentPosition],
+ BytesRead=recv(NetBuf->fd,&conn->Data[CurrentPosition],
conn->Length-CurrentPosition,0);
if (BytesRead==SOCKET_ERROR) {
#ifdef CYGWIN
t@@ -340,15 +442,19 @@ gboolean ReadConnectionBufferFromWire(Player *Play) {
return TRUE;
}
-void WriteToConnectionBuffer(Player *Play,gchar *data) {
-/* Writes the null-terminated string "data" to "Play"'s connection buffer. */
-/* The message is automatically newline-terminated. Fails to write the */
-/* message without error if the buffer reaches its maximum size (although */
-/* this error will be detected when the buffer is attempted to be written */
-/* to the wire, below) */
+void QueuePlayerMessageForSend(Player *Play,gchar *data) {
+ QueueMessageForSend(&Play->NetBuf,data);
+}
+
+void QueueMessageForSend(NetworkBuffer *NetBuf,gchar *data) {
+/* Writes the null-terminated string "data" to the network buffer, ready */
+/* to be sent to the wire when the network connection becomes free. The */
+/* message is automatically terminated. Fails to write the message without */
+/* error if the buffer reaches its maximum size (although this error will */
+/* be detected when an attempt is made to write the buffer to the wire). */
int AddLength,NewLength;
ConnBuf *conn;
- conn=&Play->WriteBuf;
+ conn=&NetBuf->WriteBuf;
AddLength=strlen(data)+1;
NewLength=conn->DataPresent+AddLength;
if (NewLength > conn->Length) {
t@@ -360,21 +466,25 @@ void WriteToConnectionBuffer(Player *Play,gchar *data) {
}
memcpy(&conn->Data[conn->DataPresent],data,AddLength);
conn->DataPresent=NewLength;
- conn->Data[NewLength-1]='\n';
+ conn->Data[NewLength-1]=NetBuf->Terminator;
+}
+
+gboolean WritePlayerDataToWire(Player *Play) {
+ return WriteDataToWire(&Play->NetBuf);
}
-gboolean WriteConnectionBufferToWire(Player *Play) {
-/* Writes any waiting data in "Play"'s connection buffer to the wire. */
-/* Returns TRUE on success, or FALSE if the buffer's maximum length is */
-/* reached, or the remote end has closed the connection. */
+gboolean WriteDataToWire(NetworkBuffer *NetBuf) {
+/* Writes any waiting data in the network buffer to the wire. Returns */
+/* TRUE on success, or FALSE if the buffer's maximum length is */
+/* reached, or the remote end has closed the connection. */
ConnBuf *conn;
int CurrentPosition,BytesSent;
- conn=&Play->WriteBuf;
+ conn=&NetBuf->WriteBuf;
if (!conn->Data || !conn->DataPresent) return TRUE;
if (conn->Length==MAXWRITEBUF) return FALSE;
CurrentPosition=0;
while (CurrentPosition<conn->DataPresent) {
- BytesSent=send(Play->fd,&conn->Data[CurrentPosition],
+ BytesSent=send(NetBuf->fd,&conn->Data[CurrentPosition],
conn->DataPresent-CurrentPosition,0);
if (BytesSent==SOCKET_ERROR) {
#ifdef CYGWIN
diff --git a/src/message.h b/src/message.h
t@@ -115,10 +115,26 @@ void SendPrintMessage(Player *From,char AICode,Player *T…
void SendQuestion(Player *From,char AICode,Player *To,char *Data);
#if NETWORKING
-gchar *ReadFromConnectionBuffer(Player *Play);
-gboolean ReadConnectionBufferFromWire(Player *Play);
-void WriteToConnectionBuffer(Player *Play,gchar *data);
-gboolean WriteConnectionBufferToWire(Player *Play);
+void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator);
+void BindNetworkBufferToSocket(NetworkBuffer *NetBuf,int fd);
+void ShutdownNetworkBuffer(NetworkBuffer *NetBuf);
+void SetSelectForNetworkBuffer(NetworkBuffer *NetBuf,fd_set *readfds,
+ fd_set *writefds,fd_set *errorfds,int *MaxSock);
+gboolean RespondToSelect(NetworkBuffer *NetBuf,fd_set *readfds,
+ fd_set *writefds,fd_set *errorfds,
+ gboolean *DataWaiting);
+gboolean PlayerHandleNetwork(Player *Play,gboolean ReadReady,
+ gboolean WriteReady,gboolean *DataWaiting);
+gboolean ReadPlayerDataFromWire(Player *Play);
+void QueuePlayerMessageForSend(Player *Play,gchar *data);
+gboolean WritePlayerDataToWire(Player *Play);
+gchar *GetWaitingPlayerMessage(Player *Play);
+
+gboolean ReadDataFromWire(NetworkBuffer *NetBuf);
+gboolean WriteDataToWire(NetworkBuffer *NetBuf);
+void QueueMessageForSend(NetworkBuffer *NetBuf,gchar *data);
+gchar *GetWaitingMessage(NetworkBuffer *NetBuf);
+
gchar *bgets(int fd);
#endif /* NETWORKING */
diff --git a/src/serverside.c b/src/serverside.c
t@@ -195,7 +195,7 @@ void RegisterWithMetaServer(char Up,char SendData) {
void HandleServerPlayer(Player *Play) {
gchar *buf;
gboolean MessageRead=FALSE;
- while ((buf=ReadFromConnectionBuffer(Play))!=NULL) {
+ while ((buf=GetWaitingPlayerMessage(Play))!=NULL) {
MessageRead=TRUE;
HandleServerMessage(buf,Play);
g_free(buf);
t@@ -772,7 +772,7 @@ void ServerLoop() {
struct timeval timeout;
int MinTimeout;
GString *LineBuf;
- gboolean EndOfLine;
+ gboolean EndOfLine,DataWaiting;
StartServer();
t@@ -787,11 +787,9 @@ void ServerLoop() {
topsock=ListenSock+1;
for (list=FirstServer;list;list=g_slist_next(list)) {
tmp=(Player *)list->data;
- if (!IsCop(tmp) && tmp->fd>0) {
- FD_SET(tmp->fd,&readfs);
- if (tmp->WriteBuf.DataPresent) FD_SET(tmp->fd,&writefs);
- FD_SET(tmp->fd,&errorfs);
- if (tmp->fd>=topsock) topsock=tmp->fd+1;
+ if (!IsCop(tmp)) {
+ SetSelectForNetworkBuffer(&tmp->NetBuf,&readfs,&writefs,
+ &errorfs,&topsock);
}
}
MinTimeout=GetMinimumTimeout(FirstServer);
t@@ -831,28 +829,14 @@ void ServerLoop() {
while (list) {
nextlist=g_slist_next(list);
tmp=(Player *)list->data;
- if (tmp && FD_ISSET(tmp->fd,&errorfs)) {
- g_warning("socket error from client: %d",tmp->fd);
- CleanUpServer(); bgetch(); break;
- }
- if (tmp && FD_ISSET(tmp->fd,&writefs)) {
-/* Try and empty the player's write buffer */
- if (!WriteConnectionBufferToWire(tmp)) {
+ 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;
- }
- }
- if (tmp && FD_ISSET(tmp->fd,&readfs)) {
-/* Read any waiting data into the player's read buffer */
- if (!ReadConnectionBufferFromWire(tmp)) {
-/* remove player! */
- if (RemovePlayerFromServer(tmp,WantQuit)) break;
- tmp=NULL;
- } else {
+ if (RemovePlayerFromServer(tmp,WantQuit)) break;
+ tmp=NULL;
+ } else if (tmp && DataWaiting) {
/* If any complete messages were read, process them */
- HandleServerPlayer(tmp);
- }
+ HandleServerPlayer(tmp);
}
list=nextlist;
}
t@@ -933,31 +917,24 @@ static void GuiDoCommand(GtkWidget *widget,gpointer data…
static void GuiHandleSocket(gpointer data,gint socket,
GdkInputCondition condition) {
Player *Play;
+ gboolean DataWaiting;
Play = (Player *)data;
/* Sanity check - is the player still around? */
if (!g_slist_find(FirstServer,(gpointer)Play)) return;
- if (condition&GDK_INPUT_WRITE) {
- if (!WriteConnectionBufferToWire(Play)) {
- if (RemovePlayerFromServer(Play,WantQuit)) GuiQuitServer();
- } else if (Play->WriteBuf.DataPresent==0) {
- SetSocketWriteTest(Play,FALSE);
- }
- }
- if (condition&GDK_INPUT_READ) {
- if (!ReadConnectionBufferFromWire(Play)) {
- if (RemovePlayerFromServer(Play,WantQuit)) GuiQuitServer();
- } else {
- HandleServerPlayer(Play);
- GuiSetTimeouts(); /* We may have set some new timeouts */
- }
+ if (!PlayerHandleNetwork(Play,condition&GDK_INPUT_READ,
+ condition&GDK_INPUT_WRITE,&DataWaiting)) {
+ if (RemovePlayerFromServer(Play,WantQuit)) GuiQuitServer();
+ } else if (DataWaiting) {
+ HandleServerPlayer(Play);
+ GuiSetTimeouts(); /* We may have set some new timeouts */
}
}
void SetSocketWriteTest(Player *Play,gboolean WriteTest) {
if (Play->InputTag) gdk_input_remove(Play->InputTag);
- Play->InputTag=gdk_input_add(Play->fd,
+ Play->InputTag=gdk_input_add(Play->NetBuf.fd,
GDK_INPUT_READ|(WriteTest ? GDK_INPUT_WRITE : 0),
GuiHandleSocket,(gpointer)Play);
}
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.