diff --git a/src/options.c b/src/options.c index 6cae7ee..6f36ba4 100644 --- a/src/options.c +++ b/src/options.c @@ -254,6 +254,19 @@ static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) return 1; } +int opt_get_error(lua_State *L, p_socket ps) +{ + int val = 0; + socklen_t len = sizeof(val); + if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { + lua_pushnil(L); + lua_pushstring(L, "getsockopt failed"); + return 2; + } + lua_pushstring(L, socket_strerror(val)); + return 1; +} + static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) { int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ diff --git a/src/options.h b/src/options.h index 55447f7..1cabd7d 100644 --- a/src/options.h +++ b/src/options.h @@ -42,6 +42,7 @@ int opt_get_linger(lua_State *L, p_socket ps); int opt_get_reuseaddr(lua_State *L, p_socket ps); int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); int opt_get_ip_multicast_if(lua_State *L, p_socket ps); +int opt_get_error(lua_State *L, p_socket ps); /* invokes the appropriate option handler */ int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); diff --git a/src/tcp.c b/src/tcp.c index efb92c9..6594bda 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -73,6 +73,7 @@ static t_opt optget[] = { {"reuseaddr", opt_get_reuseaddr}, {"tcp-nodelay", opt_get_tcp_nodelay}, {"linger", opt_get_linger}, + {"error", opt_get_error}, {NULL, NULL} }; diff --git a/src/udp.c b/src/udp.c index ec805b6..5945dca 100644 --- a/src/udp.c +++ b/src/udp.c @@ -85,6 +85,7 @@ static t_opt optset[] = { static t_opt optget[] = { {"ip-multicast-if", opt_get_ip_multicast_if}, {"ip-multicast-loop", opt_get_ip_multicast_loop}, + {"error", opt_get_error}, {NULL, NULL} }; diff --git a/test/test_socket_error.lua b/test/test_socket_error.lua new file mode 100644 index 0000000..9bd0bc7 --- /dev/null +++ b/test/test_socket_error.lua @@ -0,0 +1,27 @@ +local socket = require "socket" + +local host, port = "127.0.0.1", "5462" + +assert(socket.bind(host, port)):close() + +local sock = socket.tcp() +sock:settimeout(0) + +local ok, err = sock:connect(host, port) +assert(not ok) +assert('timeout' == err) + +for i = 1, 10 do + -- select pass even if socket has error + local _, rec, err = socket.select(nil, {sock}, 1) + assert('timeout' == err) + assert(not next(rec)) + err = sock:getoption("error") -- i get 'connection refused' on WinXP + if err then + print("Passed! Error is '" .. err .. "'.") + os.exit(0) + end +end + +print("Fail! No error detected!") +os.exit(1)