//for receiving DIO broadcast int create_diorecv_socket(lua_State *L) { lua_pushlightfunction(L, libstorm_net_udpsocket); lua_pushnumber(L, diorecvport); lua_pushlightfunction(L, diorecv_callback); lua_call(L,2,1); lua_setglobal(L, "diorecv_sock"); return 0; }
//actions that take place in a root node int rpl_root_func(lua_State *L) { //socket for listening to DIS and responding with DIO unicast lua_pushlightfunction(L, create_disrecv_socket); lua_call(L, 0, 0); //socket for broadcasting DIO lua_pushlightfunction(L, create_diobcast_socket); lua_call(L, 0, 0); //initialize DIO table lua_pushlightfunction(L, dio_init); lua_pushnumber(L, 1); //rank of root lua_pushnumber(L, 1); //root is grounded lua_pushlightfunction(L, libstorm_os_getipaddrstring); lua_call(L, 0, 1);//dodag id is same as ip addr for root lua_pushnumber(L, 0); //etx is 0, directly connected to border router lua_pushnumber(L, 1);//version 1 lua_call(L, 5, 0); //initialize DIS table lua_pushlightfunction(L, dis_init); lua_call(L, 0, 0); //set TFLAg to 0 to show that trickle timer is not currently running lua_pushnumber(L, 0); lua_setglobal(L, "TFLAG"); //Set trickle timer parameters //minimum interval size in seconds lua_pushnumber(L, 5); lua_setglobal(L, "IMIN"); //number of doublings of imin lua_pushnumber(L, 16); lua_setglobal(L, "IMAX"); //number of consistent messages for no transmission lua_pushnumber(L, 1); lua_setglobal(L, "K"); //set global trickle instance flag, to keep track whether we are running the right instance or an old instance lua_pushnumber(L, 0); lua_setglobal(L, "TRICKLE_INSTANCE"); //set flag to show that DIS is not being multicast lua_pushnumber(L, 0); lua_setglobal(L, "dismflag"); //set empty routing table (routing table only for root node) lua_newtable(L); lua_setglobal(L, "routing_table"); return 0; }
int bcast_dio(lua_State *L) { //libstorm_net_sendto(socket, payload, ip, port) //multicast address: "ff02::1" lua_pushlightfunction(L, libstorm_net_sendto); lua_getglobal(L, "diobcast_sock"); lua_pushlightfunction(L, libmsgpack_mp_pack); lua_getglobal(L, "DIO"); lua_call(L,1,1); lua_pushstring(L, "ff02::1"); lua_pushnumber(L, diorecvport); lua_call(L, 4, 1); return 0; }
LUALIB_API void luaI_openlib (lua_State *L, const char *libname, const luaL_Reg *l, int nup, int ftype) { if (libname) { int size = libsize(l); /* check whether lib already exists */ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); lua_getfield(L, -1, libname); /* get _LOADED[libname] */ if (!lua_istable(L, -1)) { /* not found? */ lua_pop(L, 1); /* remove previous result */ /* try global variable (and create one if it does not exist) */ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) luaL_error(L, "name conflict for module " LUA_QS, libname); lua_pushvalue(L, -1); lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ } lua_remove(L, -2); /* remove _LOADED table */ lua_insert(L, -(nup+1)); /* move library table to below upvalues */ } for (; l->name; l++) { int i; for (i=0; i<nup; i++) /* copy upvalues to the top */ lua_pushvalue(L, -nup); if (ftype == LUA_USELIGHTFUNCTIONS) lua_pushlightfunction(L, l->func); else lua_pushcclosure(L, l->func, nup); lua_setfield(L, -(nup+2), l->name); } lua_pop(L, nup); /* remove upvalues */ }
int t_timeout(lua_State *L) { //function invoked after t ticks, time to check if c<k and transmit int t= lua_tonumber(L, lua_upvalueindex(1)); int i= lua_tonumber(L, lua_upvalueindex(2)); int l_inst= lua_tonumber(L, lua_upvalueindex(3)); //local instance number //first check if the current trickle instance is same as instance running //global instance lua_getglobal(L, "TRICKLE_INSTANCE"); int g_inst = lua_tonumber(L, -1); if(g_inst!= l_inst) { //new instance of trickle timer has been started, this one must be stopped return cord_return(L, 0); } else { lua_getglobal(L, "C"); lua_getglobal(L, "k"); if(lua_tonumber(L, -2)<lua_tonumber(L,-1)) //if(c<k) { //transmit lua_pushlightfunction(L, bcast_dio); lua_call(L, 0, 0); } lua_pushnumber(L, i); lua_pushnumber(L, l_inst); cord_set_continuation(L, i_timeout, 2); //call i_timeout after (i-t) ticks return nc_invoke_sleep(L, (i-t) * SECOND_TICKS); } }
//actions to perform upon receipt of dis int disrecv_callback(lua_State *L) { //if floating, don't respond with DIO lua_getglobal(L, "DIO"); lua_pushstring(L, "grounded"); lua_gettable(L, -2); if(lua_tonumber(L, -1)==0) { return 0; } //get DIS msg from payload char *srcip = (char *)lua_tostring(L, 2); /* //Should I unpack DIS?? lua_pushlightfunction(L, libmsgpack_mp_unpack); lua_pushvalue(L, 1); lua_call(L, 1, 1); */ //Unicast back DIO lua_pushlightfunction(L, libstorm_net_sendto); lua_getglobal(L, "disrecv_sock"); lua_pushlightfunction(L, libmsgpack_mp_pack); lua_getglobal(L, "DIO"); lua_call(L, 1, 1); lua_pushstring(L, srcip); lua_pushnumber(L, diorecvport); lua_call(L,4,1); lua_getglobal(L, "TFLAG"); if(lua_tonumber(L, -1)==0) { //set TFLAG to show that trickle timer is currently running lua_pushnumber(L, 1); lua_setglobal(L, "TFLAG"); //call the trickle timer, let it run concurrently in the background lua_pushlightfunction(L, trickle_timer); lua_call(L, 0, 0); } return 0; }
int luaR_findfunction(lua_State *L, const luaL_reg *ptable) { int found; const char *key = luaL_checkstring(L, 2); luaR_result res = luaR_findkey(ptable, key, LUAR_FINDFUNCTION, &found); if (found) lua_pushlightfunction(L, (void*)(size_t)res); else lua_pushnil(L); return 1; }
int mcast_dis(lua_State *L) { lua_pushlightfunction(L, libstorm_net_sendto); lua_getglobal(L, "dismcast_sock"); lua_pushlightfunction(L, libmsgpack_mp_pack); lua_getglobal(L, "DIS"); lua_call(L,1,1); lua_pushstring(L, "ff02::1"); lua_pushnumber(L, disrecvport); lua_call(L, 4, 1); lua_getglobal(L, "dismflag"); if(lua_tonumber(L, -1)==1) { cord_set_continuation(L, mcast_dis, 0); return nc_invoke_sleep(L, 5 * SECOND_TICKS); //can be changed } else { return cord_return(L, 0); } }
/* Prefix Table: Dest: Ip ADDR Hop : int cc :int 1-> ip addr 2-> ip addr ... ... */ int send_dao(lua_State *L) { lua_pushlightfunction(L, libmsgpack_mp_unpack); lua_pushvalue(L, 1); lua_call(L, 1, 1); int t_idx = lua_gettop(L); //index of prefix table lua_pushstring(L, hop); lua_gettable(L, t_idx); int hop = lua_tonumber(L, -1); lua_pop(L, 1); //pop the old hop, increment lua_pushnumber(L, hop+1); lua_pushlightfunction(L, libstorm_net_getipaddrstring); lua_call(L,0,1); lua_settable(L , t_idx); lua_pushstring(L, "hop"); lua_pushnumber(L, hop+1); lua_settable(L, t_idx); lua_pushlightfunction(L, libstorm_net_sendto); lua_getglobal(L, "dao_socket"); lua_pushlightfunction(L, libmsgpack_mp_pack); lua_pushvalue(L, t_idx); lua_call(L,1,1); lua_getglobal(L, "PrefParent"); lua_pushnumber(L, daoport); lua_call(L, 4, 1); //Check if DAO_ACK has been received after 5 seconds lua_pushlightfunction(L, libmsgpack_mp_pack); lua_pushvalue(L, tab_index); lua_call(L, 1, 1); cord_set_continuation(L, check_daoack, 1); return nc_invoke_sleep(L, 5 * SECOND_TICKS); //can be changed }
int dis_init(lua_State *L) { //DIS = {Node ID} lua_createtable(L, 0, 2); int table_index=lua_gettop(L); lua_pushstring(L, "node_id"); lua_pushlightfunction(L, libstorm_os_getnodeid); lua_call(L, 0, 1); lua_settable(L, table_index); lua_setglobal(L, "DIS"); return 0; }
LUALIB_API int luaopen_package (lua_State *L) { int i; /* create new type _LOADLIB */ #if LUA_OPTIMIZE_MEMORY == 0 luaL_newmetatable(L, "_LOADLIB"); lua_pushlightfunction(L, gctm); lua_setfield(L, -2, "__gc"); #else luaL_rometatable(L, "_LOADLIB", (void*)lmt); #endif /* create `package' table */ luaL_register_light(L, LUA_LOADLIBNAME, pk_funcs); #if defined(LUA_COMPAT_LOADLIB) lua_getfield(L, -1, "loadlib"); lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); #endif lua_pushvalue(L, -1); lua_replace(L, LUA_ENVIRONINDEX); /* create `loaders' table */ lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); /* fill it with pre-defined loaders */ for (i=0; loaders[i] != NULL; i++) { lua_pushcfunction(L, loaders[i]); lua_rawseti(L, -2, i+1); } lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ /* store config information */ lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" LUA_EXECDIR "\n" LUA_IGMARK); lua_setfield(L, -2, "config"); /* set field `loaded' */ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); lua_setfield(L, -2, "loaded"); /* set field `preload' */ lua_newtable(L); lua_setfield(L, -2, "preload"); lua_pushvalue(L, LUA_GLOBALSINDEX); luaL_register(L, NULL, ll_funcs); /* open lib into global table */ lua_pop(L, 1); return 1; /* return 'package' table */ }
//(rank, gf, dodag_id, etx, version)->nil int dio_init(lua_State *L) { //DIO = { Rank, G/F, Dodag ID, ETX, Node ID, Version } lua_getglobal(L, "DIO"); int table_index=lua_gettop(L); lua_pushstring(L, "rank"); lua_pushvalue(L, lua_tonumber(L, 1)+1); //parent rank is the first parameter lua_settable(L, table_index); lua_pushstring(L, "GF"); lua_tonumber(L, 2); lua_settable(L, table_index); lua_pushstring(L, "dodag_id"); lua_pushvalue(L, 3); lua_settable(L, table_index); lua_pushstring(L, "etx"); //same as rank? lua_pushvalue(L, 4); lua_settable(L, table_index); lua_pushstring(L, "node_id"); lua_pushlightfunction(L, libstorm_os_getnodeid); lua_call(L, 0, 1); lua_settable(L, table_index); lua_pushstring(L, "version"); lua_pushvalue(L, 5); lua_settable(L, table_index); //following line might not be necessary: //lua_pushvalue(L, table_index); lua_setglobal(L, "DIO"); return 0; }
int rpl_float_func(lua_State *L) { //socket for listening to DIS and responding with DIO unicast lua_pushlightfunction(L, create_disrecv_socket); lua_call(L, 0, 0); //socket for multicasting DIS lua_pushlightfunction(L, create_dismcast_socket); lua_call(L, 0, 0); //socket for receiving DIO unicast/ broadcast lua_pushlightfunction(L, create_diorecv_socket); lua_call(L, 0, 0); //socket for broadcasting DIO lua_pushlightfunction(L, create_diobcast_socket); lua_call(L, 0, 0); //initialize DIO table lua_createtable(L, 0, 6); lua_setglobal(L, "DIO"); lua_pushlightfunction(L, dio_init); lua_pushnumber(L, -1); //rank of floating node lua_pushnumber(L, 0); //floating lua_pushnumber(L, -1); //not associated to any dodag, so dodag_id is -1 lua_pushnumber(L, 10000); //infinite etx lua_pushnumber(L, -1);//no version yet since node is floating lua_call(L, 5, 0); //initialize DIS table lua_pushlightfunction(L, dis_init); lua_call(L, 0, 0); //set flag to show that DIS is being multicast lua_pushnumber(L, 1); lua_setglobal(L, "dismflag"); //start DIS multicast lua_pushlightfunction(L, mcast_dis); lua_call(L, 0, 0); //set TFLAg to 0 to show that trickle timer is not currently running lua_pushnumber(L, 0); lua_setglobal(L, "TFLAG"); //Set trickle timer parameters //minimum interval size in seconds lua_pushnumber(L, 5); lua_setglobal(L, "IMIN"); //number of doublings of imin lua_pushnumber(L, 16); lua_setglobal(L, "IMAX"); //number of consistent messages for no transmission lua_pushnumber(L, 1); lua_setglobal(L, "K"); //set global trickle instance flag, to keep track whether we are running the right instance or an old instance lua_pushnumber(L, 0); lua_setglobal(L, "TRICKLE_INSTANCE"); //set empty parent table (only for non-root nodes) lua_newtable(L); lua_setglobal(L, "parent_table"); return 0; }
int diorecv_callback(lua_State *L) { lua_pushlightfunction(L, libmsgpack_mp_unpack); lua_pushvalue(L, 1); lua_call(L, 1, 1); int tab_index=lua_gettop(L); //DIO received char *srcip = (char *)lua_tostring(L, 2); //stop DIS multicast lua_getglobal(L, "dismflag"); //flag that checks if dis is still being multicast if(lua_tonumber(L, -1)==1) { lua_pushlightfunction(L, libstorm_net_close); lua_getglobal(L, "dismcast_sock"); lua_call(L, 1, 0); lua_pushnumber(L, 0); lua_setglobal(L, "dismflag"); } lua_getglobal(L, "DIO"); int self_dio= lua_gettop(L); lua_pushstring(L, "rank"); lua_gettable(L, self_dio); int s_rank = lua_tonumber(L, -1); if(lua_tonumber(L, -1)>1) // not a root node { lua_pushstring(L, "rank"); lua_gettable(L, tab_index); int p_rank = lua_tonumber(L, -1); if(p_rank < s_rank) { //add to parent list lua_getglobal(L, "parent_table"); lua_pushstring(L, srcip); lua_pushnumber(L, p_rank); lua_settable(L, -3); lua_setglobal(L, "parent_table"); } if((s_rank == 10000) || (s_rank > (p_rank+1))) { //set preferred parent as incoming DIO, which is on top of the stack lua_pushstring(L, srcip); lua_setglobal(L, "PrefParent"); lua_pop(L, 1); //Update self dio with new rank, gf, dodag_id, etx and version (from parent) lua_pushlightfunction(L, dio_init); lua_pushstring(L, "rank"); lua_pushnumber(L, lua_tonumber(L, -1)+1);//push new rank lua_pushnumber(L, 1);//GF=1 lua_pushstring(L, "dodag_id"); lua_gettable(L, tab_index);//same dodag_id as parent lua_pushstring(L, "etx"); lua_gettable(L, tab_index); int etx=lua_tonumber(L, -1); lua_pop(L, 1); lua_pushnumber(L,etx+1);//etx of parent+1 (for now,later add another measure for calculating etx) lua_pushstring(L, "version"); lua_gettable(L, tab_index);//same dodag_version as parent lua_call(L, 5, 0); //inconsistent state reached, reset everything and start trickle timer again //**STOP THE OLD INSTANCE OF TRICKLE TIMER** lua_getglobal(L, "TRICKLE_INSTANCE"); lua_pushnumber(L, lua_tonumber(L, -1)+1); lua_setglobal(L, "TRICKLE_INSTANCE"); lua_pushlightfunction(L, trickle_timer); lua_call(L, 0, 0); } else { //consistent state, increment C(trickle timer counter) lua_getglobal(L, "C"); lua_pushnumber(L, lua_tonumber(L, -1)+1); lua_setglobal(L, "C"); } } return 0; }
int check_daoack(lua_State *L) { lua_pushlightfunction(L, libmsgpack_mp_unpack); lua_pushvalue(L, lua_upvalueindex(1)); lua_call(L, 1, 1); int t_idx=lua_gettop(L); lua_pushstring(L, "dest"); lua_gettable(L, t_idx); char *d_ip= (char *)lua_tostring(L, -1); lua_getglobal(L, "DAO_ACK"); int dt_idx=lua_gettop(L); lua_pushstring(L, -2); //ip address of required destination lua_gettable(L, -2); if(isnil(L, -1)) //No dao_ack for this ip addr { lua_getglobal(L, "PFLAG"); int pflag = lua_tonumber(L, -1); if(pflag > 5) //more than 5 retransmissions already occured to this parent { //Parent is dead, find new parent lua_getglobal(L, "parent_table"); int p_idx=lua_gettop(L); lua_pushnil(L); if(lua_next(L, p_idx)==0) // no elements in the parent table { //send poisoning DIO to release all children //rebroadcast DIS //reinitialise dio, dis, all tables } else { //IP Addr of next parent is at index -2 char *p_ip = (char *)lua_tostring(L, -2); int p_rank = lua_tonumber(L, -1); //rank of new parent lua_pop(L, 1); //now Parent IP is on top of the stack (after popping rank) lua_setglobal(L, "PrefParent"); //remove node from parent table lua_pushstring(L, p_ip); int ref = luaL_ref (L, p_idx); luaL_unref(L, p_idx, ref); //remove all nodes from parent table whose rank is less than new rank lua_pushnil(L); while(lua_next(L, p_idx)!=0) { if(lua_tonumber(L, -1) > p_rank) { lua_pushvalue(L, -2); // srcip (key) of next parent) ref = luaL_ref (L, p_idx); luaL_unref(L, p_idx, ref); //remove entry from table //lua_pop(L, 1); //if lua_unref does not pop reference from top of the stack } lua_pop(L, 1); } //send dis to preferred parent, wait for DIO lua_pushlightfunction(L, libstorm_net_sendto); lua_getglobal(L,"diomcast_sock"); lua_pushlightfunction(L, libmsgpack_mp_pack); lua_getglobal(L, "DIS"); lua_call(L, 1, 1); lua_pushstring(L, p_ip); lua_pushnumber(L, disrecvport); lua_call(L, 4, 1); //send new DAO all the way to the root with your own information } lua_pushnumber(L, 0); lua_setglobal(L, "PFLAG"); return 0; } lua_pushnumber(L, pflag + 1); lua_setglobal(L, "PFLAG"); lua_pushlightfunction(L, send_dao); lua_pushvalue(L, 1); //push the packed prefix table onto the stack lua_call(L, 1, 0); } else //ACK Received, no need to call send again, remove DAO_ACK from table { lua_pushstring(L, d_ip); int ref = luaL_ref (L, p_idx); luaL_unref(L, p_idx, ref); lua_pushvalue(L, dt_idx); lua_setglobal(L, "DAO_ACK"); lua_pushnumber(L, 0); lua_setglobal(L, "PFLAG"); //Parent flag, to check if prefparent is alive } return 0; }