+static int lua_socket_ip_connect(lua_State *l, int protocol) {
+ int ret;
+ struct sockaddr_in r;
+ char *address;
+ int port;
+ lua_socket *ls;
+ lua_list *ll;
+
+ ll = lua_listfromstate(l);
+ if(!ll)
+ return 0;
+
+ if(!lua_isfunction(l, 3) || !lua_islong(l, 2))
+ return 0;
+
+ address = (char *)lua_tostring(l, 1);
+ if(!address)
+ return 0;
+
+ port = lua_tolong(l, 2);
+
+ ls = (lua_socket *)luamalloc(sizeof(lua_socket));
+ if(!ls)
+ return 0;
+
+ ls->sockettype = PF_INET;
+ ls->fd = getipsocket(address, port, protocol, &r);
+ if(ls->fd < 0) {
+ luafree(ls);
+ return 0;
+ }
+
+ ret = connect(ls->fd, (struct sockaddr *)&r, sizeof(struct sockaddr_in));
+ return handleconnect(ret, l, ll, ls);
+}
+
+static int lua_socket_ip_bind(lua_State *l, int protocol) {
+ lua_list *ll;
+ char *address;
+ int port;
+ lua_socket *ls;
+ struct sockaddr_in r;
+
+ ll = lua_listfromstate(l);
+ if(!ll)
+ return 0;
+
+ if(!lua_isfunction(l, 3) || !lua_islong(l, 2))
+ return 0;
+
+ /* address can be nil or a string */
+ if(!lua_isnil(l, 1) && !lua_isstring(l, 1))
+ return 0;
+
+ address = (char *)lua_tostring(l, 1);
+ port = lua_tolong(l, 2);
+
+ ls = (lua_socket *)luamalloc(sizeof(lua_socket));
+ if(!ls)
+ return 0;
+
+ ls->sockettype = PF_INET;
+ ls->fd = getipsocket(address, port, protocol, &r);
+ if(ls->fd <= -1) {
+ luafree(ls);
+ return 0;
+ }
+
+ if(
+ (bind(ls->fd, (struct sockaddr *)&r, sizeof(struct sockaddr_in)) == -1) ||
+ (listen(ls->fd, 5) == -1)
+ ) {
+ close(ls->fd);
+ luafree(ls);
+ return 0;
+ }
+
+ ls->state = SOCKET_LISTENING;
+ ls->parent = NULL;
+
+ registerluasocket(ll, ls, POLLIN, 1);
+
+ lua_pushlong(l, ls->identifier);
+ return 1;
+}
+
+static int lua_socket_tcp_connect(lua_State *l) {
+ return lua_socket_ip_connect(l, SOCK_STREAM);
+}
+
+static int lua_socket_tcp_bind(lua_State *l) {
+ return lua_socket_ip_bind(l, SOCK_STREAM);
+}
+
+static int lua_socket_udp_connect(lua_State *l) {
+ return lua_socket_ip_connect(l, SOCK_DGRAM);
+}
+
+static int lua_socket_udp_bind(lua_State *l) {
+ return lua_socket_ip_bind(l, SOCK_DGRAM);
+}
+