Skip to content

Commit 3a7b7bb

Browse files
Sandeep PinnintiSandeep Pinninti
authored andcommitted
Rfe/ric 979 distributed ping pong example (#56)
* DistributedPingPong commit * Distributed Ping Pong testing --------- Co-authored-by: Sandeep Pinninti <sandeep.pinninti@prod.hclpnp.com>
1 parent 61164d4 commit 3a7b7bb

6 files changed

Lines changed: 160 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
protocol PingPongProtocol{
2+
in ping(`int`);
3+
out ping(`int`);
4+
in pong(`int`);
5+
out pong(`int`);
6+
};
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
capsule PingPongServer : TCPServer {
2+
3+
4+
[[rt::header_preface]]
5+
`
6+
#include <iostream>
7+
using namespace std;
8+
9+
`
10+
[[rt::impl_preface]]
11+
`
12+
13+
#include <chrono>
14+
#include <thread>
15+
using namespace std;
16+
17+
18+
`
19+
20+
[[rt::decl]]
21+
`
22+
public:
23+
bool injectPing = false;
24+
virtual void init();
25+
`
26+
[[rt::impl]]
27+
`
28+
void PingPongServer::init(){
29+
int ac = RTMain::argCount();
30+
const char * const * av = RTMain::argStrings();
31+
32+
while( --ac > 0 ) {
33+
const char* arg = *++av;
34+
if( RTMemoryUtil::strcmp( arg, "-remotePort=", 12 ) == 0 )
35+
config.remotePort = RTMemoryUtil::atoi(*av + 12);
36+
if( RTMemoryUtil::strcmp( arg, "-port=", 6 ) == 0 )
37+
config.port = RTMemoryUtil::atoi(*av + 6);
38+
if( RTMemoryUtil::strcmp( arg, "-injectFirstPing", 16 ) == 0 )
39+
injectPing = true;
40+
}
41+
42+
cout << "Incoming port: " << config.port << endl << flush;
43+
}
44+
`
45+
service behavior port player: PingPongProtocol;
46+
statemachine {
47+
redefine _initial: initial -> WaitForRequest `
48+
49+
CALLSUPER;
50+
cout << "TCP server started!" << endl;
51+
52+
// Inject first signal
53+
if (injectPing) {
54+
cout << "Sleeping 1 second before injecting a signal ..." << endl;
55+
chrono::seconds timespan(1);
56+
this_thread::sleep_for(timespan);
57+
cout << "Sleeping done" << endl;
58+
59+
RTMessage * msg = context()->newMsg();
60+
int* data = new int(0);
61+
62+
msg->setData(data, &RTType_int);
63+
msg->setSignal(PingPongProtocol::Base::rti_ping);
64+
msg->setPriority(General);
65+
msg->setDestination(this, &player, 0);
66+
msg->internData();
67+
68+
context()->receive(msg, context());
69+
}
70+
`;
71+
};
72+
};
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
capsule Player {
2+
[[rt::decl]]
3+
`
4+
public: int count = 0;
5+
`
6+
7+
service behavior port server~: PingPongProtocol;
8+
behavior port timer : Timing;
9+
statemachine {
10+
state WaitForBall{
11+
ping: on server.ping
12+
`
13+
bool b = true; // ping
14+
count = *((int*) rtdata);
15+
timer.informIn(RTTimespec(1, 0), &b, &RTType_bool);
16+
`;
17+
pong: on server.pong
18+
`
19+
bool b = false; // pong
20+
count = *((int*) rtdata);
21+
timer.informIn(RTTimespec(1, 0), &b, &RTType_bool);
22+
`;
23+
timmer: on timer.timeout
24+
`
25+
bool isPing = *((bool*) rtdata);
26+
if (isPing)
27+
server.pong(count + 1).send();
28+
else
29+
server.ping(count + 1).send();
30+
31+
`;
32+
33+
};
34+
initial -> WaitForBall;
35+
};
36+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# pingpong-distributed
2+
A distributed [DevOps Code RealTime](https://www.hcl-software.com/devops-code-realtime) application consisting of two executables that send ping and pong messages back and forth. The applications communicate with each other using the library [TCP server](../TcpServer/).
3+
4+
## Usage
5+
Start each application with command-line arguments specifying a local and remote port. For example:
6+
```
7+
Top.EXE -URTS_DEBUG=quit -port=15000 -remotePort=16000
8+
```
9+
10+
In this case the started executable will listen for incoming messages on port 15000 and send outgoing messages to port 16000. The other application should then be started with the reversed arguments, i.e. with `-port=16000 -remotePort=15000`. It is assumed that both applications run on the same machine. If you want to run them on separate machines, edit `PingPongServer::init()` to add another command-line argument for specifying the remote hostname.
11+
12+
Initially both applications will wait for each other to send the first event, so nothing will happen. There are several ways to make the ping pong game start:
13+
* pass the `-injectFirstPing` argument to one of applications. Then the first message will be injected programmatically from within the application. For example:
14+
```
15+
TOP.EXE -URTS_DEBUG=quit -port=15000 -remotePort=16000
16+
TOP.EXE -URTS_DEBUG=quit -port=16000 -remotePort=15000 -injectFirstPing
17+
```
18+
* inject either the "ping" or "pong" event on the "PingPongServer::player" port. You can do this from another application by using the JSON API provided by [TCP server](../TcpServer/).
19+
* attach to one of the applications using the Code RealTime and send the "timeout" event to the "Player::timer" port.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
3+
capsule TOP {
4+
5+
[[rt::impl]]
6+
`
7+
#include <iostream>
8+
#include <chrono>
9+
#include <ctime>
10+
#include <iomanip>
11+
`
12+
/* Ports */
13+
/* Parts */
14+
part player : Player;
15+
part pingPongServer : PingPongServer;
16+
/* Connectors */
17+
connect pingPongServer.player with player.server;
18+
/* State Machine */
19+
statemachine {
20+
state State1;
21+
initial -> State1 ;
22+
};
23+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let tc = TCF.define(TCF.CPP_TRANSFORM);
2+
tc.topCapsule = 'TOP';
3+
tc.targetFolder = 'DistributedPingPong_target';
4+
tc.prerequisites = ['../TcpServer/tcpServerLib.tcjs'];

0 commit comments

Comments
 (0)