src/error.c
author Tero Marttila <terom@fixme.fi>
Sun, 03 May 2009 17:16:30 +0300
branchnew-transport
changeset 164 7847a7c3b678
parent 156 6534a4ac957b
child 178 3d357d055d67
permissions -rw-r--r--
remove ERR_READ_EOF, add more general errors, add missing _general_error_desc, and have error_name return for SUCCESS

#include "error.h"

// for the error_desc tables
#include "sock.h"
#include "sock_gnutls.h"
#include "module.h"

#include <string.h>
#include <stdio.h>

struct error_desc _core_error_desc[] = {
    {   ERR_CALLOC,                         "calloc",                                   ERR_EXTRA_NONE      },
    {   ERR_STRDUP,                         "strdup",                                   ERR_EXTRA_NONE      },
    {   ERR_SIGACTION,                      "sigaction",                                ERR_EXTRA_ERRNO     },
    {   ERR_ACCESS_READ,                    "access(R_OK)",                             ERR_EXTRA_ERRNO     },
    {   ERR_GETADDRINFO,                    "getaddrinfo",                              ERR_EXTRA_GAI       },
    {   ERR_GETADDRINFO_EMPTY,              "getaddrinfo: no results",                  ERR_EXTRA_NONE      },
    {   ERR_EVENT_NEW,                      "event_new",                                ERR_EXTRA_NONE      },
    {   ERR_EVENT_ADD,                      "event_add",                                ERR_EXTRA_NONE      },
    {   ERR_EVSQL_NEW_PQ,                   "evsql_new_pq",                             ERR_EXTRA_NONE      },
    {   ERR_EVSQL_QUERY_EXEC,               "evsql_query_exec",                         ERR_EXTRA_NONE      },
    {   ERR_CMD_OPT,                        "argv",                                     ERR_EXTRA_STR       },
    {   _ERR_INVALID,                       NULL,                                       0                   }

}, _sock_error_desc[] = {
    {   ERR_SOCKET,                         "socket",                                   ERR_EXTRA_ERRNO     },
    {   ERR_CONNECT,                        "connect",                                  ERR_EXTRA_ERRNO     },
    {   ERR_READ,                           "read",                                     ERR_EXTRA_ERRNO     },
    {   ERR_WRITE,                          "write",                                    ERR_EXTRA_ERRNO     },
    {   ERR_WRITE_EOF,                      "write: EOF",                               ERR_EXTRA_NONE      },
    {   ERR_FCNTL,                          "fcntl",                                    ERR_EXTRA_ERRNO     },
    {   ERR_CLOSE,                          "close",                                    ERR_EXTRA_ERRNO     },
    {   ERR_GETSOCKOPT,                     "getsockopt",                               ERR_EXTRA_ERRNO     },
    {   ERR_OPEN,                           "open",                                     ERR_EXTRA_ERRNO     },
    {   _ERR_INVALID,                       NULL,                                       0                   }

}, _sock_gnutls_error_desc[] = {
    {   ERR_GNUTLS_CERT_ALLOC_CRED,         "gnutls_certificate_allocate_credentials",  ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_GLOBAL_INIT,             "gnutls_global_init",                       ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_SET_DEFAULT_PRIORITY,    "gnutls_set_default_priority",              ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_CRED_SET,                "gnutls_credentials_set",                   ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_HANDSHAKE,               "gnutls_handshake",                         ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_RECORD_SEND,             "gnutls_record_send",                       ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_RECORD_RECV,             "gnutls_record_recv",                       ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_RECORD_GET_DIRECTION,    "gnutls_record_get_direction",              ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_CERT_VERIFY_PEERS2,      "gnutls_certificate_verify_peers2",         ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_CERT_VERIFY,             "X.509 Certificate verification failed",    ERR_EXTRA_STR       },
    {   ERR_GNUTLS_CERT_SET_X509_TRUST_FILE,"gnutls_certificate_set_x509_trust_file",   ERR_EXTRA_GNUTLS    },
    {   ERR_GNUTLS_CERT_SET_X509_KEY_FILE,  "gnutls_certificate_set_x509_key_file",     ERR_EXTRA_GNUTLS    },
    {   _ERR_INVALID,                       NULL,                                       0                   }

}, _irc_error_desc[] = {
    {   ERR_LINE_TOO_LONG,                  "IRC line is too long",                     ERR_EXTRA_NONE      },
    {   ERR_LINE_INVALID_TOKEN,             "Illegal token value for IRC line",         ERR_EXTRA_NONE      },
    {   ERR_INVALID_NM,                     "Invalid nickmask",                         ERR_EXTRA_NONE      },
    {   ERR_INVALID_NICK_LENGTH,            "Nickname is too long",                     ERR_EXTRA_NONE      },
    
    // extra: the name of the invalid field
    {   ERR_IRC_NET_INFO,                   "invalid irc_net_info",                     ERR_EXTRA_STR       },
    {   ERR_IRC_NET_STATE,                  "invalid irc_net state for operation",      ERR_EXTRA_NONE      },
    {   ERR_IRC_CHAN_STATE,                 "invalid irc_chan state for operation",     ERR_EXTRA_NONE      },

    {   _ERR_INVALID,                       NULL,                                       0                   }

}, _config_error_desc[] = {
    {   ERR_CONFIG_NAME,                    "unknown config option",                    ERR_EXTRA_STR       },
    {   ERR_CONFIG_TYPE,                    "invalid config type",                      ERR_EXTRA_NONE      },
    {   ERR_CONFIG_REQUIRED,                "missing required value",                   ERR_EXTRA_STR       },
    {   ERR_CONFIG_VALUE,                   "invalid value",                            ERR_EXTRA_STR       },
    {   ERR_CONFIG_PARAMS,                  "invalid number of paramters",              ERR_EXTRA_NONE      },

    {   _ERR_INVALID,                       NULL,                                       0                   }

}, _module_error_desc[] = {
    {   ERR_MODULE_NAME,                    "invalid module name",                      ERR_EXTRA_NONE      },
    {   ERR_MODULE_DUP,                     "module already loaded",                    ERR_EXTRA_NONE      },
    {   ERR_MODULE_PATH,                    "invalid module path",                      ERR_EXTRA_STR       },
    {   ERR_MODULE_OPEN,                    "module dlopen() failed",                   ERR_EXTRA_STR       },
    {   ERR_MODULE_SYM,                     "module dlsym() failed",                    ERR_EXTRA_STR       },
    {   ERR_MODULE_INIT_FUNC,               "invalid module init func",                 ERR_EXTRA_STR       },
    {   ERR_MODULE_CONF,                    "module_conf",                              ERR_EXTRA_STR       },
    {   _ERR_INVALID,                       NULL,                                       0                   }

}, _lua_error_desc[] = {
    {   ERR_LUA_MEM,                        "lua: out of memory",                       ERR_EXTRA_STR       },
    {   ERR_LUA_SYNTAX,                     "lua: syntax error",                        ERR_EXTRA_STR       },
    {   ERR_LUA_RUN,                        "lua: runtime error",                       ERR_EXTRA_STR       },
    {   ERR_LUA_ERR,                        "lua: error handling error",                ERR_EXTRA_STR       },
    {   ERR_LUA_FILE,                       "lua: error loading file",                  ERR_EXTRA_STR       },
    {   _ERR_INVALID,                       NULL,                                       0                   }

}, _pcre_error_desc[] = {
    {   ERR_PCRE_COMPILE,                   "pcre_compile",                             ERR_EXTRA_STR       },
    {   ERR_PCRE_EXEC,                      "pcre_exec",                                ERR_EXTRA_STR       },
    {   _ERR_INVALID,                       NULL,                                       0                   }
}, _general_error_desc[] = {
    {   ERR_MISC,                           "miscellaneous error",                      ERR_EXTRA_STR       },
    {   ERR_CMD_OPT,                        "invalid command line option",              ERR_EXTRA_STR       },
    {   ERR_DUP_NAME,                       "duplicate name",                           ERR_EXTRA_STR       },
    {   ERR_EOF,                            "EOF",                                      ERR_EXTRA_NONE      },
    {   ERR_MEM,                            "memory allocation error",                  ERR_EXTRA_NONE      },
    {   ERR_NOT_IMPLEMENTED,                "function not implemented",                 ERR_EXTRA_NONE      },
    {   _ERR_INVALID,                       NULL,                                       0                   }
};

/**
 * Array of error_desc tables
 */
static struct error_desc* _desc_tables[] = {
    _core_error_desc,
    _sock_error_desc,
    _sock_gnutls_error_desc,
    _irc_error_desc,
    _config_error_desc,
    _module_error_desc,
    _lua_error_desc,
    _pcre_error_desc,
    _general_error_desc,
    NULL
};

/**
 * Look up the error_desc for the given error code
 */
static const struct error_desc* error_lookup_desc (err_t code)
{
    struct error_desc **desc_table, *desc = NULL;

    // iterate over each defined error_desc array
    for (desc_table = _desc_tables; *desc_table; desc_table++) {
        for (desc = *desc_table; desc->code && desc->name; desc++) {
            // compare code
            if (desc->code == code)
                // found
                return desc;
        }
    }
    
    // not found
    return NULL;    
}

const char *error_name (err_t code)
{
    const struct error_desc *desc;
    
    if (!code)
        // no error...
        return "success";

    else if ((desc = error_lookup_desc(code)))
        // found an error_desc for it
        return desc->name;

    else
        // unknown
        return "[unknown]";
}

const char *error_msg (const struct error_info *err)
{
    static char msg[ERROR_MSG_MAXLEN];
    const struct error_desc *desc;
    
    // do we have an error_desc for it?
    if ((desc = error_lookup_desc(err->code)) == NULL)
        // ???
        snprintf(msg, ERROR_MSG_MAXLEN, "[%#.8x]: %#.8x", err->code, err->extra);
    
    else
        // intrepret .extra
        switch (desc->extra_type) {
            case ERR_EXTRA_NONE:
                // no additional info
                snprintf(msg, ERROR_MSG_MAXLEN, "%s", desc->name);
                break;
            
            case ERR_EXTRA_ERRNO:
                // strerror
                snprintf(msg, ERROR_MSG_MAXLEN, "%s: %s", desc->name, strerror(err->extra));
                break;
            
            case ERR_EXTRA_GAI:
                // gai_strerror
                snprintf(msg, ERROR_MSG_MAXLEN, "%s: %s", desc->name, gai_strerror(err->extra));
                break;
            
            case ERR_EXTRA_GNUTLS:
                // gnutls_strerror
                snprintf(msg, ERROR_MSG_MAXLEN, "%s: %s", desc->name, gnutls_strerror(err->extra));
                break;
            
            case ERR_EXTRA_STR:
                // static error message string
                snprintf(msg, ERROR_MSG_MAXLEN, "%s: %s", desc->name, err->extra_str);
                break;

            default:
                // ???
                snprintf(msg, ERROR_MSG_MAXLEN, "%s: %#.8x", desc->name, err->extra);
                break;
        }   

    // return static pointer
    return msg;
}