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 *);