+static void lua_socket_poll_event(int fd, short events);
+
+static int setnonblock(int fd) {
+ int ret;
+
+ /* WTB exceptions */
+ ret = fcntl(fd, F_GETFL, 0);
+ if(ret < 0) {
+ close(fd);
+ return -1;
+ }
+
+ ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK);
+ if(ret < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+static int getunixsocket(char *path, struct sockaddr_un *r) {
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+
+ if(fd <= -1)
+ return -1;
+
+ memset(r, 0, sizeof(struct sockaddr_un));
+ r->sun_family = PF_UNIX;
+ strlcpy(r->sun_path, path, sizeof(r->sun_path));
+
+ return setnonblock(fd);
+}
+
+/* note ADDRESS not HOSTNAME */
+static int getipsocket(char *address, int port, int protocol, struct sockaddr_in *r) {
+ int fd;
+ int val = 1;
+
+ memset(r, 0, sizeof(struct sockaddr_in));
+ r->sin_family = PF_INET;
+
+ if(address) {
+ if(!inet_aton(address, &r->sin_addr)) {
+ Error("lua", ERR_ERROR, "Could not parse address: %s", address);
+ return -1;
+ }
+ } else {
+ address = INADDR_ANY;
+ }
+
+ fd = socket(AF_INET, protocol, 0);
+
+ if(fd <= -1)
+ return -1;
+
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+
+ r->sin_port = htons(port);
+ return setnonblock(fd);
+}
+
+static void registerluasocket(lua_list *ll, lua_socket *ls, int mask, int settag) {
+ /* this whole identifier thing should probably use userdata stuff */
+ ls->identifier = nextidentifier++;
+
+ if(settag) {
+ ls->tag = luaL_ref(ll->l, LUA_REGISTRYINDEX);
+ ls->handler = luaL_ref(ll->l, LUA_REGISTRYINDEX);
+ }
+ ls->l = ll;
+
+ ls->next = ll->sockets;
+ ll->sockets = ls;
+
+ registerhandler(ls->fd, mask, lua_socket_poll_event);
+}
+
+static int handleconnect(int ret, lua_State *l, lua_list *ll, lua_socket *ls) {
+ if(ret == 0) {
+ ls->state = SOCKET_CONNECTED;
+ } else if(ret == -1 && (errno == EINPROGRESS)) {
+ ls->state = SOCKET_CONNECTING;
+ } else {
+ luafree(ls);
+ close(ls->fd);
+ return 0;
+ }
+
+ ls->parent = NULL;
+ registerluasocket(ll, ls, (ls->state==SOCKET_CONNECTED?POLLIN:POLLOUT) | POLLERR | POLLHUP, 1);
+
+ lua_pushboolean(l, ls->state==SOCKET_CONNECTED?1:0);
+ lua_pushlong(l, ls->identifier);
+ return 2;
+}