예제 #1
0
static int moonbase_image_draw_clip( lua_State *s )
{
	void *image;
	struct rectangle src, dst;

	image = *(void**)luaL_checkudata( s, 1, "moonbase_image" );
	luacom_read_array( s, 2, "ii", 1, &dst.x, 2, &dst.y );
	lua_len( s, 2 );
	if ( lua_tointeger(s, -1) == 4 ) {
		luacom_read_array( s, 2, "ii", 3, &dst.w, 4, &dst.h );
	} else {
		dst.w = 0;
		dst.h = 0;
	}
	luacom_read_array( s, 3, "ii", 1, &src.x, 2, &src.y );
	lua_len( s, 3 );
	if ( lua_tointeger(s, -1) == 4 ) {
		luacom_read_array( s, 3, "ii", 3, &src.w, 4, &src.h );
	} else {
		src.w = 0;
		src.h = 0;
	}
	image_draw_clip( &dst, image, &src );
	return 0;
}
예제 #2
0
파일: Solver.c 프로젝트: maxbannach/grazil
static int Solver_query(struct lua_State *state) {
  
  LGL* lgl = get_lgl(state);

  if (lua_gettop(state) != 2) {
    lua_pushliteral(state, "Query must be called with arguments self and a table");
    lua_error(state);
  }

  int type = lua_type(state, 2);

  if (type != LUA_TTABLE) {
    lua_pushliteral(state, "Query must be called with a table argument");
    lua_error(state);
  }

  lua_newtable (state); // Stack pos 3

  lua_len(state, 2);
  lua_Integer len = lua_tointeger(state, -1);
  lua_pop(state, 1);
  for (int j = 1; j <= len; j++) {
    lua_geti(state, 2, j);
    lua_Integer c = lua_tointeger (state, -1);
    if (!c) {
      lua_pushliteral(state, "Array may contain only non-zero integers");
      lua_error(state);    
    }
    lua_pop(state,1);
    lua_pushinteger(state, lglderef(lgl, c));
    lua_seti(state, 3, j);
  }     

  return 1;
}
예제 #3
0
int luaL_returnlen(lua_State* L, int index)
{
  lua_len(L, index);
  int len = lua_tointeger(L,-1);
  lua_pop(L, 1);
  return len;
}
예제 #4
0
파일: LuaState.cpp 프로젝트: skryabiin/core
	int LuaState::length() {
		lua_len(_L, -1);
		int len = pullStack<int>();
		addStackAdditions(1);
		popStackAdditions();		
		return len;
	}
예제 #5
0
static bool load_room_resets( lua_State *L, D_ROOM *room )
{
   int num, i;
   D_RESET *r;
   
   if( !L || !room )
      return FALSE;
   
   lua_pushstring( L, "resets" );
   lua_gettable( L, -2 );
   lua_len( L, -1 );
   num = luaL_checknumber( L, -1 );
   lua_pop( L, 1 );
   for( i = 1; i <= num; i++ ) //iterate through the resets
   {
      lua_rawgeti( L, -1, i );
      if( ( r = load_reset( L ) ) == NULL )
      {
         bug( "Error: Unable to allocate memory for new reset." );
         return FALSE;
      }
      AttachToList( r, room->resets ); //attach it to the room's reset list
      lua_pop( L, 1 );
   }
   return TRUE;
}
예제 #6
0
static bool load_area_rooms( lua_State *L, D_AREA *area )
{
   int numRooms, i;
   D_ROOM *room;
   
   if( !L || !area )
      return FALSE;
   
   lua_getglobal( L, "rooms" );
   if( !lua_istable( L, -1 ) )
   {
      bug( "Error: 'rooms' is not a valid table.\n" ); //if an area doesn't have rooms then fail the load
      return FALSE;
   }
   //numRooms = lua_len( L, -1 );
   lua_len( L, -1 );
   numRooms= luaL_checknumber( L, -1 );
   lua_pop( L, 1 );
   for( i = 1; i <= numRooms; i++ ) //iterate through the rooms
   {
      lua_rawgeti( L, -1, i );
      if( ( room = load_room( L ) ) == NULL )
      {
         bug( "Error: Unable to allocate memory for new room." );
         return FALSE;
      }
      AttachToList( room, area->rooms ); //attach it to the area's room list
      lua_pop( L, 1 );
   }
   return TRUE;
}
예제 #7
0
static bool load_area_mobiles( lua_State *L, D_AREA *area )
{
   int numMob = 0, i = 0;
   D_MOBILE *mob;
   
   if( !L || !area )
      return FALSE;
      
   lua_getglobal( L, "mobiles" );
   if( !lua_istable( L, -1 ) )
   {
      bug( "Error: 'mobiles' is not a valid table.\n" );
      return FALSE;
   }
   //numMob = lua_len( L, -1 );
   lua_len( L, -1 );
   numMob = luaL_checknumber( L, -1 );
   lua_pop( L, 1 );
   for( i = 1; i <= numMob; i++ )
   {
      lua_rawgeti( L, -1, i );
      if( ( mob = load_mobile( L ) ) == NULL )
      {
         bug( "Error: Unable to allocate memory for new mobile." );
         return FALSE;
      }
      AttachToList( mob, npc_list );
      AttachToList( mob, area->mobiles );
      lua_pop( L, 1 );
   }
   
   return TRUE;
}
예제 #8
0
static bool load_area_objects( lua_State *L, D_AREA *area )
{
   int numObj = 0, i = 0;
   D_OBJ *obj;
   
   if( !L || !area )
      return FALSE;
      
   lua_getglobal( L, "objects" );
   if( !lua_istable( L, -1 ) )
   {
      bug( "Error: 'objects' is not a valid table.\n" );
      return FALSE;
   }
   //numObj = lua_len( L, -1 );
   lua_len( L, -1 );
   numObj = luaL_checknumber( L, -1 );
   lua_pop( L, 1 );
   for( i = 1; i <= numObj; i++ )
   {
      lua_rawgeti( L, -1, i );
      if( ( obj = load_object( L ) ) == NULL )
      {
         bug( "Error: Unable to allocate memory for new object." );
         return FALSE;
      }
      AttachToList( obj, obj_list );
      AttachToList( obj, area->objects );
      lua_pop( L, 1 );
   }
   
   return TRUE;
}
예제 #9
0
파일: Solver.c 프로젝트: maxbannach/grazil
static int Solver_addDIMACSSeqence(struct lua_State *state) {

  LGL* lgl = get_lgl(state);

  int n = lua_gettop (state);
  int success;
  for (int i = 2; i <= n; i++) {
    int type = lua_type (state, i);
    if (type == LUA_TTABLE) {
      // Iterate over the entries of the table
      lua_len(state, i);
      lua_Integer len = lua_tointeger(state, -1);
      lua_pop(state, 1);
      for (int j = 1; j <= len; j++) {
	lua_geti(state, i, j);
	lua_Integer c = lua_tointegerx (state, -1, &success);
	if (!success) {
	  lua_pushliteral(state, "Illegal argument in DIMACS sequence");
	  lua_error(state);    
	}
	lgladd (lgl, c);
	lua_pop(state, 1);	
      }      
    } else {
      lua_Integer c = lua_tointegerx (state, i, &success);
      if (!success) {
	lua_pushliteral(state, "Illegal argument in DIMACS sequence");
	lua_error(state);    
      }
      lgladd (lgl, c);
    }
  }

  return 0;
}
예제 #10
0
void dt_lua_debug_table_internal(lua_State *L, int t, const char *function, int line)
{
  t = lua_absindex(L,t);
  /* table is in the stack at index 't' */
  lua_len(L,t);
  printf("lua table at index %d at %s:%d (length %f)\n", t, function, line,lua_tonumber(L,-1));
  lua_pop(L,1);
  if(lua_type(L, t) != LUA_TTABLE)
  {
    printf("\tnot a table: %s\n", lua_typename(L, lua_type(L, t)));
    return;
  }
  lua_pushnil(L); /* first key */
  while(lua_next(L, t ) != 0)
  {
    /* uses 'key' (at index -2) and 'value' (at index -1) */
    if(lua_type(L,-2) != LUA_TNUMBER) {
      printf("%s - %s\n", lua_tostring(L, -2), lua_typename(L, lua_type(L, -1)));
    } else {
      printf("%f - %s\n", luaL_checknumber(L, -2), lua_typename(L, lua_type(L, -1)));
    }

    /* removes 'value'; keeps 'key' for next iteration */
    lua_pop(L, 1);
  }
}
예제 #11
0
파일: zzzz.c 프로젝트: apkbox/luaasplite
static int luax_len(lua_State *L, int index)
{
    int len;
    lua_len(L, index);
    len = (int)lua_tonumber(L, -1);
    lua_pop(L, 1);
    return len;
}
예제 #12
0
LUALIB_API int luaL_len (lua_State *L, int idx) {
  int l;
  int isnum;
  lua_len(L, idx);
  l = (int)lua_tointegerx(L, -1, &isnum);
  if (!isnum)
	luaL_error(L, "object length is not a number");
  lua_pop(L, 1);  /* remove object */
  return l;
}
예제 #13
0
int luaL_len (lua_State *L, int i) {
  int res = 0, isnum = 0;
  luaL_checkstack(L, 1, "not enough stack slots");
  lua_len(L, i);
  res = (int)lua_tointegerx(L, -1, &isnum);
  lua_pop(L, 1);
  if (!isnum)
    luaL_error(L, "object length is not a number");
  return res;
}
예제 #14
0
파일: compat-5.3.c 프로젝트: hishamhm/dit
COMPAT53_API lua_Integer luaL_len (lua_State *L, int i) {
  lua_Integer res = 0;
  int isnum = 0;
  luaL_checkstack(L, 1, "not enough stack slots");
  lua_len(L, i);
  res = lua_tointegerx(L, -1, &isnum);
  lua_pop(L, 1);
  if (!isnum)
    luaL_error(L, "object length is not an integer");
  return res;
}
예제 #15
0
파일: lauxlib.cpp 프로젝트: aappleby/Lumina
int luaL_len (LuaThread *L, int idx) {
  THREAD_CHECK(L);
  int l;
  int isnum;
  lua_len(L, idx);
  l = (int)lua_tointegerx(L, -1, &isnum);
  if (!isnum)
    luaL_error(L, "object length is not a number");
  L->stack_.pop();  /* remove object */
  return l;
}
예제 #16
0
LUA_INLINE int luaL_len(lua_State* L, int i)
{
    luaL_checkstack(L, 1, "not enough stack slots");
    lua_len(L, i);
    int is_num = 0;
    int res = int(lua_tointegerx(L, -1, &is_num));
    lua_pop(L, 1);
    if (!is_num) {
        luaL_error(L, "object length is not a number");
    }
    return res;
}
예제 #17
0
static D_ROOM *load_room( lua_State *L )
{
   D_ROOM *r;
   D_EXIT *e;
   int i=0, numExits=0;
   
   if( !L )
      return NULL;
      
   
   if( ( r = new_room() ) == NULL )
   {
      return NULL;
   }
   
   lua_pushstring( L, "vnum" );
   lua_gettable( L, -2 );
   r->vnum = (int)luaL_checknumber( L, -1 );
   lua_pop( L, 1 );
   
   lua_pushstring( L, "name" );
   lua_gettable( L, -2 );
   r->name = strdup( luaL_checkstring( L, -1 ) );
   lua_pop( L, 1 );
   
   lua_pushstring( L, "desc" );
   lua_gettable( L, -2 );
   r->desc = strdup( luaL_checkstring( L, -1 ) );
   lua_pop( L, 1 );
   
   lua_pushstring( L, "exits" );
   lua_gettable( L, -2 );
   //numExits = lua_len( L, -1 );
   lua_len( L, -1 );
   numExits = luaL_checknumber( L, -1 );
   lua_pop( L, 1 );
   for( i = 1; i <= numExits; i++ ) //iterate through the exits
   {
      lua_rawgeti( L, -1, i );
      if( ( e = load_exit( L ) ) == NULL )
      {
         bug( "Error: Unable to allocate memory for new exit." );
         continue;
      }
      AttachToList( e, r->exits ); //attach it to the room's exit list
      lua_pop( L, 1 );
   }
   lua_pop( L, 1 );

   load_room_resets( L, r );
   lua_pop( L, 1 );
   return r;
}
예제 #18
0
static int impl_unit_attacks_next(lua_State *L)
{
	lua_len(L, 1);
	int n = luaL_checknumber(L, 2) + 1;
	int max_n = luaL_checknumber(L, -1);
	if(n > max_n) {
		return 0;
	}
	lua_pushnumber(L, n);
	lua_pushvalue(L, -1);
	lua_gettable(L, 1);
	return 2;
}
예제 #19
0
static int list_Unpack(lua_State* L) {
	luaC_checkmethod(L, 1);
	lua_len(L, 1);
	int n = lua_tointeger(L, -1);
	lua_pop(L, 1);
	int s = luaL_optinteger(L, 2, 1);
	if (s < 0) s = n + s + 1;
	if ((s < 1) || (s > n)) return luaL_argerror(L, 2, "'from' index out of range");
	int e = luaL_optinteger(L, 3, s);
	if (e < 0) e = n + e + 1;
	if ((e < s) || (e > n)) return luaL_argerror(L, 3, "'to' index out of range");
	n = e - s + 1;
	lua_settop(L, 1);
	lua_checkstack(L, n);
	for (int i = s; (i <= e); i++) lua_rawgeti(L, 1, i);
	return n;
}
예제 #20
0
static st_lua_command_t *
st_lua_create_op_commands(lua_State *lua_vm, char *modulename,
                          char *op, size_t *size)
{
    *size = 0;

    lua_pushstring(lua_vm, op);
    lua_gettable(lua_vm, -2);

    lua_len(lua_vm, -1);
    int num_op_handlers = lua_tonumber(lua_vm, -1);
    lua_pop(lua_vm, 1);

    st_lua_command_t *ophandlers = calloc(num_op_handlers, sizeof(st_lua_command_t));
    int index = 0;

    lua_pushnil(lua_vm);
    while(lua_next(lua_vm, -2)) {
        char *dbname = NULL;
        if (st_lua_get_string_from_table(lua_vm, "database", &dbname) != 0) {
            //SHC_ERROR("Database not defined for the %s statement at index %d in the %s module",
            //          op, index, modulename);
            free(ophandlers);
            return NULL;
        }

        st_lua_command_t *current = &ophandlers[index++];

        st_lua_fill_command(lua_vm, current, op, dbname);

        lua_pushstring(lua_vm, "pre");
        lua_gettable(lua_vm, -2);

        current->pre_function_ref = luaL_ref(lua_vm, LUA_REGISTRYINDEX);

        lua_pushstring(lua_vm, "post");
        lua_gettable(lua_vm, -2);
        current->post_function_ref = luaL_ref(lua_vm, LUA_REGISTRYINDEX);

        lua_pop(lua_vm, 1);
    }
    lua_pop(lua_vm,1);

    *size = num_op_handlers;
    return ophandlers;
}
예제 #21
0
static int moonbase_image_draw( lua_State *s )
{
	void *image;
	struct rectangle r;

	image = *(void**)luaL_checkudata( s, 1, "moonbase_image" );
	luacom_read_array( s, 2, "ii", 1, &r.x, 2, &r.y );
	lua_len( s, 2 );
	if ( lua_tointeger(s, -1) == 4 ) {
		luacom_read_array( s, 2, "ii", 3, &r.w, 4, &r.h );
	} else {
		r.w = 0;
		r.h = 0;
	}
	image_draw( &r, image );
	return 0;
}
예제 #22
0
/**
 * Loads a WML file into a config
 * - Arg 1: WML file path
 * - Arg 2: (optional) Array of preprocessor defines, or false to skip preprocessing (true is also valid)
 * - Arg 3: (optional) Path to a schema file for validation (omit for no validation)
 * - Ret: config
 */
static int intf_load_wml(lua_State* L)
{
	std::string file = luaL_checkstring(L, 1);
	bool preprocess = true;
	preproc_map defines_map;
	if(lua_type(L, 2) == LUA_TBOOLEAN) {
		preprocess = luaW_toboolean(L, 2);
	} else if(lua_type(L, 2) == LUA_TTABLE || lua_type(L, 2) == LUA_TUSERDATA) {
		lua_len(L, 2);
		int n = lua_tonumber(L, -1);
		lua_pop(L, 1);
		for(int i = 0; i < n; i++) {
			lua_geti(L, 2, i);
			if(!lua_isstring(L, -1)) {
				return luaL_argerror(L, 2, "expected bool or array of strings");
			}
			std::string define = lua_tostring(L, -1);
			lua_pop(L, 1);
			if(!define.empty()) {
				defines_map.emplace(define, preproc_define(define));
			}
		}
	} else if(!lua_isnoneornil(L, 2)) {
		return luaL_argerror(L, 2, "expected bool or array of strings");
	}
	std::string schema_path = luaL_optstring(L, 3, "");
	std::shared_ptr<schema_validation::schema_validator> validator;
	if(!schema_path.empty()) {
		validator.reset(new schema_validation::schema_validator(filesystem::get_wml_location(schema_path)));
		validator->set_create_exceptions(false); // Don't crash if there's an error, just go ahead anyway
	}
	std::string wml_file = filesystem::get_wml_location(file);
	filesystem::scoped_istream stream;
	config result;
	if(preprocess) {
		stream = preprocess_file(wml_file, &defines_map);
	} else {
		stream.reset(new std::ifstream(wml_file));
	}
	read(result, *stream, validator.get());
	luaW_pushconfig(L, result);
	return 1;
}
void HLSLParserListener::Assign()
{
    int
        index;

    lua_checkstack( State, 3 );

    assert( lua_istable( State, -2) );

    #if LUA_VERSION_NUM >= 502
        lua_len( State, -2 );
        index = lua_tointeger( State, -1 );
        lua_pop( State, 1 );
    #else
        index = lua_objlen( State, -2 );
    #endif

    lua_rawseti( State, -2, index + 1 );
}
void HLSLParserListener::AddValue( const std::string & value )
{
    int
        index;

    lua_checkstack( State, 3 );

    assert( lua_istable( State, -1 ) );

    #if LUA_VERSION_NUM >= 502
        lua_len( State, -1 );
        index = lua_tointeger( State, -1 );
        lua_pop( State, 1 );
    #else
        index = lua_objlen( State, -1 );
    #endif

    lua_pushstring( State, value.c_str() );
    lua_rawseti( State, -2, index + 1 );
}
예제 #25
0
static int lua_to_bundle_cfg(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct bundle_cfg *bundle)
{
	int pop, pop2, idx;

	if ((pop = lua_getfrom(L, from, name)) < 0)
		return -1;

	if (!lua_istable(L, -1))
		return -1;

	if (lua_to_host_set(L, TABLE, "clients", &bundle->clients))
		return -1;

	/* Read streams array */
	if ((pop2 = lua_getfrom(L, TABLE, "streams")) < 0)
		return -1;

	if (!lua_istable(L, -1))
		return -1;

	lua_len(prox_lua(), -1);
	bundle->n_stream_cfgs = lua_tointeger(prox_lua(), -1);
	lua_pop(prox_lua(), 1);

	if (bundle->n_stream_cfgs >= sizeof(bundle->stream_cfgs)/sizeof(bundle->stream_cfgs[0]))
		return -1;
	plogx_dbg("loading bundle cfg with %d streams\n", bundle->n_stream_cfgs);
	idx = 0;
	lua_pushnil(L);
	while (lua_next(L, -2)) {
		if (lua_to_stream_cfg(L, STACK, NULL, socket, &bundle->stream_cfgs[idx]))
			return -1;

		++idx;
		lua_pop(L, 1);
	}
	lua_pop(L, pop2);

	lua_pop(L, pop);
	return 0;
}
예제 #26
0
static int lua_to_bundle_cfg(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct bundle_cfg *bundle, struct hash_set *hs)
{
	int pop, pop2, idx;
	int clients_loaded = 0;

	if ((pop = lua_getfrom(L, from, name)) < 0)
		return -1;

	if (!lua_istable(L, -1))
		return -1;

	lua_len(prox_lua(), -1);
	bundle->n_stream_cfgs = lua_tointeger(prox_lua(), -1);
	lua_pop(prox_lua(), 1);

	bundle->stream_cfgs = prox_zmalloc(sizeof(*bundle->stream_cfgs) * bundle->n_stream_cfgs, socket);

	plogx_dbg("loading bundle cfg with %d streams\n", bundle->n_stream_cfgs);
	idx = 0;
	lua_pushnil(L);
	while (lua_next(L, -2)) {
		if (!clients_loaded) {
			if (lua_to_host_set(L, TABLE, "clients", &bundle->clients)) {
				return -1;
			}
			clients_loaded = 1;
		}
		if (lua_to_stream_cfg(L, STACK, NULL, socket, &bundle->stream_cfgs[idx], hs)) {
			return -1;
		}

		++idx;
		lua_pop(L, 1);
	}

	lua_pop(L, pop);
	return 0;
}
예제 #27
0
static void redraw(struct glwin *win)
{
	struct glwin_thread_state thread_state;
	glwin_get_thread_state(&thread_state);
	glwin_make_current(win, g_ctx);

	lua_State *L = g_L;

	static bool gl_init_attempted = false;
	static bool gl_init_result = false;

	if (!gl_init_attempted) {
		gl_init_result = glb_glcore_init(3, 3);
	}
	if (!gl_init_result) {
		printf("Failed to initialize OpenGL bindings\n");
		exit(-1);
		return;
	}

	glViewport(0, 0, win->width, win->height);
	glClearColor(0, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);

	lua_getglobal(L, "b2l_data"); //1
	if (!lua_istable(L, -1)) {
		lua_pop(L, 1);
		goto end;
	}
	lua_getfield(L, -1, "objects"); //2
	lua_getglobal(L, "current_object"); //3
	if (!lua_isstring(L, -1)) {
		lua_pop(L, 3);
		goto end;
	}
	const char *current_object = lua_tostring(L, -1);
	lua_getfield(L, -2, current_object); //4
	if (lua_isnil(L, -1)) {
		lua_pop(L, 4);
		goto end;
	}

	lua_getfield(L, -1, "type"); //5
	if(strcmp(lua_tostring(L, -1), "MESH")) {
		lua_pop(L, 5);
		goto end;
	}
	lua_getfield(L, -2, "data"); //6
	lua_getfield(L, -6, "meshes"); //7
	lua_getfield(L, -1, lua_tostring(L, -2)); //8

	if (lua_isnil(L, -1)) {
		lua_pop(L, 8);
		goto end;
	}

	if (!g_gl_state.initialized)
		init_gl_state();

	if (g_gl_state.recompile_shaders)
		g_gl_state.program_valid = recompile_shaders();

	if (!g_gl_state.initialized || !g_gl_state.program_valid) {
		lua_pop(L, 8);
		goto end;
	}

	g_gl_state.recompile_shaders = false;

	glUseProgram(g_gl_state.program);
	glBindVertexArray(g_gl_state.vao);

	if (g_gl_state.blob_updated)  {
		glBufferData(GL_ARRAY_BUFFER, g_gl_state.blob_size, g_gl_state.blob ,GL_STATIC_DRAW);
		g_gl_state.blob_updated = false;
	}

	lua_getfield(L, -1, "vertex_normal_array_offset"); //9
	int vertex_normal_array_offset = lua_tointeger(L, -1);
	lua_getfield(L, -2, "uv_array_offset"); //10
	int uv_array_offset = lua_tointeger(L, -1);

	lua_getfield(L, -3, "uv_layers"); //11
	lua_len(L, -1); //12
	int num_uv_layers = lua_tointeger(L, -1);

	int tangent_array_offset;
	if (num_uv_layers > 0) {
		lua_getfield(L, -5, "tangent_array_offset");
		tangent_array_offset = lua_tointeger(L, -1);
		lua_pop(L, 1);
	}

	lua_getfield(L, -5, "vertex_co_array_offset"); //13
	int vertex_co_array_offset = lua_tointeger(L, -1);

	lua_getfield(L, -6, "weights_per_vertex"); //14
	int weights_per_vertex = lua_tointeger(L, -1);

	int weights_array_offset;
	if (weights_per_vertex > 0) {
		lua_getfield(L, -7, "weights_array_offset");
		weights_array_offset = lua_tointeger(L, -1);
		lua_pop(L, 1);
	} else {
		weights_array_offset = -1;
	}

	lua_getfield(L, -11, "vertex_groups"); //15
	int num_vertex_groups;
	if (lua_isnil(L, -1)) {
		num_vertex_groups = 0;
	} else {
		lua_len(L, -1);
		num_vertex_groups = lua_tointeger(L, -1);
		lua_pop(L, 1);
	}

	glBindVertexBuffer(NORMAL, g_gl_state.vbo, vertex_normal_array_offset, sizeof(float) * 3);
	if (num_uv_layers > 0) {
		glBindVertexBuffer(UV, g_gl_state.vbo, uv_array_offset, sizeof(float) * 2 * num_uv_layers);
		glBindVertexBuffer(TANGENT, g_gl_state.vbo, tangent_array_offset, sizeof(float) * 4);
	}
	glBindVertexBuffer(POS, g_gl_state.vbo, vertex_co_array_offset, sizeof(float) * 3);
	if (weights_per_vertex > 0)
		glBindVertexBuffer(WEIGHTS, g_gl_state.vbo, weights_array_offset, weights_per_vertex * 4);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_gl_state.vbo);
	if (g_gl_state.normal_index >= 0) {
		glEnableVertexAttribArray(g_gl_state.normal_index);
		glVertexAttribFormat(g_gl_state.normal_index, 3, GL_FLOAT, GL_FALSE, 0);
		glVertexAttribBinding(g_gl_state.normal_index, NORMAL);
	}

	if (g_gl_state.uv_index >= 0) {
		glEnableVertexAttribArray(g_gl_state.uv_index);
		glVertexAttribFormat(g_gl_state.uv_index, 2, GL_FLOAT, GL_FALSE, 0);
		glVertexAttribBinding(g_gl_state.uv_index, UV);
	}

	if (g_gl_state.pos_index >= 0) {
		glEnableVertexAttribArray(g_gl_state.pos_index);
		glVertexAttribFormat(g_gl_state.pos_index, 3, GL_FLOAT, GL_FALSE, 0);
		glVertexAttribBinding(g_gl_state.pos_index, POS);
	}
	int i = 0;
	for (i = 0; i < 6; i++) {
		if (g_gl_state.weights_index[i] >= 0 && weights_per_vertex > 0) {
			glEnableVertexAttribArray(g_gl_state.weights_index[i]);
			glVertexAttribIFormat(g_gl_state.weights_index[i], 2, GL_SHORT, 4 * i);
			glVertexAttribBinding(g_gl_state.weights_index[i], WEIGHTS);
		}
	}
	if (num_uv_layers > 0 && g_gl_state.tangent_index >= 0) {
		glEnableVertexAttribArray(g_gl_state.tangent_index);
		glVertexAttribFormat(g_gl_state.tangent_index, 4, GL_FLOAT, GL_FALSE, 0);
		glVertexAttribBinding(g_gl_state.tangent_index, TANGENT);
	}

	struct mat4 view;
	struct mat4 model;
	struct quaternion next;
	quaternion_mul(&q_delta, &q_cur, &next);
	quaternion_to_mat4(&next, &view);
	view.v[3][3] = 1;
	mat4_identity(&model);
	model.v[3][0] = g_offset[0] + g_offset_next[0];
	model.v[3][1] = g_offset[1] + g_offset_next[1];
	model.v[3][2] = g_offset[2] + g_offset_next[2];
	glUniformMatrix4fv(glGetUniformLocation(g_gl_state.program, "model"), 1, GL_FALSE, (GLfloat *)&model);
	struct mat4 ident;
	mat4_identity(&ident);
	glUniformMatrix4fv(glGetUniformLocation(g_gl_state.program, "view"), 1, GL_FALSE, (GLfloat *)&view);

	float zoom = exp(g_log_zoom);
	float zr = 100;
	struct mat4 proj;
	mat4_zero(&proj);
	proj.v[0][0] = 1.0/zoom;
	proj.v[1][1] = 1.0*win->width/(zoom*win->height);
	proj.v[2][2] = 1.0/zr;
	proj.v[3][3] = 1.0;
	glUniformMatrix4fv(glGetUniformLocation(g_gl_state.program, "proj"), 1, GL_FALSE, (GLfloat *)&proj);

	if (weights_per_vertex > 0) {
		static int render_count = 0;
		render_count++;
		double frame;
		int frame_start;
		int frame_end;
		lua_getglobal(L, "frame_start"); //16
		frame_start = lua_tointeger(L, -1);
		lua_getglobal(L, "frame_end"); //17
		frame_end = lua_tointeger(L, -1);
		lua_getglobal(L, "frame_delta"); //18
		frame = frame_start + lua_tonumber(L, -1);
		int frame_i = floorf(frame);
		double frame_fract = frame - frame_i;

		lua_getfield(L, -18, "scenes"); //19
		lua_getglobal(L, "current_scene"); //20
		lua_getfield(L, -2, lua_tostring(L, -1)); //21
		if (!lua_istable(L, -1)) {
			lua_pop(L, 20);
			goto end;
		}
		lua_getfield(L, -1, "objects");
		lua_getfield(L, -1, current_object);
		lua_getfield(L, -1, "vertex_group_transform_array_offset");
		int offset = lua_tointeger(L, -1);
		lua_pop(L, 9);
		int stride = sizeof(float) * 4 * 4 * num_vertex_groups;
		int i;
		for (i = 0; i < num_vertex_groups; i++) {
			struct mat4 res;
			struct mat4 M1;
			struct mat4 M2;
			struct mat4 *base = (struct mat4 *)(g_gl_state.blob + offset + (i * sizeof(float) * 4 * 4) + frame_i * stride);
			struct mat4 *next = (struct mat4 *)(g_gl_state.blob + offset + (i * sizeof(float) * 4 * 4) + (frame_i + 1) * stride);

			if (frame_i == (frame_end-1)) {
				next = (struct mat4 *)(g_gl_state.blob + offset + i * sizeof(float) * 4 * 4 + (frame_start) * stride);
			} else if (frame_fract == 0) {
				next = base;
			}


#if USE_SLERP
			struct mat4 temp;
			mat4_zero(&temp);
			temp.v[3][3] = 1;
			M1 = *base;
			M2 = *next;
			spherical_lerp(M1.v[0], M2.v[0], frame_fract, temp.v[0]);
			spherical_lerp(M1.v[1], M2.v[1], frame_fract, temp.v[1]);
			spherical_lerp(M1.v[2], M2.v[2], frame_fract, temp.v[2]);
			mat4_transpose(&temp, &res);
			float v1[3];
			float v2[3];
			v1[0] = M1.v[0][3];
			v1[1] = M1.v[1][3];
			v1[2] = M1.v[2][3];
			v2[0] = M2.v[0][3];
			v2[1] = M2.v[1][3];
			v2[2] = M2.v[2][3];
			lerp(v1, v2, frame_fract, res.v[3]);
#else
			mat4_zero(&res);
			res.v[3][3] = 1;
			mat4_transpose(base, &M1);
			mat4_transpose(next, &M2);
			lerp(M1.v[0], M2.v[0], frame_fract, res.v[0]);
			lerp(M1.v[1], M2.v[1], frame_fract, res.v[1]);
			lerp(M1.v[2], M2.v[2], frame_fract, res.v[2]);
			lerp(M1.v[3], M2.v[3], frame_fract, res.v[3]);
#endif

			glUniformMatrix4fv(g_gl_state.groups_index + i,
					1, /*num_vertex_groups, */
					GL_FALSE,
					(GLfloat *)&res);
		}
	}

	lua_getglobal(L, "controls"); //16
	int controls = lua_gettop(L);
	lua_getglobal(L, "materials"); //17
	int materials = lua_gettop(L);

	lua_getfield(L, -10, "index_array_offset"); //18
	int index_array_offset = lua_tointeger(L, -1);

	lua_getfield(L, -11, "submeshes"); //19
	lua_len(L, -1); //20
	int num_submeshes = lua_tointeger(L, -1);

	for (i = 0; i < num_submeshes; i++) {
		lua_rawgeti(L, -2, i + 1);
		lua_getfield(L, -1, "material_name");

		const char *material_name = lua_tostring(L, -1);

		lua_getfield(L, -2, "triangle_no");
		int triangle_no = lua_tointeger(L, -1);
		lua_getfield(L, -3, "triangle_count");
		int triangle_count = lua_tointeger(L, -1);
		lua_getfield(L, materials, material_name);
		lua_getfield(L, -1, "params");
		lua_pushnil(L);  /* first key */
		while (lua_next(L, -2)) {
			int variable = lua_gettop(L);
			const char *variable_name = lua_tostring(L, variable - 1);
			int uniform_loc = glGetUniformLocation(g_gl_state.program, variable_name);
			if (uniform_loc == -1) {
				lua_pop(L, 1);
				continue;
			}
			lua_getfield(L, variable, "value");
			int value = variable + 1;
			lua_getfield(L, variable, "datatype");
			const char *datatype = strdup(lua_tostring(L, -1));
			lua_pop(L, 1);
			if (!strcmp(datatype, "bool")) {
				int bool_value = lua_toboolean(L, value);
				glUniform1i(uniform_loc, bool_value);
			} else if (!strcmp(datatype, "vec3")) {
				lua_rawgeti(L, value, 1);
				lua_rawgeti(L, value, 2);
				lua_rawgeti(L, value, 3);
				float val[3];
				val[0] = (float)lua_tonumber(L, -3);
				val[1] = (float)lua_tonumber(L, -2);
				val[2] = (float)lua_tonumber(L, -1);
				glUniform3fv(uniform_loc, 1, val);
				lua_pop(L, 3);
			} else if (!strcmp(datatype, "float")) {
				float fval = lua_tonumber(L, value);
				glUniform1f(uniform_loc, fval);
			} else if (!strcmp(datatype, "sampler2D")) {
				lua_getfield(L, controls, variable_name);
				int control = lua_gettop(L);
				lua_getfield(L, control, "needs_upload");
				int needs_upload = lua_toboolean(L, -1);
				lua_pop(L, 1);
				if (needs_upload) {
					int texunit;
					GdkPixbuf *pbuf;
					lua_getfield(L, control, "texunit");
					texunit = lua_tointeger(L, -1) - 1;
					lua_pop(L, 1);

					lua_getfield(L, control, "pbuf");
					lua_getfield(L, -1, "_native");
					pbuf = (GdkPixbuf *)lua_touserdata(L, -1);
					lua_pop(L, 2);
					glActiveTexture(GL_TEXTURE0 + texunit);
					glBindTexture(GL_TEXTURE_2D, g_texture_names[texunit]);
					int width = gdk_pixbuf_get_width(pbuf);
					int height = gdk_pixbuf_get_height(pbuf);
					int n_chan = gdk_pixbuf_get_n_channels(pbuf);
					glPixelStorei(GL_UNPACK_ROW_LENGTH, gdk_pixbuf_get_rowstride(pbuf)/ n_chan);
					glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
					glTexImage2D(GL_TEXTURE_2D,
						0, /* level */
						n_chan > 3 ? GL_RGBA : GL_RGB,
						width,
						height,
						0, /* border */
						n_chan > 3 ? GL_RGBA : GL_RGB,
						GL_UNSIGNED_BYTE,
						gdk_pixbuf_get_pixels(pbuf));
					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
					glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
					glGenerateMipmap(GL_TEXTURE_2D);
					glUniform1i(uniform_loc, texunit);

					lua_pushboolean(L, 0);
					lua_setfield(L, control, "needs_upload");
				}
				lua_pop(L, 1);
			}
			free((void *)datatype);
			lua_pop(L, 2);
		} //while (lua_next(L, -2) != 0)
		glDrawElements(GL_TRIANGLES,
				3 * triangle_count,
				GL_UNSIGNED_SHORT,
				(void *)((int64_t)index_array_offset) + 3 * 2 * triangle_no);
		lua_pop(L, 6);
	}
	lua_pop(L, 20);
end:
	{
		GLenum err = glGetError();
		if (err)
			printf("render_scene GL error = %d\n", err);
	}
	glwin_swap_buffers(g_win);
	glwin_set_thread_state(&thread_state);
	g_need_redraw = false;
	return;
}
예제 #28
0
GLuint init_shader_str(const char *ray_v_src, const char *ray_f_src, const char *ray_g_src, lua_State *L)
{
	int i;

	const char *ray_v_src_alias = ray_v_src;
	const char *ray_g_src_alias = ray_g_src;
	const char *ray_f_src_alias = ray_f_src;

	GLuint ray_v = glCreateShader(GL_VERTEX_SHADER);
	GLuint ray_g = (ray_g_src == NULL ? 0 : glCreateShader(GL_GEOMETRY_SHADER));
	GLuint ray_f = glCreateShader(GL_FRAGMENT_SHADER);

	glShaderSource(ray_v, 1, &ray_v_src_alias, NULL);
	if(ray_g_src != NULL) glShaderSource(ray_g, 1, &ray_g_src_alias, NULL);
	glShaderSource(ray_f, 1, &ray_f_src_alias, NULL);

	glCompileShader(ray_v);
	printf("===   VERTEX SHADER ===\n");
	print_shader_log(ray_v);

	if(ray_g_src != NULL)
	{
		glCompileShader(ray_g);
		printf("=== GEOMETRY SHADER ===\n");
		print_shader_log(ray_g);
	}

	glCompileShader(ray_f);
	printf("=== FRAGMENT SHADER ===\n");
	print_shader_log(ray_f);

	GLuint out_shader = glCreateProgram();
	printf("Attaching shaders\n");
	glAttachShader(out_shader, ray_v);
	if(ray_g_src != NULL) glAttachShader(out_shader, ray_g);
	glAttachShader(out_shader, ray_f);

	// TODO: outsource this to a function
	glGetError();
	printf("Binding inputs\n");
	lua_len(L, 2); int len_input = lua_tointeger(L, -1); lua_pop(L, 1);
	for(i = 0; i < len_input; i++)
	{
		lua_geti(L, 2, i+1);
		glBindAttribLocation(out_shader, i, lua_tostring(L, -1));
		lua_pop(L, 1);
	}

	if(!context_is_compat)
	{
		printf("Binding outputs\n");
		lua_len(L, 3); int len_output = lua_tointeger(L, -1); lua_pop(L, 1);
		for(i = 0; i < len_output; i++)
		{
			lua_geti(L, 3, i+1);
			glBindFragDataLocation(out_shader, i, lua_tostring(L, -1));
			lua_pop(L, 1);
		}
	}

	printf("%i\n", glGetError());

	printf("Linking! This is the part where your computer dies\n");
	glLinkProgram(out_shader);

	printf("Getting results\n");
	printf("=== OVERALL PROGRAM ===\n");
	print_program_log(out_shader);

	GLint link_status;
	glGetProgramiv(out_shader, GL_LINK_STATUS, &link_status);
	printf("Link status: %i\n", link_status);

	if(link_status == GL_TRUE)
	{
		return out_shader;

	} else {
		glDeleteProgram(out_shader);
		glDeleteShader(ray_v);
		if(ray_g_src != NULL) glDeleteShader(ray_g);
		glDeleteShader(ray_f);

		return 0;
	}
}
예제 #29
0
static void init_task_gen(struct task_base *tbase, struct task_args *targ)
{
	struct task_gen_server *task = (struct task_gen_server *)tbase;
	const int socket_id = rte_lcore_to_socket_id(targ->lconf->id);

	static char name[] = "server_mempool";
	name[0]++;
	task->mempool = rte_mempool_create(name,
					   4*1024 - 1, MBUF_SIZE,
					   targ->nb_cache_mbuf,
					   sizeof(struct rte_pktmbuf_pool_private),
					   rte_pktmbuf_pool_init, NULL,
					   rte_pktmbuf_init, 0,
					   socket_id, 0);
	PROX_PANIC(task->mempool == NULL, "Failed to allocate memory pool with %u elements\n", 4*1024 - 1);
	int pop = lua_getfrom(prox_lua(), GLOBAL, targ->streams);
	PROX_PANIC(pop < 0, "Failed to find '%s' in lua\n", targ->streams);

	lua_len(prox_lua(), -1);
	uint32_t n_listen = lua_tointeger(prox_lua(), -1);
	lua_pop(prox_lua(), 1);
	PROX_PANIC(n_listen == 0, "No services specified to listen on\n");

	task->bundle_cfgs = prox_zmalloc(n_listen * sizeof(task->bundle_cfgs[0]), socket_id);

	plogx_info("n_listen = %d\n", n_listen);

	struct hash_set *hs = prox_sh_find_socket(socket_id, "genl4_streams");
	if (hs == NULL) {
		/* Expected number of streams per bundle = 1, hash_set
		   will grow if full. */
		hs = hash_set_create(n_listen, socket_id);
		prox_sh_add_socket(socket_id, "genl4_streams", hs);
	}

	const struct rte_hash_parameters listen_table = {
		.name = name,
		.entries = n_listen * 4,
		.key_len = sizeof(struct new_tuple),
		.hash_func = rte_hash_crc,
		.hash_func_init_val = 0,
		.socket_id = socket_id,
	};
	name[0]++;

	task->listen_hash = rte_hash_create(&listen_table);
	task->listen_entries = prox_zmalloc(listen_table.entries * sizeof(task->listen_entries[0]), socket_id);

	int idx = 0;
	lua_pushnil(prox_lua());
	while (lua_next(prox_lua(), -2)) {
		task->bundle_cfgs[idx].n_stream_cfgs = 1;
		task->bundle_cfgs[idx].stream_cfgs = prox_zmalloc(sizeof(*task->bundle_cfgs[idx].stream_cfgs), socket_id);
		int ret = lua_to_stream_cfg(prox_lua(), STACK, NULL, socket_id, &task->bundle_cfgs[idx].stream_cfgs[0], hs);
		PROX_PANIC(ret, "Failed to load stream cfg\n");
		struct stream_cfg *stream = task->bundle_cfgs[idx].stream_cfgs[0];

		// TODO: check mask and add to hash for each host
		struct new_tuple nt = {
			.dst_addr = stream->servers.ip,
			.proto_id = stream->proto,
			.dst_port = stream->servers.port,
			.l2_types[0] = 0x0008,
		};

		ret = rte_hash_add_key(task->listen_hash, &nt);
		PROX_PANIC(ret < 0, "Failed to add\n");

		task->listen_entries[ret] = &task->bundle_cfgs[idx];

		plogx_dbg("Server = "IPv4_BYTES_FMT":%d\n", IPv4_BYTES(((uint8_t*)&nt.dst_addr)), rte_bswap16(nt.dst_port));
		++idx;
		lua_pop(prox_lua(), 1);
	}

	static char name2[] = "task_gen_hash2";

	name2[0]++;
	plogx_dbg("Creating bundle ctx pool\n");
	if (bundle_ctx_pool_create(name2, targ->n_concur_conn * 2, &task->bundle_ctx_pool, NULL, 0, NULL, socket_id)) {
		cmd_mem_stats();
		PROX_PANIC(1, "Failed to create conn_ctx_pool\n");
	}

	task->heap = heap_create(targ->n_concur_conn * 2, socket_id);
	task->seed = rte_rdtsc();

	/* TODO: calculate the CDF of the reply distribution and the
	   number of replies as the number to cover for 99% of the
	   replies. For now, assume that this is number is 2. */
	uint32_t queue_size = rte_align32pow2(targ->n_concur_conn * 2);

	PROX_PANIC(queue_size == 0, "Overflow resulted in queue size 0\n");
	task->fqueue = fqueue_create(queue_size, socket_id);
	PROX_PANIC(task->fqueue == NULL, "Failed to allocate local queue\n");

	uint32_t n_descriptors;

	if (targ->nb_txports) {
		PROX_PANIC(targ->nb_txports != 1, "Need exactly one TX port for L4 generation\n");
		n_descriptors = prox_port_cfg[targ->tx_port_queue[0].port].n_txd;
	} else {
		PROX_PANIC(targ->nb_txrings != 1, "Need exactly one TX ring for L4 generation\n");
		n_descriptors = 256;
	}

	struct token_time_cfg tt_cfg = {
		.bpp = targ->rate_bps,
		.period = rte_get_tsc_hz(),
		.bytes_max = n_descriptors * (ETHER_MIN_LEN + 20),
	};

	token_time_init(&task->token_time, &tt_cfg);
}

static void init_task_gen_client(struct task_base *tbase, struct task_args *targ)
{
	struct task_gen_client *task = (struct task_gen_client *)tbase;
	static char name[] = "gen_pool";
	const uint32_t socket = rte_lcore_to_socket_id(targ->lconf->id);
	name[0]++;
	task->mempool = rte_mempool_create(name,
					   4*1024 - 1, MBUF_SIZE,
					   targ->nb_cache_mbuf,
					   sizeof(struct rte_pktmbuf_pool_private),
					   rte_pktmbuf_pool_init, NULL,
					   rte_pktmbuf_init, 0,
					   socket, 0);
	PROX_PANIC(task->mempool == NULL, "Failed to allocate memory pool with %u elements\n", 4*1024 - 1);

	/* streams contains a lua table. Go through it and read each
	   stream with associated imix_fraction. */
	uint32_t imix;
	uint32_t i = 0;

	int pop = lua_getfrom(prox_lua(), GLOBAL, targ->streams);
	PROX_PANIC(pop < 0, "Failed to find '%s' in lua\n", targ->streams);

	lua_len(prox_lua(), -1);
	uint32_t n_bundle_cfgs = lua_tointeger(prox_lua(), -1);
	lua_pop(prox_lua(), 1);
	PROX_PANIC(n_bundle_cfgs == 0, "No configs specified\n");
	plogx_info("loading %d bundle_cfgs\n", n_bundle_cfgs);

	struct hash_set *hs = prox_sh_find_socket(socket, "genl4_streams");
	if (hs == NULL) {
		/* Expected number of streams per bundle = 8, hash_set
		   will grow if full. */
		hs = hash_set_create(n_bundle_cfgs * 8, socket);
		prox_sh_add_socket(socket, "genl4_streams", hs);
	}

	task->bundle_cfgs = prox_zmalloc(n_bundle_cfgs * sizeof(task->bundle_cfgs[0]), socket);
	lua_pushnil(prox_lua());

	int total_imix = 0;

	uint32_t *occur = prox_zmalloc(n_bundle_cfgs * sizeof(*occur), socket);
	struct cdf *cdf = cdf_create(n_bundle_cfgs, socket);

	while (lua_next(prox_lua(), -2)) {
		PROX_PANIC(lua_to_int(prox_lua(), TABLE, "imix_fraction", &imix) ||
			   lua_to_bundle_cfg(prox_lua(), TABLE, "bundle", socket, &task->bundle_cfgs[i], hs),
			   "Failed to load bundle cfg:\n%s\n", get_lua_to_errors());
		cdf_add(cdf, imix);
		occur[i] = imix;
		total_imix += imix;
		++i;
		lua_pop(prox_lua(), 1);
	}

	lua_pop(prox_lua(), pop);
	cdf_setup(cdf);

	PROX_PANIC(targ->max_setup_rate == 0, "Max setup rate not set\n");

	task->new_conn_cost = rte_get_tsc_hz()/targ->max_setup_rate;

	static char name2[] = "task_gen_hash";
	name2[0]++;
	plogx_dbg("Creating bundle ctx pool\n");
	if (bundle_ctx_pool_create(name2, targ->n_concur_conn, &task->bundle_ctx_pool, occur, n_bundle_cfgs, task->bundle_cfgs, socket)) {
		cmd_mem_stats();
		PROX_PANIC(1, "Failed to create conn_ctx_pool\n");
	}

	task->heap = heap_create(targ->n_concur_conn, socket);
	task->seed = rte_rdtsc();
	/* task->token_time.bytes_max = MAX_PKT_BURST * (ETHER_MAX_LEN + 20); */

	/* To avoid overflowing the tx descriptors, the token bucket
	   size needs to be limited. The descriptors are filled most
	   quickly with the smallest packets. For that reason, the
	   token bucket size is given by "number of tx descriptors" *
	   "smallest Ethernet packet". */
	PROX_ASSERT(targ->nb_txports == 1);

	struct token_time_cfg tt_cfg = {
		.bpp = targ->rate_bps,
		.period = rte_get_tsc_hz(),
		.bytes_max = prox_port_cfg[targ->tx_port_queue[0].port].n_txd * (ETHER_MIN_LEN + 20),
	};

	token_time_init(&task->token_time, &tt_cfg);
}

static void start_task_gen_client(struct task_base *tbase)
{
	struct task_gen_client *task = (struct task_gen_client *)tbase;

	token_time_reset(&task->token_time, rte_rdtsc(), 0);

	task->new_conn_tokens = 0;
	task->new_conn_last_tsc = rte_rdtsc();
}

static void stop_task_gen_client(struct task_base *tbase)
{
	struct task_gen_client *task = (struct task_gen_client *)tbase;
	struct bundle_ctx *bundle;

	while (!heap_is_empty(task->heap)) {
		bundle = BUNDLE_CTX_UPCAST(heap_pop(task->heap));
		bundle_expire(bundle, &task->bundle_ctx_pool, &task->l4_stats);
	}
}

static void start_task_gen_server(struct task_base *tbase)
{
	struct task_gen_server *task = (struct task_gen_server *)tbase;

	token_time_reset(&task->token_time, rte_rdtsc(), 0);
}

static void stop_task_gen_server(struct task_base *tbase)
{
	struct task_gen_server *task = (struct task_gen_server *)tbase;
	struct bundle_ctx *bundle;
	uint8_t out[MAX_PKT_BURST];

	while (!heap_is_empty(task->heap)) {
		bundle = BUNDLE_CTX_UPCAST(heap_pop(task->heap));
		bundle_expire(bundle, &task->bundle_ctx_pool, &task->l4_stats);
	}

	if (task->cancelled) {
		struct rte_mbuf *mbuf = task->mbuf_saved;

		out[0] = OUT_DISCARD;
		task->cancelled = 0;
		task->base.tx_pkt(&task->base, &mbuf, 1, out);
	}

	do {
		if (task->cur_mbufs_beg == task->cur_mbufs_end) {
			task->cur_mbufs_end = fqueue_get(task->fqueue, task->cur_mbufs, MAX_PKT_BURST);
			task->cur_mbufs_beg = 0;
			if (task->cur_mbufs_end == 0)
				break;
		}
		uint16_t n_pkts = task->cur_mbufs_end - task->cur_mbufs_beg;
		struct rte_mbuf **mbufs = task->cur_mbufs + task->cur_mbufs_beg;

		if (n_pkts) {
			for (uint16_t j = 0; j < n_pkts; ++j) {
				out[j] = OUT_DISCARD;
			}
			task->base.tx_pkt(&task->base, mbufs, n_pkts, out);
		}
	} while (1);
}

static struct task_init task_init_gen1 = {
	.mode_str = "genl4",
	.sub_mode_str = "server",
	.init = init_task_gen,
	.handle = handle_gen_bulk,
	.start = start_task_gen_server,
	.stop = stop_task_gen_server,
	.flag_features = TASK_FEATURE_ZERO_RX,
	.size = sizeof(struct task_gen_server),
	.mbuf_size = 2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM,
};

static struct task_init task_init_gen2 = {
	.mode_str = "genl4",
	.init = init_task_gen_client,
	.handle = handle_gen_bulk_client,
	.start = start_task_gen_client,
	.stop = stop_task_gen_client,
	.flag_features = TASK_FEATURE_ZERO_RX,
	.size = sizeof(struct task_gen_client),
	.mbuf_size = 2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM,
};

__attribute__((constructor)) static void reg_task_gen(void)
{
	reg_task(&task_init_gen1);
	reg_task(&task_init_gen2);
}
예제 #30
0
static int lua_to_stream_cfg(struct lua_State *L, enum lua_place from, const char *name, uint32_t socket, struct stream_cfg **stream_cfg, struct hash_set *hs)
{
	int pop;
	struct stream_cfg *ret;

	if ((pop = lua_getfrom(L, from, name)) < 0)
		return -1;

	if (lua_getfrom(L, TABLE, "actions") < 0)
		return -1;

	lua_len(prox_lua(), -1);
	uint32_t n_actions = lua_tointeger(prox_lua(), -1);
	lua_pop(prox_lua(), 1);

	lua_pop(L, 1);

	size_t mem_size = 0;
	mem_size += sizeof(*ret);
	/* one additional action is allocated to allow inserting an
	   additional "default" action to close down TCP sessions from
	   the client side. */
	mem_size += sizeof(ret->actions[0]) * (n_actions + 1);

	ret = prox_zmalloc(sizeof(*ret) + mem_size, socket);
	ret->n_actions = n_actions;

	size_t client_contents_len, server_contents_len;
	char proto[16];
	uint32_t timeout_us, timeout_time_wait_us;
	plogx_dbg("loading stream\n");
	if (lua_to_host_set(L, TABLE, "servers", &ret->servers))
		return -1;
	if (lua_to_string(L, TABLE, "l4_proto", proto, sizeof(proto)))
		return -1;
	if (lua_to_peer_data(L, TABLE, "client_data", socket, &ret->data[PEER_CLIENT], &client_contents_len, hs))
		return -1;
	if (lua_to_peer_data(L, TABLE, "server_data", socket, &ret->data[PEER_SERVER], &server_contents_len, hs))
		return -1;

	if (lua_to_int(L, TABLE, "timeout", &timeout_us)) {
		timeout_us = 1000000;
	}

	ret->tsc_timeout = usec_to_tsc(timeout_us);

	double up, dn;

	if (lua_to_double(L, TABLE, "up_bps", &up))
		up = 5000;// Default rate is 40 Mbps

	if (lua_to_double(L, TABLE, "dn_bps", &dn))
		dn = 5000;// Default rate is 40 Mbps

	const uint64_t hz = rte_get_tsc_hz();

	ret->tt_cfg[PEER_CLIENT] = token_time_cfg_create(up, hz, ETHER_MAX_LEN + 20);
	ret->tt_cfg[PEER_SERVER] = token_time_cfg_create(dn, hz, ETHER_MAX_LEN + 20);

	if (!strcmp(proto, "tcp")) {
		ret->proto = IPPROTO_TCP;
		ret->proc = stream_tcp_proc;
		ret->is_ended = stream_tcp_is_ended;

		if (lua_to_int(L, TABLE, "timeout_time_wait", &timeout_time_wait_us)) {
			timeout_time_wait_us = 2000000;
		}

		ret->tsc_timeout_time_wait = usec_to_tsc(timeout_time_wait_us);
	}
	else if (!strcmp(proto, "udp")) {
		plogx_dbg("loading UDP\n");
		ret->proto = IPPROTO_UDP;
		ret->proc = stream_udp_proc;
		ret->is_ended = stream_udp_is_ended;
	}
	else
		return -1;

	/* get all actions */
	if (lua_getfrom(L, TABLE, "actions") < 0)
		return -1;

	uint32_t idx = 0;
	lua_pushnil(L);
	while (lua_next(L, -2)) {
		if (lua_to_peer_action(L, STACK, NULL, &ret->actions[idx], client_contents_len, server_contents_len))
			return -1;

		stream_cfg_verify_action(ret, &ret->actions[idx]);

		idx++;

		lua_pop(L, 1);
	}
	lua_pop(L, 1);

	/* For TCP, one of the peers initiates closing down the
	   connection. This is signified by the last action having
	   with zero length. If such an action is not specified in the
	   configuration file, the default is for the client to close
	   the connection. This means that the TCP connection at the
	   client will go into a TIME_WAIT state and the server
	   releases all the resources avoiding resource starvation at
	   the server. */
	if (ret->proto == IPPROTO_TCP && ret->actions[ret->n_actions - 1].len != 0) {
		ret->actions[ret->n_actions].len = 0;
		ret->actions[ret->n_actions].beg = 0;
		ret->actions[ret->n_actions].peer = PEER_CLIENT;
		ret->n_actions++;
	}

	if (IPPROTO_TCP == ret->proto)
		stream_tcp_calc_len(ret, &ret->n_pkts, &ret->n_bytes);
	else
		stream_udp_calc_len(ret, &ret->n_pkts, &ret->n_bytes);

	lua_pop(L, pop);
	*stream_cfg = ret;
	return 0;
}