示例#1
0
/* lsocket_sock_recvfrom
 * 
 * reads data from a socket
 * 
 * Arguments:
 * 	L	Lua State
 * 
 * Lua Stack:
 * 	1	the lSocket userdata
 * 	2	(optional) the length of the buffer to use for reading, defaults
 * 		to some internal value
 * 
 * Lua Returns:
 * 	+1	a string containing the data read
 *  +2	ip address if remote end
 *  +3	port of remote end
 *  or +1 false if nonblocking socket returned EAGAIN (no data available)
 *  or +1 nil if the remote end has closed the socket
 * 	or +1 nil, +2 error message on error
 */
static int lsocket_sock_recvfrom(lua_State *L)
{
	lSocket *sock = lsocket_checklSocket(L, 1);
	uint32_t howmuch = luaL_optnumber(L, 2, READER_BUFSIZ);
	if (lua_tonumber(L, 2) > UINT_MAX)
		return luaL_error(L, "bad argument #1 to 'recvfrom' (invalid number)");
	
	char sabuf[sizeof(struct sockaddr_in6)];
	struct sockaddr *sa = (struct sockaddr*) sabuf;
	socklen_t slen = sizeof(sabuf);
	char *buf = malloc(howmuch);
	int nrd = recvfrom(sock->sockfd, buf, howmuch, 0, sa, &slen);
	if (nrd < 0) {
		free(buf);
		if (errno == EAGAIN || errno == EWOULDBLOCK)
			lua_pushboolean(L, 0);
		else
			return lsocket_error(L, strerror(errno));
	} else if (nrd == 0)
		lua_pushnil(L); /* not possible for udp, so should not get here */
	else {
		lua_pushlstring(L, buf, nrd);
		free(buf);
		char ipbuf[TOSTRING_BUFSIZ];
		const char *s = _addr2string(sa, ipbuf, TOSTRING_BUFSIZ);
		if (s)
			lua_pushstring(L, s);
		else
			return lsocket_error(L, strerror(errno)); /* should not happen */
		lua_pushnumber(L, _portnumber(sa));
		return 3;
	}
	return 1;
}
示例#2
0
/* lsocket_sock_accept
 * 
 * accept a new connection on a socket
 * 
 * Arguments:
 * 	L	Lua State
 * 
 * Lua Stack:
 * 	1	the lSocket userdata
 * 
 * Lua Returns:
 * 	+1	new socket, +2 client ip, +3 client port on success
 *  or +1 false if nonblocking socket returned EAGAIN
 * 	or +1 nil, +2 error message on error
 */
static int lsocket_sock_accept(lua_State *L)
{
	lSocket *sock = lsocket_checklSocket(L, 1);
	char buf[TOSTRING_BUFSIZ];

	if (!_canacceptdata(sock->sockfd, 0)) {
		lua_pushboolean(L, 0);
		return 1;
	}
	
	char sabuf[sizeof(struct sockaddr_in6)];
	struct sockaddr *sa = (struct sockaddr*) sabuf;
	socklen_t slen = sizeof(sabuf);
	int newfd = accept(sock->sockfd, sa, &slen);

	if (newfd < 0)
		return lsocket_error(L, strerror(errno));

	lSocket *nsock = lsocket_pushlSocket(L);
	nsock->sockfd = newfd;
	if (_initsocket(nsock, sa->sa_family, sock->type, sock->mcast, sock->protocol, 0) == -1)
		return lsocket_error(L, strerror(errno));
	lua_pushstring(L, _addr2string(sa, buf, TOSTRING_BUFSIZ));
	lua_pushnumber(L, _portnumber(sa));
	return 3;
}
示例#3
0
// deprecated: may hang up, use dns.resolve for cooperative dns query
static int
_resolve(lua_State *L) {
    const char* host = luaL_checkstring(L, 1);
    struct addrinfo *res = 0;
	int err, i;
	char buf[sizeof(struct in6_addr)];

    struct addrinfo hints;
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;

    err = getaddrinfo(host, NULL, &hints, &res);
    if(err != 0) {
        lua_pushnil(L);
        lua_pushinteger(L, err);
        return 2;
    }

    i = 1;
    lua_newtable(L);
    while(res) {
        // ignore all unsupported address
        if((res->ai_family == AF_INET || res->ai_family == AF_INET6) && res->ai_socktype == SOCK_STREAM) {
            lua_createtable(L, 0, 2);
            lua_pushinteger(L, res->ai_family);
            lua_setfield(L, -2, "family");
            lua_pushstring(L, _addr2string(res->ai_addr, buf, sizeof(buf)));
            lua_setfield(L, -2, "addr");
            lua_rawseti(L, -2, i++);
        }
        res = res->ai_next;
    }
    return 1;
}
示例#4
0
/* lsocket_getinterfaces
 * 
 * enumerates all available interfaces
 * 
 * Arguments:
 * 	L	lua State
 * 
 * Lua Stack:
 * 	-
 * 
 * Lua Returns:
 * 	+1	a table with information on all available interfaces. For each
 * 		interface, a subtable is returned with the fields name, family,
 * 		address and mask
 */
static int lsocket_getinterfaces(lua_State *L)
{
	struct ifaddrs *ifa;
	char buf[TOSTRING_BUFSIZ];
	const char *s;
	int i = 1;

	if (getifaddrs(&ifa) < 0)
		return lsocket_error(L, strerror(errno));
	
	lua_newtable(L);
	while (ifa) {
		lua_newtable(L);
		lua_pushliteral(L, "name");
		lua_pushstring(L, ifa->ifa_name);
		lua_rawset(L, -3);
		s = _addr2string(ifa->ifa_addr, buf, TOSTRING_BUFSIZ);
		if (s) {
			lua_pushliteral(L, "family");
			lua_pushstring(L, ifa->ifa_addr->sa_family == AF_INET ? LSOCKET_INET : LSOCKET_INET6);
			lua_rawset(L, -3);
			lua_pushliteral(L, "addr");
			lua_pushstring(L, s);
			lua_rawset(L, -3);
			s = _addr2string(ifa->ifa_netmask, buf, TOSTRING_BUFSIZ);
			if (s) {
				lua_pushliteral(L, "mask");
				lua_pushstring(L, s);
				lua_rawset(L, -3);
			}
			lua_rawseti(L, -2, i++);
		} else
			lua_pop(L, 1);
		ifa = ifa->ifa_next;
	}

	freeifaddrs(ifa);
	return 1;
}
示例#5
0
/* _push_sockname
 * 
 * helper for lsocket_sock_info: create a table with fields port, family
 * and addr from the sockaddr passed as argument, and leave it on the
 * stack. Leave nil on error.
 * 
 * Arguments:
 * 	L	Lua State
 *	sa	pointer to sockaddr to get data from
 * 
 * Lua Returns:
 * 	+1 table with info about address, or nil
 */
static void _push_sockname(lua_State *L, struct sockaddr *sa)
{
	char buf[TOSTRING_BUFSIZ];
	const char *s;
	lua_newtable(L);
	lua_pushliteral(L, "port");
	lua_pushnumber(L, _portnumber(sa));
	lua_rawset(L, -3);
	lua_pushliteral(L, "family");
	lua_pushstring(L, sa->sa_family == AF_INET ? LSOCKET_INET : LSOCKET_INET6);
	lua_rawset(L, -3);
	lua_pushliteral(L, "addr");
	s = _addr2string(sa, buf, TOSTRING_BUFSIZ);
	if (s) {
		lua_pushstring(L, s);
		lua_rawset(L, -3);
	} else {
		lua_pop(L, 1);
	}
}
示例#6
0
/* lsocket_resolve
 * 
 * resolves a name to an address
 * 
 * Arguments:
 * 	L	lua State
 * 
 * Lua Stack:
 * 	1	name of host to resolve
 * 
 * Lua Returns:
 * 	+1	a table of all addresses the argument resolves to. For each address,
 * 		a subtable with the fields family and addr is created.
 */
static int lsocket_resolve(lua_State *L)
{
	const char *name = luaL_checkstring(L, 1);
	char buf[TOSTRING_BUFSIZ];
	struct addrinfo hint, *info =0;
	memset(&hint, 0, sizeof(hint));
	hint.ai_family = AF_UNSPEC;
	if (_needsnolookup(name))
		hint.ai_flags = AI_NUMERICHOST;

	int err = getaddrinfo(name, 0, &hint, &info);
    if (err != 0) {
		if (info) freeaddrinfo(info);
		return lsocket_error(L, gai_strerror(err));
	}

	int i = 1;
	lua_newtable(L);
	while (info) {
		if (info->ai_family == AF_INET || info->ai_family == AF_INET6) {
			lua_newtable(L);
			lua_pushliteral(L, "family");
			lua_pushstring(L, info->ai_family == AF_INET ? LSOCKET_INET : LSOCKET_INET6);
			lua_rawset(L, -3);
			lua_pushliteral(L, "addr");
			lua_pushstring(L, _addr2string(info->ai_addr, buf, TOSTRING_BUFSIZ));
			lua_rawset(L, -3);
			lua_rawseti(L, -2, i++);
			info = info->ai_next;
		}
		/* silently ignore unknown address families */
	}
	
	freeaddrinfo(info);
	return 1;
}