]>
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 lua_socket_unix_connect(lua_State
*l
) {
33 ll
= lua_listfromstate(l
);
37 if(!lua_isfunction(l
, 2))
40 path
= (char *)lua_tostring(l
, 1);
44 ls
= (lua_socket
*)luamalloc(sizeof(lua_socket
));
48 ls
->fd
= socket(AF_UNIX
, SOCK_STREAM
, 0);
54 memset(&r
, 0, sizeof(r
));
55 r
.sun_family
= AF_UNIX
;
56 strlcpy(r
.sun_path
, path
, sizeof(r
.sun_path
));
58 /* don't really like this, there's a macro in sys/un.h but it's not there under FreeBSD */
59 len
= sizeof(r
.sun_family
) + strlen(r
.sun_path
) + 1;
62 ret
= fcntl(ls
->fd
, F_GETFL
, 0);
69 ret
= fcntl(ls
->fd
, F_SETFL
, ret
| O_NONBLOCK
);
76 ret
= connect(ls
->fd
, (struct sockaddr
*)&r
, len
);
78 ls
->state
= SOCKET_CONNECTED
;
79 } else if(ret
== -1 && (errno
== EINPROGRESS
)) {
80 ls
->state
= SOCKET_CONNECTING
;
87 /* this whole identifier thing should probably use userdata stuff */
88 ls
->identifier
= nextidentifier
++;
89 ls
->tag
= luaL_ref(l
, LUA_REGISTRYINDEX
);
90 ls
->handler
= luaL_ref(l
, LUA_REGISTRYINDEX
);
94 ls
->next
= ll
->sockets
;
97 registerhandler(ls
->fd
, (ls
->state
==SOCKET_CONNECTED
?POLLIN
:POLLOUT
) | POLLERR
| POLLHUP
, lua_socket_poll_event
);
99 lua_pushboolean(l
, ls
->state
==SOCKET_CONNECTED
?1:0);
100 lua_pushlong(l
, ls
->identifier
);
104 static lua_socket
*socketbyfd(int fd
) {
108 for(l
=lua_head
;l
;l
=l
->next
)
109 for(ls
=l
->sockets
;ls
;ls
=ls
->next
)
116 static lua_socket
*socketbyidentifier(long identifier
) {
120 for(l
=lua_head
;l
;l
=l
->next
)
121 for(ls
=l
->sockets
;ls
;ls
=ls
->next
)
122 if(ls
->identifier
== identifier
)
128 static void lua_socket_call_close(lua_socket
*ls
) {
131 for(c
=ls
->l
->sockets
,p
=NULL
;c
;p
=c
,c
=c
->next
) {
133 if(ls
->state
== SOCKET_CLOSED
)
136 ls
->state
= SOCKET_CLOSED
;
137 deregisterhandler(ls
->fd
, 1);
139 lua_vnpcall(ls
, "close", "");
142 ls
->l
->sockets
= ls
->next
;
147 luaL_unref(ls
->l
->l
, LUA_REGISTRYINDEX
, ls
->tag
);
148 luaL_unref(ls
->l
->l
, LUA_REGISTRYINDEX
, ls
->handler
);
157 static int lua_socket_write(lua_State
*l
) {
163 buf
= (char *)lua_tostring(l
, 2);
165 if(!lua_islong(l
, 1) || !buf
) {
169 len
= lua_strlen(l
, 2);
171 ls
= socketbyidentifier(lua_tolong(l
, 1));
172 if(!ls
|| (ls
->state
!= SOCKET_CONNECTED
)) {
177 ret
= write(ls
->fd
, buf
, len
);
178 if(ret
== -1 && (errno
== EAGAIN
)) {
179 deregisterhandler(ls
->fd
, 0);
180 registerhandler(ls
->fd
, POLLIN
| POLLOUT
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
187 lua_socket_call_close(ls
);
190 deregisterhandler(ls
->fd
, 0);
191 registerhandler(ls
->fd
, POLLIN
| POLLOUT
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
198 static int lua_socket_close(lua_State
*l
) {
201 if(!lua_islong(l
, 1))
202 LUA_RETURN(l
, LUA_FAIL
);
204 ls
= socketbyidentifier(lua_tolong(l
, 1));
205 if(!ls
|| (ls
->state
== SOCKET_CLOSED
))
206 LUA_RETURN(l
, LUA_FAIL
);
208 lua_socket_call_close(ls
);
210 LUA_RETURN(l
, LUA_OK
);
213 static void lua_socket_poll_event(int fd
, short events
) {
214 lua_socket
*ls
= socketbyfd(fd
);
215 if(!ls
|| (ls
->state
== SOCKET_CLOSED
))
218 if(events
& (POLLERR
| POLLHUP
)) {
219 lua_socket_call_close(ls
);
224 case SOCKET_CONNECTING
:
225 if(events
& POLLOUT
) {
226 deregisterhandler(fd
, 0);
227 registerhandler(fd
, POLLIN
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
228 ls
->state
= SOCKET_CONNECTED
;
230 lua_vnpcall(ls
, "connect", "");
233 case SOCKET_CONNECTED
:
234 if(events
& POLLOUT
) {
235 deregisterhandler(fd
, 0);
236 registerhandler(fd
, POLLIN
| POLLERR
| POLLHUP
, lua_socket_poll_event
);
238 lua_vnpcall(ls
, "flush", "");
240 if(events
& POLLIN
) {
244 bytesread
= read(fd
, buf
, sizeof(buf
));
245 if((bytesread
== -1) && (errno
== EAGAIN
))
249 lua_socket_call_close(ls
);
253 lua_vnpcall(ls
, "read", "L", buf
, (long)bytesread
);
259 void lua_socket_closeall(lua_list
*l
) {
261 lua_socket_call_close(l
->sockets
);
264 void lua_registersocketcommands(lua_State
*l
) {
265 lua_register(l
, "socket_unix_connect", lua_socket_unix_connect
);
266 lua_register(l
, "socket_close", lua_socket_close
);
267 lua_register(l
, "socket_write", lua_socket_write
);