static void lua_socket_call_close(lua_socket *ls) { lua_socket *p, *c; for(c=ls->l->sockets;c;c=p) { p = c->next; if(c->parent == ls) lua_socket_call_close(c); } for(c=ls->l->sockets,p=NULL;c;p=c,c=c->next) { if(c == ls) { if(ls->state == SOCKET_CLOSED) return; ls->state = SOCKET_CLOSED; deregisterhandler(ls->fd, 1); lua_vnpcall(ls, "close", ""); if(!p) { ls->l->sockets = ls->next; } else { p->next = ls->next; } if(!ls->parent) { luaL_unref(ls->l->l, LUA_REGISTRYINDEX, ls->tag); luaL_unref(ls->l->l, LUA_REGISTRYINDEX, ls->handler); } luafree(ls); return; } } }
static int lua_socket_write(lua_State *l) { char *buf; long len; lua_socket *ls; int ret; buf = (char *)lua_tostring(l, 2); if(!lua_islong(l, 1) || !buf) { lua_pushint(l, -1); return 1; } len = lua_strlen(l, 2); ls = socketbyidentifier(lua_tolong(l, 1)); if(!ls || (ls->state != SOCKET_CONNECTED)) { lua_pushint(l, -1); return 1; } ret = write(ls->fd, buf, len); if(ret == -1 && (errno == EAGAIN)) { deregisterhandler(ls->fd, 0); registerhandler(ls->fd, POLLIN | POLLOUT | POLLERR | POLLHUP, lua_socket_poll_event); lua_pushint(l, 0); return 1; } if(ret == -1) lua_socket_call_close(ls); if(ret < len) { deregisterhandler(ls->fd, 0); registerhandler(ls->fd, POLLIN | POLLOUT | POLLERR | POLLHUP, lua_socket_poll_event); } lua_pushint(l, ret); return 1; }
void _fini() { deregisterhook(HOOK_NICK_NEWNICK, &nr_nick); deregisterhook(HOOK_NICK_LOSTNICK, &nr_nick); deregisterhandler(nickrate_listenfd,1); }
static void lua_socket_poll_event(int fd, short events) { lua_socket *ls = socketbyfd(fd); if(!ls || (ls->state == SOCKET_CLOSED)) return; if(events & (POLLERR | POLLHUP)) { lua_socket_call_close(ls); return; } switch(ls->state) { case SOCKET_CONNECTING: if(events & POLLOUT) { deregisterhandler(fd, 0); registerhandler(fd, POLLIN | POLLERR | POLLHUP, lua_socket_poll_event); ls->state = SOCKET_CONNECTED; lua_vnpcall(ls, "connect", ""); } break; case SOCKET_CONNECTED: if(events & POLLOUT) { deregisterhandler(fd, 0); registerhandler(fd, POLLIN | POLLERR | POLLHUP, lua_socket_poll_event); lua_vnpcall(ls, "flush", ""); } if(events & POLLIN) { char buf[8192 * 2]; int bytesread; bytesread = read(fd, buf, sizeof(buf)); if((bytesread == -1) && (errno == EAGAIN)) return; if(bytesread <= 0) { lua_socket_call_close(ls); return; } lua_vnpcall(ls, "read", "L", buf, (long)bytesread); } break; case SOCKET_LISTENING: if(events & POLLIN) { struct sockaddr_in rip; struct sockaddr_un run; lua_socket *ls2; unsigned int len; int fd2; if(ls->sockettype == PF_INET) { len = sizeof(rip); fd2 = accept(fd, (struct sockaddr *)&rip, &len); } else { len = sizeof(run); fd2 = accept(fd, (struct sockaddr *)&run, &len); } if(fd2 == -1) return; ls2 = (lua_socket *)luamalloc(sizeof(lua_socket)); if(!ls2) { close(fd2); return; } ls2->fd = fd2; ls2->state = SOCKET_CONNECTED; ls2->tag = ls->tag; ls2->handler = ls->handler; ls2->parent = ls; ls2->sockettype = ls->sockettype; registerluasocket(ls->l, ls2, POLLIN | POLLERR | POLLHUP, 0); lua_vnpcall(ls, "accept", "l", ls2->identifier); } break; } }