]>
jfr.im git - irc/quakenet/newserv.git/blob - lua/luasocket.c
1 /* Copyright (C) Chris Porter 2007 */
6 #include <netinet/in.h>
7 #include <sys/socket.h>
11 #include "../lib/strlfunc.h"
12 #include "../core/events.h"
17 #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__)
20 * instead of these identifiers I could just use the file descriptor...
21 * BUT I can't remember the exact semantics of the fd table WRT reuse...
23 static long nextidentifier
= 0;
24 static void lua_socket_poll_event(int fd
, short events
);
26 static int getunixsocket(char *path
, struct sockaddr_un
*r
) {
27 int fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
33 memset(r
, 0, sizeof(struct sockaddr_un
));
34 r
->sun_family
= AF_UNIX
;
35 strlcpy(r
->sun_path
, path
, sizeof(r
->sun_path
));
38 ret
= fcntl(fd
, F_GETFL
, 0);
44 ret
= fcntl(fd
, F_SETFL
, ret
| O_NONBLOCK
);
53 static void registerluasocket(lua_list
*ll
, lua_socket
*ls
, int mask
, int settag
) {
54 /* this whole identifier thing should probably use userdata stuff */
55 ls
->identifier
= nextidentifier
++;
58 ls
->tag
= luaL_ref(ll
->l
, LUA_REGISTRYINDEX
);
59 ls
->handler
= luaL_ref(ll
->l
, LUA_REGISTRYINDEX
);
63 ls
->next
= ll
->sockets
;
66 registerhandler(ls
->fd
, mask
, lua_socket_poll_event
);
69 static int lua_socket_unix_connect(lua_State
*l
) {
76 ll
= lua_listfromstate(l
);
80 if(!lua_isfunction(l
, 2))
83 path
= (char *)lua_tostring(l
, 1);
87 ls
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
91 ls
->fd
= getunixsocket(path
, &r
);
97 ret
= connect(ls
->fd
, (struct sockaddr
*)&r
, sizeof(r
.sun_family
) + strlen(r
.sun_path
));
99 ls
->state
= SOCKET_CONNECTED
;
100 } else if(ret
== -1 && (errno
== EINPROGRESS
)) {
101 ls
->state
= SOCKET_CONNECTING
;
109 registerluasocket(ll
, ls
, (ls
->state
==SOCKET_CONNECTED
?POLLIN
:POLLOUT
) | POLLERR
| POLLHUP
, 1);
111 lua_pushboolean(l
, ls
->state
==SOCKET_CONNECTED
?1:0);
112 lua_pushlong(l
, ls
->identifier
);
116 static int lua_socket_unix_bind(lua_State
*l
) {
120 struct sockaddr_un r
;
122 ll
= lua_listfromstate(l
);
126 if(!lua_isfunction(l
, 2))
129 path
= (char *)lua_tostring(l
, 1);
133 ls
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
137 ls
->fd
= getunixsocket(path
, &r
);
146 (bind(ls
->fd
, (struct sockaddr
*)&r
, strlen(r
.sun_path
) + sizeof(r
.sun_family
)) == -1) ||
147 (listen(ls
->fd
, 5) == -1)
154 ls
->state
= SOCKET_LISTENING
;
157 registerluasocket(ll
, ls
, POLLIN
, 1);
159 lua_pushlong(l
, ls
->identifier
);
163 static lua_socket
*socketbyfd(int fd
) {
167 for(l
=lua_head
;l
;l
=l
->next
)
168 for(ls
=l
->sockets
;ls
;ls
=ls
->next
)
175 static lua_socket
*socketbyidentifier(long identifier
) {
179 for(l
=lua_head
;l
;l
=l
->next
)
180 for(ls
=l
->sockets
;ls
;ls
=ls
->next
)
181 if(ls
->identifier
== identifier
)
187 static void lua_socket_call_close(lua_socket
*ls
) {
190 for(c
=ls
->l
->sockets
;c
;c
=p
) {
193 lua_socket_call_close(c
);
196 for(c
=ls
->l
->sockets
,p
=NULL
;c
;p
=c
,c
=c
->next
) {
198 if(ls
->state
== SOCKET_CLOSED
)
201 ls
->state
= SOCKET_CLOSED
;
202 deregisterhandler(ls
->fd
, 1);
204 lua_vnpcall(ls
, "close", "");
207 ls
->l
->sockets
= ls
->next
;
213 luaL_unref(ls
->l
->l
, LUA_REGISTRYINDEX
, ls
->tag
);
214 luaL_unref(ls
->l
->l
, LUA_REGISTRYINDEX
, ls
->handler
);
223 static int lua_socket_write(lua_State
*l
) {
229 buf
= (char *)lua_tostring(l
, 2);
231 if(!lua_islong(l
, 1) || !buf
) {
235 len
= lua_strlen(l
, 2);
237 ls
= socketbyidentifier(lua_tolong(l
, 1));
238 if(!ls
|| (ls
->state
!= SOCKET_CONNECTED
)) {
243 ret
= write(ls
->fd
, buf
, len
);
244 if(ret
== -1 && (errno
== EAGAIN
)) {
245 deregisterhandler(ls
->fd
, 0);
246 registerhandler(ls
->fd
, POLLIN
| POLLOUT
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
253 lua_socket_call_close(ls
);
256 deregisterhandler(ls
->fd
, 0);
257 registerhandler(ls
->fd
, POLLIN
| POLLOUT
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
264 static int lua_socket_close(lua_State
*l
) {
267 if(!lua_islong(l
, 1))
268 LUA_RETURN(l
, LUA_FAIL
);
270 ls
= socketbyidentifier(lua_tolong(l
, 1));
271 if(!ls
|| (ls
->state
== SOCKET_CLOSED
))
272 LUA_RETURN(l
, LUA_FAIL
);
274 lua_socket_call_close(ls
);
276 LUA_RETURN(l
, LUA_OK
);
279 static void lua_socket_poll_event(int fd
, short events
) {
280 lua_socket
*ls
= socketbyfd(fd
);
281 if(!ls
|| (ls
->state
== SOCKET_CLOSED
))
284 if(events
& (POLLERR
| POLLHUP
)) {
285 lua_socket_call_close(ls
);
290 case SOCKET_CONNECTING
:
291 if(events
& POLLOUT
) {
292 deregisterhandler(fd
, 0);
293 registerhandler(fd
, POLLIN
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
294 ls
->state
= SOCKET_CONNECTED
;
296 lua_vnpcall(ls
, "connect", "");
299 case SOCKET_CONNECTED
:
300 if(events
& POLLOUT
) {
301 deregisterhandler(fd
, 0);
302 registerhandler(fd
, POLLIN
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
304 lua_vnpcall(ls
, "flush", "");
306 if(events
& POLLIN
) {
310 bytesread
= read(fd
, buf
, sizeof(buf
));
311 if((bytesread
== -1) && (errno
== EAGAIN
))
315 lua_socket_call_close(ls
);
319 lua_vnpcall(ls
, "read", "L", buf
, (long)bytesread
);
322 case SOCKET_LISTENING
:
323 if(events
& POLLIN
) {
324 struct sockaddr_un r
;
326 unsigned int len
= sizeof(r
);
328 int fd2
= accept(fd
, (struct sockaddr
*)&r
, &len
);
332 ls2
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
339 ls2
->state
= SOCKET_CONNECTED
;
341 ls2
->handler
= ls
->handler
;
344 registerluasocket(ls
->l
, ls2
, POLLIN
| POLLERR
| POLLHUP
, 0);
345 lua_vnpcall(ls
, "accept", "l", ls2
->identifier
);
351 void lua_socket_closeall(lua_list
*l
) {
353 lua_socket_call_close(l
->sockets
);
356 void lua_registersocketcommands(lua_State
*l
) {
357 lua_register(l
, "socket_unix_connect", lua_socket_unix_connect
);
358 lua_register(l
, "socket_unix_bind", lua_socket_unix_bind
);
359 lua_register(l
, "socket_close", lua_socket_close
);
360 lua_register(l
, "socket_write", lua_socket_write
);