aboutsummaryrefslogtreecommitdiff
path: root/src/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcp.c')
-rw-r--r--src/tcp.c85
1 files changed, 81 insertions, 4 deletions
diff --git a/src/tcp.c b/src/tcp.c
index dc7683d..28f38f5 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -1,5 +1,6 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* TCP object 2* TCP object
3* LuaSocket toolkit
3* 4*
4* RCS ID: $Id$ 5* RCS ID: $Id$
5\*=========================================================================*/ 6\*=========================================================================*/
@@ -13,7 +14,6 @@
13#include "auxiliar.h" 14#include "auxiliar.h"
14#include "socket.h" 15#include "socket.h"
15#include "inet.h" 16#include "inet.h"
16#include "error.h"
17#include "tcp.h" 17#include "tcp.h"
18 18
19/*=========================================================================*\ 19/*=========================================================================*\
@@ -28,9 +28,13 @@ static int meth_getpeername(lua_State *L);
28static int meth_receive(lua_State *L); 28static int meth_receive(lua_State *L);
29static int meth_accept(lua_State *L); 29static int meth_accept(lua_State *L);
30static int meth_close(lua_State *L); 30static int meth_close(lua_State *L);
31static int meth_setoption(lua_State *L);
31static int meth_timeout(lua_State *L); 32static int meth_timeout(lua_State *L);
32static int meth_fd(lua_State *L); 33static int meth_fd(lua_State *L);
33static int meth_dirty(lua_State *L); 34static int meth_dirty(lua_State *L);
35static int opt_nodelay(lua_State *L);
36static int opt_keepalive(lua_State *L);
37static int opt_linger(lua_State *L);
34 38
35/* tcp object methods */ 39/* tcp object methods */
36static luaL_reg tcp[] = { 40static luaL_reg tcp[] = {
@@ -45,11 +49,21 @@ static luaL_reg tcp[] = {
45 {"getsockname", meth_getsockname}, 49 {"getsockname", meth_getsockname},
46 {"timeout", meth_timeout}, 50 {"timeout", meth_timeout},
47 {"close", meth_close}, 51 {"close", meth_close},
52 {"setoption", meth_setoption},
53 {"__gc", meth_close},
48 {"fd", meth_fd}, 54 {"fd", meth_fd},
49 {"dirty", meth_dirty}, 55 {"dirty", meth_dirty},
50 {NULL, NULL} 56 {NULL, NULL}
51}; 57};
52 58
59/* socket option handlers */
60static luaL_reg opt[] = {
61 {"keepalive", opt_keepalive},
62 {"nodelay", opt_nodelay},
63 {"linger", opt_linger},
64 {NULL, NULL}
65};
66
53/* functions in library namespace */ 67/* functions in library namespace */
54static luaL_reg func[] = { 68static luaL_reg func[] = {
55 {"tcp", global_create}, 69 {"tcp", global_create},
@@ -71,6 +85,7 @@ void tcp_open(lua_State *L)
71 aux_add2group(L, "tcp{server}", "tcp{any}"); 85 aux_add2group(L, "tcp{server}", "tcp{any}");
72 aux_add2group(L, "tcp{client}", "tcp{client, server}"); 86 aux_add2group(L, "tcp{client}", "tcp{client, server}");
73 aux_add2group(L, "tcp{server}", "tcp{client, server}"); 87 aux_add2group(L, "tcp{server}", "tcp{client, server}");
88 /* both server and client objects are selectable */
74 aux_add2group(L, "tcp{client}", "select{able}"); 89 aux_add2group(L, "tcp{client}", "select{able}");
75 aux_add2group(L, "tcp{server}", "select{able}"); 90 aux_add2group(L, "tcp{server}", "select{able}");
76 /* define library functions */ 91 /* define library functions */
@@ -97,18 +112,80 @@ static int meth_receive(lua_State *L)
97} 112}
98 113
99/*-------------------------------------------------------------------------*\ 114/*-------------------------------------------------------------------------*\
115* Option handlers
116\*-------------------------------------------------------------------------*/
117static int meth_setoption(lua_State *L)
118{
119 return aux_meth_setoption(L, opt);
120}
121
122static int opt_boolean(lua_State *L, int level, int name)
123{
124 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
125 int val = aux_checkboolean(L, 2);
126 if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) {
127 lua_pushnil(L);
128 lua_pushstring(L, "setsockopt failed");
129 return 2;
130 }
131 lua_pushnumber(L, 1);
132 return 1;
133}
134
135/* disables the Nagle algorithm */
136static int opt_nodelay(lua_State *L)
137{
138 struct protoent *pe = getprotobyname("TCP");
139 if (!pe) {
140 lua_pushnil(L);
141 lua_pushstring(L, "getprotobyname");
142 return 2;
143 }
144 return opt_boolean(L, pe->p_proto, TCP_NODELAY);
145}
146
147static int opt_keepalive(lua_State *L)
148{
149 return opt_boolean(L, SOL_SOCKET, SO_KEEPALIVE);
150}
151
152int opt_linger(lua_State *L)
153{
154 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
155 struct linger li;
156 if (!lua_istable(L, 2))
157 luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE));
158 lua_pushstring(L, "onoff");
159 lua_gettable(L, 2);
160 if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid onoff field");
161 li.l_onoff = (int) lua_tonumber(L, -1);
162 lua_pushstring(L, "linger");
163 lua_gettable(L, 2);
164 if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid linger field");
165 li.l_linger = (int) lua_tonumber(L, -1);
166 if (setsockopt(tcp->sock, SOL_SOCKET, SO_LINGER,
167 (char *) &li, sizeof(li) < 0)) {
168 lua_pushnil(L);
169 lua_pushstring(L, "setsockopt failed");
170 return 2;
171 }
172 lua_pushnumber(L, 1);
173 return 1;
174}
175
176/*-------------------------------------------------------------------------*\
100* Select support methods 177* Select support methods
101\*-------------------------------------------------------------------------*/ 178\*-------------------------------------------------------------------------*/
102static int meth_fd(lua_State *L) 179static int meth_fd(lua_State *L)
103{ 180{
104 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1); 181 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
105 lua_pushnumber(L, tcp->sock); 182 lua_pushnumber(L, tcp->sock);
106 return 1; 183 return 1;
107} 184}
108 185
109static int meth_dirty(lua_State *L) 186static int meth_dirty(lua_State *L)
110{ 187{
111 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1); 188 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
112 lua_pushboolean(L, !buf_isempty(&tcp->buf)); 189 lua_pushboolean(L, !buf_isempty(&tcp->buf));
113 return 1; 190 return 1;
114} 191}
@@ -207,7 +284,7 @@ static int meth_accept(lua_State *L)
207 if (client->sock == SOCK_INVALID) { 284 if (client->sock == SOCK_INVALID) {
208 if (tm_get(tm) == 0) { 285 if (tm_get(tm) == 0) {
209 lua_pushnil(L); 286 lua_pushnil(L);
210 error_push(L, IO_TIMEOUT); 287 io_pusherror(L, IO_TIMEOUT);
211 return 2; 288 return 2;
212 } 289 }
213 } else break; 290 } else break;