1 /*=========================================================================*\
2 * Common option interface
4 \*=========================================================================*/
13 /*=========================================================================*\
14 * Internal functions prototypes
15 \*=========================================================================*/
16 static int opt_setmembership(lua_State
*L
, p_socket ps
, int level
, int name
);
17 static int opt_setboolean(lua_State
*L
, p_socket ps
, int level
, int name
);
18 static int opt_getboolean(lua_State
*L
, p_socket ps
, int level
, int name
);
19 static int opt_set(lua_State
*L
, p_socket ps
, int level
, int name
,
21 static int opt_get(lua_State
*L
, p_socket ps
, int level
, int name
,
24 /*=========================================================================*\
26 \*=========================================================================*/
27 /*-------------------------------------------------------------------------*\
28 * Calls appropriate option handler
29 \*-------------------------------------------------------------------------*/
30 int opt_meth_setoption(lua_State
*L
, p_opt opt
, p_socket ps
)
32 const char *name
= luaL_checkstring(L
, 2); /* obj, name, ... */
33 while (opt
->name
&& strcmp(name
, opt
->name
))
37 sprintf(msg
, "unsupported option `%.35s'", name
);
38 luaL_argerror(L
, 2, msg
);
40 return opt
->func(L
, ps
);
43 int opt_meth_getoption(lua_State
*L
, p_opt opt
, p_socket ps
)
45 const char *name
= luaL_checkstring(L
, 2); /* obj, name, ... */
46 while (opt
->name
&& strcmp(name
, opt
->name
))
50 sprintf(msg
, "unsupported option `%.35s'", name
);
51 luaL_argerror(L
, 2, msg
);
53 return opt
->func(L
, ps
);
56 /* enables reuse of local address */
57 int opt_set_reuseaddr(lua_State
*L
, p_socket ps
)
59 return opt_setboolean(L
, ps
, SOL_SOCKET
, SO_REUSEADDR
);
62 int opt_get_reuseaddr(lua_State
*L
, p_socket ps
)
64 return opt_getboolean(L
, ps
, SOL_SOCKET
, SO_REUSEADDR
);
67 /* enables reuse of local port */
68 int opt_set_reuseport(lua_State
*L
, p_socket ps
)
70 return opt_setboolean(L
, ps
, SOL_SOCKET
, SO_REUSEPORT
);
73 int opt_get_reuseport(lua_State
*L
, p_socket ps
)
75 return opt_getboolean(L
, ps
, SOL_SOCKET
, SO_REUSEPORT
);
78 /* disables the Naggle algorithm */
79 int opt_set_tcp_nodelay(lua_State
*L
, p_socket ps
)
81 return opt_setboolean(L
, ps
, IPPROTO_TCP
, TCP_NODELAY
);
84 int opt_get_tcp_nodelay(lua_State
*L
, p_socket ps
)
86 return opt_getboolean(L
, ps
, IPPROTO_TCP
, TCP_NODELAY
);
89 int opt_set_keepalive(lua_State
*L
, p_socket ps
)
91 return opt_setboolean(L
, ps
, SOL_SOCKET
, SO_KEEPALIVE
);
94 int opt_get_keepalive(lua_State
*L
, p_socket ps
)
96 return opt_getboolean(L
, ps
, SOL_SOCKET
, SO_KEEPALIVE
);
99 int opt_set_dontroute(lua_State
*L
, p_socket ps
)
101 return opt_setboolean(L
, ps
, SOL_SOCKET
, SO_DONTROUTE
);
104 int opt_set_broadcast(lua_State
*L
, p_socket ps
)
106 return opt_setboolean(L
, ps
, SOL_SOCKET
, SO_BROADCAST
);
109 int opt_set_ip_multicast_loop(lua_State
*L
, p_socket ps
)
111 return opt_setboolean(L
, ps
, IPPROTO_IP
, IP_MULTICAST_LOOP
);
114 int opt_get_ip_multicast_loop(lua_State
*L
, p_socket ps
)
116 return opt_getboolean(L
, ps
, IPPROTO_IP
, IP_MULTICAST_LOOP
);
119 int opt_set_linger(lua_State
*L
, p_socket ps
)
121 struct linger li
; /* obj, name, table */
122 if (!lua_istable(L
, 3)) auxiliar_typeerror(L
,3,lua_typename(L
, LUA_TTABLE
));
123 lua_pushstring(L
, "on");
125 if (!lua_isboolean(L
, -1))
126 luaL_argerror(L
, 3, "boolean 'on' field expected");
127 li
.l_onoff
= (u_short
) lua_toboolean(L
, -1);
128 lua_pushstring(L
, "timeout");
130 if (!lua_isnumber(L
, -1))
131 luaL_argerror(L
, 3, "number 'timeout' field expected");
132 li
.l_linger
= (u_short
) lua_tonumber(L
, -1);
133 return opt_set(L
, ps
, SOL_SOCKET
, SO_LINGER
, (char *) &li
, sizeof(li
));
136 int opt_get_linger(lua_State
*L
, p_socket ps
)
138 struct linger li
; /* obj, name */
139 int len
= sizeof(li
);
140 int err
= opt_get(L
, ps
, SOL_SOCKET
, SO_LINGER
, (char *) &li
, &len
);
144 lua_pushboolean(L
, li
.l_onoff
);
145 lua_setfield(L
, -2, "on");
146 lua_pushinteger(L
, li
.l_linger
);
147 lua_setfield(L
, -2, "timeout");
151 int opt_set_ip_multicast_ttl(lua_State
*L
, p_socket ps
)
153 int val
= (int) luaL_checknumber(L
, 3); /* obj, name, int */
154 return opt_set(L
, ps
, IPPROTO_IP
, IP_MULTICAST_TTL
,
155 (char *) &val
, sizeof(val
));
158 int opt_set_ip_multicast_if(lua_State
*L
, p_socket ps
)
160 const char *address
= luaL_checkstring(L
, 3); /* obj, name, ip */
162 val
.s_addr
= htonl(INADDR_ANY
);
163 if (strcmp(address
, "*") && !inet_aton(address
, &val
))
164 luaL_argerror(L
, 3, "ip expected");
165 return opt_set(L
, ps
, IPPROTO_IP
, IP_MULTICAST_IF
,
166 (char *) &val
, sizeof(val
));
169 int opt_get_ip_multicast_if(lua_State
*L
, p_socket ps
)
172 socklen_t len
= sizeof(val
);
173 if (getsockopt(*ps
, IPPROTO_IP
, IP_MULTICAST_IF
, (char *) &val
, &len
) < 0) {
175 lua_pushstring(L
, "getsockopt failed");
178 lua_pushstring(L
, inet_ntoa(val
));
182 int opt_set_ip_add_membership(lua_State
*L
, p_socket ps
)
184 return opt_setmembership(L
, ps
, IPPROTO_IP
, IP_ADD_MEMBERSHIP
);
187 int opt_set_ip_drop_membersip(lua_State
*L
, p_socket ps
)
189 return opt_setmembership(L
, ps
, IPPROTO_IP
, IP_DROP_MEMBERSHIP
);
192 int opt_set_ip6_v6only(lua_State
*L
, p_socket ps
)
194 return opt_setboolean(L
, ps
, IPPROTO_IPV6
, IPV6_V6ONLY
);
197 /*=========================================================================*\
199 \*=========================================================================*/
200 static int opt_setmembership(lua_State
*L
, p_socket ps
, int level
, int name
)
202 struct ip_mreq val
; /* obj, name, table */
203 if (!lua_istable(L
, 3)) auxiliar_typeerror(L
,3,lua_typename(L
, LUA_TTABLE
));
204 lua_pushstring(L
, "multiaddr");
206 if (!lua_isstring(L
, -1))
207 luaL_argerror(L
, 3, "string 'multiaddr' field expected");
208 if (!inet_aton(lua_tostring(L
, -1), &val
.imr_multiaddr
))
209 luaL_argerror(L
, 3, "invalid 'multiaddr' ip address");
210 lua_pushstring(L
, "interface");
212 if (!lua_isstring(L
, -1))
213 luaL_argerror(L
, 3, "string 'interface' field expected");
214 val
.imr_interface
.s_addr
= htonl(INADDR_ANY
);
215 if (strcmp(lua_tostring(L
, -1), "*") &&
216 !inet_aton(lua_tostring(L
, -1), &val
.imr_interface
))
217 luaL_argerror(L
, 3, "invalid 'interface' ip address");
218 return opt_set(L
, ps
, level
, name
, (char *) &val
, sizeof(val
));
222 int opt_get(lua_State
*L
, p_socket ps
, int level
, int name
, void *val
, int* len
)
224 socklen_t socklen
= *len
;
225 if (getsockopt(*ps
, level
, name
, (char *) val
, &socklen
) < 0) {
227 lua_pushstring(L
, "getsockopt failed");
235 int opt_set(lua_State
*L
, p_socket ps
, int level
, int name
, void *val
, int len
)
237 if (setsockopt(*ps
, level
, name
, (char *) val
, len
) < 0) {
239 lua_pushstring(L
, "setsockopt failed");
242 lua_pushnumber(L
, 1);
246 static int opt_getboolean(lua_State
*L
, p_socket ps
, int level
, int name
)
249 int len
= sizeof(val
);
250 int err
= opt_get(L
, ps
, level
, name
, (char *) &val
, &len
);
253 lua_pushboolean(L
, val
);
257 static int opt_setboolean(lua_State
*L
, p_socket ps
, int level
, int name
)
259 int val
= auxiliar_checkboolean(L
, 3); /* obj, name, bool */
260 return opt_set(L
, ps
, level
, name
, (char *) &val
, sizeof(val
));