Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Titan » Support for STOMP in Titan
Support for STOMP in Titan [message #1770103] Tue, 08 August 2017 11:24
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Dear all,

STOMP is a text-oriented messaging protocol maybe not so exciting in itself ( sometimes it is quoted as being an IoT protocol, but it has not been specifically designed for over-the-wire efficiency); but besides its' own capabilities, I will use it to demonstrate Websocket subprotocols and coding/configuring a translation port.

Support for STOMP version 1.2 (as specified in https://stomp.github.io/stomp-specification-1.2.html) comes in the form of a protocol module
git://git.eclipse.org/gitroot/titan/titan.ProtocolModules.STOMP.git

As the messages are a mix of UTF-8 and unrestricted binary, a handwritten codec has been produced.
The protocol is typically being used over TCP or TLS so it should be combined with the TCP or the ( more feature rich) IPL4 test port.


As a message broker I have used a default installation of Apache Apollo 1.7.1, which "is a faster, more reliable, easier to maintain
messaging broker built from the foundations of the original ActiveMQ", but I guess any STOMP-capable message broker could be equally used.

The installation instructions for Apollo can be found in
https://activemq.apache.org/apollo/documentation/getting-started.html


After starting the message broker installed in /var/lib with

 "/var/lib/mybroker/bin/apollo-broker" run
 

the following is displayed:

    _____                .__  .__
   /  _  \ ______   ____ |  | |  |   ____
  /  /_\  \\____ \ /  _ \|  | |  |  /  _ \
 /    |    \  |_> >  <_> )  |_|  |_(  <_> )
 \____|__  /   __/ \____/|____/____/\____/
         \/|__|  Apache Apollo (1.7.1)


Loading configuration file '/var/lib/mybroker/etc/apollo.xml'.
INFO  | OS     : Linux 4.4.0-83-generic (Ubuntu 16.04.2 LTS)
INFO  | JVM    : OpenJDK 64-Bit Server VM 1.8.0_131 (Oracle Corporation)
INFO  | Apollo : 1.7.1 (at: /home/ntaf/apache-apollo-1.7.1)
INFO  | OS is restricting the open file limit to: 100000
INFO  | Accepting connections at: tcp://0.0.0.0:61613
INFO  | Accepting connections at: tls://0.0.0.0:61614
INFO  | Starting store: leveldb store at /var/lib/mybroker/data
INFO  | Accepting connections at: ws://0.0.0.0:61623/
INFO  | Accepting connections at: wss://0.0.0.0:61624/
INFO  | virtual host startup is waiting on store startup
INFO  | virtual host startup is no longer waiting.  It waited a total of 1 seconds.
INFO  | Administration interface available at: https://127.0.0.1:61681/
INFO  | Administration interface available at: http://127.0.0.1:61680/



As indicated, TCP connections are expected on port 61613, while TLS connections on port 61614.


The TTCN-3 code used establishes a TCP/TLS connection (depending on the value of the module parameter tsp_use_ssl)
 if(tsp_use_ssl) {
    vl_result :=f_IPL4_connect(p, tsp_hostname, 61614,"",0, -1, {ssl := {} }, {}  );
  }
  else {

    vl_result :=f_IPL4_connect( p, tsp_hostname, 61613,"",0, -1, {tcp := {} }, {} );
  }


after which it sends a CONNECT message with the default credentials (remember to change these in a production environment) ,
followed by a SEND with a text message.


module STOMP_test 
{

modulepar {

  charstring tsp_hostname:="127.0.0.1"  
  boolean    tsp_use_ssl:=false 
}


import from IPL4asp_Types all;
import from IPL4asp_PortType all;
import from STOMP_Types all;



//*************************************************************************
function f_STOMPMessage_len(  in octetstring stream,   inout ro_integer args) return integer
//*************************************************************************

{    
  // return  f_calc_STOMP_length(stream);

  return f_GetSTOMPmsgLength(stream);

}

type component GeneralComp
{
  port IPL4asp_PT p;
  timer t;    
  var IPL4asp_Types.Result  c_res:= { errorCode := omit, connId  := omit, os_error_code:=omit, os_error_text:= omit };   

}

type component SystemComp
{
  port IPL4asp_PT p;
}



//*******************************************************************************************
//Templates


template STOMPFrame t_message:=
{

  command:=MESSAGE,
  headers:={ {header_name:="foo", header_value:="Hello"}, {header_name:="foo", header_value:="World"}},
  payload:=omit 


}


template STOMPFrame t_send:=
{

  command:=SEND,
  headers:={ {header_name:="destination", header_value:="/queue/a"}, {header_name:="receipt", header_value:="message-12345"}/*,{header_name:="content-length", header_value:="14"}*/},
  payload:=char2oct("Hello queue of Titans!!")  


}

:
:
template STOMPFrame t_connect0:=
{

  command:=CONNECT,
  headers:={ {header_name:="accept-version", header_value:="1.2"}, {header_name:="host", header_value:="mybroker"},
    {header_name:="login", header_value:="admin"},{header_name:="passcode", header_value:="password"}},
  payload:=omit


}

template  ASP_Send t_data(in integer p_id, in octetstring pdu ) :={
  connId:=p_id,
  proto:=omit,
  msg:=pdu
}


testcase TC_stomp() runs on GeneralComp system SystemComp {


  var ASP_RecvFrom v_ASP_RecvFrom	
  var STOMPFrame   v_frame;
  var octetstring v_pdu:=''O;
  var IPL4asp_Types.Result  vl_result; 
  var integer v_cid, v_ret;

  map(self:p, system:p); 

  vl_result := c_res;

  if(tsp_use_ssl) {
    vl_result :=f_IPL4_connect(p, tsp_hostname, 61614,"",0, -1, {ssl := {} }, {}  );
  }
  else {

    vl_result :=f_IPL4_connect( p, tsp_hostname, 61613,"",0, -1, {tcp := {} }, {} );
  }

  log("connect result",vl_result);
  if (not(ispresent(vl_result.connId)))
  {
    log("Could not connect");
    stop;
  } 

  v_cid:=vl_result.connId; 

  //register message length function of STOMP with IPL4:
  //*************************************************************************
  var f_IPL4_getMsgLen getMsg_Func := refers(f_STOMPMessage_len);
  f_IPL4_setGetMsgLen(p,v_cid, getMsg_Func, {});
  //*************************************************************************


  v_ret:=f_STOMP_enc(valueof(t_connect0), v_pdu)



  p.send(t_data(v_cid, v_pdu));
  t.start(1.0) 

  alt 
  { 
    [] p.receive(ASP_RecvFrom:?) -> value v_ASP_RecvFrom
    { 
      v_ret:= f_STOMP_dec(v_ASP_RecvFrom.msg, v_frame);
      log(v_frame);
    }
    [] t.timeout{log("Bye")}

  } 


  v_ret:=f_STOMP_enc(valueof(t_send), v_pdu)

  log("----------> :",v_pdu);

  p.send(t_data(v_cid, v_pdu));
  t.start(1.0) 

  alt 
  { 
    [] p.receive(ASP_RecvFrom:?) -> value v_ASP_RecvFrom
    { 
      log("----------> :",oct2char(v_ASP_RecvFrom.msg));

      v_ret:= f_STOMP_dec(v_ASP_RecvFrom.msg,v_frame);
      log(v_frame);
    }
    [] t.timeout{log("Bye")}

  } 

  //close  TCP/TLS connection

  vl_result :=    f_IPL4_close(p, v_cid)
  log("close result",vl_result) 

  setverdict(pass);
}

control {

  execute(TC_stomp());


}

}


After compilation and execution, the following log file is generated (with tsp_use_ssl:=true)

08:57:11.042462 - TTCN-3 Main Test Component started on esekilxxen1844. Version: CRL 113 200/6 R2A.
08:57:11.042595 - TTCN Logger v2.2 options: TimeStampFormat:=Time; LogEntityName:=No; LogEventTypes:=No; SourceInfoFormat:=Single; *.FileMask:=LOG_ALL; *.ConsoleMask:=ERROR | USER; LogFileSize:=0; LogFileNumber:=1; DiskFullAction:=Error
08:57:11.042778 - Connected to MC.
08:57:11.049736 - Executing control part of module STOMP_test.
08:57:11.049777 STOMP_test.ttcn:339 Execution of control part in module STOMP_test started.
08:57:11.049850 STOMP_test.ttcn:255 Test case TC_stomp started.
08:57:11.049885 STOMP_test.ttcn:255 Initializing variables, timers and ports of component type STOMP_test.GeneralComp inside testcase TC_stomp.
08:57:11.049999 STOMP_test.ttcn:255 Port p was started.
08:57:11.050027 STOMP_test.ttcn:255 Component type STOMP_test.GeneralComp was initialized.
08:57:11.050073 STOMP_test.ttcn:264 Mapping port mtc:p to system:p.
08:57:11.050146 STOMP_test.ttcn:264 Port p was mapped to system:p.
08:57:11.050215 STOMP_test.ttcn:264 Map operation of mtc:p to system:p finished.
08:57:11.050275 STOMP_test.ttcn:269 entering f__IPL4__PROVIDER__connect: :0 -> 127.0.0.1:61614 / SSL
08:57:11.140974 STOMP_test.ttcn:276 connect result{ errorCode := omit, connId := 1, os_error_code := omit, os_error_text := omit }
08:57:11.141235 STOMP_test.ttcn:296 Sent on p to system @IPL4asp_Types.ASP_Send : { connId := 1, proto := omit, msg := '434F4E4E4543540A6163636570742D76657273696F6E3A312E320A686F73743A6D7962726F6B65720A6C6F67696E3A61646D696E0A70617373636F64653A70617373776F72640A0A00'O }
08:57:11.141349 STOMP_test.ttcn:297 Start timer t: 1 s
08:57:11.144155 STOMP_test.ttcn:299 Message enqueued on p from system @IPL4asp_Types.ASP_RecvFrom : { connId := 1, remName := "127.0.0.1", remPort := 61614, locName := "127.0.0.1", locPort := 55414, proto := { ssl := { } }, userData := 0, msg := '434F4E4E45435445440A76657273696F6E3A312E320A7365727665723A6170616368652D61706F6C6C6F2F312E372E310A686F73742D69643A6D7962726F6B65720A73657373696F6E3A6D7962726F6B65722D37370A68656172742D626561743A3130302C31303030300A757365722D69643A61646D696E0A0A000A'O } id 1
08:57:11.144228 STOMP_test.ttcn:301 Receive operation on port p succeeded, message from system(): @IPL4asp_Types.ASP_RecvFrom : { connId := 1, remName := "127.0.0.1", remPort := 61614, locName := "127.0.0.1", locPort := 55414, proto := { ssl := { } }, userData := 0, msg := '434F4E4E45435445440A76657273696F6E3A312E320A7365727665723A6170616368652D61706F6C6C6F2F312E372E310A686F73742D69643A6D7962726F6B65720A73657373696F6E3A6D7962726F6B65722D37370A68656172742D626561743A3130302C31303030300A757365722D69643A61646D696E0A0A000A'O } id 1
08:57:11.144254 STOMP_test.ttcn:301 Message with id 1 was extracted from the queue of p.
08:57:11.144295 STOMP_test.ttcn:304 { command := CONNECTED (9), headers := { { header_name := "version", header_value := "1.2" }, { header_name := "server", header_value := "apache-apollo/1.7.1" }, { header_name := "host-id", header_value := "mybroker" }, { header_name := "session", header_value := "mybroker-77" }, { header_name := "heart-beat", header_value := "100,10000" }, { header_name := "user-id", header_value := "admin" } }, payload := omit }
08:57:11.144389 STOMP_test.ttcn:313 ----------> :'53454E440A64657374696E6174696F6E3A2F71756575652F610A726563656970743A6D6573736167652D31323334350A636F6E74656E742D6C656E6774683A32330A0A48656C6C6F207175657565206F6620546974616E73212100'O
08:57:11.144496 STOMP_test.ttcn:315 Sent on p to system @IPL4asp_Types.ASP_Send : { connId := 1, proto := omit, msg := '53454E440A64657374696E6174696F6E3A2F71756575652F610A726563656970743A6D6573736167652D31323334350A636F6E74656E742D6C656E6774683A32330A0A48656C6C6F207175657565206F6620546974616E73212100'O }
08:57:11.144572 STOMP_test.ttcn:316 Warning: Re-starting timer t, which is already active (running or expired).
08:57:11.144597 STOMP_test.ttcn:316 Start timer t: 1 s
08:57:11.146214 STOMP_test.ttcn:318 Message enqueued on p from system @IPL4asp_Types.ASP_RecvFrom : { connId := 1, remName := "127.0.0.1", remPort := 61614, locName := "127.0.0.1", locPort := 55414, proto := { ssl := { } }, userData := 0, msg := '524543454950540A726563656970742D69643A6D6573736167652D31323334350A0A000A'O } id 2
08:57:11.146279 STOMP_test.ttcn:320 Receive operation on port p succeeded, message from system(): @IPL4asp_Types.ASP_RecvFrom : { connId := 1, remName := "127.0.0.1", remPort := 61614, locName := "127.0.0.1", locPort := 55414, proto := { ssl := { } }, userData := 0, msg := '524543454950540A726563656970742D69643A6D6573736167652D31323334350A0A000A'O } id 2
08:57:11.146301 STOMP_test.ttcn:320 Message with id 2 was extracted from the queue of p.
08:57:11.146316 STOMP_test.ttcn:322 ----------> :"RECEIPT\nreceipt-id:message-12345\n\n" & char(0, 0, 0, 0) & "\n"
08:57:11.146378 STOMP_test.ttcn:325 { command := RECEIPT (13), headers := { { header_name := "receipt-id", header_value := "message-12345" } }, payload := omit }
08:57:11.146416 STOMP_test.ttcn:333 p: f__IPL4__close:  proto { unspecified := { } } connId 1
08:57:11.146528 STOMP_test.ttcn:334 close result{ errorCode := omit, connId := 1, os_error_code := omit, os_error_text := omit }
08:57:11.146564 STOMP_test.ttcn:336 setverdict(pass): none -> pass
08:57:11.146594 STOMP_test.ttcn:336 Terminating component type STOMP_test.GeneralComp.
08:57:11.146611 STOMP_test.ttcn:336 Stop timer t: 1 s
08:57:11.146628 STOMP_test.ttcn:336 Removing unterminated mapping between port p and system:p.
08:57:11.146648 STOMP_test.ttcn:336 Port p was unmapped from system:p.
08:57:11.146674 STOMP_test.ttcn:336 Port p was stopped.
08:57:11.146690 STOMP_test.ttcn:336 Component type STOMP_test.GeneralComp was shut down inside testcase TC_stomp.
08:57:11.146705 STOMP_test.ttcn:336 Waiting for PTCs to finish.
08:57:11.146773 STOMP_test.ttcn:336 Setting final verdict of the test case.
08:57:11.146800 STOMP_test.ttcn:336 Local verdict of MTC: pass
08:57:11.146819 STOMP_test.ttcn:336 No PTCs were created.
08:57:11.146833 STOMP_test.ttcn:336 Test case TC_stomp finished. Verdict: pass
08:57:11.146851 STOMP_test.ttcn:341 Execution of control part in module STOMP_test finished.
08:57:11.153706 - Verdict statistics: 0 none (0.00 %), 1 pass (100.00 %), 0 inconc (0.00 %), 0 fail (0.00 %), 0 error (0.00 %).
08:57:11.153784 - Test execution summary: 1 test case was executed. Overall verdict: pass
08:57:11.153800 - Exit was requested from MC. Terminating MTC.




CONNECT is acknowledged with CONNECTED, and SEND with a RECEIPT.



Code is attached as usual. Next we will examine using STOMP over websocket and what it entails from TTCN-3 code perspective.

Best regards
Elemer
  • Attachment: STOMP.tgz
    (Size: 306.90KB, Downloaded 120 times)
Previous Topic:Support for MongoDB
Next Topic:No custom encoding function found
Goto Forum:
  


Current Time: Tue Apr 23 04:02:08 GMT 2024

Powered by FUDForum. Page generated in 0.03819 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top