aboutsummaryrefslogtreecommitdiff
path: root/src/tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tcp.c')
-rw-r--r--src/tcp.c164
1 files changed, 82 insertions, 82 deletions
diff --git a/src/tcp.c b/src/tcp.c
index 28f38f5..098e29d 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -29,10 +29,10 @@ static int meth_receive(lua_State *L);
29static int meth_accept(lua_State *L); 29static int meth_accept(lua_State *L);
30static int meth_close(lua_State *L); 30static int meth_close(lua_State *L);
31static int meth_setoption(lua_State *L); 31static int meth_setoption(lua_State *L);
32static int meth_timeout(lua_State *L); 32static int meth_settimeout(lua_State *L);
33static int meth_fd(lua_State *L); 33static int meth_fd(lua_State *L);
34static int meth_dirty(lua_State *L); 34static int meth_dirty(lua_State *L);
35static int opt_nodelay(lua_State *L); 35static int opt_tcp_nodelay(lua_State *L);
36static int opt_keepalive(lua_State *L); 36static int opt_keepalive(lua_State *L);
37static int opt_linger(lua_State *L); 37static int opt_linger(lua_State *L);
38 38
@@ -47,7 +47,7 @@ static luaL_reg tcp[] = {
47 {"setsockname", meth_bind}, 47 {"setsockname", meth_bind},
48 {"getpeername", meth_getpeername}, 48 {"getpeername", meth_getpeername},
49 {"getsockname", meth_getsockname}, 49 {"getsockname", meth_getsockname},
50 {"timeout", meth_timeout}, 50 {"settimeout", meth_settimeout},
51 {"close", meth_close}, 51 {"close", meth_close},
52 {"setoption", meth_setoption}, 52 {"setoption", meth_setoption},
53 {"__gc", meth_close}, 53 {"__gc", meth_close},
@@ -59,7 +59,7 @@ static luaL_reg tcp[] = {
59/* socket option handlers */ 59/* socket option handlers */
60static luaL_reg opt[] = { 60static luaL_reg opt[] = {
61 {"keepalive", opt_keepalive}, 61 {"keepalive", opt_keepalive},
62 {"nodelay", opt_nodelay}, 62 {"tcp-nodelay", opt_tcp_nodelay},
63 {"linger", opt_linger}, 63 {"linger", opt_linger},
64 {NULL, NULL} 64 {NULL, NULL}
65}; 65};
@@ -83,8 +83,8 @@ void tcp_open(lua_State *L)
83 aux_add2group(L, "tcp{master}", "tcp{any}"); 83 aux_add2group(L, "tcp{master}", "tcp{any}");
84 aux_add2group(L, "tcp{client}", "tcp{any}"); 84 aux_add2group(L, "tcp{client}", "tcp{any}");
85 aux_add2group(L, "tcp{server}", "tcp{any}"); 85 aux_add2group(L, "tcp{server}", "tcp{any}");
86 aux_add2group(L, "tcp{client}", "tcp{client, server}"); 86 aux_add2group(L, "tcp{client}", "tcp{client,server}");
87 aux_add2group(L, "tcp{server}", "tcp{client, server}"); 87 aux_add2group(L, "tcp{server}", "tcp{client,server}");
88 /* both server and client objects are selectable */ 88 /* both server and client objects are selectable */
89 aux_add2group(L, "tcp{client}", "select{able}"); 89 aux_add2group(L, "tcp{client}", "select{able}");
90 aux_add2group(L, "tcp{server}", "select{able}"); 90 aux_add2group(L, "tcp{server}", "select{able}");
@@ -121,7 +121,7 @@ static int meth_setoption(lua_State *L)
121 121
122static int opt_boolean(lua_State *L, int level, int name) 122static int opt_boolean(lua_State *L, int level, int name)
123{ 123{
124 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); 124 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1);
125 int val = aux_checkboolean(L, 2); 125 int val = aux_checkboolean(L, 2);
126 if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) { 126 if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) {
127 lua_pushnil(L); 127 lua_pushnil(L);
@@ -132,8 +132,8 @@ static int opt_boolean(lua_State *L, int level, int name)
132 return 1; 132 return 1;
133} 133}
134 134
135/* disables the Nagle algorithm */ 135/* disables the Naggle algorithm */
136static int opt_nodelay(lua_State *L) 136static int opt_tcp_nodelay(lua_State *L)
137{ 137{
138 struct protoent *pe = getprotobyname("TCP"); 138 struct protoent *pe = getprotobyname("TCP");
139 if (!pe) { 139 if (!pe) {
@@ -155,13 +155,13 @@ int opt_linger(lua_State *L)
155 struct linger li; 155 struct linger li;
156 if (!lua_istable(L, 2)) 156 if (!lua_istable(L, 2))
157 luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE)); 157 luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE));
158 lua_pushstring(L, "onoff"); 158 lua_pushstring(L, "on");
159 lua_gettable(L, 2); 159 lua_gettable(L, 2);
160 if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid onoff field"); 160 if (!lua_isboolean(L, -1)) luaL_argerror(L, 2, "invalid 'on' field");
161 li.l_onoff = (int) lua_tonumber(L, -1); 161 li.l_onoff = lua_toboolean(L, -1);
162 lua_pushstring(L, "linger"); 162 lua_pushstring(L, "timeout");
163 lua_gettable(L, 2); 163 lua_gettable(L, 2);
164 if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid linger field"); 164 if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid 'timeout' field");
165 li.l_linger = (int) lua_tonumber(L, -1); 165 li.l_linger = (int) lua_tonumber(L, -1);
166 if (setsockopt(tcp->sock, SOL_SOCKET, SO_LINGER, 166 if (setsockopt(tcp->sock, SOL_SOCKET, SO_LINGER,
167 (char *) &li, sizeof(li) < 0)) { 167 (char *) &li, sizeof(li) < 0)) {
@@ -178,122 +178,122 @@ int opt_linger(lua_State *L)
178\*-------------------------------------------------------------------------*/ 178\*-------------------------------------------------------------------------*/
179static int meth_fd(lua_State *L) 179static int meth_fd(lua_State *L)
180{ 180{
181 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); 181 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1);
182 lua_pushnumber(L, tcp->sock); 182 lua_pushnumber(L, tcp->sock);
183 return 1; 183 return 1;
184} 184}
185 185
186static int meth_dirty(lua_State *L) 186static int meth_dirty(lua_State *L)
187{ 187{
188 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); 188 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1);
189 lua_pushboolean(L, !buf_isempty(&tcp->buf)); 189 lua_pushboolean(L, !buf_isempty(&tcp->buf));
190 return 1; 190 return 1;
191} 191}
192 192
193/*-------------------------------------------------------------------------*\ 193/*-------------------------------------------------------------------------*\
194* Just call inet methods 194* Waits for and returns a client object attempting connection to the
195\*-------------------------------------------------------------------------*/ 195* server object
196static int meth_getpeername(lua_State *L)
197{
198 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
199 return inet_meth_getpeername(L, &tcp->sock);
200}
201
202static int meth_getsockname(lua_State *L)
203{
204 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
205 return inet_meth_getsockname(L, &tcp->sock);
206}
207
208/*-------------------------------------------------------------------------*\
209* Just call tm methods
210\*-------------------------------------------------------------------------*/
211static int meth_timeout(lua_State *L)
212{
213 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
214 return tm_meth_timeout(L, &tcp->tm);
215}
216
217/*-------------------------------------------------------------------------*\
218* Closes socket used by object
219\*-------------------------------------------------------------------------*/ 196\*-------------------------------------------------------------------------*/
220static int meth_close(lua_State *L) 197static int meth_accept(lua_State *L)
221{ 198{
222 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); 199 struct sockaddr_in addr;
223 sock_destroy(&tcp->sock); 200 socklen_t addr_len = sizeof(addr);
224 return 0; 201 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
202 p_tm tm = &server->tm;
203 p_tcp client = lua_newuserdata(L, sizeof(t_tcp));
204 tm_markstart(tm);
205 aux_setclass(L, "tcp{client}", -1);
206 for ( ;; ) {
207 sock_accept(&server->sock, &client->sock,
208 (SA *) &addr, &addr_len, tm_get(tm));
209 if (client->sock == SOCK_INVALID) {
210 if (tm_get(tm) == 0) {
211 lua_pushnil(L);
212 io_pusherror(L, IO_TIMEOUT);
213 return 2;
214 }
215 } else break;
216 }
217 /* initialize remaining structure fields */
218 io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock);
219 tm_init(&client->tm, -1, -1);
220 buf_init(&client->buf, &client->io, &client->tm);
221 return 1;
225} 222}
226 223
227/*-------------------------------------------------------------------------*\ 224/*-------------------------------------------------------------------------*\
228* Turns a master tcp object into a client object. 225* Turns a master object into a server object
229\*-------------------------------------------------------------------------*/ 226\*-------------------------------------------------------------------------*/
230static int meth_connect(lua_State *L) 227static int meth_bind(lua_State *L)
231{ 228{
232 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 229 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
233 const char *address = luaL_checkstring(L, 2); 230 const char *address = luaL_checkstring(L, 2);
234 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 231 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
235 const char *err = inet_tryconnect(&tcp->sock, address, port); 232 int backlog = (int) luaL_optnumber(L, 4, 1);
233 const char *err = inet_trybind(&tcp->sock, address, port, backlog);
236 if (err) { 234 if (err) {
237 lua_pushnil(L); 235 lua_pushnil(L);
238 lua_pushstring(L, err); 236 lua_pushstring(L, err);
239 return 2; 237 return 2;
240 } 238 }
241 /* turn master object into a client object */ 239 /* turn master object into a server object */
242 aux_setclass(L, "tcp{client}", 1); 240 aux_setclass(L, "tcp{server}", 1);
243 lua_pushnumber(L, 1); 241 lua_pushnumber(L, 1);
244 return 1; 242 return 1;
245} 243}
246 244
247/*-------------------------------------------------------------------------*\ 245/*-------------------------------------------------------------------------*\
248* Turns a master object into a server object 246* Turns a master tcp object into a client object.
249\*-------------------------------------------------------------------------*/ 247\*-------------------------------------------------------------------------*/
250static int meth_bind(lua_State *L) 248static int meth_connect(lua_State *L)
251{ 249{
252 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 250 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
253 const char *address = luaL_checkstring(L, 2); 251 const char *address = luaL_checkstring(L, 2);
254 unsigned short port = (unsigned short) luaL_checknumber(L, 3); 252 unsigned short port = (unsigned short) luaL_checknumber(L, 3);
255 int backlog = (int) luaL_optnumber(L, 4, 1); 253 const char *err = inet_tryconnect(&tcp->sock, address, port);
256 const char *err = inet_trybind(&tcp->sock, address, port, backlog);
257 if (err) { 254 if (err) {
258 lua_pushnil(L); 255 lua_pushnil(L);
259 lua_pushstring(L, err); 256 lua_pushstring(L, err);
260 return 2; 257 return 2;
261 } 258 }
262 /* turn master object into a server object */ 259 /* turn master object into a client object */
263 aux_setclass(L, "tcp{server}", 1); 260 aux_setclass(L, "tcp{client}", 1);
264 lua_pushnumber(L, 1); 261 lua_pushnumber(L, 1);
265 return 1; 262 return 1;
266} 263}
267 264
268/*-------------------------------------------------------------------------*\ 265/*-------------------------------------------------------------------------*\
269* Waits for and returns a client object attempting connection to the 266* Closes socket used by object
270* server object
271\*-------------------------------------------------------------------------*/ 267\*-------------------------------------------------------------------------*/
272static int meth_accept(lua_State *L) 268static int meth_close(lua_State *L)
273{ 269{
274 struct sockaddr_in addr; 270 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
275 socklen_t addr_len = sizeof(addr); 271 sock_destroy(&tcp->sock);
276 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); 272 return 0;
277 p_tm tm = &server->tm; 273}
278 p_tcp client = lua_newuserdata(L, sizeof(t_tcp)); 274
279 tm_markstart(tm); 275/*-------------------------------------------------------------------------*\
280 aux_setclass(L, "tcp{client}", -1); 276* Just call inet methods
281 for ( ;; ) { 277\*-------------------------------------------------------------------------*/
282 sock_accept(&server->sock, &client->sock, 278static int meth_getpeername(lua_State *L)
283 (SA *) &addr, &addr_len, tm_get(tm)); 279{
284 if (client->sock == SOCK_INVALID) { 280 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
285 if (tm_get(tm) == 0) { 281 return inet_meth_getpeername(L, &tcp->sock);
286 lua_pushnil(L); 282}
287 io_pusherror(L, IO_TIMEOUT); 283
288 return 2; 284static int meth_getsockname(lua_State *L)
289 } 285{
290 } else break; 286 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1);
291 } 287 return inet_meth_getsockname(L, &tcp->sock);
292 /* initialize remaining structure fields */ 288}
293 io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock); 289
294 tm_init(&client->tm, -1, -1); 290/*-------------------------------------------------------------------------*\
295 buf_init(&client->buf, &client->io, &client->tm); 291* Just call tm methods
296 return 1; 292\*-------------------------------------------------------------------------*/
293static int meth_settimeout(lua_State *L)
294{
295 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client,server}", 1);
296 return tm_meth_settimeout(L, &tcp->tm);
297} 297}
298 298
299/*=========================================================================*\ 299/*=========================================================================*\