Home » Eclipse Projects » Eclipse Titan » Dual-faced test ports: architectural considerations(Why and how to use dual-faced test ports)
Dual-faced test ports: architectural considerations [message #1736527] |
Thu, 30 June 2016 08:26 |
|
Greetings.
Typically TTCN-3 code focuses on the behaviour of a protocol layer; this layer will be connected
to the uppermost layer of a communication stack using some glue code named a system adapter(or test port- basically the same thing).
This stack is an IP stack in most of the cases, but it could be an SS7 stack, a serial port, you name it.
Frequently the term "transport" is being used to denote the communication stack in this role; so we have protocols
that connect to and use UDP, or TCP or HTTP as transport.
+------------------------------------------+
| |
| |
| Protocol behaviour |
| |
+-------------------+----------------------+
|
+-------------------v----------------------+
| |
| System adapter/test port |
| |
| |
+------------------------------------------+
|
+-------------------v----------------------+
| |
| Stack |
| |
| |
+------------------------------------------+
This article is about reusing the code of the test ports/system adapters.
Let's assume that we have already implemented a test port for a certain transport, say HTTP,
and we have two protocols, A, and B, that use HTTP as transport.
Protocol A is JSON encoded, while B is XML encoded.
The HTTP test port (published on github among Titan-related products, see https://github.com/eclipse/titan.TestPorts.HTTPmsg)
is a generic, protocol-independent port that accepts HTTP requests and responses, plus some control messages (Connect, Close etc.)
Protocol messages of A and B will be encoded and transported in HTTP bodies.
protocol A MsgA1, MsgA2, MsgA3 (JSON encoded)
protocol B MsgB1, MsgB2, MsgB3 (XML encoded)
+--------------------------------+
| |
| |
| Protocol A (JSON) |
| |
+-----------------------------------------------+
| | |
| | |
HTTP | Headers | Body |
| | |
+--------------+--------------------------------+
+--------------------------------+
| |
| |
| Protocol B (XML) |
| |
+-----------------------------------------------+
| | |
| | |
HTTP | Headers | Body |
| | |
+--------------+-------------------------------->
The upmost protocol layers describing protocol behaviour will have a test port carrying protocol messages, something like:
type port ProtA_PT message
{
inout MsgA1, MsgA2, MsgA3
}
type port ProtB_PT message
{
inout MsgB1, MsgB2, MsgB3
}
OK, so what options we have, short of writing a new test port from scratch, to connect Protocol A to HTTP?
1) Option zero - protocol-specific test ports
We can re-use the code of the HTTP test port (written in C++ for Titan) to create a protocol-specific test port:
add default headers characteristic to A (e.g. Content-Type "application/json"), invoke the appropriate JSON codecs when assembling the HTTP request
or dissecting the HTTP response etc. This is a rather simple exercise; we will have of course to modify the HTTP test port interface accordingly:
type port HTTP_ProtA_PT message
{
inout MsgA1, MsgA2, MsgA3
}
but we can achieve a quick result, we have re-used most of the HTTP test port code so ....yay!!!!
OK, now we will have to do something similar for protocol B: add deafult headers(Content-Type "application/xml") , invoke XML codecs etc.
and pretty soon we have a new test port:
type port HTTP_ProtB_PT message
{
inout MsgB1, MsgB2, MsgB3
}
So now we have three test ports in total: the generic HTTP , the one for protocol A, and the one for protocol B.
And maybe this is the moment when we get a little uncomfortable: what if some new similar protocols will appear?
We will have to have a new test port for each; if any change or correction is needed, this will have to be done across a quickly proliferating set of test ports.
Things can get quickly out of hand and we may decide that having protocol specific test ports, even it's an easy alternative,
it may prove to be difficult to manage and too costly in the long reach.
All right, so what's next???
2) Option one - mapping layer
We can implement mapping between the upper layer protocols and the test port in a separate layer, conveniently
and unsurprisingly named "mapping layer". Basically whatever has been done in C++ (or lower level code in general)
in the test port will have to be done in TTCN-3: assembling /disassembling messages, invoking codecs etc.
type component Mapping_CT
{
var boolean v_run;
port ProtA_PT ProtA_PCO;
port HTTPmsg_PT HTTP_A_PCO;
}
type component System_CT
{
port HTTPmsg_PT HTTP_A_PCO;
}
+------------------------------------------+
| |
| |
| Protocol A |
| |
+-------------------+----------------------+
| ProtA_PT
+-------------------v----------------------+
| |
| Mapping component |
| |
| |
+-------------------+----------------------+
|
|
v HTTP_PT
+-------------------+----------------------+
| |
| System |
| |
| |
+------------------------------------------+
The mapping component will run a loop function, something like:
//*************************************************************************
function f_ScanPorts runs on Mapping_CT
//*************************************************************************
{//startfunction ScanPorts
v_run := true;
while (v_run)
{//startwhile
alt
{//startalt
//*************************************************************************
// Messages received on the upper (protocol) port
//*************************************************************************
[] ProtA_PCO.receive(MsgA1:?) -> value vl_msgA1
{//startStatementBlock
//JSON-encode vl_msgA1 and make it the body of an HTTP message
//assemble HTTP headers
//open HTTP
//send HTTP request
//close HTTP
}//endStatementBlock
:
:
//*************************************************************************
// Messages received from the HTTP port
//*************************************************************************
[]HTTP_PCO.receive(HTTPResponse: ?) -> value vl_HTTPResponse;
{//startStatementBlock
//extract body from HTTP response
//JSON-decode it into protocol message
//send message on the upper port
}//endStatementBlock
:
:
}//endalt
}//endwhile
}//endfunction ScanPorts
v_run can be set to false for instance at the reception of an appropriate message on an internal control port,
permitting a controlled termination of the mapping component.
All right, this seems a bit better: in the end we have only one test port (so one separate product to maintain), at the expense of some extra TTCN-3 code and a separate mapping layer.
This separate layer could be a good option when we need to implement some complex stateful behaviour but in general this should not be necessary.
Also, one may object that we simply moved the problem out of the test port and into the TTCN-3 code of the mapping layer.
Still not an ideal situation .......
OK, anything else?
3)Option two- dual-faced test port
Dual faced test ports implement the above idea in a more elegant and transparent manner, without the need for a separate component.
This is the original definition of the HTTP test port:
type port HTTPmsg_PT message
{
// Connection handling ASPs
inout Close;
out Connect;
in Connect_result;
in Client_connected;
inout Half_close;
out Listen;
in Listen_result;
inout Shutdown;
// Message to send and receive
inout HTTPMessage;
}with { extension "provider" };
This can be extended with declarations that describe the mapping between the northern face( accepting protocol A, B, etc. messages)
and the southern face( the HTTP port itself)
type port ProtA_PT message //DualFace port
{
inout MsgA1, MsgA2, MsgA3
}with
{ extension
"user HTTPmsg_PT
out(
MsgA1 -> HTTPMessage: function(f_assemble_Request_from_MsgA1);
MsgA2 -> HTTPMessage: function(f_assemble_Request_from_MsgA2);
MsgA3 -> HTTPMessage: function(f_assemble_Request_from_MsgA3)
)
in(
HTTPMessage -> MsgA1 : function(f_dec_Response_to_MsgA1),
MsgA2 : function(f_dec_Response_to_MsgA2),
MsgA3 : function(f_dec_Response_to_MsgA3);
Close -> - : .....
)
"
}
The mapping functions will have to be implemented manually and will do all steps of the mapping: encoding/decoding, message assembling/disassembling etc.)
function f_assemble_Request_from_MsgA1 runs on ProtocolA_CT
{
var HTTPRequest v_HTTPRequest
var HTTPMessage v_HTTPMessage
//MsgA received
//send Connect
//if Connect_result is OK
//v_HTTPRequest.client_id optional,
//v_HTTPRequest.method:= "GET";
//v_HTTPRequest.uri:=....;
//v_HTTPRequest.version_major:=1;
//v_HTTPRequest.version_minor:=0;
//v_HTTPRequest.header:=
//v_HTTPRequest.body =f_encode(v_msgA1) //JSON encoding of msgA1
//v_HTTPMessage.request:=v_HTTPRequest;
//port.send(v_HTTPMessage)
//send Close
}
The end result: only one test port, no additional layer or component, and a minimal number of extra lines of easily readable TTCN-3 code.
So far, this seems to be the winning option. Viewed from a product perspective,
all transport issues can be solved with a small number of test ports (UDP, TCP, SCTP, HTTP and so on..), one for each transport stack.
In fact, instead of HTTP, I could also have used UDP or TCP as an example.
Several dual-faced test port examples have been published in this forum:
Dual-faced IPL4 test port in UDP mode
Example of ping (ICMP) over a layer 2 test port with Titan
Example of SNMP over UDP
and the reference guide supplies further details.
The standard describes these ports as "ports with translation capability" in
TTCN-3 Language Extensions:
Configuration and Deployment Support
5.2 Ports with translation capability
Besides the above example, the dual-faced test ports can be used in all kinds of protocol translations, such as translating between two different versions of the same protocol,
but also translating between say SIP and ISUP, as a protocol gateway, connecting the IP and SS7 realm.
Best regards
Elemer
[Updated on: Thu, 30 June 2016 14:16] Report message to a moderator
|
|
| | | | | |
Re: Dual-faced test ports: architectural considerations [message #1809771 is a reply to message #1809631] |
Tue, 23 July 2019 06:46 |
|
Hi Ash,
there seems to be a confusion here: the HTTPmsg port is a protocol-specific one, see option zero;
to use it for HTTP, you don't need any dual faced or mapping layout; you can use it as is.
It makes sense though to use the IPL4 test port instead of it, in dual-faced or mapping mode as IPL4 will add extra functionality: IPv6, SSL/TLS etc.
So the idea is that instead of many protocol-tailored ports one can use a generic one (TCP/UDP) plus a translation,
So if you need basic HTTP, feel free to use the HTTPmsg with no provider extension whatsoever.
BR
Elemer
[Updated on: Fri, 26 July 2019 07:08] Report message to a moderator
|
|
| | |
Goto Forum:
Current Time: Thu Apr 25 17:27:26 GMT 2024
Powered by FUDForum. Page generated in 0.05305 seconds
|