beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luasocket / src / options.c
blob6cae7eeb9248f61db155ade164d9ec599b879223
1 /*=========================================================================*\
2 * Common option interface
3 * LuaSocket toolkit
4 \*=========================================================================*/
5 #include <string.h>
7 #include "lauxlib.h"
9 #include "auxiliar.h"
10 #include "options.h"
11 #include "inet.h"
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,
20 void *val, int len);
21 static int opt_get(lua_State *L, p_socket ps, int level, int name,
22 void *val, int* len);
24 /*=========================================================================*\
25 * Exported functions
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))
34 opt++;
35 if (!opt->func) {
36 char msg[45];
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))
47 opt++;
48 if (!opt->func) {
49 char msg[45];
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");
124 lua_gettable(L, 3);
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");
129 lua_gettable(L, 3);
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);
141 if (err)
142 return err;
143 lua_newtable(L);
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");
148 return 1;
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 */
161 struct in_addr val;
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)
171 struct in_addr val;
172 socklen_t len = sizeof(val);
173 if (getsockopt(*ps, IPPROTO_IP, IP_MULTICAST_IF, (char *) &val, &len) < 0) {
174 lua_pushnil(L);
175 lua_pushstring(L, "getsockopt failed");
176 return 2;
178 lua_pushstring(L, inet_ntoa(val));
179 return 1;
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 /*=========================================================================*\
198 * Auxiliar functions
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");
205 lua_gettable(L, 3);
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");
211 lua_gettable(L, 3);
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));
221 static
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) {
226 lua_pushnil(L);
227 lua_pushstring(L, "getsockopt failed");
228 return 2;
230 *len = socklen;
231 return 0;
234 static
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) {
238 lua_pushnil(L);
239 lua_pushstring(L, "setsockopt failed");
240 return 2;
242 lua_pushnumber(L, 1);
243 return 1;
246 static int opt_getboolean(lua_State *L, p_socket ps, int level, int name)
248 int val = 0;
249 int len = sizeof(val);
250 int err = opt_get(L, ps, level, name, (char *) &val, &len);
251 if (err)
252 return err;
253 lua_pushboolean(L, val);
254 return 1;
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));