tImproved error code handling - 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 b3875bd825494c795438861554e458bd7976bb45
(DIR) parent abe6c14d16a9b123bbeee7c042e4f45ed8131f58
(HTM) Author: Ben Webb <ben@salilab.org>
Date: Thu, 27 Sep 2001 15:26:59 +0000
Improved error code handling
Diffstat:
M src/dopewars.h | 16 +++++++++++++++-
M src/message.c | 107 +++++++++++++++++++++++++++++--
M src/message.h | 8 ++++++++
3 files changed, 124 insertions(+), 7 deletions(-)
---
(DIR) diff --git a/src/dopewars.h b/src/dopewars.h
t@@ -264,6 +264,20 @@ typedef struct _NetworkBuffer NetworkBuffer;
typedef void (*NBCallBack)(NetworkBuffer *NetBuf,gboolean Read,gboolean Write);
+typedef enum {
+ ET_NOERROR, ET_CUSTOM, ET_ERRNO,
+#ifdef CYGWIN
+ ET_WIN32, ET_WINSOCK
+#else
+ ET_HERRNO
+#endif
+} ErrorType;
+
+typedef struct _LastError {
+ gint code;
+ ErrorType type;
+} LastError;
+
/* Handles reading and writing messages from/to a network connection */
struct _NetworkBuffer {
int fd; /* File descriptor of the socket */
t@@ -276,7 +290,7 @@ struct _NetworkBuffer {
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 */
- gint Error; /* If non-zero, any error from the last operation */
+ LastError error; /* Any error from the last operation */
};
struct PLAYER_T {
(DIR) diff --git a/src/message.c b/src/message.c
t@@ -273,6 +273,90 @@ gboolean HaveAbility(Player *Play,gint Type) {
else return (Play->Abil.Shared[Type]);
}
+void ClearError(LastError *error) {
+ error->type=ET_NOERROR;
+}
+
+void SetError(LastError *error,ErrorType type,gint code) {
+ error->type=type;
+ error->code=code;
+}
+
+typedef struct _ErrStr {
+ int code;
+ char *string;
+} ErrStr;
+
+static ErrStr CustomErrStr[] = {
+ { E_FULLBUF,N_("Connection dropped due to full buffer") },
+ { 0,NULL }
+};
+
+#ifdef CYGWIN
+
+static ErrStr WSAErrStr[] = {
+ { WSANOTINITIALISED,N_("WinSock has not been properly initialised") },
+ { WSAENETDOWN,N_("The network subsystem has failed") },
+ { WSAEADDRINUSE,N_("Address already in use") },
+ { WSAENETDOWN,N_("Cannot reach the network") },
+ { WSAETIMEDOUT,N_("The connection timed out") },
+ { WASEMFILE,N_("Out of file descriptors") },
+ { WASENOBUFS,N_("Out of buffer space") },
+ { WSAEOPNOTSUPP,N_("Operation not supported") },
+ { WSAECONNABORTED,N_("Connection aborted due to failure") },
+ { WSAECONNRESET,N_("Connection reset by remote host") },
+ { WSAECONNREFUSED,N_("Connection refused") },
+ { WSAEAFNOSUPPORT,N_("Address family not supported") },
+ { WSAEPROTONOSUPPORT,N_("Protocol not supported") },
+ { WSAESOCKTNOSUPPORT,N_("Socket type not supported") },
+ { WSAHOST_NOT_FOUND,N_("Host not found") },
+ { WSATRY_AGAIN,N_("Temporary name server error - try again later") },
+ { WSANO_RECOVERY,N_("Failed to contact nameserver") },
+ { WSANO_DATA,N_("Valid name, but no DNS data record present") },
+ { 0,NULL }
+};
+
+#else
+
+static ErrStr DNSErrStr[] = {
+ { HOST_NOT_FOUND,N_("Host not found") },
+ { TRY_AGAIN,N_("Temporary name server error - try again later") },
+ { 0,NULL }
+};
+
+#endif
+
+static gchar *LookupErrorCode(gint code,ErrStr *str,gchar *fallbackstr) {
+ for (;str && str->string;str++) {
+ if (code==str->code) return g_strdup(_(str->string));
+ }
+ return g_strdup_printf(fallbackstr,code);
+}
+
+gchar *GetErrorString(LastError *error) {
+ switch (error->type) {
+ case ET_NOERROR:
+ return NULL;
+ case ET_CUSTOM:
+ return LookupErrorCode(error->code,CustomErrStr,
+ _("Unknown internal error code %d"));
+ case ET_ERRNO:
+ return g_strdup(strerror(error->code));
+#ifdef CYGWIN
+ case ET_WIN32:
+ return NULL;
+ case ET_WINSOCK:
+ return LookupErrorCode(error->code,WSAErrStr,
+ _("Unknown WinSock error code %d"));
+#else
+ case ET_HERRNO:
+ return LookupErrorCode(error->code,DNSErrStr,
+ _("Unknown DNS error code %d"));
+#endif
+ }
+ return NULL;
+}
+
#if NETWORKING
static void NetBufCallBack(NetworkBuffer *NetBuf) {
if (NetBuf && NetBuf->CallBack) {
t@@ -300,7 +384,7 @@ void InitNetworkBuffer(NetworkBuffer *NetBuf,char Terminator,char StripChar) {
NetBuf->ReadBuf.Length=NetBuf->WriteBuf.Length=0;
NetBuf->ReadBuf.DataPresent=NetBuf->WriteBuf.DataPresent=0;
NetBuf->WaitConnect=FALSE;
- NetBuf->Error=0;
+ ClearError(&NetBuf->error);
}
void SetNetworkBufferCallBack(NetworkBuffer *NetBuf,NBCallBack CallBack,
t@@ -335,6 +419,7 @@ gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,gchar *RemoteHost,
retval=StartConnect(&NetBuf->fd,RemoteHost,RemotePort,TRUE);
if (retval) {
+ SetError(&NetBuf->error,ET_HERRNO,h_errno);
ConnectError(retval); return FALSE;
} else {
NetBuf->WaitConnect=TRUE;
t@@ -537,6 +622,7 @@ gboolean ReadDataFromWire(NetworkBuffer *NetBuf) {
while(1) {
if (CurrentPosition>=conn->Length) {
if (conn->Length==MAXREADBUF) {
+ SetError(&NetBuf->error,ET_CUSTOM,E_FULLBUF);
return FALSE; /* drop connection */
}
if (conn->Length==0) conn->Length=256; else conn->Length*=2;
t@@ -549,10 +635,13 @@ gboolean ReadDataFromWire(NetworkBuffer *NetBuf) {
Error = GetSocketError();
#ifdef CYGWIN
if (Error==WSAEWOULDBLOCK) break;
- else { NetBuf->Error = Error; return FALSE; }
+ else { SetError(&NetBuf->error,ET_WINSOCK,Error); return FALSE; }
#else
if (Error==EAGAIN) break;
- else if (Error!=EINTR) { NetBuf->Error = Error; return FALSE; }
+ else if (Error!=EINTR) {
+ SetError(&NetBuf->error,ET_ERRNO,Error);
+ return FALSE;
+ }
#endif
} else if (BytesRead==0) {
return FALSE;
t@@ -607,7 +696,10 @@ gboolean WriteDataToWire(NetworkBuffer *NetBuf) {
int CurrentPosition,BytesSent,Error;
conn=&NetBuf->WriteBuf;
if (!conn->Data || !conn->DataPresent) return TRUE;
- if (conn->Length==MAXWRITEBUF) return FALSE;
+ if (conn->Length==MAXWRITEBUF) {
+ SetError(&NetBuf->error,ET_CUSTOM,E_FULLBUF);
+ return FALSE;
+ }
CurrentPosition=0;
while (CurrentPosition<conn->DataPresent) {
BytesSent=send(NetBuf->fd,&conn->Data[CurrentPosition],
t@@ -616,10 +708,13 @@ gboolean WriteDataToWire(NetworkBuffer *NetBuf) {
Error=GetSocketError();
#ifdef CYGWIN
if (Error==WSAEWOULDBLOCK) break;
- else { NetBuf->Error=Error; return FALSE; }
+ else { SetError(&NetBuf->error,ET_WINSOCK,Error); return FALSE; }
#else
if (Error==EAGAIN) break;
- else if (Error!=EINTR) { NetBuf->Error=Error; return FALSE; }
+ else if (Error!=EINTR) {
+ SetError(&NetBuf->error,ET_ERRNO,Error);
+ return FALSE;
+ }
#endif
} else {
CurrentPosition+=BytesSent;
(DIR) diff --git a/src/message.h b/src/message.h
t@@ -49,6 +49,10 @@ typedef enum {
C_MEETPLAYER, C_FIGHT, C_FIGHTDONE
} AICode;
+typedef enum {
+ E_FULLBUF
+} CustomError;
+
#define DT_LOCATION 'A'
#define DT_DRUG 'B'
#define DT_GUN 'C'
t@@ -138,6 +142,10 @@ gboolean HandleWaitingMetaServerData(HttpConnection *conn,GSList **listpt);
void ClearServerList(GSList **listpt);
#endif /* NETWORKING */
+void ClearError(LastError *error);
+void SetError(LastError *error,ErrorType type,gint code);
+gchar *GetErrorString(LastError *error);
+
extern GSList *FirstClient;
extern void (*ClientMessageHandlerPt) (char *,Player *);