tImproved error code handling - vaccinewars - be a doctor and try to vaccinate … | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit b3875bd825494c795438861554e458bd7976bb45 | |
parent abe6c14d16a9b123bbeee7c042e4f45ed8131f58 | |
Author: Ben Webb <[email protected]> | |
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(-) | |
--- | |
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 { | |
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 Terminat… | |
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,g… | |
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; | |
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… | |
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 *); |