Exemplo n.º 1
0
bool CLuaHandleSynced::SetupUnsynced(const string& code, const string& filename)
{
	if ((L == NULL) || code.empty()) {
		return false;
	}

	// make the UNSYNCED table
	unsyncedStr.Push(L);
	lua_newtable(L);
	lua_rawset(L, LUA_REGISTRYINDEX);

	unsyncedStr.GetRegistry(L);

	AddBasicCalls(); // into UNSYNCED

	// remove Script.Kill()
	lua_pushstring(L, "Script");
	lua_rawget(L, -2);
	lua_pushstring(L, "Kill");
	lua_pushnil(L);
	lua_rawset(L, -3);
	LuaPushNamedCFunc(L, "UpdateCallIn", CallOutUnsyncedUpdateCallIn);
	lua_pop(L, 1);

	lua_pushstring(L, "_G");
	unsyncedStr.GetRegistry(L);
	lua_rawset(L, -3);

	LuaPushNamedCFunc(L, "loadstring",   LoadStringData);
	LuaPushNamedCFunc(L, "CallAsTeam",   CallAsTeam);

	// load our libraries
	if (!LuaSyncedTable::PushEntries(L)                                    ||
	    !AddEntriesToTable(L, "VFS",         LuaVFS::PushUnsynced)         ||
	    !AddEntriesToTable(L, "UnitDefs",    LuaUnitDefs::PushEntries)     ||
	    !AddEntriesToTable(L, "WeaponDefs",  LuaWeaponDefs::PushEntries)   ||
	    !AddEntriesToTable(L, "FeatureDefs", LuaFeatureDefs::PushEntries)  ||
	    !AddEntriesToTable(L, "Script",      LuaUnsyncedCall::PushEntries) ||
	    !AddEntriesToTable(L, "Script",      LuaScream::PushEntries)       ||
	    !AddEntriesToTable(L, "Spring",      LuaSyncedRead::PushEntries)   ||
	    !AddEntriesToTable(L, "Spring",      LuaUnsyncedCtrl::PushEntries) ||
	    !AddEntriesToTable(L, "Spring",      LuaUnsyncedRead::PushEntries) ||
	    !AddEntriesToTable(L, "gl",          LuaOpenGL::PushEntries)       ||
	    !AddEntriesToTable(L, "GL",          LuaConstGL::PushEntries)      ||
	    !AddEntriesToTable(L, "Game",        LuaConstGame::PushEntries)    ||
	    !AddEntriesToTable(L, "CMD",         LuaConstCMD::PushEntries)     ||
	    !AddEntriesToTable(L, "CMDTYPE",     LuaConstCMDTYPE::PushEntries)) {
		KillLua();
		return false;
	}

	lua_pushstring(L, "math"); lua_newtable(L);
	lua_getglobal(L, "math"); LightCopyTable(-2, -1); lua_pop(L, 1);
	lua_rawset(L, -3);

	lua_pushstring(L, "table"); lua_newtable(L);
	lua_getglobal(L, "table"); LightCopyTable(-2, -1); lua_pop(L, 1);
	lua_rawset(L, -3);

	lua_pushstring(L, "string"); lua_newtable(L);
	lua_getglobal(L, "string"); LightCopyTable(-2, -1); lua_pop(L, 1);
	lua_rawset(L, -3);

	if (!CopyRealRandomFuncs()) {
		KillLua();
		return false;
	}

	lua_settop(L, 0);

	// note the absence of loadstring() -- global access
	const char* labels[] = {
		"assert",         "error",
		"print",
		"next",           "pairs",        "ipairs",
		"tonumber",       "tostring",     "type",
		"collectgarbage", "gcinfo",
		"unpack",
		"getmetatable",   "setmetatable",
		"rawequal",       "rawget",       "rawset",
		"getfenv",        "setfenv",
		"pcall",          "xpcall",
		"_VERSION",
		NULL
	};
	for (const char** l = labels; *l != NULL; l++) {
		CopyGlobalToUnsynced(*l);
	}

	// add code from the sub-class
	unsyncedStr.GetRegistry(L);
	if (!AddUnsyncedCode()) {
		KillLua();
		return false;
	}
	lua_settop(L, 0);

	if (!LoadUnsyncedCode(code, filename)) {
		KillLua();
		return false;
	}

	if (!SetupUnsyncedFunction("RecvFromSynced")      ||
	    !SetupUnsyncedFunction("Update")              ||
	    !SetupUnsyncedFunction("DrawGenesis")         ||
	    !SetupUnsyncedFunction("DrawWorld")           ||
	    !SetupUnsyncedFunction("DrawWorldPreUnit")    ||
	    !SetupUnsyncedFunction("DrawWorldShadow")     ||
	    !SetupUnsyncedFunction("DrawWorldReflection") ||
	    !SetupUnsyncedFunction("DrawWorldRefraction") ||
	    !SetupUnsyncedFunction("DrawScreenEffects")   ||
	    !SetupUnsyncedFunction("DrawScreen")          ||
	    !SetupUnsyncedFunction("DrawInMiniMap")) {
		return false;
	}

	return true;
}
Exemplo n.º 2
0
/*
 * Push a proxy userdata on the stack.
 * returns NULL if ok, else some error string related to bad idfunc behavior or module require problem
 * (error cannot happen with mode_ == eLM_ToKeeper)
 *
 * Initializes necessary structures if it's the first time 'idfunc' is being
 * used in this Lua state (metatable, registring it). Otherwise, increments the
 * reference count.
 */
char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMode mode_)
{
	DEEP_PRELUDE** proxy;

	// Check if a proxy already exists
	push_registry_subtable_mode( L, DEEP_PROXY_CACHE_KEY, "v");                                        // DPC
	lua_pushlightuserdata( L, prelude->deep);                                                          // DPC deep
	lua_rawget( L, -2);                                                                                // DPC proxy
	if ( !lua_isnil( L, -1))
	{
		lua_remove( L, -2);                                                                              // proxy
		return NULL;
	}
	else
	{
		lua_pop( L, 1);                                                                                  // DPC
	}

	MUTEX_LOCK( &U->deep_lock);
	++ (prelude->refcount);  // one more proxy pointing to this deep data
	MUTEX_UNLOCK( &U->deep_lock);

	STACK_GROW( L, 7);
	STACK_CHECK( L);

	proxy = lua_newuserdata( L, sizeof( DEEP_PRELUDE*));                                               // DPC proxy
	ASSERT_L( proxy);
	*proxy = prelude;

	// Get/create metatable for 'idfunc' (in this state)
	lua_pushlightuserdata( L, prelude->idfunc);                                                        // DPC proxy idfunc
	get_deep_lookup( L);                                                                               // DPC proxy metatable?

	if( lua_isnil( L, -1)) // // No metatable yet.
	{
		char const* modname;
		int oldtop = lua_gettop( L);                                                                     // DPC proxy nil
		lua_pop( L, 1);                                                                                  // DPC proxy
		// 1 - make one and register it
		if( mode_ != eLM_ToKeeper)
		{
			prelude->idfunc( L, eDO_metatable);                                                            // DPC proxy metatable deepversion
			if( lua_gettop( L) - oldtop != 1 || !lua_istable( L, -2) || !lua_isstring( L, -1))
			{
				lua_settop( L, oldtop);                                                                      // DPC proxy X
				lua_pop( L, 3);                                                                              //
				return "Bad idfunc(eOP_metatable): unexpected pushed value";
			}
			luaG_pushdeepversion( L);                                                                      // DPC proxy metatable deepversion deepversion
			if( !lua501_equal( L, -1, -2))
			{
				lua_pop( L, 5);                                                                              //
				return "Bad idfunc(eOP_metatable): mismatched deep version";
			}
			lua_pop( L, 2);                                                                                // DPC proxy metatable
			// make sure the idfunc didn't export __gc, as we will store our own
			lua_getfield( L, -1, "__gc");                                                                  // DPC proxy metatable __gc
			if( !lua_isnil( L, -1))
			{
				lua_pop( L, 4);                                                                              //
				return "idfunc-created metatable shouldn't contain __gc";
			}
			lua_pop( L, 1);                                                                                // DPC proxy metatable
		}
		else
		{
			// keepers need a minimal metatable that only contains __gc
			lua_newtable( L);                                                                              // DPC proxy metatable
		}
		// Add our own '__gc' method
		lua_pushcfunction( L, deep_userdata_gc);                                                         // DPC proxy metatable __gc
		lua_setfield( L, -2, "__gc");                                                                    // DPC proxy metatable

		// Memorize for later rounds
		lua_pushvalue( L, -1);                                                                           // DPC proxy metatable metatable
		lua_pushlightuserdata( L, prelude->idfunc);                                                      // DPC proxy metatable metatable idfunc
		set_deep_lookup( L);                                                                             // DPC proxy metatable

		// 2 - cause the target state to require the module that exported the idfunc
		// this is needed because we must make sure the shared library is still loaded as long as we hold a pointer on the idfunc
		{
			int oldtop = lua_gettop( L);
			modname = (char const*) prelude->idfunc( L, eDO_module);                                       // DPC proxy metatable
			// make sure the function pushed nothing on the stack!
			if( lua_gettop( L) - oldtop != 0)
			{
				lua_pop( L, 3);                                                                              //
				return "Bad idfunc(eOP_module): should not push anything";
			}
		}
		if( modname) // we actually got a module name
		{
			// somehow, L.registry._LOADED can exist without having registered the 'package' library.
			lua_getglobal( L, "require");                                                                  // DPC proxy metatable require()
			// check that the module is already loaded (or being loaded, we are happy either way)
			if( lua_isfunction( L, -1))
			{
				lua_pushstring( L, modname);                                                                 // DPC proxy metatable require() "module"
				lua_getfield( L, LUA_REGISTRYINDEX, "_LOADED");                                              // DPC proxy metatable require() "module" _R._LOADED
				if( lua_istable( L, -1))
				{
					bool_t alreadyloaded;
					lua_pushvalue( L, -2);                                                                     // DPC proxy metatable require() "module" _R._LOADED "module"
					lua_rawget( L, -2);                                                                        // DPC proxy metatable require() "module" _R._LOADED module
					alreadyloaded = lua_toboolean( L, -1);
					if( !alreadyloaded) // not loaded
					{
						int require_result;
						lua_pop( L, 2);                                                                          // DPC proxy metatable require() "module"
						// require "modname"
						require_result = lua_pcall( L, 1, 0, 0);                                                 // DPC proxy metatable error?
						if( require_result != LUA_OK)
						{
							// failed, return the error message
							lua_pushfstring( L, "error while requiring '%s' identified by idfunc(eOP_module): ", modname);
							lua_insert( L, -2);                                                                    // DPC proxy metatable prefix error
							lua_concat( L, 2);                                                                     // DPC proxy metatable error
							return lua_tostring( L, -1);
						}
					}
					else // already loaded, we are happy
					{
						lua_pop( L, 4);                                                                          // DPC proxy metatable
					}
				}
				else // no L.registry._LOADED; can this ever happen?
				{
					lua_pop( L, 6);                                                                            //
					return "unexpected error while requiring a module identified by idfunc(eOP_module)";
				}
			}
			else // a module name, but no require() function :-(
			{
				lua_pop( L, 4);                                                                              //
				return "lanes receiving deep userdata should register the 'package' library";
			}
		}
	}
	STACK_MID( L, 2);                                                                                  // DPC proxy metatable
	ASSERT_L( lua_isuserdata( L, -2));
	ASSERT_L( lua_istable( L, -1));
	lua_setmetatable( L, -2);                                                                          // DPC proxy

	// If we're here, we obviously had to create a new proxy, so cache it.
	lua_pushlightuserdata( L, (*proxy)->deep);                                                         // DPC proxy deep
	lua_pushvalue( L, -2);                                                                             // DPC proxy deep proxy
	lua_rawset( L, -4);                                                                                // DPC proxy
	lua_remove( L, -2);                                                                                // proxy
	ASSERT_L( lua_isuserdata( L, -1));
	STACK_END( L, 0);
	return NULL;
}
Exemplo n.º 3
0
/**
 * Look up a name in the given module.  This works for functions, like
 * gtk.window_new(), constants, like gtk.WINDOW_TOPLEVEL, and global variables.
 * Lua Stack: [1]=gnome [2]=name
 *
 * @name __index
 * @luaparam mod    The module to look in (a table)
 * @luaparam key    The name of the item to look up
 * @luareturn          Either a userdata (for ENUMs) or a closure (for
 *			functions)
 */
static int lg_generic_index(lua_State *L)
{
    size_t name_len, prefix_len = 0;
    const char *name = luaL_checklstring(L, 2, &name_len);
    struct func_info fi = { 0 };
    char symname[70];
    cmi mi;

    // Get the module.  No checks here because this function is called
    // by Lua and should always have the correct arguments.
    lua_getfield(L, 1, "_modinfo");
    mi = lua_touserdata(L, -1);
    lua_pop(L, 1);

    // check arguments
    if (!name || !*name)
	return luaL_error(L, "%s attempt to look up a NULL or empty string",
	    msgprefix);
    prefix_len = strlen(mi->prefix_func);
    prefix_len = MAX(prefix_len, strlen(mi->prefix_constant));
    if (name_len + prefix_len > sizeof(symname) - 10)
	return luaL_error(L, "%s key is too long, max is %d", msgprefix,
	    sizeof(symname) - 10);

    /* if it starts with an uppercase letter, it's probably an ENUM. */
    if (name[0] >= 'A' && name[0] <= 'Z') {
	int val;
	const char *prefix = mi->prefix_constant;

	typespec_t ts = { 0 };
	ts.module_idx = mi->module_idx;
	for (;;) {
	    sprintf(symname, "%s%s", prefix ? prefix : "", name);
	    // strcpy(symname, prefix);
	    // strcat(symname, name);
	    switch (lg_find_constant(L, &ts, symname, -1, &val)) {
		case 1:		// ENUM/FLAG found
		return lg_push_constant(L, ts, val);

		case 2:		// integer found
		lua_pushinteger(L, val);
		/* fall through */

		case 3:		// string found - is on Lua stack
		return 1;
	    }
	    if (!prefix)
		break;
	    prefix = NULL;
	}
    }

    // If it starts with "__", then remove that and don't look for
    // overrides.  This is something that overrides written in Lua can use,
    // to avoid recursively calling itself instead of the Gtk function.
    if (name[0] == '_' && name[1] == '_') {
	strcpy(symname, name + 2);
	if (!lg_find_func(L, mi, symname, &fi))
	    return luaL_error(L, "%s not found: %s.%s", msgprefix, mi->name,
		name);
	goto found_func;
    }

    // Check for an override (with the function prefix).
    strcpy(symname, mi->prefix_func);
    strcat(symname, name);
    lua_pushstring(L, symname);
    lua_rawget(L, 1);
    if (!lua_isnil(L, -1)) {
	lua_pushstring(L, name);
	lua_pushvalue(L, -2);
	lua_rawset(L, 1);
	return 1;
    }
    lua_pop(L, 1);

    // Otherwise, simply look it up
    if (lg_find_func(L, mi, symname, &fi))
	goto found_func;

    // maybe it's a function but with the prefix already added.
    if (*mi->prefix_func && lg_find_func(L, mi, name, &fi))
	goto found_func;
    
    // Might be a global variable.  This is not so common, therefore
    // it is not checked for earlier.
    if (lg_find_global(L, mi, symname))
	return 1;

    // "name" might not need the prefix.
    if (lg_find_global(L, mi, name))
	return 1;
    
    // Maybe it's Windows and a function with _utf8 suffix?  While there
    // are a few with the gtk_ prefix and _utf8 suffix, most have the
    // g_ or gdk_ prefix, so don't automatically add this prefix.
#ifdef LUAGNOME_win32
    strcat(symname, "_utf8");
    // sprintf(symname, "%s%s_utf8", prefix_func, name);
    if (lg_find_func(L, mi, symname, &fi))
	goto found_func;
#endif

    // Not found.
    return luaL_error(L, "%s not found: %s.%s", msgprefix, mi->name, name);

found_func:;
    lg_push_closure(L, &fi, 2);

    // cache the result of this lookup, using the key given by the user,
    // and not necessarily the name of the function that was found.
    lua_pushvalue(L, 2);	// key
    lua_pushvalue(L, -2);	// the new closure
    lua_rawset(L, 1);		// [1]=table

    return 1;
}
Exemplo n.º 4
0
static int aux_getfenv (lua_State *L) {
  lua_getfenv(L, -1);
  lua_pushliteral(L, "__fenv");
  lua_rawget(L, -2);
  return !lua_isnil(L, -1);
}
static int
ngx_http_lua_coroutine_resume(lua_State *L)
{
    lua_State                   *co;
    ngx_http_request_t          *r;
    ngx_http_lua_ctx_t          *ctx;
    ngx_http_lua_co_ctx_t       *coctx;
    ngx_http_lua_co_ctx_t       *p_coctx; /* parent co ctx */

    co = lua_tothread(L, 1);

    luaL_argcheck(L, co, 1, "coroutine expected");

    lua_pushlightuserdata(L, &ngx_http_lua_request_key);
    lua_rawget(L, LUA_GLOBALSINDEX);
    r = lua_touserdata(L, -1);
    lua_pop(L, 1);

    if (r == NULL) {
        return luaL_error(L, "no request found");
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
    if (ctx == NULL) {
        return luaL_error(L, "no request ctx found");
    }

    ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
                               | NGX_HTTP_LUA_CONTEXT_ACCESS
                               | NGX_HTTP_LUA_CONTEXT_CONTENT);

    p_coctx = ctx->cur_co_ctx;
    if (p_coctx == NULL) {
        return luaL_error(L, "no parent co ctx found");
    }

    coctx = ngx_http_lua_get_co_ctx(co, ctx);
    if (coctx == NULL) {
        return luaL_error(L, "no co ctx found");
    }

    ngx_http_lua_probe_user_coroutine_resume(r, L, co);

    if (coctx->co_status != NGX_HTTP_LUA_CO_SUSPENDED) {
        dd("coroutine resume: %d", coctx->co_status);

        lua_pushboolean(L, 0);
        lua_pushfstring(L, "cannot resume %s coroutine",
                        ngx_http_lua_co_status_names[coctx->co_status]);
        return 2;
    }

    p_coctx->co_status = NGX_HTTP_LUA_CO_NORMAL;

    coctx->parent_co_ctx = p_coctx;

    dd("set coroutine to running");
    coctx->co_status = NGX_HTTP_LUA_CO_RUNNING;

    ctx->co_op = NGX_HTTP_LUA_USER_CORO_RESUME;
    ctx->cur_co_ctx = coctx;

    /* yield and pass args to main thread, and resume target coroutine from
     * there */
    return lua_yield(L, lua_gettop(L) - 1);
}
static int
ngx_stream_lua_socket_udp_setpeername(lua_State *L)
{
    ngx_stream_session_t            *s;
    ngx_stream_lua_ctx_t            *ctx;
    ngx_str_t                        host;
    int                              port;
    ngx_resolver_ctx_t              *rctx, temp;
    int                              saved_top;
    int                              n;
    u_char                          *p;
    size_t                           len;
    ngx_url_t                        url;
    ngx_int_t                        rc;
    ngx_stream_lua_srv_conf_t       *lscf;
    ngx_udp_connection_t            *uc;
    int                              timeout;
    ngx_stream_lua_co_ctx_t         *coctx;

    ngx_stream_lua_socket_udp_upstream_t      *u;

    /*
     * TODO: we should probably accept an extra argument to setpeername()
     * to allow the user bind the datagram unix domain socket himself,
     * which is necessary for systems without autobind support.
     */

    n = lua_gettop(L);
    if (n != 2 && n != 3) {
        return luaL_error(L, "ngx.socket.udp setpeername: expecting 2 or 3 "
                          "arguments (including the object), but seen %d", n);
    }

    s = ngx_stream_lua_get_session(L);
    if (s == NULL) {
        return luaL_error(L, "no session found");
    }

    ctx = ngx_stream_get_module_ctx(s, ngx_stream_lua_module);
    if (ctx == NULL) {
        return luaL_error(L, "no ctx found");
    }

    ngx_stream_lua_check_context(L, ctx, NGX_STREAM_LUA_CONTEXT_CONTENT
                                 | NGX_STREAM_LUA_CONTEXT_TIMER);

    luaL_checktype(L, 1, LUA_TTABLE);

    p = (u_char *) luaL_checklstring(L, 2, &len);

    host.data = ngx_palloc(s->connection->pool, len + 1);
    if (host.data == NULL) {
        return luaL_error(L, "no memory");
    }

    host.len = len;

    ngx_memcpy(host.data, p, len);
    host.data[len] = '\0';

    if (n == 3) {
        port = luaL_checkinteger(L, 3);

        if (port < 0 || port > 65536) {
            lua_pushnil(L);
            lua_pushfstring(L, "bad port number: %d", port);
            return 2;
        }

    } else { /* n == 2 */
        port = 0;
    }

    lua_rawgeti(L, 1, SOCKET_CTX_INDEX);
    u = lua_touserdata(L, -1);
    lua_pop(L, 1);

    if (u) {
        if (u->session && u->session != s) {
            return luaL_error(L, "bad session");
        }

        if (u->waiting) {
            lua_pushnil(L);
            lua_pushliteral(L, "socket busy");
            return 2;
        }

        if (u->udp_connection.connection) {
            ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
                           "stream lua udp socket reconnect without "
                           "shutting down");

            ngx_stream_lua_socket_udp_finalize(s, u);
        }

        ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
                       "stream lua reuse socket upstream ctx");

    } else {
        u = lua_newuserdata(L, sizeof(ngx_stream_lua_socket_udp_upstream_t));
        if (u == NULL) {
            return luaL_error(L, "no memory");
        }

#if 1
        lua_pushlightuserdata(L, &ngx_stream_lua_udp_udata_metatable_key);
        lua_rawget(L, LUA_REGISTRYINDEX);
        lua_setmetatable(L, -2);
#endif

        lua_rawseti(L, 1, SOCKET_CTX_INDEX);
    }

    ngx_memzero(u, sizeof(ngx_stream_lua_socket_udp_upstream_t));

    u->session = s; /* set the controlling session */
    lscf = ngx_stream_get_module_srv_conf(s, ngx_stream_lua_module);

    u->conf = lscf;

    uc = &u->udp_connection;

    uc->log = *s->connection->log;

    dd("lua peer connection log: %p", &uc->log);

    lua_rawgeti(L, 1, SOCKET_TIMEOUT_INDEX);
    timeout = (ngx_int_t) lua_tointeger(L, -1);
    lua_pop(L, 1);

    if (timeout > 0) {
        u->read_timeout = (ngx_msec_t) timeout;

    } else {
        u->read_timeout = u->conf->read_timeout;
    }

    ngx_memzero(&url, sizeof(ngx_url_t));

    url.url.len = host.len;
    url.url.data = host.data;
    url.default_port = (in_port_t) port;
    url.no_resolve = 1;

    if (ngx_parse_url(s->connection->pool, &url) != NGX_OK) {
        lua_pushnil(L);

        if (url.err) {
            lua_pushfstring(L, "failed to parse host name \"%s\": %s",
                            host.data, url.err);

        } else {
            lua_pushfstring(L, "failed to parse host name \"%s\"", host.data);
        }

        return 2;
    }

    u->resolved = ngx_pcalloc(s->connection->pool,
                              sizeof(ngx_stream_lua_resolved_t));
    if (u->resolved == NULL) {
        return luaL_error(L, "no memory");
    }

    if (url.addrs && url.addrs[0].sockaddr) {
        ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
                       "stream lua udp socket network address given directly");

        u->resolved->sockaddr = url.addrs[0].sockaddr;
        u->resolved->socklen = url.addrs[0].socklen;
        u->resolved->naddrs = 1;
        u->resolved->host = url.addrs[0].name;

    } else {
        u->resolved->host = host;
        u->resolved->port = (in_port_t) port;
    }

    if (u->resolved->sockaddr) {
        rc = ngx_stream_lua_socket_resolve_retval_handler(s, u, L);
        if (rc == NGX_AGAIN) {
            return lua_yield(L, 0);
        }

        return rc;
    }

    temp.name = host;
    rctx = ngx_resolve_start(lscf->resolver, &temp);
    if (rctx == NULL) {
        u->ft_type |= NGX_STREAM_LUA_SOCKET_FT_RESOLVER;
        lua_pushnil(L);
        lua_pushliteral(L, "failed to start the resolver");
        return 2;
    }

    if (rctx == NGX_NO_RESOLVER) {
        u->ft_type |= NGX_STREAM_LUA_SOCKET_FT_RESOLVER;
        lua_pushnil(L);
        lua_pushfstring(L, "no lua_resolver defined to resolve \"%s\"",
                        host.data);
        return 2;
    }

    rctx->name = host;
#if !defined(nginx_version) || nginx_version < 1005008
    rctx->type = NGX_RESOLVE_A;
#endif
    rctx->handler = ngx_stream_lua_socket_resolve_handler;
    rctx->data = u;
    rctx->timeout = lscf->resolver_timeout;

    u->co_ctx = ctx->cur_co_ctx;
    u->resolved->ctx = rctx;

    saved_top = lua_gettop(L);

    coctx = ctx->cur_co_ctx;
    ngx_stream_lua_cleanup_pending_operation(coctx);
    coctx->cleanup = ngx_stream_lua_udp_resolve_cleanup;

    if (ngx_resolve_name(rctx) != NGX_OK) {
        ngx_log_debug0(NGX_LOG_DEBUG_STREAM, s->connection->log, 0,
                       "stream lua udp socket fail to run resolver "
                       "immediately");

        u->ft_type |= NGX_STREAM_LUA_SOCKET_FT_RESOLVER;

        u->resolved->ctx = NULL;
        lua_pushnil(L);
        lua_pushfstring(L, "%s could not be resolved", host.data);

        return 2;
    }

    if (u->waiting == 1) {
        /* resolved and already connecting */
        return lua_yield(L, 0);
    }

    n = lua_gettop(L) - saved_top;
    if (n) {
        /* errors occurred during resolving or connecting
         * or already connected */
        return n;
    }

    /* still resolving */

    u->waiting = 1;
    u->prepare_retvals = ngx_stream_lua_socket_resolve_retval_handler;

    coctx->data = u;

    ctx->write_event_handler = ngx_stream_lua_content_wev_handler;

    return lua_yield(L, 0);
}
static int
ngx_http_lua_uthread_wait(lua_State *L)
{
    int                          i, nargs, nrets;
    lua_State                   *sub_co;
    ngx_http_request_t          *r;
    ngx_http_lua_ctx_t          *ctx;
    ngx_http_lua_co_ctx_t       *coctx, *sub_coctx;

    lua_pushlightuserdata(L, &ngx_http_lua_request_key);
    lua_rawget(L, LUA_GLOBALSINDEX);
    r = lua_touserdata(L, -1);
    lua_pop(L, 1);

    if (r == NULL) {
        return luaL_error(L, "no request found");
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
    if (ctx == NULL) {
        return luaL_error(L, "no request ctx found");
    }

    ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
                               | NGX_HTTP_LUA_CONTEXT_ACCESS
                               | NGX_HTTP_LUA_CONTEXT_CONTENT);

    coctx = ctx->cur_co_ctx;

    nargs = lua_gettop(L);

    for (i = 1; i <= nargs; i++) {
        sub_co = lua_tothread(L, i);

        luaL_argcheck(L, sub_co, i, "lua thread expected");

        sub_coctx = ngx_http_lua_get_co_ctx(sub_co, ctx);
        if (sub_coctx == NULL) {
            return luaL_error(L, "no co ctx found for the ngx.thread "
                              "instance given");
        }

        if (!sub_coctx->is_uthread) {
            return luaL_error(L, "attempt to wait on a coroutine that is "
                              "not a user thread");
        }

        if (sub_coctx->parent_co_ctx != coctx) {
            return luaL_error(L, "only the parent coroutine can wait on the "
                              "thread");
        }

        switch (sub_coctx->co_status) {
        case NGX_HTTP_LUA_CO_ZOMBIE:

            ngx_http_lua_probe_info("found zombie child");

            nrets = lua_gettop(sub_coctx->co);

            dd("child retval count: %d, %s: %s", n,
                    luaL_typename(sub_coctx->co, -1),
                    lua_tostring(sub_coctx->co, -1));

            if (nrets) {
                lua_xmove(sub_coctx->co, L, nrets);
            }

#if 1
            ngx_http_lua_del_thread(r, L, ctx, sub_coctx);
            ctx->uthreads--;
#endif

            return nrets;

        default:
            /* still alive */
            break;
        }

        ngx_http_lua_probe_user_thread_wait(L, sub_coctx->co);
        sub_coctx->waited_by_parent = 1;
    }

    return lua_yield(L, 0);
}
Exemplo n.º 8
0
/* args-opts -- proc/nil error */
static int ex_spawn(lua_State *L)
{
  struct spawn_params *params;
  int have_options;
  switch (lua_type(L, 1)) {
  default: return luaL_typerror(L, 1, "string or table");
  case LUA_TSTRING:
    switch (lua_type(L, 2)) {
    default: return luaL_typerror(L, 2, "table");
    case LUA_TNONE: have_options = 0; break;
    case LUA_TTABLE: have_options = 1; break;
    }
    break;
  case LUA_TTABLE:
    have_options = 1;
	/* avoid issues with strict.lua */
	lua_pushstring(L, "command");		/* opts ... cmd */
	lua_rawget(L, 1);
    if (!lua_isnil(L, -1)) {
      /* convert {command=command,arg1,...} to command {arg1,...} */
      lua_insert(L, 1);                 /* cmd opts ... */
    }
    else {
      /* convert {arg0,arg1,...} to arg0 {arg1,...} */
      size_t i, n = lua_objlen(L, 1);
      lua_rawgeti(L, 1, 1);             /* opts ... nil cmd */
      lua_insert(L, 1);                 /* cmd opts ... nil */
      for (i = 2; i <= n; i++) {
        lua_rawgeti(L, 2, i);           /* cmd opts ... nil argi */
        lua_rawseti(L, 2, i - 1);       /* cmd opts ... nil */
      }
      lua_rawseti(L, 2, n);             /* cmd opts ... */
    }
    if (lua_type(L, 1) != LUA_TSTRING)
      return luaL_error(L, "bad command option (string expected, got %s)",
                        luaL_typename(L, 1));
    break;
  }
  params = spawn_param_init(L);
  /* get filename to execute */
  spawn_param_filename(params);
  /* get arguments, environment, and redirections */
  if (have_options) {
    lua_getfield(L, 2, "args");         /* cmd opts ... argtab */
    switch (lua_type(L, -1)) {
    default:
      return luaL_error(L, "bad args option (table expected, got %s)",
                        luaL_typename(L, -1));
    case LUA_TNIL:
      lua_pop(L, 1);                    /* cmd opts ... */
      lua_pushvalue(L, 2);              /* cmd opts ... opts */
      if (0) /*FALLTHRU*/
    case LUA_TTABLE:
      if (lua_objlen(L, 2) > 0)
        return
          luaL_error(L, "cannot specify both the args option and array values");
      spawn_param_args(params);         /* cmd opts ... */
      break;
    }
    lua_getfield(L, 2, "env");          /* cmd opts ... envtab */
    switch (lua_type(L, -1)) {
    default:
      return luaL_error(L, "bad env option (table expected, got %s)",
                        luaL_typename(L, -1));
    case LUA_TNIL:
      break;
    case LUA_TTABLE:
      spawn_param_env(params);          /* cmd opts ... */
      break;
    }

    lua_getfield(L, 2, "show");          /* cmd opts ... envtab */
    spawn_param_show(params, lua_type(L, -1) == LUA_TBOOLEAN ? lua_toboolean(L, -1) : 0);

    lua_getfield(L, 2, "shell");          /* cmd opts ... envtab */
    spawn_param_useshell(params, lua_type(L, -1) == LUA_TBOOLEAN ? lua_toboolean(L, -1) : 1);

    get_redirect(L, 2, "stdin", params);    /* cmd opts ... */
    get_redirect(L, 2, "stdout", params);   /* cmd opts ... */
    get_redirect(L, 2, "stderr", params);   /* cmd opts ... */
  }
  return spawn_param_execute(params);   /* proc/nil error */
}
Exemplo n.º 9
0
//in: linda_ud key [[val] ...]
//out: true or nil
int keepercall_set( lua_State* L)
{
	bool_t should_wake_writers = FALSE;
	STACK_GROW( L, 6);

	// retrieve fifos associated with the linda
	push_table( L, 1);                                // ud key [val [, ...]] fifos
	lua_replace( L, 1);                               // fifos key [val [, ...]]

	// make sure we have a value on the stack
	if( lua_gettop( L) == 2)                          // fifos key
	{
		keeper_fifo* fifo;
		lua_pushvalue( L, -1);                          // fifos key key
		lua_rawget( L, 1);                              // fifos key fifo|nil
		// empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged!
		fifo = (keeper_fifo*) lua_touserdata( L, -1);
		if( fifo != NULL) // might be NULL if we set a nonexistent key to nil
		{                                               // fifos key fifo
			if( fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it
			{
				lua_pop( L, 1);                             // fifos key
				lua_pushnil( L);                            // fifos key nil
				lua_rawset( L, -3);                         // fifos
			}
			else
			{
				// we create room if the fifo was full but it is no longer the case
				should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit);
				lua_remove( L, -2);                         // fifos fifo
				lua_newtable( L);                           // fifos fifo {}
				lua_setuservalue( L, -2);                   // fifos fifo
				fifo->first = 1;
				fifo->count = 0;
			}
		}
	}
	else // set/replace contents stored at the specified key?
	{
		int count = lua_gettop( L) - 2; // number of items we want to store
		keeper_fifo* fifo;                              // fifos key [val [, ...]]
		lua_pushvalue( L, 2);                           // fifos key [val [, ...]] key
		lua_rawget( L, 1);                              // fifos key [val [, ...]] fifo|nil
		fifo = (keeper_fifo*) lua_touserdata( L, -1);
		if( fifo == NULL) // can be NULL if we store a value at a new key
		{                                               // fifos key [val [, ...]] nil
			// no need to wake writers in that case, because a writer can't wait on an inexistent key
			lua_pop( L, 1);                               // fifos key [val [, ...]]
			fifo_new( L);                                 // fifos key [val [, ...]] fifo
			lua_pushvalue( L, 2);                         // fifos key [val [, ...]] fifo key
			lua_pushvalue( L, -2);                        // fifos key [val [, ...]] fifo key fifo
			lua_rawset( L, 1);                            // fifos key [val [, ...]] fifo
		}
		else // the fifo exists, we just want to update its contents
		{                                               // fifos key [val [, ...]] fifo
			// we create room if the fifo was full but it is no longer the case
			should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit);
			// empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged!
			lua_newtable( L);                             // fifos key [val [, ...]] fifo {}
			lua_setuservalue( L, -2);                     // fifos key [val [, ...]] fifo
			fifo->first = 1;
			fifo->count = 0;
		}
		fifo = prepare_fifo_access( L, -1);
		// move the fifo below the values we want to store
		lua_insert( L, 3);                              // fifos key fifo [val [, ...]]
		fifo_push( L, fifo, count);                     // fifos key fifo
	}
	return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0;
}
Exemplo n.º 10
0
static void
ngx_http_lua_timer_handler(ngx_event_t *ev)
{
    int                      n;
    lua_State               *L;
    ngx_int_t                rc;
    ngx_connection_t        *c = NULL;
    ngx_http_request_t      *r = NULL;
    ngx_http_lua_ctx_t      *ctx;
    ngx_http_cleanup_t      *cln;
    ngx_pool_cleanup_t      *pcln;

    ngx_http_lua_timer_ctx_t         tctx;
    ngx_http_lua_main_conf_t        *lmcf;
    ngx_http_core_loc_conf_t        *clcf;
    ngx_http_lua_timer_log_ctx_t    *logctx;

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                   "lua ngx.timer expired");

    ngx_memcpy(&tctx, ev->data, sizeof(ngx_http_lua_timer_ctx_t));
    ngx_free(ev);
    ev = NULL;

    lmcf = tctx.lmcf;

    lmcf->pending_timers--;

    if (lmcf->running_timers >= lmcf->max_running_timers) {
        ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                      "%i lua_max_running_timers are not enough",
                      lmcf->max_running_timers);
        goto failed;
    }

    c = ngx_http_lua_create_fake_connection(tctx.pool);
    if (c == NULL) {
        goto failed;
    }

    logctx = ngx_palloc(c->pool, sizeof(ngx_http_lua_timer_log_ctx_t));
    if (logctx == NULL) {
        goto failed;
    }

    logctx->connection = c;

    c->log->handler = ngx_http_lua_log_timer_error;
    c->log->data = logctx;

    c->listening = tctx.listening;
    c->addr_text = tctx.client_addr_text;

    r = ngx_http_lua_create_fake_request(c);
    if (r == NULL) {
        goto failed;
    }

    r->main_conf = tctx.main_conf;
    r->srv_conf = tctx.srv_conf;
    r->loc_conf = tctx.loc_conf;

    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

#if defined(nginx_version) && nginx_version >= 1003014

    ngx_set_connection_log(r->connection, clcf->error_log);

#else

    c->log->file = clcf->error_log->file;

    if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
        c->log->log_level = clcf->error_log->log_level;
    }

#endif

    dd("lmcf: %p", lmcf);

    ctx = ngx_http_lua_create_ctx(r);
    if (ctx == NULL) {
        goto failed;
    }

    if (tctx.vm_state) {
        ctx->vm_state = tctx.vm_state;

        pcln = ngx_pool_cleanup_add(r->pool, 0);
        if (pcln == NULL) {
            goto failed;
        }

        pcln->handler = ngx_http_lua_cleanup_vm;
        pcln->data = tctx.vm_state;
    }

    ctx->cur_co_ctx = &ctx->entry_co_ctx;

    L = ngx_http_lua_get_lua_vm(r, ctx);

    cln = ngx_http_cleanup_add(r, 0);
    if (cln == NULL) {
        goto failed;
    }

    cln->handler = ngx_http_lua_request_cleanup_handler;
    cln->data = ctx;
    ctx->cleanup = &cln->handler;

    ctx->entered_content_phase = 1;
    ctx->context = NGX_HTTP_LUA_CONTEXT_TIMER;

    r->read_event_handler = ngx_http_block_reading;

    ctx->cur_co_ctx->co_ref = tctx.co_ref;
    ctx->cur_co_ctx->co = tctx.co;
    ctx->cur_co_ctx->co_status = NGX_HTTP_LUA_CO_RUNNING;

    dd("r connection: %p, log %p", r->connection, r->connection->log);

    /*  save the request in coroutine globals table */
    ngx_http_lua_set_req(tctx.co, r);

    lmcf->running_timers++;

    lua_pushboolean(tctx.co, tctx.premature);

    n = lua_gettop(tctx.co);
    if (n > 2) {
        lua_insert(tctx.co, 2);
    }

#ifdef NGX_LUA_USE_ASSERT
    ctx->cur_co_ctx->co_top = 1;
#endif

    rc = ngx_http_lua_run_thread(L, r, ctx, n - 1);

    dd("timer lua run thread: %d", (int) rc);

    if (rc == NGX_ERROR || rc >= NGX_OK) {
        /* do nothing */

    } else if (rc == NGX_AGAIN) {
        rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 0);

    } else if (rc == NGX_DONE) {
        rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 1);

    } else {
        rc = NGX_OK;
    }

    ngx_http_lua_finalize_request(r, rc);
    return;

failed:

    if (tctx.co_ref && tctx.co) {
        lua_pushlightuserdata(tctx.co, &ngx_http_lua_coroutines_key);
        lua_rawget(tctx.co, LUA_REGISTRYINDEX);
        luaL_unref(tctx.co, -1, tctx.co_ref);
        lua_settop(tctx.co, 0);
    }

    if (tctx.vm_state) {
        ngx_http_lua_cleanup_vm(tctx.vm_state);
    }

    if (c) {
        ngx_http_lua_close_fake_connection(c);

    } else if (tctx.pool) {
        ngx_destroy_pool(tctx.pool);
    }
}
Exemplo n.º 11
0
static int
ngx_http_lua_ngx_timer_at(lua_State *L)
{
    int                      nargs, co_ref;
    u_char                  *p;
    lua_State               *vm;  /* the main thread */
    lua_State               *co;
    ngx_msec_t               delay;
    ngx_event_t             *ev;
    ngx_http_request_t      *r;
    ngx_connection_t        *saved_c = NULL;
    ngx_http_lua_ctx_t      *ctx;
#if 0
    ngx_http_connection_t   *hc;
#endif

    ngx_http_lua_timer_ctx_t      *tctx = NULL;
    ngx_http_lua_main_conf_t      *lmcf;
#if 0
    ngx_http_core_main_conf_t     *cmcf;
#endif

    nargs = lua_gettop(L);
    if (nargs < 2) {
        return luaL_error(L, "expecting at least 2 arguments but got %d",
                          nargs);
    }

    delay = (ngx_msec_t) (luaL_checknumber(L, 1) * 1000);

    luaL_argcheck(L, lua_isfunction(L, 2) && !lua_iscfunction(L, 2), 2,
                 "Lua function expected");

    r = ngx_http_lua_get_req(L);
    if (r == NULL) {
        return luaL_error(L, "no request");
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);

    if (ngx_exiting && delay > 0) {
        lua_pushnil(L);
        lua_pushliteral(L, "process exiting");
        return 2;
    }

    lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);

    if (lmcf->pending_timers >= lmcf->max_pending_timers) {
        lua_pushnil(L);
        lua_pushliteral(L, "too many pending timers");
        return 2;
    }

    if (lmcf->watcher == NULL) {
        /* create the watcher fake connection */

        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                       "lua creating fake watcher connection");

        if (ngx_cycle->files) {
            saved_c = ngx_cycle->files[0];
        }

        lmcf->watcher = ngx_get_connection(0, ngx_cycle->log);

        if (ngx_cycle->files) {
            ngx_cycle->files[0] = saved_c;
        }

        if (lmcf->watcher == NULL) {
            return luaL_error(L, "no memory");
        }

        /* to work around the -1 check in ngx_worker_process_cycle: */
        lmcf->watcher->fd = (ngx_socket_t) -2;

        lmcf->watcher->idle = 1;
        lmcf->watcher->read->handler = ngx_http_lua_abort_pending_timers;
        lmcf->watcher->data = lmcf;
    }

    vm = ngx_http_lua_get_lua_vm(r, ctx);

    co = lua_newthread(vm);

    /* L stack: time func [args] thread */

    ngx_http_lua_probe_user_coroutine_create(r, L, co);

    lua_createtable(co, 0, 0);  /* the new globals table */

    /* co stack: global_tb */

    lua_createtable(co, 0, 1);  /* the metatable */
    ngx_http_lua_get_globals_table(co);
    lua_setfield(co, -2, "__index");
    lua_setmetatable(co, -2);

    /* co stack: global_tb */

    ngx_http_lua_set_globals_table(co);

    /* co stack: <empty> */

    dd("stack top: %d", lua_gettop(L));

    lua_xmove(vm, L, 1);    /* move coroutine from main thread to L */

    /* L stack: time func [args] thread */
    /* vm stack: empty */

    lua_pushvalue(L, 2);    /* copy entry function to top of L*/

    /* L stack: time func [args] thread func */

    lua_xmove(L, co, 1);    /* move entry function from L to co */

    /* L stack: time func [args] thread */
    /* co stack: func */

    ngx_http_lua_get_globals_table(co);
    lua_setfenv(co, -2);

    /* co stack: func */

    lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
    lua_rawget(L, LUA_REGISTRYINDEX);

    /* L stack: time func [args] thread corountines */

    lua_pushvalue(L, -2);

    /* L stack: time func [args] thread coroutines thread */

    co_ref = luaL_ref(L, -2);
    lua_pop(L, 1);

    /* L stack: time func [args] thread */

    if (nargs > 2) {
        lua_pop(L, 1);  /* L stack: time func [args] */
        lua_xmove(L, co, nargs - 2);  /* L stack: time func */

        /* co stack: func [args] */
    }

    p = ngx_alloc(sizeof(ngx_event_t) + sizeof(ngx_http_lua_timer_ctx_t),
                  r->connection->log);
    if (p == NULL) {
        goto nomem;
    }

    ev = (ngx_event_t *) p;

    ngx_memzero(ev, sizeof(ngx_event_t));

    p += sizeof(ngx_event_t);

    tctx = (ngx_http_lua_timer_ctx_t *) p;

    tctx->premature = 0;
    tctx->co_ref = co_ref;
    tctx->co = co;
    tctx->main_conf = r->main_conf;
    tctx->srv_conf = r->srv_conf;
    tctx->loc_conf = r->loc_conf;
    tctx->lmcf = lmcf;

    tctx->pool = ngx_create_pool(128, ngx_cycle->log);
    if (tctx->pool == NULL) {
        goto nomem;
    }

    if (r->connection) {
        tctx->listening = r->connection->listening;

    } else {
        tctx->listening = NULL;
    }

    if (r->connection->addr_text.len) {
        tctx->client_addr_text.data = ngx_palloc(tctx->pool,
                                                 r->connection->addr_text.len);
        if (tctx->client_addr_text.data == NULL) {
            goto nomem;
        }

        ngx_memcpy(tctx->client_addr_text.data, r->connection->addr_text.data,
                   r->connection->addr_text.len);
        tctx->client_addr_text.len = r->connection->addr_text.len;

    } else {
        tctx->client_addr_text.len = 0;
        tctx->client_addr_text.data = NULL;
    }

    if (ctx && ctx->vm_state) {
        tctx->vm_state = ctx->vm_state;
        tctx->vm_state->count++;

    } else {
        tctx->vm_state = NULL;
    }

    ev->handler = ngx_http_lua_timer_handler;
    ev->data = tctx;
    ev->log = ngx_cycle->log;

    lmcf->pending_timers++;

    ngx_add_timer(ev, delay);

    lua_pushinteger(L, 1);
    return 1;

nomem:

    if (tctx && tctx->pool) {
        ngx_destroy_pool(tctx->pool);
    }

    lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
    lua_rawget(L, LUA_REGISTRYINDEX);
    luaL_unref(L, -1, co_ref);

    return luaL_error(L, "no memory");
}
Exemplo n.º 12
0
ngx_int_t
ngx_http_lua_wev_handler(ngx_http_request_t *r)
{
    ngx_int_t                    rc;
    ngx_http_lua_ctx_t          *ctx;
    ngx_http_lua_main_conf_t    *lmcf;
    lua_State                   *cc;
    ngx_str_t                   *body_str;
    ngx_http_headers_out_t      *sr_headers;
    ngx_list_part_t             *part;
    ngx_table_elt_t             *header;
    ngx_uint_t                   i, index;

    dd("wev handler %.*s %.*s a:%d, postponed:%p",
       (int) r->uri.len, r->uri.data,
       (int) ngx_cached_err_log_time.len,
       ngx_cached_err_log_time.data,
       r == r->connection->data,
       r->postponed);
#if 0
    ngx_http_lua_dump_postponed(r);
#endif

    ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
    if (ctx == NULL) {
        goto error;
    }

    dd("ctx = %p", ctx);
    dd("request done: %d", (int) r->done);
    dd("cleanup done: %p", ctx->cleanup);

    if (ctx->cleanup == NULL) {
        /* already done */
        dd("cleanup is null: %.*s", (int) r->uri.len, r->uri.data);

        if (ctx->entered_content_phase) {
            ngx_http_finalize_request(r,
                                      ngx_http_lua_flush_postponed_outputs(r));
        }

        return NGX_DONE;
    }

    dd("waiting: %d, done: %d", (int) ctx->waiting,
       ctx->done);

    if (ctx->waiting && ! ctx->done) {
        dd("%.*s waiting and not done", (int) r->uri.len, r->uri.data);

#if 0
        ngx_http_lua_dump_postponed(r);
#endif

        if (r == r->connection->data && r->postponed) {
            if (r->postponed->request) {
                r->connection->data = r->postponed->request;

#if defined(nginx_version) && nginx_version >= 8012
                ngx_http_post_request(r->postponed->request, NULL);
#else
                ngx_http_post_request(r->postponed->request);
#endif

            } else {
                ngx_http_lua_flush_postponed_outputs(r);
            }
        }

        return NGX_DONE;
    }

    ctx->done = 0;

    dd("nsubreqs: %d", (int) ctx->nsubreqs);

    for (index = 0; index < ctx->nsubreqs; index++) {
        dd("summary: reqs %d, subquery %d, waiting %d, req %.*s",
           (int) ctx->nsubreqs,
           (int) index,
           (int) ctx->waiting,
           (int) r->uri.len, r->uri.data);

        cc = ctx->cc;

        /*  {{{ construct ret value */
        lua_newtable(cc);

        /*  copy captured status */
        lua_pushinteger(cc, ctx->sr_statuses[index]);
        lua_setfield(cc, -2, "status");

        /*  copy captured body */

        body_str = &ctx->sr_bodies[index];

        lua_pushlstring(cc, (char *) body_str->data, body_str->len);
        lua_setfield(cc, -2, "body");

        if (body_str->data) {
            dd("free body buffer ASAP");
            ngx_pfree(r->pool, body_str->data);
        }

        /* copy captured headers */

        lua_newtable(cc); /* res.header */

        sr_headers = ctx->sr_headers[index];

        if (sr_headers->content_length == NULL
                && sr_headers->content_length_n >= 0)
        {
            lua_pushliteral(cc, "Content-Length"); /* header key */

            lua_pushnumber(cc, sr_headers->content_length_n);
            /* head key value */

            lua_rawset(cc, -3); /* head */
        }

        if (sr_headers->content_type.len) {
            lua_pushliteral(cc, "Content-Type"); /* header key */
            lua_pushlstring(cc, (char *) sr_headers->content_type.data,
                            sr_headers->content_type.len); /* head key value */
            lua_rawset(cc, -3); /* head */
        }

        dd("saving subrequest response headers");

        part = &sr_headers->headers.part;
        header = part->elts;

        for (i = 0; /* void */; i++) {

            if (i >= part->nelts) {
                if (part->next == NULL) {
                    break;
                }

                part = part->next;
                header = part->elts;
                i = 0;
            }

            dd("checking sr header %.*s", (int) header[i].key.len,
               header[i].key.data);

#if 1
            if (header[i].hash == 0) {
                continue;
            }
#endif

            dd("pushing sr header %.*s", (int) header[i].key.len,
               header[i].key.data);

            lua_pushlstring(cc, (char *) header[i].key.data,
                            header[i].key.len); /* header key */
            lua_pushvalue(cc, -1); /* stack: table key key */

            /* check if header already exists */
            lua_rawget(cc, -3); /* stack: table key value */

            if (lua_isnil(cc, -1)) {
                lua_pop(cc, 1); /* stack: table key */

                lua_pushlstring(cc, (char *) header[i].value.data,
                                header[i].value.len); /* stack: table key value */

                lua_rawset(cc, -3); /* stack: table */

            } else {
                if (! lua_istable(cc, -1)) { /* already inserted one value */
                    lua_createtable(cc, 4, 0);
                    /* stack: table key value table */

                    lua_insert(cc, -2); /* stack: table key table value */
                    lua_rawseti(cc, -2, 1); /* stack: table key table */

                    lua_pushlstring(cc, (char *) header[i].value.data,
                                    header[i].value.len);
                    /* stack: table key table value */

                    lua_rawseti(cc, -2, lua_objlen(cc, -2) + 1);
                    /* stack: table key table */

                    lua_rawset(cc, -3); /* stack: table */

                } else {
                    lua_pushlstring(cc, (char *) header[i].value.data,
                                    header[i].value.len);
                    /* stack: table key table value */

                    lua_rawseti(cc, -2, lua_objlen(cc, -2) + 1);
                    /* stack: table key table */

                    lua_pop(cc, 2); /* stack: table */
                }
            }
        }

        lua_setfield(cc, -2, "header");

        /*  }}} */
    }

    dd("free sr_statues/headers/bodies memory ASAP");

#if 1
    ngx_pfree(r->pool, ctx->sr_statuses);

    ctx->sr_statuses = NULL;
    ctx->sr_headers = NULL;
    ctx->sr_bodies = NULL;
#endif

    lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);

    dd("about to run thread for %.*s...", (int) r->uri.len, r->uri.data);

    rc = ngx_http_lua_run_thread(lmcf->lua, r, ctx, ctx->nsubreqs);

    dd("already run thread for %.*s...", (int) r->uri.len, r->uri.data);

    if (rc == NGX_AGAIN || rc == NGX_DONE) {
        return NGX_DONE;
    }

    dd("entered content phase: %d", (int) ctx->entered_content_phase);

    if (ctx->entered_content_phase) {
        ngx_http_finalize_request(r, rc);
    }

    if (rc == NGX_OK) {
        return NGX_DECLINED;
    }

    return rc;

error:
    if (ctx->entered_content_phase) {
        ngx_http_finalize_request(r,
                                  ctx->headers_sent ? NGX_ERROR: NGX_HTTP_INTERNAL_SERVER_ERROR);
    }

    return NGX_ERROR;
}
Exemplo n.º 13
0
static void lua_pushluaobject(lua_State *L, LuaObject *f)
    // lua stack [-0, +1]
{
    lua_pushlightuserdata(L, f);
    lua_rawget(L, LUA_REGISTRYINDEX);
}
Exemplo n.º 14
0
void THAnimation::persist(LuaPersistWriter *pWriter) const
{
    lua_State *L = pWriter->getStack();

    // Write the next chained thing
    lua_rawgeti(L, luaT_environindex, 2);
    lua_pushlightuserdata(L, m_pNext);
    lua_rawget(L, -2);
    pWriter->fastWriteStackObject(-1);
    lua_pop(L, 2);

    // Write the THDrawable fields
    pWriter->writeVUInt(m_iFlags);
#define IsUsingFunctionSet(d, ht) m_fnDraw == (THAnimation_ ## d) \
                            && m_fnHitTest == (THAnimation_ ## ht)

    if(IsUsingFunctionSet(Draw, HitTest))
        pWriter->writeVUInt(1);
    else if(IsUsingFunctionSet(DrawChild, HitTestChild))
        pWriter->writeVUInt(2);
    else if(IsUsingFunctionSet(DrawMorph, HitTestMorph))
    {
        // NB: Prior version of code used the number 3 here, and forgot
        // to persist the morph target.
        pWriter->writeVUInt(4);
        lua_rawgeti(L, luaT_environindex, 2);
        lua_pushlightuserdata(L, m_pMorphTarget);
        lua_rawget(L, -2);
        pWriter->writeStackObject(-1);
        lua_pop(L, 2);
    }
    else
        pWriter->writeVUInt(0);

#undef IsUsingFunctionSet

    // Write the simple fields
    pWriter->writeVUInt(m_iAnimation);
    pWriter->writeVUInt(m_iFrame);
    pWriter->writeVInt(m_iX);
    pWriter->writeVInt(m_iY);
    pWriter->writeVInt((int)m_iSoundToPlay); // Not a VUInt, for compatibility
    pWriter->writeVInt(0); // For compatibility
    if(m_iFlags & THDF_Crop)
        pWriter->writeVInt(m_iCropColumn);

    // Write the unioned fields
    if(m_fnDraw != THAnimation_DrawChild)
    {
        pWriter->writeVInt(m_iSpeedX);
        pWriter->writeVInt(m_iSpeedY);
    }
    else
    {
        lua_rawgeti(L, luaT_environindex, 2);
        lua_pushlightuserdata(L, m_pParent);
        lua_rawget(L, -2);
        pWriter->writeStackObject(-1);
        lua_pop(L, 2);
    }

    // Write the layers
    int iNumLayers = 13;
    for( ; iNumLayers >= 1; --iNumLayers)
    {
        if(m_oLayers.iLayerContents[iNumLayers - 1] != 0)
            break;
    }
    pWriter->writeVUInt(iNumLayers);
    pWriter->writeByteStream(m_oLayers.iLayerContents, iNumLayers);
}
Exemplo n.º 15
0
// increase lua function reference counter, return functionId
int LuaJavaBridge::retainLuaFunction(lua_State *L, int functionIndex, int *retainCountReturn)
{
                                                                /* L: f ... */
    lua_pushstring(L, LUAJ_REGISTRY_FUNCTION);                  /* L: f ... key */
    lua_rawget(L, LUA_REGISTRYINDEX);                           /* L: f ... f_id */
    if (!lua_istable(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushstring(L, LUAJ_REGISTRY_FUNCTION);
        lua_pushvalue(L, -2);
        lua_rawset(L, LUA_REGISTRYINDEX);
    }

    lua_pushstring(L, LUAJ_REGISTRY_RETAIN);                    /* L: f ... f_id key */
    lua_rawget(L, LUA_REGISTRYINDEX);                           /* L: f ... f_id id_r */
    if (!lua_istable(L, -1))
    {
        lua_pop(L, 1);
        lua_newtable(L);
        lua_pushstring(L, LUAJ_REGISTRY_RETAIN);
        lua_pushvalue(L, -2);
        lua_rawset(L, LUA_REGISTRYINDEX);
    }

    // get function id
    lua_pushvalue(L, functionIndex - 2);                        /* L: f ... f_id id_r f */
    lua_rawget(L, -3);                                          /* L: f ... f_id id_r id */

    int functionId;
    if (lua_type(L, -1) != LUA_TNUMBER)
    {
        // first retain, create new id
        lua_pop(L, 1);                                          /* L: f ... f_id id_r */
        s_newFunctionId++;
        functionId = s_newFunctionId;

        lua_pushvalue(L, functionIndex - 2);                    /* L: f ... f_id id_r f */
        lua_pushinteger(L, functionId);                         /* L: f ... f_id id_r f id */
        lua_rawset(L, -4);                        /* f_id[f] = id, L: f ... f_id id_r */
        lua_pushinteger(L, functionId);                         /* L: f ... f_id id_r id */
    }
    else
    {
        functionId = lua_tonumber(L, -1);
    }

    // get function retain
    lua_pushvalue(L, -1);                                       /* L: f ... f_id id_r id id */
    lua_rawget(L, -3);                                          /* L: f ... f_id id_r id r */
    int retainCount = 1;
    if (lua_type(L, -1) != LUA_TNUMBER)
    {
        // first retain, set retain count = 1
        lua_pop(L, 1);
        lua_pushinteger(L, retainCount);
    }
    else
    {
        // add retain count
        retainCount = lua_tonumber(L, -1);
        retainCount++;
        lua_pop(L, 1);
        lua_pushinteger(L, retainCount);
    }

    lua_rawset(L, -3);                            /* id_r[id] = r, L: f ... f_id id_r */
    lua_pop(L, 2);                                              /* L: f ... */

    if (retainCountReturn) *retainCountReturn = retainCount;
    return functionId;
}
Exemplo n.º 16
0
// in: linda_ud [, key [, ...]]
int keepercall_count( lua_State* L)
{
	int top;
	push_table( L, 1);                                   // ud keys fifos
	switch( lua_gettop( L))
	{
		// no key is specified: return a table giving the count of all known keys
		case 2:                                            // ud fifos
		lua_newtable( L);                                  // ud fifos out
		lua_replace( L, 1);                                // out fifos
		lua_pushnil( L);                                   // out fifos nil
		while( lua_next( L, 2))                            // out fifos key fifo
		{
			keeper_fifo* fifo = prepare_fifo_access( L, -1); // out fifos key fifo
			lua_pop( L, 1);                                  // out fifos key
			lua_pushvalue( L, -1);                           // out fifos key key
			lua_pushinteger( L, fifo->count);                // out fifos key key count
			lua_rawset( L, -5);                              // out fifos key
		}
		lua_pop( L, 1);                                    // out
		break;

		// 1 key is specified: return its count
		case 3:                                            // ud key fifos
		{
			keeper_fifo* fifo;
			lua_replace( L, 1);                              // fifos key
			lua_rawget( L, -2);                              // fifos fifo|nil
			if( lua_isnil( L, -1)) // the key is unknown
			{                                                // fifos nil
				lua_remove( L, -2);                            // nil
			}
			else // the key is known
			{                                                // fifos fifo
				fifo = prepare_fifo_access( L, -1);            // fifos fifo
				lua_pushinteger( L, fifo->count);              // fifos fifo count
				lua_replace( L, -3);                           // count fifo
				lua_pop( L, 1);                                // count
			}
		}
		break;

		// a variable number of keys is specified: return a table of their counts
		default:                                           // ud keys fifos
		lua_newtable( L);                                  // ud keys fifos out
		lua_replace( L, 1);                                // out keys fifos
		// shifts all keys up in the stack. potentially slow if there are a lot of them, but then it should be bearable
		lua_insert( L, 2);                                 // out fifos keys
		while( (top = lua_gettop( L)) > 2)
		{
			keeper_fifo* fifo;
			lua_pushvalue( L, -1);                           // out fifos keys key
			lua_rawget( L, 2);                               // out fifos keys fifo|nil
			fifo = prepare_fifo_access( L, -1);              // out fifos keys fifo|nil
			lua_pop( L, 1);                                  // out fifos keys
			if( fifo != NULL) // the key is known
			{
				lua_pushinteger( L, fifo->count);              // out fifos keys count
				lua_rawset( L, 1);                             // out fifos keys
			}
			else // the key is unknown
			{
				lua_pop( L, 1);                                // out fifos keys
			}
		}
		lua_pop( L, 1);                                    // out
	}
	ASSERT_L( lua_gettop( L) == 1);
	return 1;
}
Exemplo n.º 17
0
static void luaL_rawgetptr(lua_State *L, int idx, void *ptr)
{
	idx = abs_index(L, idx);
	lua_pushlightuserdata(L, ptr);
	lua_rawget(L, idx);
}
Exemplo n.º 18
0
Arquivo: rpmlua.c Projeto: Tojaj/rpm
static int findkey(lua_State *L, int oper, const char *key, va_list va)
{
    char *buf;
    const char *s, *e;
    int ret = 0;
    int blen;

    blen = vsnprintf(NULL, 0, key, va);
    if (blen <= 0) {
	return -1;
    }

    buf = xmalloc(blen + 1);
    vsnprintf(buf, blen + 1, key, va);

    s = e = buf;
    lua_pushglobaltable(L);
    for (;;) {
	if (*e == '\0' || *e == '.') {
	    if (e != s) {
		lua_pushlstring(L, s, e-s);
		switch (oper) {
		case FINDKEY_REMOVE:
		    if (*e == '\0') {
			lua_pushnil(L);
			lua_rawset(L, -3);
			lua_pop(L, 1);
			break;
		    }
		case FINDKEY_RETURN:
		    lua_rawget(L, -2);
		    lua_remove(L, -2);
		    break;
		case FINDKEY_CREATE:
		    lua_rawget(L, -2);
		    if (!lua_istable(L, -1)) {
			lua_pop(L, 1);
			lua_newtable(L);
			lua_pushlstring(L, s, e-s);
			lua_pushvalue(L, -2);
			lua_rawset(L, -4);
		    }
		    lua_remove(L, -2);
		    break;
		}
	    }
	    if (*e == '\0')
		break;
	    if (!lua_istable(L, -1)) {
		lua_pop(L, 1);
		ret = -1;
		break;
	    }
	    s = e+1;
	}
	e++;
    }
    free(buf);

    return ret;
}
Exemplo n.º 19
0
static int js_getter_index (lua_State* L)
{
	// stack: self, key, _self

	while (lua_gettop(L) < 3) {
		lua_pushnil(L);
	}

	// _self or self
	if (lua_isnil(L, 3)) {
		lua_pushvalue(L, 1);
	} else {
		lua_pushvalue(L, 3);
	}

	if (lua_getmetatable(L, -1) == 0) {
		lua_pushnil(L);
		return 1;
	}

	// stack: self, key, _self, (_self or self), mt
	// Check getters
	lua_getfield(L, -1, "getters");
	if (!lua_isnil(L, -1)) {
		lua_pushvalue(L, 2);
		lua_rawget(L, -2);
		if (!lua_isnil(L, -1)) {
			lua_pushvalue(L, 1);
			lua_call(L, 1, 1);
			return 1;
		}
		lua_remove(L, -1);
	}
	lua_remove(L, -1);

	// stack: self, key, _self, (_self or self), mt
	// Get raw key or defer to proto getter
	lua_pushvalue(L, 2);
	// stack: self, key, _self, (_self or self), mt, key
	lua_rawget(L, -3);

	// stack: self, key, _self, (_self or self), mt, (_self or self)[key]
	if (lua_isnil(L, -1)) {
		// stack: self, key, _self, (_self or self), mt, nil
		lua_getfield(L, -2, "proto");
		// stack: self, key, _self, (_self or self), mt, nil, mt.proto
		lua_insert(L, 2);
		// stack: self, mt.proto, key, _self, (_self or self), mt, nil
		lua_remove(L, -1);
		// stack: self, mt.proto, key, _self, (_self or self), mt
		lua_remove(L, -1);
		// stack: self, mt.proto, key, _self, (_self or self)
		lua_remove(L, -1);
		// stack: self, mt.proto, key, _self
		lua_remove(L, -1);
		// stack: self, mt.proto, key
		return js_proto_get(L);
	}

	return 1;
}
Exemplo n.º 20
0
const char *LuaSerializer::unpickle(lua_State *l, const char *pos)
{
	LUA_DEBUG_START(l);

	// tables are also unpickled recursively, so we can run out of Lua stack space if we're not careful
	// start by ensuring we have enough (this grows the stack if necessary)
	// (20 is somewhat arbitrary)
	if (!lua_checkstack(l, 20))
		luaL_error(l, "The Lua stack couldn't be extended (not enough memory?)");

	char type = *pos++;

	switch (type) {

		case 'f': {
			char *end;
			double f = strtod(pos, &end);
			if (pos == end) throw SavedGameCorruptException();
			lua_pushnumber(l, f);
			pos = end+1; // skip newline
			break;
		}

		case 'b': {
			if (*pos != '0' && *pos != '1') throw SavedGameCorruptException();
			bool b = (*pos == '0') ? false : true;
			lua_pushboolean(l, b);
			pos++;
			break;
		}

		case 's': {
			char *end;
			int len = strtol(pos, const_cast<char**>(&end), 0);
			if (pos == end) throw SavedGameCorruptException();
			end++; // skip newline
			lua_pushlstring(l, end, len);
			pos = end + len;
			break;
		}

		case 't': {
			lua_newtable(l);

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");
			pos = unpickle(l, pos);
			lua_pushvalue(l, -3);
			lua_rawset(l, -3);
			lua_pop(l, 1);

			while (*pos != 'n') {
				pos = unpickle(l, pos);
				pos = unpickle(l, pos);
				lua_rawset(l, -3);
			}
			pos++;

			break;
		}

		case 'r': {
			pos = unpickle(l, pos);

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");
			lua_pushvalue(l, -2);
			lua_rawget(l, -2);

			if (lua_isnil(l, -1))
				throw SavedGameCorruptException();

			lua_insert(l, -3);
			lua_pop(l, 2);

			break;
		}

		case 'u': {
			const char *end;
			if (!LuaObjectBase::Deserialize(pos, &end))
				throw SavedGameCorruptException();
			pos = end;
			break;
		}

		case 'o': {
			const char *end = strchr(pos, '\n');
			if (!end) throw SavedGameCorruptException();
			int len = end - pos;
			end++; // skip newline

			const char *cl = pos;

			// unpickle the object, and insert it beneath the method table value
			pos = unpickle(l, end);

			// If it is a reference, don't run the unserializer. It has either
			// already been run, or the data is still building (cyclic
			// references will do that to you.)
			if (*end != 'r') {
				// get PiSerializerClasses[typename]
				lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerClasses");
				lua_pushlstring(l, cl, len);
				lua_gettable(l, -2);
				lua_remove(l, -2);

				if (lua_isnil(l, -1)) {
					lua_pop(l, 2);
					break;
				}

				lua_getfield(l, -1, "Unserialize");
				if (lua_isnil(l, -1)) {
					lua_pushlstring(l, cl, len);
					luaL_error(l, "No Unserialize method found for class '%s'\n", lua_tostring(l, -1));
				}

				lua_insert(l, -3);
				lua_pop(l, 1);

				pi_lua_protected_call(l, 1, 1);
			}

			break;
		}

		default:
			throw SavedGameCorruptException();
	}

	LUA_DEBUG_END(l, 1);

	return pos;
}
Exemplo n.º 21
0
int CLuaVector4Defs::Create ( lua_State* luaVM )
{
    CVector4D vector;

    CScriptArgReader argStream ( luaVM );
    if ( argStream.NextIsTable () )
    {
        lua_pushvalue ( luaVM, 1 );

        lua_pushstring ( luaVM, "x" );
        lua_rawget ( luaVM, -2 );
        if ( lua_isnumber ( luaVM, -1 ) )
        {
            vector.fX = ( float ) lua_tonumber ( luaVM, -1 );
            lua_pop ( luaVM, 1 );
        }
        else
        {
            lua_pop ( luaVM, 1 );
            lua_rawgeti ( luaVM, -1, 1 );
            if ( lua_isnumber ( luaVM, -1 ) )
                vector.fX = ( float ) lua_tonumber ( luaVM, -1 );
            lua_pop ( luaVM, 1 );
        }

        lua_pushstring ( luaVM, "y" );
        lua_rawget ( luaVM, -2 );
        if ( lua_isnumber ( luaVM, -1 ) )
        {
            vector.fY = ( float ) lua_tonumber ( luaVM, -1 );
            lua_pop ( luaVM, 1 );
        }
        else
        {
            lua_pop ( luaVM, 1 );
            lua_rawgeti ( luaVM, -1, 2 );
            if ( lua_isnumber ( luaVM, -1 ) )
                vector.fY = ( float ) lua_tonumber ( luaVM, -1 );
            lua_pop ( luaVM, 1 );
        }

        lua_pushstring ( luaVM, "z" );
        lua_rawget ( luaVM, -2 );
        if ( lua_isnumber ( luaVM, -1 ) )
        {
            vector.fZ = ( float ) lua_tonumber ( luaVM, -1 );
            lua_pop ( luaVM, 1 );
        }
        else
        {
            lua_pop ( luaVM, 1 );
            lua_rawgeti ( luaVM, -1, 3 );
            if ( lua_isnumber ( luaVM, -1 ) )
                vector.fZ = ( float ) lua_tonumber ( luaVM, -1 );
            lua_pop ( luaVM, 1 );
        }

        lua_pushstring ( luaVM, "w" );
        lua_rawget ( luaVM, -2 );
        if ( lua_isnumber ( luaVM, -1 ) )
        {
            vector.fW = ( float ) lua_tonumber ( luaVM, -1 );
            lua_pop ( luaVM, 1 );
        }
        else
        {
            lua_pop ( luaVM, 1 );
            lua_rawgeti ( luaVM, -1, 4 );
            if ( lua_isnumber ( luaVM, -1 ) )
                vector.fW = ( float ) lua_tonumber ( luaVM, -1 );
            lua_pop ( luaVM, 1 );
        }
    }
    else if ( argStream.NextIsNumber () )
    {
        argStream.ReadNumber ( vector.fX );
        if ( argStream.NextIsNumber () )
        {
            argStream.ReadNumber ( vector.fY );
            if ( argStream.NextIsNumber () )
                argStream.ReadNumber ( vector.fZ );
            if ( argStream.NextIsNumber () )
                argStream.ReadNumber ( vector.fW );
        }
    }
    else if ( argStream.NextIsVector4D () )
    {
        argStream.ReadVector4D ( vector );
    }

    lua_pushvector ( luaVM, vector );
    return 1;
}
Exemplo n.º 22
0
void LuaSerializer::pickle(lua_State *l, int to_serialize, std::string &out, std::string key)
{
	static char buf[256];

	LUA_DEBUG_START(l);

	// tables are pickled recursively, so we can run out of Lua stack space if we're not careful
	// start by ensuring we have enough (this grows the stack if necessary)
	// (20 is somewhat arbitrary)
	if (!lua_checkstack(l, 20))
		luaL_error(l, "The Lua stack couldn't be extended (out of memory?)");

	to_serialize = lua_absindex(l, to_serialize);
	int idx = to_serialize;

	if (lua_getmetatable(l, idx)) {
		lua_getfield(l, -1, "class");
		if (lua_isnil(l, -1))
			lua_pop(l, 2);

		else {
			const char *cl = lua_tostring(l, -1);
			snprintf(buf, sizeof(buf), "o%s\n", cl);

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerClasses");

			lua_getfield(l, -1, cl);
			if (lua_isnil(l, -1))
				luaL_error(l, "No Serialize method found for class '%s'\n", cl);

			lua_getfield(l, -1, "Serialize");
			if (lua_isnil(l, -1))
				luaL_error(l, "No Serialize method found for class '%s'\n", cl);

			lua_pushvalue(l, idx);
			pi_lua_protected_call(l, 1, 1);

			idx = lua_gettop(l);

			if (lua_isnil(l, idx)) {
				lua_pop(l, 5);
				LUA_DEBUG_END(l, 0);
				return;
			}

			out += buf;
		}
	}

	switch (lua_type(l, idx)) {
		case LUA_TNIL:
			break;

		case LUA_TNUMBER: {
			snprintf(buf, sizeof(buf), "f%f\n", lua_tonumber(l, idx));
			out += buf;
			break;
		}

		case LUA_TBOOLEAN: {
			snprintf(buf, sizeof(buf), "b%d", lua_toboolean(l, idx) ? 1 : 0);
			out += buf;
			break;
		}

		case LUA_TSTRING: {
			lua_pushvalue(l, idx);
			size_t len;
			const char *str = lua_tolstring(l, -1, &len);
			snprintf(buf, sizeof(buf), "s" SIZET_FMT "\n", len);
			out += buf;
			out.append(str, len);
			lua_pop(l, 1);
			break;
		}

		case LUA_TTABLE: {
			lua_pushinteger(l, lua_Integer(lua_topointer(l, to_serialize)));         // ptr

			lua_getfield(l, LUA_REGISTRYINDEX, "PiSerializerTableRefs");    // ptr reftable
			lua_pushvalue(l, -2);                                           // ptr reftable ptr
			lua_rawget(l, -2);                                              // ptr reftable ???

			if (!lua_isnil(l, -1)) {
				out += "r";
				pickle(l, -3, out, key);
				lua_pop(l, 3);                                              // [empty]
			}

			else {
				out += "t";

				lua_pushvalue(l, -3);                                       // ptr reftable nil ptr
				lua_pushvalue(l, to_serialize);                                      // ptr reftable nil ptr table
				lua_rawset(l, -4);                                          // ptr reftable nil
				pickle(l, -3, out, key);
				lua_pop(l, 3);                                              // [empty]

				lua_pushvalue(l, idx);
				lua_pushnil(l);
				while (lua_next(l, -2)) {

					lua_pushvalue(l, -2);
					const char *k = lua_tostring(l, -1);
					std::string new_key = key + "." + (k? std::string(k) : "<" + std::string(lua_typename(l, lua_type(l, -1))) + ">");
					lua_pop(l, 1);

					// Copy the values to pickle, as they might be mutated by the pickling process.
					pickle(l, -2, out, new_key);
					pickle(l, -1, out, new_key);
					lua_pop(l, 1);
				}
				lua_pop(l, 1);
				out += "n";
			}

			break;
		}

		case LUA_TUSERDATA: {
			out += "u";

			LuaObjectBase *lo = static_cast<LuaObjectBase*>(lua_touserdata(l, idx));
			void *o = lo->GetObject();
			if (!o)
				Error("Lua serializer '%s' tried to serialize an invalid '%s' object", key.c_str(), lo->GetType());

			out += lo->Serialize();
			break;
		}

		default:
			Error("Lua serializer '%s' tried to serialize %s value", key.c_str(), lua_typename(l, lua_type(l, idx)));
			break;
	}

	if (idx != lua_absindex(l, to_serialize)) // It means we called a transformation function on the data, so we clean it up.
		lua_pop(l, 5);

	LUA_DEBUG_END(l, 0);
}
Exemplo n.º 23
0
static int luaB_rawget (lua_State *L) {
  luaL_checktype(L, 1, LUA_TTABLE);
  luaL_checkany(L, 2);
  lua_rawget(L, 1);
  return 1;
}
Exemplo n.º 24
0
int tLuaObject::index(lua_State* L)
{
  lua_rawget(L, -2);
  return 1;
}
int
ngx_http_lua_coroutine_create_helper(lua_State *L, ngx_http_request_t **pr,
    ngx_http_lua_ctx_t **pctx, ngx_http_lua_co_ctx_t **pcoctx)
{
    lua_State                     *mt;  /* the main thread */
    lua_State                     *co;  /* new coroutine to be created */
    ngx_http_request_t            *r;
    ngx_http_lua_main_conf_t      *lmcf;
    ngx_http_lua_ctx_t            *ctx;
    ngx_http_lua_co_ctx_t         *coctx; /* co ctx for the new coroutine */

    luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
                 "Lua function expected");

    lua_pushlightuserdata(L, &ngx_http_lua_request_key);
    lua_rawget(L, LUA_GLOBALSINDEX);
    r = lua_touserdata(L, -1);
    lua_pop(L, 1);

    if (r == NULL) {
        return luaL_error(L, "no request found");
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
    if (ctx == NULL) {
        return luaL_error(L, "no request ctx found");
    }

    ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
                               | NGX_HTTP_LUA_CONTEXT_ACCESS
                               | NGX_HTTP_LUA_CONTEXT_CONTENT);

    lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
    mt = lmcf->lua;

    /* create new coroutine on root Lua state, so it always yields
     * to main Lua thread
     */
    co = lua_newthread(mt);

    ngx_http_lua_probe_user_coroutine_create(r, L, co);

    coctx = ngx_http_lua_create_co_ctx(r, ctx);
    if (coctx == NULL) {
        return luaL_error(L, "out of memory");
    }

    coctx->co = co;
    coctx->co_status = NGX_HTTP_LUA_CO_SUSPENDED;

    /* make new coroutine share globals of the parent coroutine.
     * NOTE: globals don't have to be separated! */
    lua_pushvalue(L, LUA_GLOBALSINDEX);
    lua_xmove(L, co, 1);
    lua_replace(co, LUA_GLOBALSINDEX);

    lua_xmove(mt, L, 1);    /* move coroutine from main thread to L */

    lua_pushvalue(L, 1);    /* copy entry function to top of L*/
    lua_xmove(L, co, 1);    /* move entry function from L to co */

    if (pcoctx) {
        *pcoctx = coctx;
    }

    if (pctx) {
        *pctx = ctx;
    }

    if (pr) {
        *pr = r;
    }

    return 1;    /* return new coroutine to Lua */
}
Exemplo n.º 26
0
static void mar_encode_value(lua_State *L, mar_Buffer *buf, int val, size_t *idx)
{
    size_t l;
    int val_type = lua_type(L, val);
    lua_pushvalue(L, val);

    buf_write(L, (void*)&val_type, MAR_CHR, buf);
    switch (val_type) {
    case LUA_TBOOLEAN: {
        int int_val = lua_toboolean(L, -1);
        buf_write(L, (void*)&int_val, MAR_CHR, buf);
        break;
    }
    case LUA_TSTRING: {
        const char *str_val = lua_tolstring(L, -1, &l);
        buf_write(L, (void*)&l, MAR_I32, buf);
        buf_write(L, str_val, l, buf);
        break;
    }
    case LUA_TNUMBER: {
        lua_Number num_val = lua_tonumber(L, -1);
        buf_write(L, (void*)&num_val, MAR_I64, buf);
        break;
    }
    case LUA_TTABLE: {
        int tag, ref;
        lua_pushvalue(L, -1);
        lua_rawget(L, SEEN_IDX);
        if (!lua_isnil(L, -1)) {
            ref = lua_tointeger(L, -1);
            tag = MAR_TREF;
            buf_write(L, (void*)&tag, MAR_CHR, buf);
            buf_write(L, (void*)&ref, MAR_I32, buf);
            lua_pop(L, 1);
        }
        else {
            mar_Buffer rec_buf;
            lua_pop(L, 1); /* pop nil */
            if (luaL_getmetafield(L, -1, "__persist")) {
                tag = MAR_TUSR;

                lua_pushvalue(L, -2); /* self */
                lua_call(L, 1, 1);
                if (!lua_isfunction(L, -1)) {
                    luaL_error(L, "__persist must return a function");
                }

                lua_remove(L, -2); /* __persist */

                lua_newtable(L);
                lua_pushvalue(L, -2); /* callback */
                lua_rawseti(L, -2, 1);

                buf_init(L, &rec_buf);
                mar_encode_table(L, &rec_buf, idx);

                buf_write(L, (void*)&tag, MAR_CHR, buf);
                buf_write(L, (void*)&rec_buf.head, MAR_I32, buf);
                buf_write(L, rec_buf.data, rec_buf.head, buf);
                buf_done(L, &rec_buf);
                lua_pop(L, 1);
            }
            else {
                tag = MAR_TVAL;

                lua_pushvalue(L, -1);
                lua_pushinteger(L, (*idx)++);
                lua_rawset(L, SEEN_IDX);

                lua_pushvalue(L, -1);
                buf_init(L, &rec_buf);
                mar_encode_table(L, &rec_buf, idx);
                lua_pop(L, 1);

                buf_write(L, (void*)&tag, MAR_CHR, buf);
                buf_write(L, (void*)&rec_buf.head, MAR_I32, buf);
                buf_write(L, rec_buf.data,rec_buf.head, buf);
                buf_done(L, &rec_buf);
            }
        }
        break;
    }
    case LUA_TFUNCTION: {
        int tag, ref;
        lua_pushvalue(L, -1);
        lua_rawget(L, SEEN_IDX);
        if (!lua_isnil(L, -1)) {
            ref = lua_tointeger(L, -1);
            tag = MAR_TREF;
            buf_write(L, (void*)&tag, MAR_CHR, buf);
            buf_write(L, (void*)&ref, MAR_I32, buf);
            lua_pop(L, 1);
        }
        else {
            mar_Buffer rec_buf;
            int i;
            lua_Debug ar;
            lua_pop(L, 1); /* pop nil */

            lua_pushvalue(L, -1);
            lua_getinfo(L, ">nuS", &ar);
            if (ar.what[0] != 'L') {
                luaL_error(L, "attempt to persist a C function '%s'", ar.name);
            }
            tag = MAR_TVAL;
            lua_pushvalue(L, -1);
            lua_pushinteger(L, (*idx)++);
            lua_rawset(L, SEEN_IDX);

            lua_pushvalue(L, -1);
            buf_init(L, &rec_buf);
            lua_dump(L, (lua_Writer)buf_write, &rec_buf);

            buf_write(L, (void*)&tag, MAR_CHR, buf);
            buf_write(L, (void*)&rec_buf.head, MAR_I32, buf);
            buf_write(L, rec_buf.data, rec_buf.head, buf);
            buf_done(L, &rec_buf);
            lua_pop(L, 1);

            lua_newtable(L);
            for (i=1; i <= ar.nups; i++) {
                lua_getupvalue(L, -2, i);
                lua_rawseti(L, -2, i);
            }

            buf_init(L, &rec_buf);
            mar_encode_table(L, &rec_buf, idx);

            buf_write(L, (void*)&rec_buf.head, MAR_I32, buf);
            buf_write(L, rec_buf.data, rec_buf.head, buf);
            buf_done(L, &rec_buf);
            lua_pop(L, 1);
        }

        break;
    }
    case LUA_TUSERDATA: {
        int tag, ref;
        lua_pushvalue(L, -1);
        lua_rawget(L, SEEN_IDX);
        if (!lua_isnil(L, -1)) {
            ref = lua_tointeger(L, -1);
            tag = MAR_TREF;
            buf_write(L, (void*)&tag, MAR_CHR, buf);
            buf_write(L, (void*)&ref, MAR_I32, buf);
            lua_pop(L, 1);
        }
        else {
            mar_Buffer rec_buf;
            lua_pop(L, 1); /* pop nil */
            if (luaL_getmetafield(L, -1, "__persist")) {
                tag = MAR_TUSR;

                lua_pushvalue(L, -2);
                lua_pushinteger(L, (*idx)++);
                lua_rawset(L, SEEN_IDX);

                lua_pushvalue(L, -2);
                lua_call(L, 1, 1);
                if (!lua_isfunction(L, -1)) {
                    luaL_error(L, "__persist must return a function");
                }
                lua_newtable(L);
                lua_pushvalue(L, -2);
                lua_rawseti(L, -2, 1);
                lua_remove(L, -2);

                buf_init(L, &rec_buf);
                mar_encode_table(L, &rec_buf, idx);

                buf_write(L, (void*)&tag, MAR_CHR, buf);
                buf_write(L, (void*)&rec_buf.head, MAR_I32, buf);
		buf_write(L, rec_buf.data, rec_buf.head, buf);
		buf_done(L, &rec_buf);
            }
            else {
                luaL_error(L, "attempt to encode userdata (no __persist hook)");
            }
            lua_pop(L, 1);
        }
        break;
    }
    case LUA_TNIL: break;
    default:
        luaL_error(L, "invalid value type (%s)", lua_typename(L, val_type));
    }
    lua_pop(L, 1);
}
Exemplo n.º 27
0
TOLUA_API void tolua_open (lua_State* L)
{
    int top = lua_gettop(L);
    lua_pushstring(L,"tolua_opened");
    lua_rawget(L,LUA_REGISTRYINDEX);
    if (!lua_isboolean(L,-1))
    {
        lua_pushstring(L,"tolua_opened");
        lua_pushboolean(L,1);
        lua_rawset(L,LUA_REGISTRYINDEX);
        
        
        /** create value root table
         */
        lua_pushstring(L, TOLUA_VALUE_ROOT);
        lua_newtable(L);
        lua_rawset(L, LUA_REGISTRYINDEX);

#ifndef LUA_VERSION_NUM /* only prior to lua 5.1 */
        /* create peer object table */
        lua_pushstring(L, "tolua_peers");
        lua_newtable(L);
        /* make weak key metatable for peers indexed by userdata object */
        lua_newtable(L);
        lua_pushliteral(L, "__mode");
        lua_pushliteral(L, "k");
        lua_rawset(L, -3);                /* stack: string peers mt */
        lua_setmetatable(L, -2);   /* stack: string peers */
        lua_rawset(L,LUA_REGISTRYINDEX);
#endif

        /* create object ptr -> udata mapping table */
        lua_pushstring(L,"tolua_ubox");
        lua_newtable(L);
        /* make weak value metatable for ubox table to allow userdata to be
           garbage-collected */
        lua_newtable(L);
        lua_pushliteral(L, "__mode");
        lua_pushliteral(L, "v");
        lua_rawset(L, -3);               /* stack: string ubox mt */
        lua_setmetatable(L, -2);  /* stack: string ubox */
        lua_rawset(L,LUA_REGISTRYINDEX);
        
//        /* create object ptr -> class type mapping table */
//        lua_pushstring(L, "tolua_ptr2type");
//        lua_newtable(L);
//        lua_rawset(L, LUA_REGISTRYINDEX);

        lua_pushstring(L,"tolua_super");
        lua_newtable(L);
        lua_rawset(L,LUA_REGISTRYINDEX);
        lua_pushstring(L,"tolua_gc");
        lua_newtable(L);
        lua_rawset(L,LUA_REGISTRYINDEX);

        /* create gc_event closure */
        lua_pushstring(L, "tolua_gc_event");
        lua_pushstring(L, "tolua_gc");
        lua_rawget(L, LUA_REGISTRYINDEX);
        lua_pushstring(L, "tolua_super");
        lua_rawget(L, LUA_REGISTRYINDEX);
        lua_pushcclosure(L, class_gc_event, 2);
        lua_rawset(L, LUA_REGISTRYINDEX);

        tolua_newmetatable(L,"tolua_commonclass");

        tolua_module(L,NULL,0);
        tolua_beginmodule(L,NULL);
        tolua_module(L,"tolua",0);
        tolua_beginmodule(L,"tolua");
        tolua_function(L,"type",tolua_bnd_type);
        tolua_function(L,"takeownership",tolua_bnd_takeownership);
        tolua_function(L,"releaseownership",tolua_bnd_releaseownership);
        tolua_function(L,"cast",tolua_bnd_cast);
        tolua_function(L,"isnull",tolua_bnd_isnulluserdata);
        tolua_function(L,"inherit", tolua_bnd_inherit);
#ifdef LUA_VERSION_NUM /* lua 5.1 */
        tolua_function(L, "setpeer", tolua_bnd_setpeer);
        tolua_function(L, "getpeer", tolua_bnd_getpeer);
#endif

        tolua_endmodule(L);
        tolua_endmodule(L);
    }
    lua_settop(L,top);
}
Exemplo n.º 28
0
// decrease lua function reference counter, return counter
int LuaJavaBridge::releaseLuaFunctionById(int functionId)
{
    lua_State *L = s_luaState;
                                                                /* L: */
    lua_pushstring(L, LUAJ_REGISTRY_FUNCTION);                  /* L: key */
    lua_rawget(L, LUA_REGISTRYINDEX);                           /* L: f_id */
    if (!lua_istable(L, -1))
    {
        lua_pop(L, 1);
        LOGD("%s", "luajreleaseLuaFunctionById() - LUAJ_REGISTRY_FUNCTION not exists");
        return 0;
    }

    lua_pushstring(L, LUAJ_REGISTRY_RETAIN);                    /* L: f_id key */
    lua_rawget(L, LUA_REGISTRYINDEX);                           /* L: f_id id_r */
    if (!lua_istable(L, -1))
    {
        lua_pop(L, 2);
        LOGD("%s", "luajreleaseLuaFunctionById() - LUAJ_REGISTRY_RETAIN not exists");
        return 0;
    }

    lua_pushinteger(L, functionId);                             /* L: f_id id_r id */
    lua_rawget(L, -2);                                          /* L: f_id id_r r */
    if (lua_type(L, -1) != LUA_TNUMBER)
    {
        lua_pop(L, 3);
        LOGD("luajreleaseLuaFunctionById() - function id %d not found", functionId);
        return 0;
    }

    int retainCount = lua_tonumber(L, -1);
    retainCount--;

    if (retainCount > 0)
    {
        // update counter
        lua_pop(L, 1);                                          /* L: f_id id_r */
        lua_pushinteger(L, functionId);                         /* L: f_id id_r id */
        lua_pushinteger(L, retainCount);                        /* L: f_id id_r id r */
        lua_rawset(L, -3);                        /* id_r[id] = r, L: f_id id_r */
        lua_pop(L, 2);
        LOGD("luajreleaseLuaFunctionById() - function id %d retain count = %d", functionId, retainCount);
        return retainCount;
    }

    // remove lua function reference
    lua_pop(L, 1);                                              /* L: f_id id_r */
    lua_pushinteger(L, functionId);                             /* L: f_id id_r id */
    lua_pushnil(L);                                             /* L: f_id id_r id nil */
    lua_rawset(L, -3);                          /* id_r[id] = nil, L: f_id id_r */

    lua_pop(L, 1);                                              /* L: f_id */
    lua_pushnil(L);                                             /* L: f_id nil */
    while (lua_next(L, -2) != 0)                                /* L: f_id f id */
    {
        int value = lua_tonumber(L, -1);
        lua_pop(L, 1);                                          /* L: f_id f */
        if (value == functionId)
        {
            lua_pushnil(L);                                     /* L: f_id f nil */
            lua_rawset(L, -3);                   /* f_id[f] = nil, L: f_id */
            break;
        }
    }                                                           /* L: f_id */

    lua_pop(L, 1);
    LOGD("luajreleaseLuaFunctionById() - function id %d released", functionId);
    return 0;
}
Exemplo n.º 29
0
LUALIB_API void  luaL_getmetatable (lua_State *L, const char *tname) {
  lua_pushstring(L, tname);
  lua_rawget(L, LUA_REGISTRYINDEX);
}
Exemplo n.º 30
0
int AudioBinder::Sound_create(lua_State *L)
{
    StackChecker checker(L, "AudioBinder::Sound_create", 1);

    Binder binder(L);

    const char *fileName = luaL_checkstring(L, 1);

    std::vector<char> sig;
    int flags = gpath_getDriveFlags(gpath_getPathDrive(fileName));
    if (flags & GPATH_RO)
    {
        append(sig, fileName, strlen(fileName) + 1);
    }
    else
    {
        if (flags & GPATH_REAL)
        {
            append(sig, fileName, strlen(fileName) + 1);

            struct stat s;
            stat(gpath_transform(fileName), &s);
            append(sig, &s.st_mtime, sizeof(s.st_mtime));
        }
    }

    GGSound *sound = NULL;

    luaL_rawgetptr(L, LUA_REGISTRYINDEX, &keySound);

    if (sig.empty())
    {
        lua_pushnil(L);
    }
    else
    {
        lua_pushlstring(L, &sig[0], sig.size());
        lua_rawget(L, -2);
    }

    if (!lua_isnil(L, -1))
    {
        sound = static_cast<GGSound*>(lua_touserdata(L, -1));
        sound->ref();
    }
    else
    {
        gaudio_Error error;
        sound = new GGSound(L, fileName, &error, sig);

        switch (error)
        {
        case GAUDIO_NO_ERROR:
            break;
        case GAUDIO_CANNOT_OPEN_FILE:
            sound->unref();
            luaL_error(L, "%s: No such file or directory.", fileName);
            break;
        case GAUDIO_UNRECOGNIZED_FORMAT:
            sound->unref();
            luaL_error(L, "%s: Sound format is not recognized.", fileName);
            break;
        case GAUDIO_ERROR_WHILE_READING:
            sound->unref();
            luaL_error(L, "%s: Error while reading.", fileName);
            break;
        case GAUDIO_UNSUPPORTED_FORMAT:
            sound->unref();
            luaL_error(L, "%s: Sound format is not supported.", fileName);
            break;
        case GAUDIO_INTERNAL_ERROR:
            sound->unref();
            luaL_error(L, "%s: Sound internal error.", fileName);
            break;
        }
    }

    lua_pop(L, 2);

    binder.pushInstance("Sound", sound);

    return 1;
}