Hi,
while I am adding scripting support to the mobile application I tried using a primitive interface between the scripting implementation and the mobile application. On new indications a callback in the primitive interface user will be invoked and there is a generic submit function that will dispatch (switch/case) over the primitive and call the right internal functions. To prototype this I have implemented "timer" support, SMS and the started/shutdown handling through primitives.
The neat thing about this approach is that I don't tie a specific scripting solution into the code, the indications are generic enough to be useful in multiple contexts, the submit/dispatch is about high level operations ("send SMS", "switch device off") that map to other programming languages as well. E.g. it is easy to imagine that one writes a TCP/IP adapter to send these primitives to another process/application.
The controversial part is that this code is not using a msgb. Normally the primitive header is inside a msgb and then more or less points to itself. But in the scripting layer case the "timer", "new sms", "network selection" are already fully parsed objects (or where never parsed from a network representation) so are normally not located in a msgb in any form.
One option is not to bother and deal with the primitive header just being embedded in another structure. The concept of request/response/indication is bigger than network messages.
The other is to create a dummy msgb to obey the interface and follow the existing users but I am not sure what we would gain.
For XYZ->internal we can use direct function calls and avoid the indirection of the primitives and for indications either call directly into the scripting code or create a script_indications struct and put it into the struct osmocom_ms. Only downside that doing RPC requires more work? So far I only forsee a single "script_indications" callback.
comments? opinions?
holger
Hi Holger,
thanks for bringing this up. The original idea of introducing osmo_prim was for asynchronous primitives being exchanged between individual parts of a protocol stack. I think the L1/L2 interface in OsmocomBB was one of the first users. There we also need the async nature, as primitives are sent over the serial line.
In other parts of the code, like the libosmo-sigtran MTP-USER-SAP or SCCP-USER-SAP, there are still msgb-wrapped osmo_prim, despite us currently dispatching them synchronously into the user application code.
The idea was that this could later be evolved into a system where the related msgb's are sent over a unix domain socket between applications to isolate the sigtran/sccp stack from the user application.
So my general "road map" for osmo_prim and related SAPs is in that direction: * turn SAPs into first-class citizens with infrastructure to register them, VTY introspection, etc. * have facilities for accessing SAPs from different processes via unix domain sockets and exchange osmo-prim over sockets
On Mon, Nov 20, 2017 at 08:29:35PM +0800, Holger Freyther wrote:
The neat thing about this approach is that I don't tie a specific scripting solution into the code, the indications are generic enough to be useful in multiple contexts, the submit/dispatch is about high level operations ("send SMS", "switch device off") that map to other programming languages as well. E.g. it is easy to imagine that one writes a TCP/IP adapter to send these primitives to another process/application.
I very much like this and support it. This is also how I had envisioned this feature to move ahead: First have some primitives for those operations, and then use those primitives from a language binding such as lua.
The controversial part is that this code is not using a msgb. Normally the primitive header is inside a msgb and then more or less points to itself.
Yes, and the goal of this is to have all information inside the primitive. We don't pass pointers across a SAP. All information is self-contained and only identifiers are used to refererence other state/objects. This means they can be queued, transported over sockets (at least on the same host where the struct alignment/padding/endinanness is identical), ...
But in the scripting layer case the "timer", "new sms", "network selection" are already fully parsed objects (or where never parsed from a network representation) so are normally not located in a msgb in any form.
Yes, understood. Still, those structures could probably simply be copied/wrapped into a msgb? Like the struct that represents a parsed SMS?
One option is not to bother and deal with the primitive header just being embedded in another structure. The concept of request/response/indication is bigger than network messages.
correct. However, I think it might actually be good to call things differently or to find some kind of naming to make it easy for them not to be confused?
The other is to create a dummy msgb to obey the interface and follow the existing users but I am not sure what we would gain.
We wouldn't gain anything as long as there would still be pointers or other non-serialized data inside the msgb itself. Wrapping into a msgb only makes sense if the msgb-wrapped-prim is self-contained.
At that point you gain that you can queue them, work asynchronosly on them, and that e.g. a script language VM/interpreter/... could run in a completely different process. I would love to see that, but of course if it's only possible by crating tons of new struct definitions, copying the data back and forth, etc. a shortcut like you proposed might be more realistic.
But then, given that the number of high-level primitives is expected to be rather small (perform LU, MO-SMS, MT-SMS, USSD) in theory it should not be too much data that needs to be converted?
For call control, it occurs to me only now, we could and probably should actually use the MNCC interface that OsmocomBB already offers. So existing MNCC primitives (which predate osmo_prim, but which would have been be a very good fit conceptually) can be created/used by the "script language process/thread/binding" side to create higher-level functions that can be used from the script language. So the script would simply synchonously ask for make_a_mo_voice_call(msisdn) while then the underlying C code would translate that to MNCC and use the existing socket for that?
In the end, you are doing the work, and it's your call. I see some benefits of going the msgb way, but then I don't understand the implications in detail as you do, working on the given task.
Regards, Harald
On 20. Nov 2017, at 21:25, Harald Welte laforge@gnumonks.org wrote:
Hi Holger,
Yes, understood. Still, those structures could probably simply be copied/wrapped into a msgb? Like the struct that represents a parsed SMS?
At that point you gain that you can queue them, work asynchronosly on them, and that e.g. a script language VM/interpreter/... could run in a completely different process. I would love to see that, but of course if it's only possible by crating tons of new struct definitions, copying the data back and forth, etc. a shortcut like you proposed might be more realistic.
In the end, you are doing the work, and it's your call. I see some benefits of going the msgb way, but then I don't understand the implications in detail as you do, working on the given task.
So it will be neat to just send the msgb to another application but it was easier to just put the struct on the stack and dispatch it. But as you have pointed out we have the MNCC interface, SMS will not be a big deal and the others are probably not very data intensive either. Let's try using msgb and see how that will go.
holger
baseband-devel@lists.osmocom.org