Support getoption method for tcp objects.
parent
0716cb868e
commit
8bb542baaf
|
@ -172,6 +172,7 @@ Support, Manual">
|
|||
<a href="tcp.html#connect">connect</a>,
|
||||
<a href="tcp.html#dirty">dirty</a>,
|
||||
<a href="tcp.html#getfd">getfd</a>,
|
||||
<a href="tcp.html#getoption">getoption</a>,
|
||||
<a href="tcp.html#getpeername">getpeername</a>,
|
||||
<a href="tcp.html#getsockname">getsockname</a>,
|
||||
<a href="tcp.html#getstats">getstats</a>,
|
||||
|
|
35
doc/tcp.html
35
doc/tcp.html
|
@ -396,7 +396,40 @@ disables the Nagle's algorithm for the connection.
|
|||
</ul>
|
||||
|
||||
<p class=return>
|
||||
The method returns 1 in case of success, or <b><tt>nil</tt></b> otherwise.
|
||||
The method returns 1 in case of success, or <b><tt>nil</tt></b>
|
||||
followed by an error message otherwise.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
Note: The descriptions above come from the man pages.
|
||||
</p>
|
||||
|
||||
<!-- getoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||
|
||||
<p class=name id=getoption>
|
||||
client:<b>getoption(</b>option)</b><br>
|
||||
server:<b>getoption(</b>option)</b>
|
||||
</p>
|
||||
|
||||
<p class=description>
|
||||
Gets options for the TCP object.
|
||||
See <a href=#setoption><tt>setoption</tt></a> for description of the
|
||||
option names and values.
|
||||
</p>
|
||||
|
||||
<p class=parameters>
|
||||
<tt>Option</tt> is a string with the option name.
|
||||
<ul>
|
||||
|
||||
<li> '<tt>keepalive</tt>'
|
||||
<li> '<tt>linger</tt>'
|
||||
<li> '<tt>reuseaddr</tt>'
|
||||
<li> '<tt>tcp-nodelay</tt>'
|
||||
</ul>
|
||||
|
||||
<p class=return>
|
||||
The method returns the option <tt>value</tt> in case of success, or
|
||||
<b><tt>nil</tt></b> followed by an error message otherwise.
|
||||
</p>
|
||||
|
||||
<p class=note>
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
\*=========================================================================*/
|
||||
static int opt_setmembership(lua_State *L, p_socket ps, int level, int name);
|
||||
static int opt_setboolean(lua_State *L, p_socket ps, int level, int name);
|
||||
static int opt_getboolean(lua_State *L, p_socket ps, int level, int name);
|
||||
static int opt_set(lua_State *L, p_socket ps, int level, int name,
|
||||
void *val, int len);
|
||||
static int opt_get(lua_State *L, p_socket ps, int level, int name,
|
||||
void *val, int* len);
|
||||
|
||||
/*=========================================================================*\
|
||||
* Exported functions
|
||||
|
@ -40,23 +43,51 @@ int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps)
|
|||
return opt->func(L, ps);
|
||||
}
|
||||
|
||||
int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps)
|
||||
{
|
||||
const char *name = luaL_checkstring(L, 2); /* obj, name, ... */
|
||||
while (opt->name && strcmp(name, opt->name))
|
||||
opt++;
|
||||
if (!opt->func) {
|
||||
char msg[45];
|
||||
sprintf(msg, "unsupported option `%.35s'", name);
|
||||
luaL_argerror(L, 2, msg);
|
||||
}
|
||||
return opt->func(L, ps);
|
||||
}
|
||||
|
||||
/* enables reuse of local address */
|
||||
int opt_reuseaddr(lua_State *L, p_socket ps)
|
||||
{
|
||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
|
||||
}
|
||||
|
||||
int opt_get_reuseaddr(lua_State *L, p_socket ps)
|
||||
{
|
||||
return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
|
||||
}
|
||||
|
||||
/* disables the Naggle algorithm */
|
||||
int opt_tcp_nodelay(lua_State *L, p_socket ps)
|
||||
{
|
||||
return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
|
||||
}
|
||||
|
||||
int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
|
||||
{
|
||||
return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
|
||||
}
|
||||
|
||||
int opt_keepalive(lua_State *L, p_socket ps)
|
||||
{
|
||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
|
||||
}
|
||||
|
||||
int opt_get_keepalive(lua_State *L, p_socket ps)
|
||||
{
|
||||
return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
|
||||
}
|
||||
|
||||
int opt_dontroute(lua_State *L, p_socket ps)
|
||||
{
|
||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
|
||||
|
@ -105,6 +136,21 @@ int opt_ip_drop_membersip(lua_State *L, p_socket ps)
|
|||
return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP);
|
||||
}
|
||||
|
||||
int opt_get_linger(lua_State *L, p_socket ps)
|
||||
{
|
||||
struct linger li; /* obj, name */
|
||||
int len = sizeof(li);
|
||||
int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len);
|
||||
if (err)
|
||||
return err;
|
||||
lua_newtable(L);
|
||||
lua_pushboolean(L, li.l_onoff);
|
||||
lua_setfield(L, -2, "on");
|
||||
lua_pushinteger(L, li.l_linger);
|
||||
lua_setfield(L, -2, "timeout");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
* Auxiliar functions
|
||||
\*=========================================================================*/
|
||||
|
@ -129,6 +175,19 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name)
|
|||
return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
|
||||
}
|
||||
|
||||
static
|
||||
int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
|
||||
{
|
||||
socklen_t socklen = *len;
|
||||
if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, "getsockopt failed");
|
||||
return 2;
|
||||
}
|
||||
*len = socklen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
|
||||
{
|
||||
|
@ -141,6 +200,17 @@ int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int opt_getboolean(lua_State *L, p_socket ps, int level, int name)
|
||||
{
|
||||
int val = 0;
|
||||
int len = sizeof(val);
|
||||
int err = opt_get(L, ps, level, name, (char *) &val, &len);
|
||||
if (err)
|
||||
return err;
|
||||
lua_pushboolean(L, 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 */
|
||||
|
|
|
@ -17,10 +17,17 @@
|
|||
typedef struct t_opt {
|
||||
const char *name;
|
||||
int (*func)(lua_State *L, p_socket ps);
|
||||
int (*get)(lua_State *L, p_socket ps);
|
||||
} t_opt;
|
||||
typedef t_opt *p_opt;
|
||||
|
||||
/* supported options */
|
||||
int opt_get_reuseaddr(lua_State *L, p_socket ps);
|
||||
int opt_get_tcp_nodelay(lua_State *L, p_socket ps);
|
||||
int opt_get_keepalive(lua_State *L, p_socket ps);
|
||||
int opt_get_linger(lua_State *L, p_socket ps);
|
||||
int opt_get_reuseaddr(lua_State *L, p_socket ps);
|
||||
|
||||
int opt_dontroute(lua_State *L, p_socket ps);
|
||||
int opt_broadcast(lua_State *L, p_socket ps);
|
||||
int opt_reuseaddr(lua_State *L, p_socket ps);
|
||||
|
@ -35,5 +42,6 @@ int opt_ip_drop_membersip(lua_State *L, p_socket ps);
|
|||
|
||||
/* invokes the appropriate option handler */
|
||||
int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps);
|
||||
int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps);
|
||||
|
||||
#endif
|
||||
|
|
16
src/tcp.c
16
src/tcp.c
|
@ -31,6 +31,7 @@ static int meth_shutdown(lua_State *L);
|
|||
static int meth_receive(lua_State *L);
|
||||
static int meth_accept(lua_State *L);
|
||||
static int meth_close(lua_State *L);
|
||||
static int meth_getoption(lua_State *L);
|
||||
static int meth_setoption(lua_State *L);
|
||||
static int meth_settimeout(lua_State *L);
|
||||
static int meth_getfd(lua_State *L);
|
||||
|
@ -47,6 +48,7 @@ static luaL_reg tcp[] = {
|
|||
{"connect", meth_connect},
|
||||
{"dirty", meth_dirty},
|
||||
{"getfd", meth_getfd},
|
||||
{"getoption", meth_getoption},
|
||||
{"getpeername", meth_getpeername},
|
||||
{"getsockname", meth_getsockname},
|
||||
{"getstats", meth_getstats},
|
||||
|
@ -64,6 +66,14 @@ static luaL_reg tcp[] = {
|
|||
};
|
||||
|
||||
/* socket option handlers */
|
||||
static t_opt optget[] = {
|
||||
{"keepalive", opt_get_keepalive},
|
||||
{"reuseaddr", opt_get_reuseaddr},
|
||||
{"tcp-nodelay", opt_get_tcp_nodelay},
|
||||
{"linger", opt_get_linger},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static t_opt opt[] = {
|
||||
{"keepalive", opt_keepalive},
|
||||
{"reuseaddr", opt_reuseaddr},
|
||||
|
@ -125,6 +135,12 @@ static int meth_setstats(lua_State *L) {
|
|||
/*-------------------------------------------------------------------------*\
|
||||
* Just call option handler
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int meth_getoption(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
|
||||
return opt_meth_getoption(L, optget, &tcp->sock);
|
||||
}
|
||||
|
||||
static int meth_setoption(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env lua
|
||||
|
||||
require"socket"
|
||||
|
||||
port = 8765
|
||||
|
||||
function options(o)
|
||||
print("options for", o)
|
||||
|
||||
for _, opt in ipairs{"keepalive", "reuseaddr", "tcp-nodelay"} do
|
||||
print("getoption", opt, o:getoption(opt))
|
||||
end
|
||||
|
||||
print("getoption", "linger",
|
||||
"on", o:getoption("linger").on,
|
||||
"timeout", o:getoption("linger").timeout)
|
||||
end
|
||||
|
||||
local m = socket.tcp()
|
||||
|
||||
options(m)
|
||||
|
||||
assert(m:bind("*", port))
|
||||
assert(m:listen())
|
||||
|
||||
options(m)
|
||||
|
||||
m:close()
|
||||
|
||||
local m = socket.bind("*", port)
|
||||
|
||||
options(m)
|
||||
|
||||
local c = socket.connect("localhost", port)
|
||||
|
||||
options(c)
|
||||
|
||||
local s = m:accept()
|
||||
|
||||
options(s)
|
||||
|
Loading…
Reference in New Issue