aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/reference.html1
-rw-r--r--doc/tcp.html35
-rw-r--r--src/options.c70
-rw-r--r--src/options.h8
-rw-r--r--src/tcp.c16
-rwxr-xr-xtest/tcp-getoptions41
6 files changed, 170 insertions, 1 deletions
diff --git a/doc/reference.html b/doc/reference.html
index 078d40c..d7e0923 100644
--- a/doc/reference.html
+++ b/doc/reference.html
@@ -172,6 +172,7 @@ Support, Manual">
172<a href="tcp.html#connect">connect</a>, 172<a href="tcp.html#connect">connect</a>,
173<a href="tcp.html#dirty">dirty</a>, 173<a href="tcp.html#dirty">dirty</a>,
174<a href="tcp.html#getfd">getfd</a>, 174<a href="tcp.html#getfd">getfd</a>,
175<a href="tcp.html#getoption">getoption</a>,
175<a href="tcp.html#getpeername">getpeername</a>, 176<a href="tcp.html#getpeername">getpeername</a>,
176<a href="tcp.html#getsockname">getsockname</a>, 177<a href="tcp.html#getsockname">getsockname</a>,
177<a href="tcp.html#getstats">getstats</a>, 178<a href="tcp.html#getstats">getstats</a>,
diff --git a/doc/tcp.html b/doc/tcp.html
index 9583b1f..11a0428 100644
--- a/doc/tcp.html
+++ b/doc/tcp.html
@@ -396,7 +396,40 @@ disables the Nagle's algorithm for the connection.
396</ul> 396</ul>
397 397
398<p class=return> 398<p class=return>
399The method returns 1 in case of success, or <b><tt>nil</tt></b> otherwise. 399The method returns 1 in case of success, or <b><tt>nil</tt></b>
400followed by an error message otherwise.
401</p>
402
403<p class=note>
404Note: The descriptions above come from the man pages.
405</p>
406
407<!-- getoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
408
409<p class=name id=getoption>
410client:<b>getoption(</b>option)</b><br>
411server:<b>getoption(</b>option)</b>
412</p>
413
414<p class=description>
415Gets options for the TCP object.
416See <a href=#setoption><tt>setoption</tt></a> for description of the
417option names and values.
418</p>
419
420<p class=parameters>
421<tt>Option</tt> is a string with the option name.
422<ul>
423
424<li> '<tt>keepalive</tt>'
425<li> '<tt>linger</tt>'
426<li> '<tt>reuseaddr</tt>'
427<li> '<tt>tcp-nodelay</tt>'
428</ul>
429
430<p class=return>
431The method returns the option <tt>value</tt> in case of success, or
432<b><tt>nil</tt></b> followed by an error message otherwise.
400</p> 433</p>
401 434
402<p class=note> 435<p class=note>
diff --git a/src/options.c b/src/options.c
index a464a4b..2085fdc 100644
--- a/src/options.c
+++ b/src/options.c
@@ -18,8 +18,11 @@
18\*=========================================================================*/ 18\*=========================================================================*/
19static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); 19static int opt_setmembership(lua_State *L, p_socket ps, int level, int name);
20static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); 20static int opt_setboolean(lua_State *L, p_socket ps, int level, int name);
21static int opt_getboolean(lua_State *L, p_socket ps, int level, int name);
21static int opt_set(lua_State *L, p_socket ps, int level, int name, 22static int opt_set(lua_State *L, p_socket ps, int level, int name,
22 void *val, int len); 23 void *val, int len);
24static int opt_get(lua_State *L, p_socket ps, int level, int name,
25 void *val, int* len);
23 26
24/*=========================================================================*\ 27/*=========================================================================*\
25* Exported functions 28* Exported functions
@@ -40,23 +43,51 @@ int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps)
40 return opt->func(L, ps); 43 return opt->func(L, ps);
41} 44}
42 45
46int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps)
47{
48 const char *name = luaL_checkstring(L, 2); /* obj, name, ... */
49 while (opt->name && strcmp(name, opt->name))
50 opt++;
51 if (!opt->func) {
52 char msg[45];
53 sprintf(msg, "unsupported option `%.35s'", name);
54 luaL_argerror(L, 2, msg);
55 }
56 return opt->func(L, ps);
57}
58
43/* enables reuse of local address */ 59/* enables reuse of local address */
44int opt_reuseaddr(lua_State *L, p_socket ps) 60int opt_reuseaddr(lua_State *L, p_socket ps)
45{ 61{
46 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); 62 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
47} 63}
48 64
65int opt_get_reuseaddr(lua_State *L, p_socket ps)
66{
67 return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
68}
69
49/* disables the Naggle algorithm */ 70/* disables the Naggle algorithm */
50int opt_tcp_nodelay(lua_State *L, p_socket ps) 71int opt_tcp_nodelay(lua_State *L, p_socket ps)
51{ 72{
52 return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); 73 return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
53} 74}
54 75
76int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
77{
78 return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
79}
80
55int opt_keepalive(lua_State *L, p_socket ps) 81int opt_keepalive(lua_State *L, p_socket ps)
56{ 82{
57 return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); 83 return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
58} 84}
59 85
86int opt_get_keepalive(lua_State *L, p_socket ps)
87{
88 return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
89}
90
60int opt_dontroute(lua_State *L, p_socket ps) 91int opt_dontroute(lua_State *L, p_socket ps)
61{ 92{
62 return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); 93 return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
@@ -105,6 +136,21 @@ int opt_ip_drop_membersip(lua_State *L, p_socket ps)
105 return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); 136 return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP);
106} 137}
107 138
139int opt_get_linger(lua_State *L, p_socket ps)
140{
141 struct linger li; /* obj, name */
142 int len = sizeof(li);
143 int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len);
144 if (err)
145 return err;
146 lua_newtable(L);
147 lua_pushboolean(L, li.l_onoff);
148 lua_setfield(L, -2, "on");
149 lua_pushinteger(L, li.l_linger);
150 lua_setfield(L, -2, "timeout");
151 return 1;
152}
153
108/*=========================================================================*\ 154/*=========================================================================*\
109* Auxiliar functions 155* Auxiliar functions
110\*=========================================================================*/ 156\*=========================================================================*/
@@ -130,6 +176,19 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name)
130} 176}
131 177
132static 178static
179int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
180{
181 socklen_t socklen = *len;
182 if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) {
183 lua_pushnil(L);
184 lua_pushstring(L, "getsockopt failed");
185 return 2;
186 }
187 *len = socklen;
188 return 0;
189}
190
191static
133int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) 192int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
134{ 193{
135 if (setsockopt(*ps, level, name, (char *) val, len) < 0) { 194 if (setsockopt(*ps, level, name, (char *) val, len) < 0) {
@@ -141,6 +200,17 @@ int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
141 return 1; 200 return 1;
142} 201}
143 202
203static int opt_getboolean(lua_State *L, p_socket ps, int level, int name)
204{
205 int val = 0;
206 int len = sizeof(val);
207 int err = opt_get(L, ps, level, name, (char *) &val, &len);
208 if (err)
209 return err;
210 lua_pushboolean(L, val);
211 return 1;
212}
213
144static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) 214static int opt_setboolean(lua_State *L, p_socket ps, int level, int name)
145{ 215{
146 int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ 216 int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */
diff --git a/src/options.h b/src/options.h
index 900761e..c9b2e47 100644
--- a/src/options.h
+++ b/src/options.h
@@ -17,10 +17,17 @@
17typedef struct t_opt { 17typedef struct t_opt {
18 const char *name; 18 const char *name;
19 int (*func)(lua_State *L, p_socket ps); 19 int (*func)(lua_State *L, p_socket ps);
20 int (*get)(lua_State *L, p_socket ps);
20} t_opt; 21} t_opt;
21typedef t_opt *p_opt; 22typedef t_opt *p_opt;
22 23
23/* supported options */ 24/* supported options */
25int opt_get_reuseaddr(lua_State *L, p_socket ps);
26int opt_get_tcp_nodelay(lua_State *L, p_socket ps);
27int opt_get_keepalive(lua_State *L, p_socket ps);
28int opt_get_linger(lua_State *L, p_socket ps);
29int opt_get_reuseaddr(lua_State *L, p_socket ps);
30
24int opt_dontroute(lua_State *L, p_socket ps); 31int opt_dontroute(lua_State *L, p_socket ps);
25int opt_broadcast(lua_State *L, p_socket ps); 32int opt_broadcast(lua_State *L, p_socket ps);
26int opt_reuseaddr(lua_State *L, p_socket ps); 33int opt_reuseaddr(lua_State *L, p_socket ps);
@@ -35,5 +42,6 @@ int opt_ip_drop_membersip(lua_State *L, p_socket ps);
35 42
36/* invokes the appropriate option handler */ 43/* invokes the appropriate option handler */
37int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); 44int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps);
45int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps);
38 46
39#endif 47#endif
diff --git a/src/tcp.c b/src/tcp.c
index 539ad5e..4713b23 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -31,6 +31,7 @@ static int meth_shutdown(lua_State *L);
31static int meth_receive(lua_State *L); 31static int meth_receive(lua_State *L);
32static int meth_accept(lua_State *L); 32static int meth_accept(lua_State *L);
33static int meth_close(lua_State *L); 33static int meth_close(lua_State *L);
34static int meth_getoption(lua_State *L);
34static int meth_setoption(lua_State *L); 35static int meth_setoption(lua_State *L);
35static int meth_settimeout(lua_State *L); 36static int meth_settimeout(lua_State *L);
36static int meth_getfd(lua_State *L); 37static int meth_getfd(lua_State *L);
@@ -47,6 +48,7 @@ static luaL_reg tcp[] = {
47 {"connect", meth_connect}, 48 {"connect", meth_connect},
48 {"dirty", meth_dirty}, 49 {"dirty", meth_dirty},
49 {"getfd", meth_getfd}, 50 {"getfd", meth_getfd},
51 {"getoption", meth_getoption},
50 {"getpeername", meth_getpeername}, 52 {"getpeername", meth_getpeername},
51 {"getsockname", meth_getsockname}, 53 {"getsockname", meth_getsockname},
52 {"getstats", meth_getstats}, 54 {"getstats", meth_getstats},
@@ -64,6 +66,14 @@ static luaL_reg tcp[] = {
64}; 66};
65 67
66/* socket option handlers */ 68/* socket option handlers */
69static t_opt optget[] = {
70 {"keepalive", opt_get_keepalive},
71 {"reuseaddr", opt_get_reuseaddr},
72 {"tcp-nodelay", opt_get_tcp_nodelay},
73 {"linger", opt_get_linger},
74 {NULL, NULL}
75};
76
67static t_opt opt[] = { 77static t_opt opt[] = {
68 {"keepalive", opt_keepalive}, 78 {"keepalive", opt_keepalive},
69 {"reuseaddr", opt_reuseaddr}, 79 {"reuseaddr", opt_reuseaddr},
@@ -125,6 +135,12 @@ static int meth_setstats(lua_State *L) {
125/*-------------------------------------------------------------------------*\ 135/*-------------------------------------------------------------------------*\
126* Just call option handler 136* Just call option handler
127\*-------------------------------------------------------------------------*/ 137\*-------------------------------------------------------------------------*/
138static int meth_getoption(lua_State *L)
139{
140 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
141 return opt_meth_getoption(L, optget, &tcp->sock);
142}
143
128static int meth_setoption(lua_State *L) 144static int meth_setoption(lua_State *L)
129{ 145{
130 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); 146 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
diff --git a/test/tcp-getoptions b/test/tcp-getoptions
new file mode 100755
index 0000000..f9b3d1b
--- /dev/null
+++ b/test/tcp-getoptions
@@ -0,0 +1,41 @@
1#!/usr/bin/env lua
2
3require"socket"
4
5port = 8765
6
7function options(o)
8 print("options for", o)
9
10 for _, opt in ipairs{"keepalive", "reuseaddr", "tcp-nodelay"} do
11 print("getoption", opt, o:getoption(opt))
12 end
13
14 print("getoption", "linger",
15 "on", o:getoption("linger").on,
16 "timeout", o:getoption("linger").timeout)
17end
18
19local m = socket.tcp()
20
21options(m)
22
23assert(m:bind("*", port))
24assert(m:listen())
25
26options(m)
27
28m:close()
29
30local m = socket.bind("*", port)
31
32options(m)
33
34local c = socket.connect("localhost", port)
35
36options(c)
37
38local s = m:accept()
39
40options(s)
41