src/error.c
author Tero Marttila <terom@fixme.fi>
Sun, 15 Mar 2009 23:22:57 +0200
branchmodules
changeset 57 ce1accba5fc7
parent 56 942370000450
child 63 d399a1d915a3
permissions -rw-r--r--
slight cleanup to move module funcs to a 'struct module_funcs'

#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_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_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_READ_EOF,                       "read: EOF",                                ERR_EXTRA_NONE      },
    {   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_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_INVALID,                       NULL,                                       0                   }

}, _irc_proto_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      },
    {   _ERR_INVALID,                       NULL,                                       0                   }
}, _module_error_desc[] = {
    {   ERR_MODULE_OPEN,                    "module dlopen() failed",                   ERR_EXTRA_STR       },
    {   ERR_MODULE_NAME,                    "invalid module name",                      ERR_EXTRA_NONE      },
    {   ERR_MODULE_INIT_FUNC,               "invalid module init func",                 ERR_EXTRA_STR       },
    {   ERR_MODULE_CONF,                    "module_conf",                              ERR_EXTRA_STR       },
    {   _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_proto_error_desc,
    _module_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;
    
    // do we have an error_desc for it?
    if ((desc = error_lookup_desc(code)))
        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;
}