mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-25 12:08:21 +01:00
Support getoption method for tcp objects.
This commit is contained in:
parent
0716cb868e
commit
8bb542baaf
@ -172,6 +172,7 @@ Support, Manual">
|
|||||||
<a href="tcp.html#connect">connect</a>,
|
<a href="tcp.html#connect">connect</a>,
|
||||||
<a href="tcp.html#dirty">dirty</a>,
|
<a href="tcp.html#dirty">dirty</a>,
|
||||||
<a href="tcp.html#getfd">getfd</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#getpeername">getpeername</a>,
|
||||||
<a href="tcp.html#getsockname">getsockname</a>,
|
<a href="tcp.html#getsockname">getsockname</a>,
|
||||||
<a href="tcp.html#getstats">getstats</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>
|
</ul>
|
||||||
|
|
||||||
<p class=return>
|
<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>
|
||||||
|
|
||||||
<p class=note>
|
<p class=note>
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
\*=========================================================================*/
|
\*=========================================================================*/
|
||||||
static int opt_setmembership(lua_State *L, p_socket ps, int level, int name);
|
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_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,
|
static int opt_set(lua_State *L, p_socket ps, int level, int name,
|
||||||
void *val, int len);
|
void *val, int len);
|
||||||
|
static int opt_get(lua_State *L, p_socket ps, int level, int name,
|
||||||
|
void *val, int* len);
|
||||||
|
|
||||||
/*=========================================================================*\
|
/*=========================================================================*\
|
||||||
* Exported functions
|
* Exported functions
|
||||||
@ -40,23 +43,51 @@ int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps)
|
|||||||
return opt->func(L, 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 */
|
/* enables reuse of local address */
|
||||||
int opt_reuseaddr(lua_State *L, p_socket ps)
|
int opt_reuseaddr(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
|
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 */
|
/* disables the Naggle algorithm */
|
||||||
int opt_tcp_nodelay(lua_State *L, p_socket ps)
|
int opt_tcp_nodelay(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
|
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)
|
int opt_keepalive(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
|
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)
|
int opt_dontroute(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
|
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);
|
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
|
* 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));
|
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
|
static
|
||||||
int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
|
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;
|
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)
|
static int opt_setboolean(lua_State *L, p_socket ps, int level, int name)
|
||||||
{
|
{
|
||||||
int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */
|
int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */
|
||||||
|
@ -17,10 +17,17 @@
|
|||||||
typedef struct t_opt {
|
typedef struct t_opt {
|
||||||
const char *name;
|
const char *name;
|
||||||
int (*func)(lua_State *L, p_socket ps);
|
int (*func)(lua_State *L, p_socket ps);
|
||||||
|
int (*get)(lua_State *L, p_socket ps);
|
||||||
} t_opt;
|
} t_opt;
|
||||||
typedef t_opt *p_opt;
|
typedef t_opt *p_opt;
|
||||||
|
|
||||||
/* supported options */
|
/* 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_dontroute(lua_State *L, p_socket ps);
|
||||||
int opt_broadcast(lua_State *L, p_socket ps);
|
int opt_broadcast(lua_State *L, p_socket ps);
|
||||||
int opt_reuseaddr(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 */
|
/* invokes the appropriate option handler */
|
||||||
int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps);
|
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
|
#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_receive(lua_State *L);
|
||||||
static int meth_accept(lua_State *L);
|
static int meth_accept(lua_State *L);
|
||||||
static int meth_close(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_setoption(lua_State *L);
|
||||||
static int meth_settimeout(lua_State *L);
|
static int meth_settimeout(lua_State *L);
|
||||||
static int meth_getfd(lua_State *L);
|
static int meth_getfd(lua_State *L);
|
||||||
@ -47,6 +48,7 @@ static luaL_reg tcp[] = {
|
|||||||
{"connect", meth_connect},
|
{"connect", meth_connect},
|
||||||
{"dirty", meth_dirty},
|
{"dirty", meth_dirty},
|
||||||
{"getfd", meth_getfd},
|
{"getfd", meth_getfd},
|
||||||
|
{"getoption", meth_getoption},
|
||||||
{"getpeername", meth_getpeername},
|
{"getpeername", meth_getpeername},
|
||||||
{"getsockname", meth_getsockname},
|
{"getsockname", meth_getsockname},
|
||||||
{"getstats", meth_getstats},
|
{"getstats", meth_getstats},
|
||||||
@ -64,6 +66,14 @@ static luaL_reg tcp[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* socket option handlers */
|
/* 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[] = {
|
static t_opt opt[] = {
|
||||||
{"keepalive", opt_keepalive},
|
{"keepalive", opt_keepalive},
|
||||||
{"reuseaddr", opt_reuseaddr},
|
{"reuseaddr", opt_reuseaddr},
|
||||||
@ -125,6 +135,12 @@ static int meth_setstats(lua_State *L) {
|
|||||||
/*-------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------*\
|
||||||
* Just call option handler
|
* 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)
|
static int meth_setoption(lua_State *L)
|
||||||
{
|
{
|
||||||
p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
|
p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
|
||||||
|
41
test/tcp-getoptions
Executable file
41
test/tcp-getoptions
Executable file
@ -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
Block a user