How to check a received message type on OMNeT++? - omnet++

I have declared three different message types in OMNeT++:
Layer
Ack
Reject
What I want to achieve is that every node in my network can send any type of message mentioned above. So that every message type has its own variables. But since the handleMessage(cMessage*) function accepts cMessage* type, I need to know the type of message to be able to cast it accordingly.
How would I go about it?
Here is my Layer message type:
message Layer {
int layer;
simtime_t timeFrame;
}

Each your message type is represented by a class that inherits from cMessage. Therefore, dynamic_cast may be used to recognize the type of message, for example this way:
void YourClass::handleMessage(cMessage * msg) {
Layer * layer = dynamic_cast<Layer*> (msg);
if (layer != nullptr) {
// received Layer
} else {
Ack* ack = dynamic_cast<Ack*> (msg);
if (ack != nullptr) {
// received Ack
} else {
Reject* rej= dynamic_cast<Reject*> (msg);
if (rej != nullptr) {
// received Reject
}
}
}

Related

Timer-based sending of message

I want to implement a timer-based message scheme in VEINs/OMNeT++. Here is a scenario: one node sends message to many nodes (let's say 5 nodes). Each node after receiving message sets its timer to broadcast message to other nodes in a network basing on its distance from sender node, such that the furthest node, set shortest timer. And when a node receives message from other nodes before its timer expired, it cancels the timer. But if the timer expires and it has not received any message from other nodes it broadcast the message.
I tried followed explanation in this link
How to implement timers in Omnet++?
I have declared a timer message in the initialize() function
MyApp::Initialize(int stage)
{
RstValueEvt = new cMessage("reset value evt");
}
Then onWSM function for receiving message checks if a message is received again, I check the timer event, if it is scheduled I cancel the timer using:
MyApp::onWSM(BaseFrame1609* frame)
infoMsg* wsm = check _and_cast<infoMsg>(frame)
if(wsm.getrecipient==myId)
{
if(RstValueEvt->isScheduled())
{ cancelEvent(RstValueEvt); }
else{scheduleAt(simTime()+timer, RstValueEvt);
//creating copy of the message that I need to rebroadcast
cMessage* copyMessage = (cMessage *)infoMsg.dup;
}
}
My issue, is how to make this node broadcast the copy of message(infoMsg) to all nodes in the network when timer expires, that is how to handle this message in handleselfmsg fcn and onWSM fcn?
I suggest the following way to achieve your goal:
declare in your class a message for storing received broadcast message, e.g.
cMessage * toBroadcastMsg;
in constructor set
toBroadcastMsg = nullptr;
create an instance of selfmessage (timer):
MyApp::initialize() {
// ...
RstValueEvt = new cMessage("reset value evt");
// ... }
check whether your selfmessage (timer) expires:
MyApp::handleSelfMsg(cMessage* msg) {
// ...
if (RstValueEvt == msg && toBroadcastMsg != nullptr) {
// (2) send a message from toBroadcastMsg
// ...
toBroadcastMsg = nullptr;
}
schedule the timer after receiving a broadcast message as well as store a duplicate of received broadcast message:
MyApp::onWSM(BaseFrame1609_4* wsm) {
if(wsm.getrecipient == myId) {
if(RstValueEvt->isScheduled()) {
cancelEvent(RstValueEvt);
} else {
scheduleAt(simTime() + timer, RstValueEvt);
// (1) remember copy of the message for future use
toBroadcastMsg = wsm->dup;
}
}

How to make one node communicate with multiple nodes?

I am trying to make my nodes communicate among themselves without changing any data in the message.
Like node one and two echos tictocMsg with themselves node two and three echos the different message in this case rndMsg.
How ever this did not work with me.
simple Txc1
{
gates:
input in1;
input in2;
output out1;
output out2;
}
//
// Two instances (tic and toc) of Txc1 connected both ways.
// Tic and toc will pass messages to one another.
//
network Tictoc1
{
#display("bgb=628,433");
submodules:
tic: Txc1 {
#display("p=264,321");
}
toc: Txc1;
rnd: Txc1 {
#display("p=474,100");
}
connections allowunconnected:
toc.out1 --> tic.in1;
tic.out1 --> toc.in1;
toc.out2 --> rnd.in1;
rnd.out1 --> toc.in2;
}
I want to make toc node to send tictocMsg to tic node only and rndMsg to rnd node only
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* Derive the Txc1 class from cSimpleModule. In the Tictoc1 network,
* both the `tic' and `toc' modules are Txc1 objects, created by OMNeT++
* at the beginning of the simulation.
*/
class Txc1 : public cSimpleModule
{
protected:
// The following redefined virtual function holds the algorithm.
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
// The module class needs to be registered with OMNeT++
Define_Module(Txc1);
void Txc1::initialize()
{
// Initialize is called at the beginning of the simulation.
// To bootstrap the tic-toc-tic-toc process, one of the modules needs
// to send the first message. Let this be `tic'.
// Am I Tic or Toc?
if (strcmp("tic", getName()) == 0) {
// create and send first message on gate "out". "tictocMsg" is an
// arbitrary string which will be the name of the message object.
cMessage *msg = new cMessage("tictocMsg");
send(msg, "out1");
}
if (strcmp("rnd",getName())==0){
cMessage *msg = new cMessage("rndMsg");
send(msg, "out1");
}
}
void Txc1::handleMessage(cMessage *msg)
{
// The handleMessage() method is called whenever a message arrives
// at the module. Here, we just send it to the other module, through
// gate `out'. Because both `tic' and `toc' does the same, the message
send(msg,"out1");
// send out the message
}
I have tried to change it to
send(msg,"in1","out1") ;
send(msg,"in2","out2") ;
tried
send(msg,out1)}
else{
send(msg,out2)}
}
by far both did not work for me is there any way to make it happen?
The node in the middle (i.e. toc) has to somehow recognize received messages. For example it may check the name of the message. Let's assume that:
toc after receiving message with the name tictocMsg sends it to tic,
toc after receiving message with the name rndMsg sends it to rnd,
tic and rnd after receiving message send it to toc.
The following piece of code performs the above rules:
void Txc1::handleMessage(cMessage *msg) {
if (isName("toc")) {
if (msg->isName("tictocMsg")) {
send(msg,"out1");
} else if (msg->isName("rndMsg")) {
send(msg,"out2");
}
} else {
// other nodes just sends this message back
send(msg,"out1");
}
}

How to control packet generation rate and send interval

I am trying to create an UDP application where the packet generation rate and packet send interval can be controlled separately.
My code is in https://github.com/11187162/udpApp
With the above code, I am not getting the expected outcome and getting the following runtime error:
scheduleAt(): Message (omnetpp::cMessage)sendTimer is currently
scheduled, use cancelEvent() before rescheduling -- in module
(inet::UdpOwnApp) SensorNetworkShowcaseA.sensor3.app[0] (id=176), at
t=0.058384669093s, event #10
The code for handleMessageWhenUp() is given below.
void UdpOwnApp::handleMessageWhenUp(cMessage *msg)
{
if (msg->isSelfMessage()) {
ASSERT(msg == selfMsg);
switch (selfMsg->getKind()) {
case START:
processStart();
break;
case GENERATE:
generatePacket();
break;
case SEND:
processSend();
break;
case STOP:
processStop();
break;
default:
throw cRuntimeError("Invalid kind %d in self message", (int)selfMsg->getKind());
}
}
else
socket.processMessage(msg);
}
Would anyone please help me?
Thank you
You have written that "generation rate and packet send interval can be controlled separately" but you use the same self-message for control generation of packets as well as for sending of the packets. When a self-message is scheduled it cannot be scheduled again.
Consider adding a new self-message for generation of packets.
By the way: numGenerate is set to zero and it is never changed.
EDIT
Assuming that selfMsg1 is used for generating packets only the following code may be used:
void UdpOwnApp::handleMessageWhenUp(cMessage *msg) {
if (msg->isSelfMessage()) {
if (msg == selfMsg) {
switch (selfMsg->getKind()) {
case START:
processStart();
break;
case SEND:
processSend();
break;
case STOP:
processStop();
break;
default:
throw cRuntimeError("Invalid kind %d in self message", (int)selfMsg->getKind());
}
} else if (msg == selfMsg1) {
if (selfMsg1->getKind() == GENERATE) {
generatePacket();
}
}
}
else
socket.processMessage(msg);
}
And in initialize() you should create an instance of selfMsg1.

The external ID of wsm message sender

I am using OMNET 5.0, SUMO-0.25.0 and VEINS-4.4. When a vehicle receive a message; onData() is called. I can get external ID of the current vehicle using mobility->getExternalId(); but how I know the the external ID of wsm message sender
The code for initialize():
void TraCIDemo11p::initialize(int stage) {
BaseWaveApplLayer::initialize(stage);
if (stage == 0) {
mobility = TraCIMobilityAccess().get(getParentModule());
traci = mobility->getCommandInterface();
traciVehicle = mobility->getVehicleCommandInterface();
annotations = AnnotationManagerAccess().getIfExists();
ASSERT(annotations);
getExternalID = mobility->getExternalId();
sentMessage = false;
lastDroveAt = simTime();
findHost()->subscribe(parkingStateChangedSignal, this);
isParking = false;
sendWhileParking = par("sendWhileParking").boolValue();
}
}
The code for onData():
void TraCIDemo11p::onData(WaveShortMessage* wsm) {
std::cout << " I am "<< getExternalID <<"and I received a message from ???? "<<endl;
findHost()->getDisplayString().updateWith("r=16,green");
annotations->scheduleErase(1, annotations->drawLine(wsm->getSenderPos(), mobility->getPositionAt(simTime()), "blue"));
if (mobility->getRoadId()[0] != ':')
traciVehicle->changeRoute(wsm->getWsmData(), 9999);
if (!sentMessage)
sendMessage(wsm->getWsmData());
}
A vehicle can be represented by two identifiers, either that one gotten from SUMO (i.e., calling getExternalId()) or that one of veins (myId normally), the one used in WaveShortMessage after calling getSenderAddress() is myId so I suggest that you focus on that last one.
Take a look on these two files to get a better idea on the used identifier and the existing methods: "BaseWaveApplLayer.h/.cc" & "WaveShortMessage_m.h/.cc"
I hope this helps.

Poco c++ Websocket server connection reset by peer

I am writing a kind of chat server app where a message received from one websocket client is sent out to all other websocket clients. To do this, I keep the connected clients in a list. When a client disconnects, I need to remove it from the list (so that future "sends" do not fail).
However, sometimes when a client disconnects, the server just gets an exception "connection reset by peer", and the code does not get chance to remove from the client list. Is there a way to guarantee a "nice" notification that the connection has been reset?
My code is:
void WsRequestHandler::handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)
{
int n;
Poco::Timespan timeOut(5,0);
try
{
req.set("Connection","Upgrade"); // knock out any extra tokens firefox may send such as "keep-alive"
ws = new WebSocket(req, resp);
ws->setKeepAlive(false);
connectedSockets->push_back(this);
do
{
flags = 0;
if (!ws->poll(timeOut,Poco::Net::Socket::SELECT_READ || Poco::Net::Socket::SELECT_ERROR))
{
// cout << ".";
}
else
{
n = ws->receiveFrame(buffer, sizeof(buffer), flags);
if (n > 0)
{
if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_BINARY)
{
// process and send out to all other clients
DoReceived(ws, buffer, n);
}
}
}
}
while ((flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
// client has closed, so remove from list
for (vector<WsRequestHandler *>::iterator it = connectedSockets->begin() ; it != connectedSockets->end(); ++it)
{
if (*it == this)
{
connectedSockets->erase(it);
logger->information("Connection closed %s", ws->peerAddress().toString());
break;
}
}
delete(ws);
ws = NULL;
}
catch (WebSocketException& exc)
{
//never gets called
}
}
See receiveFrame() documentation:
Returns the number of bytes received. A return value of 0 means that the peer has shut down or closed the connection.
So if receiveFrame() call returns zero, you can act acordingly.
I do not know if this is an answer to the question, but the implementation you have done does not deal with PING frames. This is currently (as of my POCO version: 1.7.5) not done automatically by the POCO framework. I put up a question about that recently. According to the RFC (6465), the ping and pong frames are used (among others) as a keep-alive function. This may therefore be critical to get right in order to get your connection stable over time. Much of this is guess-work from my side as I am experimenting with this now myself.
#Alex, you are a main developer of POCO I believe, a comment on my answer would be much appreciated.
I extended the catch, to do some exception handling for "Connection reset by peer".
catch (Poco::Net::WebSocketException& exc)
{
// Do something
}
catch (Poco::Exception& e)
{
// This is where the "Connection reset by peer" lands
}
A bit late to the party here... but I am using Poco and Websockets as well - and properly handling disconnects was tricky.
I ended up implementing a simple ping functionality myself where the client side sends an ACK message for every WS Frame it receives. A separate thread on the server side tries to read the ACK messages - and it will now detect when the client has disconnected by looking at flags | WebSocket::FRAME_OP_CLOSE.
//Serverside - POCO. Start thread for receiving ACK packages. Needed in order to detect when websocket is closed!
thread t0([&]()->void{
while((!KillFlag && ws!= nullptr && flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE && machineConnection != nullptr){
try{
if(ws == nullptr){
return;
}
if(ws->available() > 0){
int len = ws->receiveFrame(buffer, sizeof(buffer), flags);
}
else{
Util::Sleep(10);
}
}
catch(Poco::Exception &pex){
flags = flags | WebSocket::FRAME_OP_CLOSE;
return;
}
catch(...){
//log::info(string("Unknown exception in ACK Thread drained"));
return;
}
}
log::debug("OperatorWebHandler::HttpRequestHandler() Websocket Acking thread DONE");
});
on the client side I just send a dummy "ACK" message back to the server (JS) every time I receive a WS frame from the server (POCO).
websocket.onmessage = (evt) => {
_this.receivedData = JSON.parse(evt.data);
websocket.send("ACK");
};
It is not about disconnect handling, rather about the stability of the connection.
Had some issues with POCO Websocket server in StreamSocket mode and C# client. Sometimes the client sends Pong messages with zero length payload and disconnect occurs so I added Ping and Pong handling code.
int WebSocketImpl::receiveBytes(void* buffer, int length, int)
{
char mask[4];
bool useMask;
_frameFlags = 0;
for (;;) {
int payloadLength = receiveHeader(mask, useMask);
int frameOp = _frameFlags & WebSocket::FRAME_OP_BITMASK;
if (frameOp == WebSocket::FRAME_OP_PONG || frameOp ==
WebSocket::FRAME_OP_PING) {
std::vector<char> tmp(payloadLength);
if (payloadLength != 0) {
receivePayload(tmp.data(), payloadLength, mask, useMask);
}
if (frameOp == WebSocket::FRAME_OP_PING) {
sendBytes(tmp.data(), payloadLength, WebSocket::FRAME_OP_PONG);
}
continue;
}
if (payloadLength <= 0)
return payloadLength;
if (payloadLength > length)
throw WebSocketException(Poco::format("Insufficient buffer for
payload size %d", payloadLength),
WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
return receivePayload(reinterpret_cast<char*>(buffer), payloadLength,
mask, useMask);
}
}

Resources