static void socket_accept(int fd, int flags, void *data) { int sock, error; struct sockaddr_in remote; socklen_t n; qsocket_t *socket; lua_State *state; qengine_t *engine; qactor_t *actor; UNUSED(fd); UNUSED(flags); n = sizeof(remote); socket = (qsocket_t*)data; qassert(socket->state == QINET_STATE_ACCEPTING); actor = qactor_get(socket->aid); if (actor == NULL) { return; } actor->waiting_netio = 0; state = actor->state; sock = qnet_tcp_accept(socket->fd, (struct sockaddr*)&remote, &n, &error); if (sock == -1) { lua_pushnil(state); lua_pushfstring(state, "%s accept error:%s", socket->peer, strerror(error)); qlua_resume(state, 2); return; } /* restore the listen fd state */ engine = qactor_get_engine(actor->aid); qevent_del(&socket->event, QEVENT_READ); socket->state = QINET_STATE_LISTENING; socket = new_tcp_socket(sock, state, actor, &remote); if (!socket) { qnet_close(fd); lua_pushnil(state); lua_pushliteral(state, "create socket error"); qlua_resume(state, 2); return; } lua_pushlightuserdata(state, socket); qlua_resume(state, 1); return; }
static void socket_connect(int fd, int flags, void *data) { int error; socklen_t len; struct sockaddr_in remote; qsocket_t *socket; lua_State *state; qengine_t *engine; qactor_t *actor; UNUSED(flags); UNUSED(data); actor = (qactor_t*)data; actor->waiting_netio = 0; state = actor->state; engine = qactor_get_engine(actor->aid); socket = new_tcp_socket(fd, state, actor, &remote); if (!socket) { qnet_close(fd); lua_pushnil(state); lua_pushliteral(state, "create socket error"); qlua_resume(state, 2); return; } socket->state = QINET_STATE_CONNECTED; error = 0; len = sizeof(error); getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len); if (error == -1) { qevent_del(&socket->event, socket->event.events); qnet_close(socket->event.fd); } else if (error == 0) { qevent_del(&socket->event, QEVENT_WRITE); } lua_pushlightuserdata(state, socket); qlua_resume(state, 1); return; }
SOCKET make_tcp_connection(const char *host, unsigned short port, unsigned int *ip) { struct sockaddr_in sin; SOCKET f; memset(&sin, 0, sizeof(sin)); sin.sin_port = htons(port); sin.sin_family = AF_INET; if((sin.sin_addr.s_addr = lookup_ip(host)) == 0) return INVALID_SOCKET; if(ip) *ip = sin.sin_addr.s_addr; if((f = new_tcp_socket(ON_NONBLOCKING)) == INVALID_SOCKET) return INVALID_SOCKET; /* if an interface was specify, bind to it before connecting */ if(global.iface) bind_interface(f, global.iface, 0); /* turn on TCP/IP keepalive messages */ set_keepalive(f, 1); log_message_level(LOG_LEVEL_DEBUG, "make_tcp_connection: connecting to %s:%hu", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); if(connect(f, (struct sockaddr *) &sin, sizeof(sin)) < 0) { if(N_ERRNO != EINPROGRESS #ifdef WIN32 /* winsock returns EWOULDBLOCK even in nonblocking mode! ugh!!! */ && N_ERRNO != EWOULDBLOCK #endif ) { nlogerr("make_tcp_connection", "connect"); CLOSE(f); return INVALID_SOCKET; } log_message_level(LOG_LEVEL_SERVER, "make_tcp_connection: connection to %s in progress", host); } else log_message_level(LOG_LEVEL_SERVER, "make_tcp_connection: connection established to %s", host); return f; }
static int qltcp_accept(lua_State *state) { int fd, error; int timeout; struct sockaddr_in remote; socklen_t n; qactor_t *actor; qsocket_t *socket; qengine_t *engine; socket = (qsocket_t*)lua_touserdata(state, 1); n = sizeof(remote); actor = qlua_get_actor(state); timeout = (int)lua_tonumber(state, 2); UNUSED(timeout); if (socket == NULL) { lua_pushnil(state); lua_pushfstring(state, "socket nil"); return 2; } if (!socket->accept) { lua_pushnil(state); lua_pushfstring(state, "not accept socket"); return 2; } if (socket->state != QINET_STATE_LISTENING && socket->state != QINET_STATE_ACCEPTING) { lua_pushnil(state); lua_pushfstring(state, "socket state %d error", socket->state); return 2; } fd = qnet_tcp_accept(socket->fd, (struct sockaddr*)&remote, &n, &error); if (fd == -1) { lua_pushnil(state); lua_pushfstring(state, "%s accept error:%s", socket->peer, strerror(error)); return 2; } if (fd == 0) { engine = qactor_get_engine(actor->aid); socket->state = QINET_STATE_ACCEPTING; socket->event.read = socket_accept; qevent_add(engine, &socket->event, QEVENT_READ); actor->waiting_netio = 1; return lua_yield(state, 0); } socket = new_tcp_socket(fd, state, actor, &remote); if (!socket) { qnet_close(fd); lua_pushnil(state); lua_pushliteral(state, "create socket error"); return 2; } lua_pushlightuserdata(state, socket); return 1; }