Hi! As some of you will have noticed, I've been working hard on a TCAP implementation. As this is now getting into pretty good shape, I'm looking at implementing MAP.
Right now I'm trying to come up with a good design to implement both MAP client (let's say a SGSN or MSC that issues a Location Updating Request) and server applications (think of HLR receiving + processing the Loc Upd Req). The full flow of primitives can be seen in the attached diagram (which by the way was designed unsing the new gen_ladder tool from git://git.osmocom.org/gen_ladder.git). In TCAP, it is relatively hard to grasp that every message consists of a dialogue part and an (optional) collection of component parts. The dialogue and component state machines are separate but interact. Since a lot of functionality is possibly contained in one PDU, this ladder diagram does not really care about actual messages/packets, but about the sequencing of primitives. First, terminology: client: A "request-side" client like a SGSN or MSC wanting to do loc upd libmap-cl: The libosmo-map instance at the client libtcap-cl: The libosmo-tcap instance at the client [between the two libtcap instances we have the signalling link] libtcap-srv: The libosmo-tcap instance at the server libmap-srv: The libosmo-map instance at the server server: The "responder-side" server like a HLR that receives loc upd 1) MAP-OPEN primitive is sent sent from client to libosmo-map. Note that no actual packets are exchanged on the signalling linke yet! 2) two MAP-INVOKE component requests are sent to libosmo-map. They contain the actual location updating requests (two of them for two different MS) 3) MAP-DELIMITER.req primitive is issued by client to libosmo-map. At this point, a TCAP TC-BEGIN.req primitive is issued to libosmo-tcap. libosmo-tcap assembles a TCAP message consisting of a TC-BEGIN dialogue portion (including loc upd req application context) containing two TC-INVOKE components. This message is sent over the signalling link. 4) The server libosmo-tcap receives the TC-BEGIN message with two TC-INVOKE components. It issues a TC-BEGIN.indication to libosmo-map, which in turn generates a MAP-OPEN.indicatin for the server application 5) The server application checks if it supports the application context and then confirms the MAP-OPEN by a MAP-OPEN.response primitive. This primitive is "cached" at libosmo-map at that time. 6) the server libosmo-tcap sends the first TC-INVOKE.indication to libosmo-map which forwards it to the server application. the application respondes with a 'result-last' primitive that is passed up to libosmo-tcap 7) the server libosmo-tcap sends the second TC-INVOKE.indication to libosmo-map which forwards it to the server application. the application respondes with a 'result-last' primitive that is passed up to libosmo-tcap Since this TC-INVOKE.ind is flagged as 'last', libosmo-map will issue a MAP-DELIMITER.indication to the server program. 8) The server application responds with MAP-DELIMITER.request, which triggers libosmo-map to issue a TC-CONTINUE.request, which in turn triggers generating the TCAP TC-CONTINUE message containing the two TC-RESULT-Last components [...] This primitive sequencing is mandated by the combination of the ITU-T Q.77x specifications and the GSM TS 09.02 / 29.002. Now the task at hand is to decide on the software architecture and which parts have to be handled synchronously or not. It was my idea to pass everything by-value at the libosmo-tcap/libosmo-map interface. While they both keep state information, I do not want to pass any information by reference at thee inter-layer boundaries. This might cause headaches in memory management (reference counting, etc.) Another aspect is that the actual execution of the function (e.g. location updating operation) might not be finished synchronously. If the server process implements a HLR, the HLR might be implemented as on-disk storage (e.g. SQL). In that case, the MAP-INVOKE.ind containing the location update will trigger some disk access. Only once that disk access has finished, the corresponding MAP-RESULT-L.req can be generated. The rough idea would be to have a queue of those tcap<->map primitives. This way, we could have single-threaed or (with proper locking) a thread pool approach, where each thread then dequeues one primitive, processes it, and sends a response primitive once it is finished. Any feedback/comments to this proposed architecture are most welcome. Regards, Harald -- - Harald Welte <lafo...@gnumonks.org> http://laforge.gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6)
map_client_server.ps.gz
Description: Binary data