]>
jfr.im git - irc/quakenet/newserv.git/blob - lua/luasocket.c
1 /* Copyright (C) Chris Porter 2007 */
6 #include <sys/socket.h>
7 #include <netinet/in.h>
9 #define __USE_MISC /* inet_aton */
11 #include <arpa/inet.h>
16 #include "../lib/strlfunc.h"
17 #include "../core/events.h"
22 #define lua_vnpcall(F2, N2, S2, ...) _lua_vpcall(F2->l->l, (void *)F2->handler, LUA_POINTERMODE, "lsR" S2 , F2->identifier, N2, F2->tag , ##__VA_ARGS__)
25 * instead of these identifiers I could just use the file descriptor...
26 * BUT I can't remember the exact semantics of the fd table WRT reuse...
28 static long nextidentifier
= 0;
29 static void lua_socket_poll_event(int fd
, short events
);
31 static int setnonblock(int fd
) {
35 ret
= fcntl(fd
, F_GETFL
, 0);
41 ret
= fcntl(fd
, F_SETFL
, ret
| O_NONBLOCK
);
49 static int getunixsocket(char *path
, struct sockaddr_un
*r
) {
50 int fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
55 memset(r
, 0, sizeof(struct sockaddr_un
));
56 r
->sun_family
= PF_UNIX
;
57 strlcpy(r
->sun_path
, path
, sizeof(r
->sun_path
));
59 return setnonblock(fd
);
62 /* note ADDRESS not HOSTNAME */
63 static int getipsocket(char *address
, int port
, int protocol
, struct sockaddr_in
*r
) {
67 memset(r
, 0, sizeof(struct sockaddr_in
));
68 r
->sin_family
= PF_INET
;
71 if(!inet_aton(address
, &r
->sin_addr
)) {
72 Error("lua", ERR_ERROR
, "Could not parse address: %s", address
);
79 fd
= socket(AF_INET
, protocol
, 0);
84 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof(val
));
86 r
->sin_port
= htons(port
);
87 return setnonblock(fd
);
90 static void registerluasocket(lua_list
*ll
, lua_socket
*ls
, int mask
, int settag
) {
91 /* this whole identifier thing should probably use userdata stuff */
92 ls
->identifier
= nextidentifier
++;
95 ls
->tag
= luaL_ref(ll
->l
, LUA_REGISTRYINDEX
);
96 ls
->handler
= luaL_ref(ll
->l
, LUA_REGISTRYINDEX
);
100 ls
->next
= ll
->sockets
;
103 registerhandler(ls
->fd
, mask
, lua_socket_poll_event
);
106 static int handleconnect(int ret
, lua_State
*l
, lua_list
*ll
, lua_socket
*ls
) {
108 ls
->state
= SOCKET_CONNECTED
;
109 } else if(ret
== -1 && (errno
== EINPROGRESS
)) {
110 ls
->state
= SOCKET_CONNECTING
;
118 registerluasocket(ll
, ls
, (ls
->state
==SOCKET_CONNECTED
?POLLIN
:POLLOUT
) | POLLERR
| POLLHUP
, 1);
120 lua_pushboolean(l
, ls
->state
==SOCKET_CONNECTED
?1:0);
121 lua_pushlong(l
, ls
->identifier
);
125 static int lua_socket_unix_connect(lua_State
*l
) {
127 struct sockaddr_un r
;
132 ll
= lua_listfromstate(l
);
136 if(!lua_isfunction(l
, 2))
139 path
= (char *)lua_tostring(l
, 1);
143 ls
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
147 ls
->sockettype
= PF_UNIX
;
148 ls
->fd
= getunixsocket(path
, &r
);
154 ret
= connect(ls
->fd
, (struct sockaddr
*)&r
, sizeof(r
.sun_family
) + strlen(r
.sun_path
));
155 return handleconnect(ret
, l
, ll
, ls
);
158 static int lua_socket_unix_bind(lua_State
*l
) {
162 struct sockaddr_un r
;
164 ll
= lua_listfromstate(l
);
168 if(!lua_isfunction(l
, 2))
171 path
= (char *)lua_tostring(l
, 1);
175 ls
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
179 ls
->sockettype
= PF_UNIX
;
180 ls
->fd
= getunixsocket(path
, &r
);
189 (bind(ls
->fd
, (struct sockaddr
*)&r
, strlen(r
.sun_path
) + sizeof(r
.sun_family
)) == -1) ||
190 (listen(ls
->fd
, 5) == -1)
197 ls
->state
= SOCKET_LISTENING
;
200 registerluasocket(ll
, ls
, POLLIN
, 1);
202 lua_pushlong(l
, ls
->identifier
);
206 static int lua_socket_ip_connect(lua_State
*l
, int protocol
) {
208 struct sockaddr_in r
;
214 ll
= lua_listfromstate(l
);
218 if(!lua_isfunction(l
, 3) || !lua_islong(l
, 2))
221 address
= (char *)lua_tostring(l
, 1);
225 port
= lua_tolong(l
, 2);
227 ls
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
231 ls
->sockettype
= PF_INET
;
232 ls
->fd
= getipsocket(address
, port
, protocol
, &r
);
238 ret
= connect(ls
->fd
, (struct sockaddr
*)&r
, sizeof(struct sockaddr_in
));
239 return handleconnect(ret
, l
, ll
, ls
);
242 static int lua_socket_ip_bind(lua_State
*l
, int protocol
) {
247 struct sockaddr_in r
;
249 ll
= lua_listfromstate(l
);
253 if(!lua_isfunction(l
, 3) || !lua_islong(l
, 2))
256 /* address can be nil or a string */
257 if(!lua_isnil(l
, 1) && !lua_isstring(l
, 1))
260 address
= (char *)lua_tostring(l
, 1);
261 port
= lua_tolong(l
, 2);
263 ls
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
267 ls
->sockettype
= PF_INET
;
268 ls
->fd
= getipsocket(address
, port
, protocol
, &r
);
275 (bind(ls
->fd
, (struct sockaddr
*)&r
, sizeof(struct sockaddr_in
)) == -1) ||
276 (listen(ls
->fd
, 5) == -1)
283 ls
->state
= SOCKET_LISTENING
;
286 registerluasocket(ll
, ls
, POLLIN
, 1);
288 lua_pushlong(l
, ls
->identifier
);
292 static int lua_socket_tcp_connect(lua_State
*l
) {
293 return lua_socket_ip_connect(l
, SOCK_STREAM
);
296 static int lua_socket_tcp_bind(lua_State
*l
) {
297 return lua_socket_ip_bind(l
, SOCK_STREAM
);
300 static int lua_socket_udp_connect(lua_State
*l
) {
301 return lua_socket_ip_connect(l
, SOCK_DGRAM
);
304 static int lua_socket_udp_bind(lua_State
*l
) {
305 return lua_socket_ip_bind(l
, SOCK_DGRAM
);
308 static lua_socket
*socketbyfd(int fd
) {
312 for(l
=lua_head
;l
;l
=l
->next
)
313 for(ls
=l
->sockets
;ls
;ls
=ls
->next
)
320 static lua_socket
*socketbyidentifier(long identifier
) {
324 for(l
=lua_head
;l
;l
=l
->next
)
325 for(ls
=l
->sockets
;ls
;ls
=ls
->next
)
326 if(ls
->identifier
== identifier
)
332 static void lua_socket_call_close(lua_socket
*ls
) {
335 for(c
=ls
->l
->sockets
;c
;c
=p
) {
338 lua_socket_call_close(c
);
341 for(c
=ls
->l
->sockets
,p
=NULL
;c
;p
=c
,c
=c
->next
) {
343 if(ls
->state
== SOCKET_CLOSED
)
346 ls
->state
= SOCKET_CLOSED
;
347 deregisterhandler(ls
->fd
, 1);
349 lua_vnpcall(ls
, "close", "");
352 ls
->l
->sockets
= ls
->next
;
358 luaL_unref(ls
->l
->l
, LUA_REGISTRYINDEX
, ls
->tag
);
359 luaL_unref(ls
->l
->l
, LUA_REGISTRYINDEX
, ls
->handler
);
368 static int lua_socket_write(lua_State
*l
) {
374 buf
= (char *)lua_tostring(l
, 2);
376 if(!lua_islong(l
, 1) || !buf
) {
380 len
= lua_strlen(l
, 2);
382 ls
= socketbyidentifier(lua_tolong(l
, 1));
383 if(!ls
|| (ls
->state
!= SOCKET_CONNECTED
)) {
388 ret
= write(ls
->fd
, buf
, len
);
389 if(ret
== -1 && (errno
== EAGAIN
)) {
390 deregisterhandler(ls
->fd
, 0);
391 registerhandler(ls
->fd
, POLLIN
| POLLOUT
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
398 lua_socket_call_close(ls
);
401 deregisterhandler(ls
->fd
, 0);
402 registerhandler(ls
->fd
, POLLIN
| POLLOUT
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
409 static int lua_socket_close(lua_State
*l
) {
412 if(!lua_islong(l
, 1))
413 LUA_RETURN(l
, LUA_FAIL
);
415 ls
= socketbyidentifier(lua_tolong(l
, 1));
416 if(!ls
|| (ls
->state
== SOCKET_CLOSED
))
417 LUA_RETURN(l
, LUA_FAIL
);
419 lua_socket_call_close(ls
);
421 LUA_RETURN(l
, LUA_OK
);
424 static void lua_socket_poll_event(int fd
, short events
) {
425 lua_socket
*ls
= socketbyfd(fd
);
426 if(!ls
|| (ls
->state
== SOCKET_CLOSED
))
429 if(events
& (POLLERR
| POLLHUP
)) {
430 lua_socket_call_close(ls
);
435 case SOCKET_CONNECTING
:
436 if(events
& POLLOUT
) {
437 deregisterhandler(fd
, 0);
438 registerhandler(fd
, POLLIN
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
439 ls
->state
= SOCKET_CONNECTED
;
441 lua_vnpcall(ls
, "connect", "");
444 case SOCKET_CONNECTED
:
445 if(events
& POLLOUT
) {
446 deregisterhandler(fd
, 0);
447 registerhandler(fd
, POLLIN
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
449 lua_vnpcall(ls
, "flush", "");
451 if(events
& POLLIN
) {
455 bytesread
= read(fd
, buf
, sizeof(buf
));
456 if((bytesread
== -1) && (errno
== EAGAIN
))
460 lua_socket_call_close(ls
);
464 lua_vnpcall(ls
, "read", "L", buf
, (long)bytesread
);
467 case SOCKET_LISTENING
:
468 if(events
& POLLIN
) {
469 struct sockaddr_in rip
;
470 struct sockaddr_un run
;
475 if(ls
->sockettype
== PF_INET
) {
477 fd2
= accept(fd
, (struct sockaddr
*)&rip
, &len
);
480 fd2
= accept(fd
, (struct sockaddr
*)&run
, &len
);
485 ls2
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
492 ls2
->state
= SOCKET_CONNECTED
;
494 ls2
->handler
= ls
->handler
;
496 ls2
->sockettype
= ls
->sockettype
;
498 registerluasocket(ls
->l
, ls2
, POLLIN
| POLLERR
| POLLHUP
, 0);
499 lua_vnpcall(ls
, "accept", "l", ls2
->identifier
);
505 void lua_socket_closeall(lua_list
*l
) {
507 lua_socket_call_close(l
->sockets
);
510 void lua_registersocketcommands(lua_State
*l
) {
511 lua_register(l
, "socket_unix_connect", lua_socket_unix_connect
);
512 lua_register(l
, "socket_unix_bind", lua_socket_unix_bind
);
513 lua_register(l
, "socket_tcp_connect", lua_socket_tcp_connect
);
514 lua_register(l
, "socket_tcp_bind", lua_socket_tcp_bind
);
515 lua_register(l
, "socket_udp_connect", lua_socket_udp_connect
);
516 lua_register(l
, "socket_udp_bind", lua_socket_udp_bind
);
517 lua_register(l
, "socket_close", lua_socket_close
);
518 lua_register(l
, "socket_write", lua_socket_write
);