From c51d4acf1c2a8675a3bb043e799ff4390cef47d6 Mon Sep 17 00:00:00 2001 From: Diego Nehab Date: Sat, 16 Aug 2003 00:06:04 +0000 Subject: [PATCH] Adjusted a few inconsistencies with the manual. --- TODO | 30 +++++- etc/dict.lua | 2 +- etc/tftp.lua | 4 +- logo.ps | 210 ++++++++++++++++++++++++++++++++++++++++ samples/daytimeclnt.lua | 2 +- samples/echoclnt.lua | 12 +-- samples/echosrvr.lua | 9 +- samples/tinyirc.lua | 6 +- src/ftp.lua | 4 +- src/http.lua | 2 +- src/inet.c | 29 ++++-- src/smtp.lua | 12 +-- src/tcp.c | 182 +++++++++++++++++----------------- src/timeout.c | 2 +- src/timeout.h | 2 +- src/udp.c | 10 +- src/usocket.c | 6 +- src/wsocket.c | 6 +- test/smtptest.lua | 16 +-- test/testclnt.lua | 22 ++--- 20 files changed, 412 insertions(+), 156 deletions(-) create mode 100644 logo.ps diff --git a/TODO b/TODO index ffc1ab0..d36f6ea 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,34 @@ -- Melhorar a interface de setoptions (aceitar nada como true, por exemplo) +URL e URI eh a mesma coisa? + +Check spelling +Fazer uma página com os exemplos. +Ajeitar links pras RFCs. +Usar DFN no lugar de pra definiccoes. +Usar VAR pra argumentos? +Usar CODE pros trechos? funciona como PRE? +Usar PRE { margin-botton: 1em; } pra pular linha antes do +Trocar todos os por <... id=bla>? +Make sure all .html are STRICT 4.01 +Add license.txt. +Check RFC links. +Add lots of hyperlinks +Check all function names (must use . or :) +Make sure IPv4 goes away +The words function and method should follow the convention +Adjust dates in all files +Test the library on every system possible +Document socket.time and socket.sleep +Create the windows executable. + +Implement time critical stuff from code module in C. +Add service name translation. + +Ajeitar o protocolo da lua_socketlibopen()... + +- testar os options! - testar em várias plataformas - adicionar exemplos de expansão: pipe, local, named pipe -* Como mostrar um erro em lua_socketlibopen()... * O location do "redirect" pode ser relativo ao servidor atual (não pode, mas os servidores fazem merda...) * Ajeitar para Lua 5.0 diff --git a/etc/dict.lua b/etc/dict.lua index 9926538..933c1c8 100644 --- a/etc/dict.lua +++ b/etc/dict.lua @@ -32,7 +32,7 @@ end function dict_open() local sock, err = socket.connect("dict.org", 2628) if not sock then return nil, err end - sock:timeout(10) + sock:settimeout(10) local code, par = get_status(sock, 220) if code then return nil, code end return sock diff --git a/etc/tftp.lua b/etc/tftp.lua index d1b5594..4113034 100644 --- a/etc/tftp.lua +++ b/etc/tftp.lua @@ -82,8 +82,8 @@ function Public.get(url) local udp, err = socket.udp() if not udp then return nil, err end -- convert from name to ip if needed - parsed.host = socket.toip(parsed.host) - udp:timeout(1) + parsed.host = socket.dns.toip(parsed.host) + udp:settimeout(1) -- first packet gives data host/port to be used for data transfers retries = 0 repeat diff --git a/logo.ps b/logo.ps new file mode 100644 index 0000000..8b5809a --- /dev/null +++ b/logo.ps @@ -0,0 +1,210 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: Lua logo +%%Creator: lua@tecgraf.puc-rio.br +%%CreationDate: Wed Nov 29 19:04:04 EDT 2000 +%%BoundingBox: -45 0 1035 1080 +%%Pages: 1 +%%EndComments +%%EndProlog + +%------------------------------------------------------------------------------ +% +% Copyright (C) 1998-2000. All rights reserved. +% Graphic design by Alexandre Nakonechny (nako@openlink.com.br). +% PostScript programming by the Lua team (lua@tecgraf.puc-rio.br). +% +% Permission is hereby granted, without written agreement and without license +% or royalty fees, to use, copy, and distribute this logo for any purpose, +% including commercial applications, subject to the following conditions: +% +% * The origin of this logo must not be misrepresented; you must not +% claim that you drew the original logo. We recommend that you give credit +% to the graphics designer in all printed matter that includes the logo. +% +% * The only modification you can make is to adapt the orbiting text to +% your product name. +% +% * The logo can be used in any scale as long as the relative proportions +% of its elements are maintained. +% +%------------------------------------------------------------------------------ + +/LABEL (tekcoS) def + +%-- DO NOT CHANGE ANYTHING BELOW THIS LINE ------------------------------------ + +/PLANETCOLOR {0 0 0.5 setrgbcolor} bind def +/HOLECOLOR {1.0 setgray} bind def +/ORBITCOLOR {0.5 setgray} bind def +/LOGOFONT {/Helvetica 0.90} def +/LABELFONT {/Helvetica 0.36} def + +%------------------------------------------------------------------------------ + +/MOONCOLOR {PLANETCOLOR} bind def +/LOGOCOLOR {HOLECOLOR} bind def +/LABELCOLOR {ORBITCOLOR} bind def + +/LABELANGLE 325 def +/LOGO (Lua) def + +/DASHANGLE 10 def +/HALFDASHANGLE DASHANGLE 2 div def + +% moon radius. planet radius is 1. +/r 1 2 sqrt 2 div sub def + +/D {0 360 arc fill} bind def +/F {exch findfont exch scalefont setfont} bind def + +% place it nicely on the paper +/RESOLUTION 1024 def +RESOLUTION 2 div dup translate +RESOLUTION 2 div 2 sqrt div dup scale + +%-------------------------------------------------------------------- planet -- +PLANETCOLOR +0 0 1 D + +%---------------------------------------------------------------------- hole -- +HOLECOLOR +1 2 r mul sub dup r D + +%---------------------------------------------------------------------- moon -- +MOONCOLOR +1 1 r D + +%---------------------------------------------------------------------- logo -- +LOGOCOLOR +LOGOFONT +F +LOGO stringwidth pop 2 div neg +-0.5 moveto +LOGO show + +%------------------------------------------------------------------------------ +% based on code from Blue Book Program 10, on pages 167--169 +% available at ftp://ftp.adobe.com/pub/adobe/displaypostscript/bluebook.shar + +% str ptsize centerangle radius outsidecircletext -- +/outsidecircletext { + circtextdict begin + /radius exch def + /centerangle exch def + /ptsize exch def + /str exch def + + gsave + str radius ptsize findhalfangle + centerangle + add rotate + str + { /charcode exch def + ( ) dup 0 charcode put outsideplacechar + } forall + + grestore + end +} def + +% string radius ptsize findhalfangle halfangle +/findhalfangle { + 4 div add + exch + stringwidth pop 2 div + exch + 2 mul 3.1415926535 mul div 360 mul +} def + +/circtextdict 16 dict def +circtextdict begin + + /outsideplacechar { + /char exch def + /halfangle char radius ptsize findhalfangle def + gsave + halfangle neg rotate + 1.4 0 translate + 90 rotate + char stringwidth pop 2 div neg 0 moveto + char show + grestore + halfangle 2 mul neg rotate + } def + +end + +%--------------------------------------------------------------------- label -- +LABELFONT +F + +/LABELSIZE LABELFONT exch pop def +/LABELRADIUS LABELSIZE 3 div 1 r add sub neg 1.02 mul def + + +/HALFANGLE + LABEL LABELRADIUS LABELSIZE findhalfangle + HALFDASHANGLE div ceiling HALFDASHANGLE mul +def + +/LABELANGLE + 60 LABELANGLE HALFANGLE sub + lt + { + HALFANGLE + HALFANGLE DASHANGLE div floor DASHANGLE mul + eq + {LABELANGLE DASHANGLE div ceiling DASHANGLE mul} + {LABELANGLE HALFDASHANGLE sub DASHANGLE div round DASHANGLE mul HALFDASHANGLE add} + ifelse + } + {HALFANGLE 60 add} + ifelse +def + +LABELCOLOR +LABEL +LABELSIZE +LABELANGLE +LABELRADIUS +outsidecircletext + +%--------------------------------------------------------------------- orbit -- +ORBITCOLOR +0.03 setlinewidth +[1 r add 3.1415926535 180 div HALFDASHANGLE mul mul] 0 setdash +newpath +0 0 +1 r add +3 copy +30 +LABELANGLE HALFANGLE add +arcn +stroke +60 +LABELANGLE HALFANGLE sub +2 copy +lt {arc stroke} {4 {pop} repeat} ifelse + +%------------------------------------------------------------------ copyright -- +/COPYRIGHT +(Graphic design by A. Nakonechny. Copyright (c) 1998, All rights reserved.) +def + +LABELCOLOR +LOGOFONT +32 div +F +2 sqrt 0.99 mul +dup +neg +moveto +COPYRIGHT +90 rotate +%show + +%---------------------------------------------------------------------- done -- +showpage + +%%Trailer +%%EOF diff --git a/samples/daytimeclnt.lua b/samples/daytimeclnt.lua index 5064fff..29abe17 100644 --- a/samples/daytimeclnt.lua +++ b/samples/daytimeclnt.lua @@ -10,7 +10,7 @@ if arg then host = arg[1] or host port = arg[2] or port end -host = socket.toip(host) +host = socket.dns.toip(host) udp = socket.udp() print("Using host '" ..host.. "' and port " ..port.. "...") udp:setpeername(host, port) diff --git a/samples/echoclnt.lua b/samples/echoclnt.lua index e028b86..56bd123 100644 --- a/samples/echoclnt.lua +++ b/samples/echoclnt.lua @@ -10,17 +10,17 @@ if arg then host = arg[1] or host port = arg[2] or port end -host = socket.toip(host) +host = socket.dns.toip(host) udp, err = socket.udp() -if not udp then print(err) exit() end -err = udp:setpeername(host, port) -if err then print(err) exit() end +assert(udp, err) +ret, err = udp:setpeername(host, port) +assert(ret, err) print("Using host '" ..host.. "' and port " .. port .. "...") while 1 do line = io.read() if not line then os.exit() end - err = udp:send(line) - if err then print(err) os.exit() end + ret, err = udp:send(line) + if not ret then print(err) os.exit() end dgram, err = udp:receive() if not dgram then print(err) os.exit() end print(dgram) diff --git a/samples/echosrvr.lua b/samples/echosrvr.lua index 127ccb8..a7ed03c 100644 --- a/samples/echosrvr.lua +++ b/samples/echosrvr.lua @@ -12,11 +12,12 @@ if arg then end print("Binding to host '" ..host.. "' and port " ..port.. "...") udp, err = socket.udp() -if not udp then print(err) os.exit() end -err = udp:setsockname(host, port) -if err then print(err) os.exit() end -udp:timeout(5) +assert(udp, err) +ret, err = udp:setsockname(host, port) +assert(ret, err) +udp:settimeout(5) ip, port = udp:getsockname() +assert(ip, port) print("Waiting packets on " .. ip .. ":" .. port .. "...") while 1 do dgram, ip, port = udp:receivefrom() diff --git a/samples/tinyirc.lua b/samples/tinyirc.lua index d9cb896..b48b90a 100644 --- a/samples/tinyirc.lua +++ b/samples/tinyirc.lua @@ -15,10 +15,10 @@ end server1, error = socket.bind(host, port1) assert(server1, error) -server1:timeout(1) -- make sure we don't block in accept +server1:settimeout(1) -- make sure we don't block in accept server2, error = socket.bind(host, port2) assert(server2, error) -server2:timeout(1) -- make sure we don't block in accept +server2:settimeout(1) -- make sure we don't block in accept io.write("Servers bound\n") @@ -55,7 +55,7 @@ while 1 do io.write("Waiting for clients\n") local new = input:accept() if new then - new:timeout(1) + new:settimeout(1) io.write("Inserting client in set\n") set:insert(new) end diff --git a/src/ftp.lua b/src/ftp.lua index 9d75d2a..25226a6 100644 --- a/src/ftp.lua +++ b/src/ftp.lua @@ -224,7 +224,7 @@ function Private.port(control) local server, ctl_ip ctl_ip, answer = control:getsockname() server, answer = socket.bind(ctl_ip, 0) - server:timeout(Public.TIMEOUT) + server:settimeout(Public.TIMEOUT) local ip, p, ph, pl ip, p = server:getsockname() pl = math.mod(p, 256) @@ -404,7 +404,7 @@ function Private.open(parsed) local control, err = socket.connect(parsed.host, parsed.port) if not control then return nil, err end -- make sure we don't block forever - control:timeout(Public.TIMEOUT) + control:settimeout(Public.TIMEOUT) -- check greeting local code, answer = Private.greet(control) if not code then return nil, answer end diff --git a/src/http.lua b/src/http.lua index 4ef2c87..212e8f6 100644 --- a/src/http.lua +++ b/src/http.lua @@ -553,7 +553,7 @@ function Public.request_cb(request, response) sock, response.error = socket.connect(parsed.host, parsed.port) if not sock then return response end -- set connection timeout so that we do not hang forever - sock:timeout(Public.TIMEOUT) + sock:settimeout(Public.TIMEOUT) -- send request message response.error = Private.send_request(sock, request.method, Private.request_uri(parsed), request.headers, request.body_cb) diff --git a/src/inet.c b/src/inet.c index 574399c..f15a5a4 100644 --- a/src/inet.c +++ b/src/inet.c @@ -20,6 +20,7 @@ static int inet_global_toip(lua_State *L); static int inet_global_tohostname(lua_State *L); static void inet_pushresolved(lua_State *L, struct hostent *hp); +/* DNS functions */ static luaL_reg func[] = { { "toip", inet_global_toip }, { "tohostname", inet_global_tohostname }, @@ -34,7 +35,19 @@ static luaL_reg func[] = { \*-------------------------------------------------------------------------*/ void inet_open(lua_State *L) { - luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); + lua_pushstring(L, LUASOCKET_LIBNAME); + lua_gettable(L, LUA_GLOBALSINDEX); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring(L, LUASOCKET_LIBNAME); + lua_pushvalue(L, -2); + lua_settable(L, LUA_GLOBALSINDEX); + } + lua_pushstring(L, "dns"); + lua_newtable(L); + luaL_openlib(L, NULL, func, 0); + lua_settable(L, -3); lua_pop(L, 1); } @@ -100,10 +113,11 @@ int inet_meth_getpeername(lua_State *L, p_sock ps) socklen_t peer_len = sizeof(peer); if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { lua_pushnil(L); - return 1; + lua_pushstring(L, "getpeername failed"); + } else { + lua_pushstring(L, inet_ntoa(peer.sin_addr)); + lua_pushnumber(L, ntohs(peer.sin_port)); } - lua_pushstring(L, inet_ntoa(peer.sin_addr)); - lua_pushnumber(L, ntohs(peer.sin_port)); return 2; } @@ -116,10 +130,11 @@ int inet_meth_getsockname(lua_State *L, p_sock ps) socklen_t local_len = sizeof(local); if (getsockname(*ps, (SA *) &local, &local_len) < 0) { lua_pushnil(L); - return 1; + lua_pushstring(L, "getsockname failed"); + } else { + lua_pushstring(L, inet_ntoa(local.sin_addr)); + lua_pushnumber(L, ntohs(local.sin_port)); } - lua_pushstring(L, inet_ntoa(local.sin_addr)); - lua_pushnumber(L, ntohs(local.sin_port)); return 2; } diff --git a/src/smtp.lua b/src/smtp.lua index 209825b..5249160 100644 --- a/src/smtp.lua +++ b/src/smtp.lua @@ -243,7 +243,7 @@ function Private.open(server) -- connect to server and make sure we won't hang local sock, err = socket.connect(server, Public.PORT) if not sock then return nil, err end - sock:timeout(Public.TIMEOUT) + sock:settimeout(Public.TIMEOUT) -- initial server greeting code, answer = Private.check_answer(sock, 220) if not code then return nil, answer end @@ -305,10 +305,10 @@ end ----------------------------------------------------------------------------- function Public.mail(message) local sock, err = Private.open(message.server) - if not sock then return err end + if not sock then return nil, err end local code, answer = Private.send(sock, message) - if not code then return answer end - code, answer = Private.close(sock) - if code then return nil end - return answer + if not code then return nil, answer end + code, answer = Private.close(sock) + if code then return 1 + else return nil, answer end end diff --git a/src/tcp.c b/src/tcp.c index 28f38f5..098e29d 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -29,10 +29,10 @@ static int meth_receive(lua_State *L); static int meth_accept(lua_State *L); static int meth_close(lua_State *L); static int meth_setoption(lua_State *L); -static int meth_timeout(lua_State *L); +static int meth_settimeout(lua_State *L); static int meth_fd(lua_State *L); static int meth_dirty(lua_State *L); -static int opt_nodelay(lua_State *L); +static int opt_tcp_nodelay(lua_State *L); static int opt_keepalive(lua_State *L); static int opt_linger(lua_State *L); @@ -47,7 +47,7 @@ static luaL_reg tcp[] = { {"setsockname", meth_bind}, {"getpeername", meth_getpeername}, {"getsockname", meth_getsockname}, - {"timeout", meth_timeout}, + {"settimeout", meth_settimeout}, {"close", meth_close}, {"setoption", meth_setoption}, {"__gc", meth_close}, @@ -59,7 +59,7 @@ static luaL_reg tcp[] = { /* socket option handlers */ static luaL_reg opt[] = { {"keepalive", opt_keepalive}, - {"nodelay", opt_nodelay}, + {"tcp-nodelay", opt_tcp_nodelay}, {"linger", opt_linger}, {NULL, NULL} }; @@ -83,8 +83,8 @@ void tcp_open(lua_State *L) aux_add2group(L, "tcp{master}", "tcp{any}"); aux_add2group(L, "tcp{client}", "tcp{any}"); aux_add2group(L, "tcp{server}", "tcp{any}"); - aux_add2group(L, "tcp{client}", "tcp{client, server}"); - aux_add2group(L, "tcp{server}", "tcp{client, server}"); + aux_add2group(L, "tcp{client}", "tcp{client,server}"); + aux_add2group(L, "tcp{server}", "tcp{client,server}"); /* both server and client objects are selectable */ aux_add2group(L, "tcp{client}", "select{able}"); aux_add2group(L, "tcp{server}", "select{able}"); @@ -121,7 +121,7 @@ static int meth_setoption(lua_State *L) static int opt_boolean(lua_State *L, int level, int name) { - p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); + p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); int val = aux_checkboolean(L, 2); if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) { lua_pushnil(L); @@ -132,8 +132,8 @@ static int opt_boolean(lua_State *L, int level, int name) return 1; } -/* disables the Nagle algorithm */ -static int opt_nodelay(lua_State *L) +/* disables the Naggle algorithm */ +static int opt_tcp_nodelay(lua_State *L) { struct protoent *pe = getprotobyname("TCP"); if (!pe) { @@ -155,13 +155,13 @@ int opt_linger(lua_State *L) struct linger li; if (!lua_istable(L, 2)) luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE)); - lua_pushstring(L, "onoff"); + lua_pushstring(L, "on"); lua_gettable(L, 2); - if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid onoff field"); - li.l_onoff = (int) lua_tonumber(L, -1); - lua_pushstring(L, "linger"); + if (!lua_isboolean(L, -1)) luaL_argerror(L, 2, "invalid 'on' field"); + li.l_onoff = lua_toboolean(L, -1); + lua_pushstring(L, "timeout"); lua_gettable(L, 2); - if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid linger field"); + if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid 'timeout' field"); li.l_linger = (int) lua_tonumber(L, -1); if (setsockopt(tcp->sock, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li) < 0)) { @@ -178,93 +178,18 @@ int opt_linger(lua_State *L) \*-------------------------------------------------------------------------*/ static int meth_fd(lua_State *L) { - p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); + p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); lua_pushnumber(L, tcp->sock); return 1; } static int meth_dirty(lua_State *L) { - p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); + p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); lua_pushboolean(L, !buf_isempty(&tcp->buf)); return 1; } -/*-------------------------------------------------------------------------*\ -* Just call inet methods -\*-------------------------------------------------------------------------*/ -static int meth_getpeername(lua_State *L) -{ - p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); - return inet_meth_getpeername(L, &tcp->sock); -} - -static int meth_getsockname(lua_State *L) -{ - p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); - return inet_meth_getsockname(L, &tcp->sock); -} - -/*-------------------------------------------------------------------------*\ -* Just call tm methods -\*-------------------------------------------------------------------------*/ -static int meth_timeout(lua_State *L) -{ - p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); - return tm_meth_timeout(L, &tcp->tm); -} - -/*-------------------------------------------------------------------------*\ -* Closes socket used by object -\*-------------------------------------------------------------------------*/ -static int meth_close(lua_State *L) -{ - p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); - sock_destroy(&tcp->sock); - return 0; -} - -/*-------------------------------------------------------------------------*\ -* Turns a master tcp object into a client object. -\*-------------------------------------------------------------------------*/ -static int meth_connect(lua_State *L) -{ - p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); - const char *address = luaL_checkstring(L, 2); - unsigned short port = (unsigned short) luaL_checknumber(L, 3); - const char *err = inet_tryconnect(&tcp->sock, address, port); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - /* turn master object into a client object */ - aux_setclass(L, "tcp{client}", 1); - lua_pushnumber(L, 1); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Turns a master object into a server object -\*-------------------------------------------------------------------------*/ -static int meth_bind(lua_State *L) -{ - p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); - const char *address = luaL_checkstring(L, 2); - unsigned short port = (unsigned short) luaL_checknumber(L, 3); - int backlog = (int) luaL_optnumber(L, 4, 1); - const char *err = inet_trybind(&tcp->sock, address, port, backlog); - if (err) { - lua_pushnil(L); - lua_pushstring(L, err); - return 2; - } - /* turn master object into a server object */ - aux_setclass(L, "tcp{server}", 1); - lua_pushnumber(L, 1); - return 1; -} - /*-------------------------------------------------------------------------*\ * Waits for and returns a client object attempting connection to the * server object @@ -296,6 +221,81 @@ static int meth_accept(lua_State *L) return 1; } +/*-------------------------------------------------------------------------*\ +* Turns a master object into a server object +\*-------------------------------------------------------------------------*/ +static int meth_bind(lua_State *L) +{ + p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); + const char *address = luaL_checkstring(L, 2); + unsigned short port = (unsigned short) luaL_checknumber(L, 3); + int backlog = (int) luaL_optnumber(L, 4, 1); + const char *err = inet_trybind(&tcp->sock, address, port, backlog); + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + /* turn master object into a server object */ + aux_setclass(L, "tcp{server}", 1); + lua_pushnumber(L, 1); + return 1; +} + +/*-------------------------------------------------------------------------*\ +* Turns a master tcp object into a client object. +\*-------------------------------------------------------------------------*/ +static int meth_connect(lua_State *L) +{ + p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); + const char *address = luaL_checkstring(L, 2); + unsigned short port = (unsigned short) luaL_checknumber(L, 3); + const char *err = inet_tryconnect(&tcp->sock, address, port); + if (err) { + lua_pushnil(L); + lua_pushstring(L, err); + return 2; + } + /* turn master object into a client object */ + aux_setclass(L, "tcp{client}", 1); + lua_pushnumber(L, 1); + return 1; +} + +/*-------------------------------------------------------------------------*\ +* Closes socket used by object +\*-------------------------------------------------------------------------*/ +static int meth_close(lua_State *L) +{ + p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); + sock_destroy(&tcp->sock); + return 0; +} + +/*-------------------------------------------------------------------------*\ +* Just call inet methods +\*-------------------------------------------------------------------------*/ +static int meth_getpeername(lua_State *L) +{ + p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); + return inet_meth_getpeername(L, &tcp->sock); +} + +static int meth_getsockname(lua_State *L) +{ + p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); + return inet_meth_getsockname(L, &tcp->sock); +} + +/*-------------------------------------------------------------------------*\ +* Just call tm methods +\*-------------------------------------------------------------------------*/ +static int meth_settimeout(lua_State *L) +{ + p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1); + return tm_meth_settimeout(L, &tcp->tm); +} + /*=========================================================================*\ * Library functions \*=========================================================================*/ diff --git a/src/timeout.c b/src/timeout.c index 6a30e3a..38d1135 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -125,7 +125,7 @@ void tm_open(lua_State *L) * time: time out value in seconds * mode: "b" for block timeout, "t" for total timeout. (default: b) \*-------------------------------------------------------------------------*/ -int tm_meth_timeout(lua_State *L, p_tm tm) +int tm_meth_settimeout(lua_State *L, p_tm tm) { int ms = lua_isnil(L, 2) ? -1 : (int) (luaL_checknumber(L, 2)*1000.0); const char *mode = luaL_optstring(L, 3, "b"); diff --git a/src/timeout.h b/src/timeout.h index 32eb836..ef2f533 100644 --- a/src/timeout.h +++ b/src/timeout.h @@ -26,6 +26,6 @@ void tm_markstart(p_tm tm); int tm_getstart(p_tm tm); int tm_get(p_tm tm); int tm_gettime(void); -int tm_meth_timeout(lua_State *L, p_tm tm); +int tm_meth_settimeout(lua_State *L, p_tm tm); #endif /* TM_H */ diff --git a/src/udp.c b/src/udp.c index b772b2e..6647711 100644 --- a/src/udp.c +++ b/src/udp.c @@ -30,7 +30,7 @@ static int meth_setsockname(lua_State *L); static int meth_setpeername(lua_State *L); static int meth_close(lua_State *L); static int meth_setoption(lua_State *L); -static int meth_timeout(lua_State *L); +static int meth_settimeout(lua_State *L); static int meth_fd(lua_State *L); static int meth_dirty(lua_State *L); static int opt_dontroute(lua_State *L); @@ -46,7 +46,7 @@ static luaL_reg udp[] = { {"sendto", meth_sendto}, {"receive", meth_receive}, {"receivefrom", meth_receivefrom}, - {"timeout", meth_timeout}, + {"settimeout", meth_settimeout}, {"close", meth_close}, {"setoption", meth_setoption}, {"__gc", meth_close}, @@ -252,10 +252,10 @@ static int opt_broadcast(lua_State *L) /*-------------------------------------------------------------------------*\ * Just call tm methods \*-------------------------------------------------------------------------*/ -static int meth_timeout(lua_State *L) +static int meth_settimeout(lua_State *L) { p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); - return tm_meth_timeout(L, &udp->tm); + return tm_meth_settimeout(L, &udp->tm); } /*-------------------------------------------------------------------------*\ @@ -297,7 +297,7 @@ static int meth_close(lua_State *L) \*-------------------------------------------------------------------------*/ static int meth_setsockname(lua_State *L) { - p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1); + p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); const char *address = luaL_checkstring(L, 2); unsigned short port = (unsigned short) luaL_checknumber(L, 3); const char *err = inet_trybind(&udp->sock, address, port, -1); diff --git a/src/usocket.c b/src/usocket.c index cdd550c..202238b 100644 --- a/src/usocket.c +++ b/src/usocket.c @@ -26,8 +26,10 @@ int sock_open(void) \*-------------------------------------------------------------------------*/ void sock_destroy(p_sock ps) { - close(*ps); - *ps = SOCK_INVALID; + if (*ps != SOCK_INVALID) { + close(*ps); + *ps = SOCK_INVALID; + } } /*-------------------------------------------------------------------------*\ diff --git a/src/wsocket.c b/src/wsocket.c index 2ce828e..f9e1084 100644 --- a/src/wsocket.c +++ b/src/wsocket.c @@ -29,8 +29,10 @@ int sock_open(void) \*-------------------------------------------------------------------------*/ void sock_destroy(p_sock ps) { - closesocket(*ps); - *ps = SOCK_INVALID; + if (*ps != SOCK_INVALID) { + closesocket(*ps); + *ps = SOCK_INVALID; + } } /*-------------------------------------------------------------------------*\ diff --git a/test/smtptest.lua b/test/smtptest.lua index 09bf634..8468408 100644 --- a/test/smtptest.lua +++ b/test/smtptest.lua @@ -209,27 +209,27 @@ insert(sent, { io.write("testing host not found: ") local c, e = socket.connect("wrong.host", 25) -local err = socket.smtp.mail{ +local ret, err = socket.smtp.mail{ from = from, rcpt = rcpt, server = "wrong.host" } -if e ~= err then fail("wrong error message") +if ret or e ~= err then fail("wrong error message") else print("ok") end io.write("testing invalid from: ") -local err = socket.smtp.mail{ +local ret, err = socket.smtp.mail{ from = ' " " (( _ * ', rcpt = rcpt, } -if not err then fail("wrong error message") +if ret or not err then fail("wrong error message") else print(err) end io.write("testing no rcpt: ") -local err = socket.smtp.mail{ +local ret, err = socket.smtp.mail{ from = from, } -if not err then fail("wrong error message") +if ret or not err then fail("wrong error message") else print(err) end io.write("clearing mailbox: ") @@ -238,8 +238,8 @@ print("ok") io.write("sending messages: ") for i = 1, table.getn(sent) do - err = socket.smtp.mail(sent[i]) - if err then fail(err) end + ret, err = socket.smtp.mail(sent[i]) + if not ret then fail(err) end io.write("+") io.stdout:flush() end diff --git a/test/testclnt.lua b/test/testclnt.lua index b58ca2b..3f217bd 100644 --- a/test/testclnt.lua +++ b/test/testclnt.lua @@ -121,7 +121,7 @@ test_methods(socket.tcp(), { "getpeername", "getsockname", "setoption", - "timeout", + "settimeout", "close", }) @@ -135,7 +135,7 @@ test_methods(socket.udp(), { "receive", "receivefrom", "setoption", - "timeout", + "settimeout", "close", }) @@ -278,7 +278,7 @@ reconnect() -- the value is not important, we only want -- to test non-blockin I/O anyways -data:timeout(200) +data:settimeout(200) test_raw(1) test_raw(17) test_raw(200) @@ -298,7 +298,7 @@ function test_totaltimeoutreceive(len, tm, sl) reconnect() pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl) remote (string.format ([[ - data:timeout(%d) + data:settimeout(%d) str = string.rep('a', %d) data:send(str) print('server: sleeping for %ds') @@ -306,7 +306,7 @@ function test_totaltimeoutreceive(len, tm, sl) print('server: woke up') data:send(str) ]], 2*tm, len, sl, sl)) - data:timeout(tm, "total") + data:settimeout(tm, "total") str, err, elapsed = data:receive(2*len) check_timeout(tm, sl, elapsed, err, "receive", "total", string.len(str) == 2*len) @@ -323,14 +323,14 @@ function test_totaltimeoutsend(len, tm, sl) reconnect() pass("%d bytes, %ds total timeout, %ds pause", len, tm, sl) remote (string.format ([[ - data:timeout(%d) + data:settimeout(%d) str = data:receive(%d) print('server: sleeping for %ds') socket.sleep(%d) print('server: woke up') str = data:receive(%d) ]], 2*tm, len, sl, sl, len)) - data:timeout(tm, "total") + data:settimeout(tm, "total") str = string.rep("a", 2*len) total, err, elapsed = data:send(str) check_timeout(tm, sl, elapsed, err, "send", "total", @@ -348,7 +348,7 @@ function test_blockingtimeoutreceive(len, tm, sl) reconnect() pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl) remote (string.format ([[ - data:timeout(%d) + data:settimeout(%d) str = string.rep('a', %d) data:send(str) print('server: sleeping for %ds') @@ -356,7 +356,7 @@ function test_blockingtimeoutreceive(len, tm, sl) print('server: woke up') data:send(str) ]], 2*tm, len, sl, sl)) - data:timeout(tm) + data:settimeout(tm) str, err, elapsed = data:receive(2*len) check_timeout(tm, sl, elapsed, err, "receive", "blocking", string.len(str) == 2*len) @@ -373,14 +373,14 @@ function test_blockingtimeoutsend(len, tm, sl) reconnect() pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl) remote (string.format ([[ - data:timeout(%d) + data:settimeout(%d) str = data:receive(%d) print('server: sleeping for %ds') socket.sleep(%d) print('server: woke up') str = data:receive(%d) ]], 2*tm, len, sl, sl, len)) - data:timeout(tm) + data:settimeout(tm) str = string.rep("a", 2*len) total, err, elapsed = data:send(str) check_timeout(tm, sl, elapsed, err, "send", "blocking",