/****************************************************************************** * Author: Alexey Melnichuk * * Copyright (C) 2014 Alexey Melnichuk * * Licensed according to the included 'LICENSE' document * * This file is part of lua-lcurl library. ******************************************************************************/ #include "lcurl.h" #include "lcerror.h" #include #include "lcutils.h" #define LCURL_ERROR_NAME LCURL_PREFIX" Error" static const char *LCURL_ERROR = LCURL_ERROR_NAME; #define LCURL_ERROR_EASY_NAME "CURL-EASY" #define LCURL_ERROR_MULTI_NAME "CURL-MULTI" #define LCURL_ERROR_SHARE_NAME "CURL-SHARE" #define LCURL_ERROR_FORM_NAME "CURL-FORM" typedef struct lcurl_error_tag{ int tp; int no; }lcurl_error_t; //{ static const char* lcurl_err_easy_mnemo(int err){ #define ERR_ENTRY(E) case CURLE_##E: return #E; switch (err){ #include "lcerr_easy.h" } return "UNKNOWN"; #undef ERR_ENTRY } static const char* lcurl_err_multi_mnemo(int err){ #define ERR_ENTRY(E) case CURLM_##E: return #E; switch (err){ #include "lcerr_multi.h" } return "UNKNOWN"; #undef ERR_ENTRY } static const char* lcurl_err_share_mnemo(int err){ #define ERR_ENTRY(E) case CURLSHE_##E: return #E; switch (err){ #include "lcerr_share.h" } return "UNKNOWN"; #undef ERR_ENTRY } static const char* lcurl_err_form_mnemo(int err){ #define ERR_ENTRY(E) case CURL_FORMADD_##E: return #E; switch (err){ #include "lcerr_form.h" } return "UNKNOWN"; #undef ERR_ENTRY } static const char* _lcurl_err_mnemo(int tp, int err){ switch(tp){ case LCURL_ERROR_EASY : return lcurl_err_easy_mnemo (err); case LCURL_ERROR_MULTI: return lcurl_err_multi_mnemo(err); case LCURL_ERROR_SHARE: return lcurl_err_share_mnemo(err); case LCURL_ERROR_FORM : return lcurl_err_form_mnemo (err); } assert(0); return ""; } static const char* _lcurl_err_msg(int tp, int err){ switch(tp){ case LCURL_ERROR_EASY : return curl_easy_strerror (err); case LCURL_ERROR_MULTI: return curl_multi_strerror(err); case LCURL_ERROR_SHARE: return curl_share_strerror(err); case LCURL_ERROR_FORM : return lcurl_err_form_mnemo(err); } assert(0); return ""; } static const char* _lcurl_err_category_name(int tp){ assert( (tp == LCURL_ERROR_EASY ) || (tp == LCURL_ERROR_MULTI) || (tp == LCURL_ERROR_SHARE) || (tp == LCURL_ERROR_FORM ) || 0 ); switch(tp){ case LCURL_ERROR_EASY: { static const char *name = LCURL_ERROR_EASY_NAME; return name; } case LCURL_ERROR_MULTI: { static const char *name = LCURL_ERROR_MULTI_NAME; return name; } case LCURL_ERROR_SHARE: { static const char *name = LCURL_ERROR_SHARE_NAME; return name; } case LCURL_ERROR_FORM: { static const char *name = LCURL_ERROR_FORM_NAME; return name; } } assert(0); return NULL; } static void _lcurl_err_pushstring(lua_State *L, int tp, int err){ lua_pushfstring(L, "[%s][%s] %s (%d)", _lcurl_err_category_name(tp), _lcurl_err_mnemo(tp, err), _lcurl_err_msg(tp, err), err ); } //} //{ int lcurl_error_create(lua_State *L, int error_type, int no){ lcurl_error_t *err = lutil_newudatap(L, lcurl_error_t, LCURL_ERROR); assert( (error_type == LCURL_ERROR_EASY ) || (error_type == LCURL_ERROR_MULTI) || (error_type == LCURL_ERROR_SHARE) || (error_type == LCURL_ERROR_FORM ) || 0 ); err->tp = error_type; err->no = no; return 1; } static lcurl_error_t *lcurl_geterror_at(lua_State *L, int i){ lcurl_error_t *err = (lcurl_error_t *)lutil_checkudatap (L, i, LCURL_ERROR); luaL_argcheck (L, err != NULL, 1, LCURL_PREFIX"error object expected"); return err; } #define lcurl_geterror(L) lcurl_geterror_at((L),1) static int lcurl_err_no(lua_State *L){ lcurl_error_t *err = lcurl_geterror(L); lua_pushinteger(L, err->no); return 1; } static int lcurl_err_msg(lua_State *L){ lcurl_error_t *err = lcurl_geterror(L); lua_pushstring(L, _lcurl_err_msg(err->tp, err->no)); return 1; } static int lcurl_err_mnemo(lua_State *L){ lcurl_error_t *err = lcurl_geterror(L); lua_pushstring(L, _lcurl_err_mnemo(err->tp, err->no)); return 1; } static int lcurl_err_tostring(lua_State *L){ lcurl_error_t *err = lcurl_geterror(L); _lcurl_err_pushstring(L, err->tp, err->no); return 1; } static int lcurl_err_equal(lua_State *L){ lcurl_error_t *lhs = lcurl_geterror_at(L, 1); lcurl_error_t *rhs = lcurl_geterror_at(L, 2); lua_pushboolean(L, ((lhs->no == rhs->no)&&(lhs->tp == rhs->tp))?1:0); return 1; } static int lcurl_err_category(lua_State *L){ lcurl_error_t *err = lcurl_geterror(L); lua_pushstring(L, _lcurl_err_category_name(err->tp)); return 1; } //} //{ int lcurl_fail_ex(lua_State *L, int mode, int error_type, int code){ if(mode == LCURL_ERROR_RETURN){ lua_pushnil(L); lcurl_error_create(L, error_type, code); return 2; } #if LUA_VERSION_NUM >= 502 // lua 5.2 lcurl_error_create(L, error_type, code); #else _lcurl_err_pushstring(L, error_type, code); #endif assert(LCURL_ERROR_RAISE == mode); return lua_error(L); } int lcurl_fail(lua_State *L, int error_type, int code){ return lcurl_fail_ex(L, LCURL_ERROR_RETURN, error_type, code); } //} static const int ERROR_CATEGORIES[] = { LCURL_ERROR_EASY, LCURL_ERROR_MULTI, LCURL_ERROR_SHARE, LCURL_ERROR_FORM, }; static const char* ERROR_CATEGORIES_NAME[] = { LCURL_ERROR_EASY_NAME, LCURL_ERROR_MULTI_NAME, LCURL_ERROR_SHARE_NAME, LCURL_ERROR_FORM_NAME, NULL }; int lcurl_error_new(lua_State *L){ int tp, no = luaL_checkint(L, 2); if (lua_isnumber(L, 1)){ tp = luaL_checkint(L, 2); } else{ tp = luaL_checkoption(L, 1, NULL, ERROR_CATEGORIES_NAME); tp = ERROR_CATEGORIES[tp]; } //! @todo checks error type value lcurl_error_create(L, tp, no); return 1; } static const struct luaL_Reg lcurl_err_methods[] = { {"no", lcurl_err_no }, {"msg", lcurl_err_msg }, {"name", lcurl_err_mnemo }, {"mnemo", lcurl_err_mnemo }, {"cat", lcurl_err_category }, {"category", lcurl_err_category }, {"__tostring", lcurl_err_tostring }, {"__eq", lcurl_err_equal }, {NULL,NULL} }; static const lcurl_const_t lcurl_error_codes[] = { #define ERR_ENTRY(N) { "E_"#N, CURLE_##N }, #include "lcerr_easy.h" #undef ERR_ENTRY /* libcurl rename CURLE_FTP_WEIRD_SERVER_REPLY to CURLE_WEIRD_SERVER_REPLY in version 7.51.0*/ /* we can not have both codes in general because we have to be able convern error number to error name*/ /* so we use newest name but add error code as alias.*/ #if LCURL_CURL_VER_GE(7,51,0) { "E_FTP_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY }, #else { "E_WEIRD_SERVER_REPLY", CURLE_FTP_WEIRD_SERVER_REPLY }, #endif #define ERR_ENTRY(N) { "E_MULTI_"#N, CURLM_##N }, #include "lcerr_multi.h" #undef ERR_ENTRY #define ERR_ENTRY(N) { "E_SHARE_"#N, CURLSHE_##N }, #include "lcerr_share.h" #undef ERR_ENTRY #define ERR_ENTRY(N) { "E_FORM_"#N, CURL_FORMADD_##N }, #include "lcerr_form.h" #undef ERR_ENTRY {NULL, 0} }; void lcurl_error_initlib(lua_State *L, int nup){ if(!lutil_createmetap(L, LCURL_ERROR, lcurl_err_methods, nup)) lua_pop(L, nup); lua_pop(L, 1); lcurl_util_set_const(L, lcurl_error_codes); lua_pushstring(L, _lcurl_err_category_name(LCURL_ERROR_EASY ));lua_setfield(L, -2, "ERROR_EASY" ); lua_pushstring(L, _lcurl_err_category_name(LCURL_ERROR_MULTI ));lua_setfield(L, -2, "ERROR_MULTI"); lua_pushstring(L, _lcurl_err_category_name(LCURL_ERROR_SHARE ));lua_setfield(L, -2, "ERROR_SHARE"); lua_pushstring(L, _lcurl_err_category_name(LCURL_ERROR_FORM ));lua_setfield(L, -2, "ERROR_FORM" ); }