[MERGED] osmocom-bb[master]: mobile: Create "ms" singleton for struct osmocom_ms

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Holger Freyther gerrit-no-reply at lists.osmocom.org
Sun Dec 3 18:09:43 UTC 2017


Holger Freyther has submitted this change and it was merged.

Change subject: mobile: Create "ms" singleton for struct osmocom_ms
......................................................................


mobile: Create "ms" singleton for struct osmocom_ms

Make the MS the script is associated with accessible to lua. Provide
access to IMSI and IMEI. The IMSI might not be available at the given
time and just return an empty string.

Example lua usage:

 print(osmo.ms():imsi());
 print(osmo.ms():imei());
 print(osmo.ms():shutdown_state())
 print(osmo.ms():started())

 function ms_started_cb(started)
	print("MS started", started)
 end

 function ms_shutdown_cb(old_state, new_state)
	print("MS shutdown", old_state, "->", new_state)
 end

 function sms_cb(sms, cause, valid)
	print("SMS data cb", sms, cause, valid)
	for i, v in pairs(sms) do
		print(i, v)
	end
 end
 function mm_cb(new_state, new_substate, old_substate)
	if new_state == 19 and new_substate == 1 then
		osmo.ms():sms_send_simple("1234", "21321324", "fooooooo", 23)
	end
 end
 local cbs = {
	Started=ms_started_cb,
	Shutdown=ms_shutdown_cb,
	Sms=sms_cb,
	Mm=mm_cb
 }

 timer = osmo.timeout(20, function()
    print("Timeout occurred after 20s")
 end)

 osmo.ms():register(cbs)

 # Can fail. Best to wait for state changes...
 print(osmo.ms().start())
 print(osmo.ms().stop(true))

Change-Id: Ia3ace33d6ba4e904b1ff8e271a02d67777334a58
---
M src/host/layer23/include/osmocom/bb/common/osmocom_data.h
M src/host/layer23/src/mobile/script_lua.c
2 files changed, 271 insertions(+), 7 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
index 8f5cdc3..486c36d 100644
--- a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
+++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
@@ -87,6 +87,7 @@
 	struct llist_head trans_list;
 
 	void *lua_state;
+	int lua_cb_ref;
 	char *lua_script;
 };
 
diff --git a/src/host/layer23/src/mobile/script_lua.c b/src/host/layer23/src/mobile/script_lua.c
index cd7e8bc..cbba070 100644
--- a/src/host/layer23/src/mobile/script_lua.c
+++ b/src/host/layer23/src/mobile/script_lua.c
@@ -23,6 +23,7 @@
 #include <lauxlib.h>
 
 #include <osmocom/bb/common/osmocom_data.h>
+#include <osmocom/bb/mobile/app_mobile.h>
 #include <osmocom/bb/common/logging.h>
 
 #include <osmocom/bb/mobile/primitives.h>
@@ -94,6 +95,30 @@
 	{ NULL, NULL },
 };
 
+/* Push table and function.   Stack+=2 */
+static bool load_cb(lua_State *L, int ref, const char *cb_name)
+{
+	lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
+	lua_pushstring(L, cb_name);
+	lua_gettable(L, -2);
+	if (lua_isnil(L, -1)) {
+		LOGP(DLUA, LOGL_DEBUG, "No handler for %s\n", cb_name);
+		lua_pop(L, 2);
+		return false;
+	}
+	return true;
+}
+
+/* Call callback. Stack-=func + args. func/args popped by lua_pcall */
+static void call_cb(lua_State *L, int args)
+{
+	int err = lua_pcall(L, args, 0, 0);
+	if (err) {
+		LOGP(DLUA, LOGL_ERROR, "lua error: %s\n", lua_tostring(L, -1));
+		lua_pop(L, 2);
+	}
+}
+
 static void handle_timeout(struct mobile_prim_intf *intf, struct mobile_timer_param *param)
 {
 	struct timer_userdata *timer = (void *)(intptr_t) param->timer_id;
@@ -108,6 +133,109 @@
 		LOGP(DLUA, LOGL_ERROR, "lua error: %s\n", lua_tostring(L, -1));
 		lua_pop(L, 1);
 	}
+}
+
+static void handle_started(struct mobile_prim_intf *intf, struct mobile_started_param *param)
+{
+	lua_State *L = intf->ms->lua_state;
+
+	if (intf->ms->lua_cb_ref == LUA_REFNIL)
+		return;
+
+	if (!load_cb(L, intf->ms->lua_cb_ref, "Started"))
+		return;
+
+	lua_pushinteger(L, param->started);
+
+	call_cb(L, 1);
+	lua_pop(L, 1);
+}
+
+static void handle_shutdown(struct mobile_prim_intf *intf, struct mobile_shutdown_param *param)
+{
+	lua_State *L = intf->ms->lua_state;
+
+	if (intf->ms->lua_cb_ref == LUA_REFNIL)
+		return;
+
+	if (!load_cb(L, intf->ms->lua_cb_ref, "Shutdown"))
+		return;
+
+	lua_pushinteger(L, param->old_state);
+	lua_pushinteger(L, param->new_state);
+
+	call_cb(L, 2);
+	lua_pop(L, 1);
+}
+
+static void handle_sms(struct mobile_prim_intf *intf, struct mobile_sms_param *param)
+{
+	lua_State *L = intf->ms->lua_state;
+
+	if (intf->ms->lua_cb_ref == LUA_REFNIL)
+		return;
+
+	if (!load_cb(L, intf->ms->lua_cb_ref, "Sms"))
+		return;
+
+	lua_createtable(L, 0, 11);
+
+	lua_pushinteger(L, param->sms.validity_minutes);
+	lua_setfield(L, -2, "validity_minutes");
+
+	lua_pushinteger(L, param->sms.reply_path_req);
+	lua_setfield(L, -2, "reply_path_req");
+
+	lua_pushinteger(L, param->sms.status_rep_req);
+	lua_setfield(L, -2, "status_rep_req");
+
+	lua_pushinteger(L, param->sms.ud_hdr_ind);
+	lua_setfield(L, -2, "ud_hdr_ind");
+
+	lua_pushinteger(L, param->sms.protocol_id);
+	lua_setfield(L, -2, "protocol_id");
+
+	lua_pushinteger(L, param->sms.data_coding_scheme);
+	lua_setfield(L, -2, "data_coding_scheme");
+
+	lua_pushinteger(L, param->sms.msg_ref);
+	lua_setfield(L, -2, "msg_ref");
+
+	lua_pushstring(L, param->sms.address);
+	lua_setfield(L, -2, "address");
+
+	lua_pushinteger(L, param->sms.time);
+	lua_setfield(L, -2, "time");
+
+	lua_pushlstring(L, (char *) param->sms.user_data, param->sms.user_data_len);
+	lua_setfield(L, -2, "user_data");
+
+	lua_pushstring(L, param->sms.text);
+	lua_setfield(L, -2, "text");
+
+	lua_pushinteger(L, param->cause_valid);
+	lua_pushinteger(L, param->cause);
+
+	call_cb(L, 3);
+	lua_pop(L, 1);
+}
+
+static void handle_mm(struct mobile_prim_intf *intf, struct mobile_mm_param *param)
+{
+	lua_State *L = intf->ms->lua_state;
+
+	if (intf->ms->lua_cb_ref == LUA_REFNIL)
+		return;
+
+	if (!load_cb(L, intf->ms->lua_cb_ref, "Mm"))
+		return;
+
+	lua_pushinteger(L, param->state);
+	lua_pushinteger(L, param->substate);
+	lua_pushinteger(L, param->prev_substate);
+
+	call_cb(L, 3);
+	lua_pop(L, 1);
 }
 
 static int lua_osmo_timeout(lua_State *L)
@@ -164,8 +292,125 @@
 	{ NULL, NULL },
 };
 
+static int lua_osmo_ms(lua_State *L)
+{
+	lua_pushlightuserdata(L, get_primitive(L)->ms);
+	luaL_getmetatable(L, "MS");
+	lua_setmetatable(L, -2);
+
+	return 1;
+}
+
+static int lua_ms_imei(lua_State *L)
+{
+	struct osmocom_ms *ms = get_primitive(L)->ms;
+
+	luaL_argcheck(L, lua_isuserdata(L, -1), 1, "No userdata");
+	lua_pushstring(L, ms->settings.imei);
+	return 1;
+}
+static int lua_ms_imsi(lua_State *L)
+{
+	struct osmocom_ms *ms = get_primitive(L)->ms;
+
+	luaL_argcheck(L, lua_isuserdata(L, -1), 1, "No userdata");
+	lua_pushstring(L, ms->subscr.imsi);
+	return 1;
+}
+
+static int lua_ms_shutdown_state(lua_State *L)
+{
+	struct osmocom_ms *ms = get_primitive(L)->ms;
+
+	lua_pushinteger(L, ms->shutdown);
+	return 1;
+}
+
+static int lua_ms_started(lua_State *L)
+{
+	struct osmocom_ms *ms = get_primitive(L)->ms;
+
+	lua_pushinteger(L, ms->started);
+	return 1;
+}
+
+static int lua_ms_register(lua_State *L)
+{
+	struct osmocom_ms *ms = get_primitive(L)->ms;
+
+	/* callbacks must be a table */
+	luaL_checktype(L, 2, LUA_TTABLE);
+
+	if (ms->lua_cb_ref != LUA_REFNIL)
+		luaL_unref(L, LUA_REGISTRYINDEX, ms->lua_cb_ref);
+	ms->lua_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+	return 0;
+}
+
+static int lua_ms_no_shutdown(lua_State *L)
+{
+	struct osmocom_ms *ms = get_primitive(L)->ms;
+	char *name;
+	int res;
+
+	res = mobile_start(ms, &name);
+	lua_pushinteger(L, res);
+	return 1;
+}
+
+static int lua_ms_shutdown(lua_State *L)
+{
+	struct osmocom_ms *ms = get_primitive(L)->ms;
+	int argc = lua_gettop(L);
+	int force = 0;
+	int res;
+
+	if (argc >= 1) {
+		luaL_argcheck(L, lua_isboolean(L, -1), 1, "Force");
+		force = lua_toboolean(L, -1);
+	}
+
+	res = mobile_stop(ms, force);
+	lua_pushinteger(L, res);
+	return 1;
+}
+
+static int lua_ms_sms_send_simple(lua_State *L)
+{
+	const char *sms_sca, *number, *text;
+	int msg_ref, rc;
+
+	luaL_argcheck(L, lua_isnumber(L, -1), 4, "msg_ref needs to be a number");
+	luaL_argcheck(L, lua_isstring(L, -2), 3, "text must be a string");
+	luaL_argcheck(L, lua_isstring(L, -3), 2, "number must be a string");
+	luaL_argcheck(L, lua_isstring(L, -4), 1, "sms_sca must be a string");
+
+	msg_ref = (int) lua_tonumber(L, -1);
+	text = lua_tostring(L, -2);
+	number = lua_tostring(L, -3);
+	sms_sca = lua_tostring(L, -4);
+
+	rc = sms_send(get_primitive(L)->ms, sms_sca, number, text, msg_ref);
+	lua_pushinteger(L, rc);
+	return 1;
+}
+
+static const struct luaL_Reg ms_funcs[] = {
+	{ "imsi", lua_ms_imsi },
+	{ "imei", lua_ms_imei },
+	{ "shutdown_state", lua_ms_shutdown_state },
+	{ "started", lua_ms_started },
+	{ "register", lua_ms_register },
+	{ "start", lua_ms_no_shutdown },
+	{ "stop", lua_ms_shutdown },
+	{ "sms_send_simple", lua_ms_sms_send_simple },
+	{ NULL, NULL },
+};
+
+
 static const struct luaL_Reg osmo_funcs[] = {
 	{ "timeout",	lua_osmo_timeout },
+	{ "ms",	lua_osmo_ms },
 	{ NULL, NULL },
 };
 
@@ -174,6 +419,18 @@
 	switch (OSMO_PRIM_HDR(&prim->hdr)) {
 	case OSMO_PRIM(PRIM_MOB_TIMER, PRIM_OP_INDICATION):
 		handle_timeout(intf, (struct mobile_timer_param *) &prim->u.timer);
+		break;
+	case OSMO_PRIM(PRIM_MOB_STARTED, PRIM_OP_INDICATION):
+		handle_started(intf, (struct mobile_started_param *) &prim->u.started);
+		break;
+	case OSMO_PRIM(PRIM_MOB_SHUTDOWN, PRIM_OP_INDICATION):
+		handle_shutdown(intf, (struct mobile_shutdown_param *) &prim->u.shutdown);
+		break;
+	case OSMO_PRIM(PRIM_MOB_SMS, PRIM_OP_INDICATION):
+		handle_sms(intf, (struct mobile_sms_param *) &prim->u.sms);
+		break;
+	case OSMO_PRIM(PRIM_MOB_MM, PRIM_OP_INDICATION):
+		handle_mm(intf, (struct mobile_mm_param *) &prim->u.mm);
 		break;
 	default:
 		LOGP(DLUA, LOGL_ERROR, "Unknown primitive: %d\n", OSMO_PRIM_HDR(&prim->hdr));
@@ -196,6 +453,16 @@
 	lua_pop(L, 1);
 }
 
+static void create_meta_table(lua_State *L, const char *name, const luaL_Reg *regs)
+{
+	luaL_newmetatable(L, name);
+	lua_pushliteral(L, "__index");
+	lua_pushvalue(L, -2);
+	lua_rawset(L, -3);
+	luaL_setfuncs(L, regs, 0);
+	lua_pop(L, 1);
+}
+
 static void add_runtime(lua_State *L, struct mobile_prim_intf *intf)
 {
 	add_globals(L);
@@ -206,13 +473,8 @@
 	lua_setglobal(L, "osmo");
 
 	/* Create metatables so we can GC objects... */
-	luaL_newmetatable(L, "Timer");
-	lua_pushliteral(L, "__index");
-	lua_pushvalue(L, -2);
-	lua_rawset(L, -3);
-	luaL_setfuncs(L, timer_funcs, 0);
-	lua_pop(L, 1);
-
+	create_meta_table(L, "Timer", timer_funcs);
+	create_meta_table(L, "MS", ms_funcs);
 
 	/* Remember the primitive pointer... store it in the registry */
 	lua_pushlightuserdata(L, lua_prim_key);
@@ -251,6 +513,7 @@
 	if (!ms->lua_state)
 		return -1;
 
+	ms->lua_cb_ref = LUA_REFNIL;
 	luaL_openlibs(ms->lua_state);
 
 	intf = mobile_prim_intf_alloc(ms);

-- 
To view, visit https://gerrit.osmocom.org/4840
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ia3ace33d6ba4e904b1ff8e271a02d67777334a58
Gerrit-PatchSet: 7
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Owner: Holger Freyther <holger at freyther.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Holger Freyther <holger at freyther.de>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list