Error: NED type 'myApp' could not be fully resolved due to a missing base type or interface? - omnet++

In my project,
I implement a new class called myApp which inherits from ApplicationBase and UdpSocket classes. When I build my project I get no error, but when I debug C/C++ application with the IDE, it displays the first error in errors section. And the command line display the second error when I run make :
Code of myApp.ned, myApp.h and myApp.cc in what follows :
I did include inet library in project references, and I tried the solution posted in The following NED types could not be fully resolved, due to a missing base type or interface.
import inet.applications.contract.IApp;
simple myApp like IApp
{
parameters:
int localPort = default(-1); // local UDP port number (-1: use ephemeral port)
int destPort; // remote UDP port number
string packetName = default("myApp");
string interfaceTableModule; // The path to the InterfaceTable module
double helloInterval #unit(s) = default(5s); // how often hello messages should be sent out
volatile double sendInterval #unit(s); // should usually be a random value, e.g. exponential(1)
double startTime #unit(s) = default(this.sendInterval); // application start time (start of the first packet)
double stopTime #unit(s) = default(-1s); // time of finishing sending, -1s means forever
double maxVariance = default(1); // This is the maximum of a random value to determine when the first hello message will be sent out
volatile double broadcastDelay #unit(s) = default(uniform(0s,0.01s));
int timeToLive = default(-1); // if not -1, set the TTL (IPv4) or Hop Limit (IPv6) field of sent packets to this value
bool dontFragment = default(false); // if true, asks IP to not fragment the message during routing
int typeOfService = default(-1); // if not -1, set the ToS (IPv4) or Traffic Class (IPv6) field of sent packets to this value
string multicastInterface = default(""); // if not empty, set the multicast output interface option on the socket (interface name expected)
bool receiveBroadcast = default(false); // if true, makes the socket receive broadcast packets
bool joinLocalMulticastGroups = default(false); // if true, makes the socket receive packets from all multicast groups set on local interfaces
#class(myApp);
gates:
input socketIn #labels(UdpControlInfo/up);
output socketOut #labels(UdpControlInfo/down);
}
#ifndef MYAPP_H_
#define MYAPP_H_
#include "inet/common/INETDefs.h"
#include "inet/applications/base/ApplicationBase.h"
#include "inet/transportlayer/contract/udp/UdpSocket.h"
#include "inet/transportlayer/contract/udp/UdpControlInfo_m.h"
#include "inet/common/ModuleAccess.h"
#include "inet/common/TimeTag_m.h"
#include "inet/common/packet/Packet.h"
#include "inet/common/lifecycle/ModuleOperations.h"
#include "inet/common/IProtocolRegistrationListener.h"
#include "inet/common/ProtocolTag_m.h"
#include "inet/linklayer/common/InterfaceTag_m.h"
#include "inet/networklayer/contract/IInterfaceTable.h"
#include "inet/networklayer/contract/ipv4/Ipv4Address.h"
#include "inet/networklayer/ipv4/IIpv4RoutingTable.h"
#include "inet/networklayer/ipv4/Ipv4Header_m.h"
#include "inet/networklayer/ipv4/Ipv4InterfaceData.h"
#include "inet/networklayer/common/FragmentationTag_m.h"
#include "inet/networklayer/common/L3AddressResolver.h"
#include "HelloMsg_m.h"
#include "XedMsg_m.h"
#include <omnetpp.h>
#include <vector>
#include <random>
#include <algorithm>
using namespace omnetpp;
using namespace inet;
using namespace std;
class myApp : public ApplicationBase, public UdpSocket::ICallback
{
protected:
//enum SelfMsgKinds { START = 1, SEND, STOP };
int localPort = -1, destPort = -1;
bool dontFragment = false;
const char *packetName = nullptr;
simtime_t startTime;
simtime_t stopTime;
// state
UdpSocket socket;
cMessage *selfMsg = nullptr;
cModule *host = nullptr;
cMessage *event = nullptr;
cPar *broadcastDelay = nullptr;
unsigned int sequencenumber = 0;
simtime_t helloInterval;
IInterfaceTable *ift = nullptr;
InterfaceEntry *interface80211ptr = nullptr;
int interfaceId = -1;
list<L3Address> neighbors;
Ipv4Address source;
/********** XED **********/
class XED
{
public:
L3Address originatorAddr, destinationAddr;
unsigned int random;
XED(const L3Address& originatorAddr, const L3Address& destinationAddr, unsigned int random)
: originatorAddr(originatorAddr), destinationAddr(destinationAddr), random(random) {};
bool operator==(const XED& other) const
{
return this->originatorAddr == other.originatorAddr && this->destinationAddr == other.destinationAddr
&& this->random == other.random;
}
};
list<XED> lr,ls;
/********** MTLSD **********/
class MTLSD
{
public:
L3Address originatorAddr, destinationAddr;
char *position;
simtime_t time;
MTLSD(const L3Address& originatorAddr, const L3Address& destinationAddr, char *position, simtime_t time)
: originatorAddr(originatorAddr), destinationAddr(destinationAddr), position(position), time(time) {};
bool operator==(const MTLSD& other) const
{
return this->originatorAddr == other.originatorAddr && this->destinationAddr == other.destinationAddr
&& this->position == other.position && this->time == time;
}
};
protected:
virtual int numInitStages() const override { return NUM_INIT_STAGES; }
virtual void initialize(int stage) override;
virtual void handleMessageWhenUp(cMessage *msg) override;
void handleSelfMessage(cMessage *msg);
/*virtual void processStart();
virtual void processSend();
virtual void processStop();*/
// lifecycle
virtual void handleStartOperation(LifecycleOperation *operation) override { start(); }
virtual void handleStopOperation(LifecycleOperation *operation) override { stop(); }
virtual void handleCrashOperation(LifecycleOperation *operation) override { stop(); }
void start();
void stop();
virtual void socketDataArrived(UdpSocket *socket, Packet *packet) override;
virtual void socketErrorArrived(UdpSocket *socket, Indication *indication) override;
virtual void socketClosed(UdpSocket *socket) override;
//virtual void generateMTLSDPacket();
//virtual Packet *generateXEDPacket();
virtual double generateRandom();
public:
myApp() {}
~myApp();
};
#endif /* MYAPP_H_ */
#include "myApp.h"
#include "inet/applications/base/ApplicationPacket_m.h"
#include "inet/applications/udpapp/UdpBasicApp.h"
#include "inet/common/TagBase_m.h"
#include "inet/networklayer/common/L3AddressTag_m.h"
#include <iterator>
using namespace std;
Define_Module(myApp);
myApp::~myApp()
{
EV << "App destructor" << endl;
cancelAndDelete(selfMsg);
}
void myApp::initialize(int stage)
{
ApplicationBase::initialize(stage);
if (stage == INITSTAGE_LOCAL)
{
sequencenumber = 0;
ift = getModuleFromPar<IInterfaceTable>(par("interfaceTableModule"), this);
event = new cMessage("event");
broadcastDelay = &par("broadcastDelay");
helloInterval = par("helloInterval");
localPort = par("localPort");
destPort = par("destPort");
packetName = par("packetName");
startTime = par("startTime");
stopTime = par("stopTime");
}
else if (stage == INITSTAGE_ROUTING_PROTOCOLS)
{
registerService(Protocol::manet, nullptr, gate("socketIn"));
registerProtocol(Protocol::manet, gate("socketOut"), nullptr);
}
}
void myApp::handleSelfMessage(cMessage *msg)
{
if (msg == event)
{
auto hello = makeShared<HelloMsg>();
Ipv4Address source = (interface80211ptr->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
hello->setChunkLength(b(128));
hello->setSrcAddress(source);
sequencenumber += 2;
hello->setSequencenumber(sequencenumber);
hello->setNextAddress(source);
hello->setHopdistance(1);
auto packet = new Packet("Hello", hello);
packet->addTagIfAbsent<L3AddressReq>()->setDestAddress(Ipv4Address(255, 255, 255, 255));
packet->addTagIfAbsent<L3AddressReq>()->setSrcAddress(source);
packet->addTagIfAbsent<InterfaceReq>()->setInterfaceId(interface80211ptr->getInterfaceId());
packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::manet);
packet->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(&Protocol::ipv4);
send(packet, "socketOut");
packet = nullptr;
hello = nullptr;
scheduleAt(simTime()+helloInterval+broadcastDelay->doubleValue(), event);
}
}
void myApp::handleMessageWhenUp(cMessage *msg)
{
if (msg->isSelfMessage())
{
handleSelfMessage(msg);
}
else if (check_and_cast<Packet *>(msg)->getTag<PacketProtocolTag>()->getProtocol() == &Protocol::manet)
{
auto recHello = staticPtrCast<HelloMsg>(check_and_cast<Packet *>(msg)->peekData<HelloMsg>()->dupShared());
if (msg->arrivedOn("socketIn"))
{
bubble("Received hello message");
Ipv4Address source = interface80211ptr->getProtocolData<Ipv4InterfaceData>()->getIPAddress();
Ipv4Address src;
unsigned int msgsequencenumber;
int numHops;
Ipv4Address next;
src = recHello->getSrcAddress();
msgsequencenumber = recHello->getSequencenumber();
next = recHello->getNextAddress();
numHops = recHello->getHopdistance();
if (src == source)
{
EV_INFO << "Hello msg dropped. This message returned to the original creator.\n";
delete msg;
return;
}
else
{
neighbors.push_back(src);
/*list<XED>::iterator findIter = find(ls.begin()->destinationAddr, ls.end()->destinationAddr, src);
if (findIter != ls.end()->destinationAddr)
{
}*/
source = (interface80211ptr->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
//socket.bind(source, localPort);
auto xed = makeShared<XedMsg>();
xed->setChunkLength(b(128)); ///size of XED message in bits
xed->setSrcAddress(source);
xed->setDstAddress(src);
double random = generateRandom();
xed->setRandom(random);
//XED item = XED(source, src, random);
//ls.push_back(item);
auto packet = new Packet("XED", xed);
packet->addTagIfAbsent<L3AddressReq>()->setDestAddress(src);
packet->addTagIfAbsent<L3AddressReq>()->setSrcAddress(source);
packet->addTagIfAbsent<InterfaceReq>()->setInterfaceId(interfaceId);
packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::ipv4);
packet->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(&Protocol::ipv4);
socket.setOutputGate(gate("socketOut"));
socket.setCallback(this);
socket.bind(source, localPort);
//emit(packetSentSignal, packet);
socket.sendTo(packet, src, destPort);
//send(packet, "socketOut");
packet = nullptr;
xed = nullptr;
/*Ipv4Address source = (interface80211ptr->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
EV << "I am node " << source << ", my neighbors are : " << endl;
list<L3Address>::iterator it;
for (it = neighbors.begin(); it != neighbors.end(); ++it)
{
EV << it. << endl;
}
for (auto const& i : neighbors)
{
EV << i.str() << endl;
}*/
EV << "I am your neighbor " << src.str();
}
delete msg;
}
else if (check_and_cast<Packet *>(msg)->getTag<PacketProtocolTag>()->getProtocol() == &Protocol::ipv4)
{
EV << "Xed message received" << endl;
//auto recXed = staticPtrCast<XedMsg>(check_and_cast<Packet *>(msg)->peekData<XedMsg>()->dupShared());
}
else
throw cRuntimeError("Message arrived on unknown gate %s", msg->getArrivalGate()->getName());
}
}
void myApp::start()
{
/*socket.setOutputGate(gate("socketOut"));
socket.setCallback(this);*/
int num_80211 = 0;
InterfaceEntry *ie;
InterfaceEntry *i_face;
const char *name;
for (int i = 0; i < ift->getNumInterfaces(); i++)
{
ie = ift->getInterface(i);
name = ie->getInterfaceName();
if (strstr(name, "wlan") != nullptr)
{
i_face = ie;
num_80211++;
interfaceId = i;
}
}
if (num_80211 == 1)
{
interface80211ptr = i_face;
interfaceId = interface80211ptr->getInterfaceId();
}
else
throw cRuntimeError("Node has found %i 80211 interfaces", num_80211);
scheduleAt(simTime() + uniform(0.0, par("maxVariance").doubleValue()), event);
}
double myApp::generateRandom()
{
double lower_bound = 10000;
double upper_bound = 100000;
uniform_real_distribution<double> unif(lower_bound,upper_bound);
default_random_engine re;
double a_random_double = unif(re);
return a_random_double;
}
void myApp::stop()
{
cancelEvent(event);
socket.close();
delayActiveOperationFinish(par("stopOperationTimeout"));
}
void myApp::socketDataArrived(UdpSocket *socket, Packet *packet)
{
emit(packetReceivedSignal, packet);
EV_INFO << "Received packet: " << UdpSocket::getReceivedPacketInfo(packet) << endl;
}
void myApp::socketErrorArrived(UdpSocket *socket, Indication *indication)
{
EV_WARN << "Ignoring UDP error report " << indication->getName() << endl;
delete indication;
}
void myApp::socketClosed(UdpSocket *socket)
{
if (operationalState == State::STOPPING_OPERATION)
startActiveOperationExtraTimeOrFinish(par("stopOperationExtraTime"));
}
Error: NED type 'myApp' could not be fully resolved due to a missing base type or interface, at /home/bocuhra/Downloads/omnetpp-5.4.1/samples/SaaS/myApp.ned:18
myApp.cc
HelloMsg_m.cc
XedMsg_m.cc
Creating executable: out/gcc-release//SaaS
/usr/bin/ld: cannot find -lINET
collect2: error: ld returned 1 exit status
Makefile:104: recipe for target 'out/gcc-release//SaaS' failed
make: *** [out/gcc-release//SaaS] Error 1

I did solve the problem by adding all ned files in my .ini file.
ned-path = .;../inet/src/inet

Related

Omnet++ Unknown Parameter in Module Error

I'm making a randomly generated network where the node will send an update massage after asking if the other node already know the update. Currently the update status is still predefined. I'm getting this error message when running the simulation:
"(omnetpp::cModule)Simplegossip1: Unknown parameter 'updated' -- in module (Sg1) Simplegossip1.node[0] (id=2), at t=0s, event #1"
Here's my code:
simplegossip1.ned (I'm using code from here How to create a randomly connected graph in OMNeT++?)
simple Sg1
{
parameters:
#display("i=block/routing");
bool updated;
gates:
input in[]; // declare in[] and out[] to be vector gates
output out[];
}
network Simplegossip1
{
parameters:
int count;
double connectedness; // 0.0<x<1.0
submodules:
node[count]: Sg1 {
gates:
in[]; // removed the size of gate
out[];
}
connections allowunconnected:
for i=0..count-2, for j=i+1..count-1, if uniform(0,1)<connectedness {
node[i].out++ --> node[j].in++;
node[i].in++ <-- node[j].out++;
}
}
sg1.cc
#include <stdio.h>
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
/**
* First attempt for gossip protocol
*/
class Sg1 : public cSimpleModule
{
public:
cMessage *askupdated = new cMessage("Ask Update");
cMessage *updated = new cMessage("Updated");
cMessage *unupdated = new cMessage("Unupdated");
cMessage *update = new cMessage("Here is the update");
protected:
virtual void forwardMessage(cMessage *msg, int dest);
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
Define_Module(Sg1);
void Sg1::initialize()
{
if (getIndex() == 0) {
// Boot the process scheduling the initial message as a self-message.
char msgname[20];
sprintf(msgname, "tic-%d", getIndex());
cMessage *msg = new cMessage(msgname);
scheduleAt(0.0, msg);
}
}
void Sg1::handleMessage(cMessage *msg)
{
int n = gateSize("out");
int k = intuniform(0, n-1);
int sid = msg->getArrivalGateId();
bool updatestatus = getParentModule()->par("updated");
if (msg == askupdated) {
if (updatestatus == true){
forwardMessage(updated,sid);
}
else {
forwardMessage(unupdated,sid);
}
}
else if (msg == unupdated) {
forwardMessage(update,sid);
}
else {
forwardMessage(askupdated,k);
}
}
void Sg1::forwardMessage(cMessage *msg, int dest)
{
// In this example, we just pick a random gate to send it on.
// We draw a random number between 0 and the size of gate `out[]'.
EV << "Forwarding message " << msg << " on port out[" << dest << "]\n";
send(msg, "out", dest);
}
And an omnet.ini file that only calling the Simplegossip1 network.
How do I solve this? Thanks in advance.
You have to change the line
bool updatestatus = getParentModule()->par("updated");
into
bool updatestatus = par("updated");
because updated is the parameter of Sg1 not of the parent of Sg1.

How to record results in omnet++

I try to record the values of electricityConsumption. For that I build the NED file like this:
simple EConsumerRSF
{
parameters:
volatile xml ElectricityConsumptionRSFLoadProfile;
volatile double sendIaTime #unit(s);
#signal[electricityConsumption](type="double");
#statistics[electricityConsumption](title="Electricity Consumption RSF Unit 1";source="electricityConsumption"; record=vector,stats; interpolationmode=none);
gates:
output outElectricityConsumptionRSF;
}
My c++ class and header file looks like this:
#ifndef __VISIONSIMULATIONOFPED_ECONSUMERRSF_H_
#define __VISIONSIMULATIONOFPED_ECONSUMERRSF_H_
#include <omnetpp.h>
#include <stdio.h>
#include <string.h>
//#include "EConsumptionRSFMessage_m.h"
using namespace omnetpp;
namespace network {
/**
* Network EConsumerRSF; see NED file for more info.
*/
//class EConsumerRSF : public EConsumptionRSFMessage
class EConsumerRSF : public cSimpleModule
{
public:
EConsumerRSF();
virtual ~EConsumerRSF();
protected:
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
// virtual void setValEConsumption(double valEConsumption);
private:
int counterSend = 1;
int counterMessage = 1;
double valEConsumption1;
double valEConsumption2;
double valEConsumption3;
double valEConsumption4;
simsignal_t electricityConsumptionSingnalId;
//double electricityConsumption;
double valEConsumption;
double aggregationOfElectricityConsumptionRSF = 0;
cMessage *endTxEvent;
cMessage *EConsumptionRSFMessage;
};
}; //namespace
#endif
#include "EConsumerRSF.h"
#include <stdio.h>
#include <string.h>
//#include "EConsumptionRSFMessage_m.h"
using namespace omnetpp;
namespace network {
Define_Module(EConsumerRSF);
EConsumerRSF::EConsumerRSF()
{
endTxEvent = nullptr;
}
EConsumerRSF::~EConsumerRSF()
{
cancelAndDelete(endTxEvent);
}
void EConsumerRSF::initialize()
{
electricityConsumptionSingnalId = registerSignal("electricityConsumption");
//Get param XMLElectricity file from simple module
cXMLElement *rootelementEConsumption = par("ElectricityConsumptionRSFLoadProfile");
cXMLElementList paramsEConsumption = rootelementEConsumption->getChildrenByTagName("param");
//Loop to iterate through all elements called param
for (const auto & element : paramsEConsumption) {
const char* valueEConsumption = element->getNodeValue();
valEConsumption = atof(valueEConsumption);
EV << "Read value: " << valEConsumption << std::endl;
if (valEConsumption > 0.0) {
//Calculation of electricity supply through utility
aggregationOfElectricityConsumptionRSF = aggregationOfElectricityConsumptionRSF + valEConsumption;
}
switch(counterMessage)
{
case 1:
valEConsumption1 = valEConsumption;
counterMessage++;
break;
case 2:
valEConsumption2 = valEConsumption;
counterMessage++;
break;
case 3:
valEConsumption3 = valEConsumption;
counterMessage++;
break;
case 4:
valEConsumption4 = valEConsumption;
counterMessage++;
break;
}
}
EConsumptionRSFMessage = new cMessage("valEConsumption");
endTxEvent = new cMessage("send/endTx");
scheduleAt(simTime(), endTxEvent);
}
void EConsumerRSF::handleMessage(cMessage *msg)
{
// Check if self message is received
if(endTxEvent->isSelfMessage()){
if(counterSend <= 4){
switch(counterSend)
{
case 1:
if(valEConsumption1 > 0.0){
double electricityConsumption = valEConsumption1;
emit(electricityConsumptionSingnalId, electricityConsumption);
send(EConsumptionRSFMessage->dup(), "outElectricityConsumptionRSF");
}else{
double electricityConsumption = 0.0000000;
emit(electricityConsumptionSingnalId, electricityConsumption);
}
counterSend++;
scheduleAt(simTime()+par("sendIaTime").doubleValue(), endTxEvent);
break;
case 2:
if(valEConsumption2 > 0.0){
double electricityConsumption = valEConsumption2;
emit(electricityConsumptionSingnalId, electricityConsumption);
send(EConsumptionRSFMessage->dup(), "outElectricityConsumptionRSF");
}else{
double electricityConsumption = 0.0000000;
emit(electricityConsumptionSingnalId, electricityConsumption);
}
counterSend++;
scheduleAt(simTime()+par("sendIaTime").doubleValue(), endTxEvent);
break;
case 3:
if(valEConsumption3 > 0.0){
double electricityConsumption = valEConsumption3;
emit(electricityConsumptionSingnalId, electricityConsumption);
send(EConsumptionRSFMessage->dup(), "outElectricityConsumptionRSF");
}else{
double electricityConsumption = 0.0000000;
emit(electricityConsumptionSingnalId, electricityConsumption);
}
counterSend++;
scheduleAt(simTime()+par("sendIaTime").doubleValue(), endTxEvent);
break;
case 4:
if(valEConsumption4 > 0.0){
double electricityConsumption = valEConsumption4;
emit(electricityConsumptionSingnalId, electricityConsumption);
send(EConsumptionRSFMessage->dup(), "outElectricityConsumptionRSF");
}else{
double electricityConsumption = 0.0000000;
emit(electricityConsumptionSingnalId, electricityConsumption);
}
counterSend++;
//cancelEvent(endTxEvent);
scheduleAt(simTime()+par("sendIaTime").doubleValue(), endTxEvent);
break;
default:
cancelEvent(endTxEvent);
break;
}
}else {
throw cRuntimeError("self-message not delivered");
cancelEvent(endTxEvent);
}
}
}
}; //namespace
and I enabled the recording in the .ini file like this:
[Config EConsumerRSF]
**.serviceTime = 1s
**.electricityConsumption.result-recording-modes = -vector
It does not even build the .vec file when I run the simulation. What am I doing wrong? Is it not possible to record results in handleMessage()? Or do I miss something?
Could please someone help me with this issue?
Thanks in advance!
There are two mistakes in the presented code:
In NED should be #statistic (instead of #statistics).
Actually in omnetpp.ini in the line:
**.electricityConsumption.result-recording-modes = -vector
you have turned off recording of vectors (a minus sign means disabling). To turn on recording of vector change it to +vector or simply remove this line.

handleMessage(): Unknown protocol: id = 47, name = udp -- in module (inet::MessageDispatcher) during network initialization

I am trying to broadcast a packet in order to discover neighborhood, when I run the simulation I got this erro :
handleMessage(): Unknown protocol: id = 47, name = udp -- in module (inet::MessageDispatcher) SaaS.host[0].at (id=77), during network initialization
My code:
#ifndef MYAPP_H_
#define MYAPP_H_
#include "inet/common/INETDefs.h"
#include "inet/transportlayer/contract/udp/UdpSocket.h"
#include <omnetpp.h>
using namespace omnetpp;
using namespace inet;
class myApp : public cSimpleModule, public UdpSocket::ICallback
{
protected:
int localPort = -1, destPort = -1;
bool dontFragment = false;
const char *packetName = nullptr;
UdpSocket socket;
cMessage *selfMsg = nullptr;
protected:
void initialize() override;
void socketDataArrived(UdpSocket *socket, Packet *packet) override;
void socketErrorArrived(UdpSocket *socket, Indication *indication) override;
void socketClosed(UdpSocket *socket) override;
public:
myApp() {}
~myApp();
};
#endif /* MYAPP_H_ */
#include "myApp.h"
#include "inet/applications/base/ApplicationPacket_m.h"
#include "inet/applications/udpapp/UdpBasicApp.h"
#include "inet/common/ModuleAccess.h"
#include "inet/common/TagBase_m.h"
#include "inet/common/TimeTag_m.h"
#include "inet/common/lifecycle/ModuleOperations.h"
#include "inet/common/packet/Packet.h"
#include "inet/networklayer/common/FragmentationTag_m.h"
#include "inet/networklayer/common/L3AddressResolver.h"
#include "inet/transportlayer/contract/udp/UdpControlInfo_m.h"
Define_Module(myApp);
myApp::~myApp()
{
EV << "App destructor" << endl;
cancelAndDelete(selfMsg);
}
void myApp::initialize()
{
localPort = par("localPort");
destPort = par("destPort");
packetName = par("packetName");
socket.setOutputGate(gate("socketOut"));
socket.bind(localPort);
socket.setBroadcast(true);
socket.setCallback(this);
std::ostringstream str;
str << getId();
Packet *packet = new Packet(str.str().c_str());
if(dontFragment)
packet->addTagIfAbsent<FragmentationReq>()->setDontFragment(true);
const auto& payload = makeShared<ApplicationPacket>();
payload->setChunkLength(B(par("messageLength")));
payload->addTag<CreationTimeTag>()->setCreationTime(simTime());
packet->insertAtBack(payload);
L3Address address;
L3AddressResolver().tryResolve("255.255.255.255", address);
emit(packetSentSignal, packet);
socket.sendTo(packet, address, destPort);
}
void myApp::socketDataArrived(UdpSocket *socket, Packet *packet)
{
EV << "Data Arrived " << endl;
}
void myApp::socketErrorArrived(UdpSocket *socket, Indication *indication)
{
EV << "Error Arrived" << endl;
}
void myApp::socketClosed(UdpSocket *socket)
{
EV << "Close socket" << endl;
}
I don't know how to do this, I need to discover neighbors and then to send a different packet to each of them.

boost asio io_context.run() segmentation error

I am trying to make simple server that remembers and operates some variables with receive short instructions.
I didn't complete this server, and I am trying to test connecting to the server.
But when I try to connect the server, it occurs segmentation fault.
It seems that be occured at io_context.run() function.
I don't know exact cause of this error in spite of reading asio's reference page.
Please help me..
I think that you don't have to read code of data(data.hpp).
This is server code.
//server.cpp
#include <iostream>
#include "network/sc_network.hpp"
int main(int argc, char *argv[])
{
try
{
if(argc != 2)
{
std::cerr << "Usage: server <port>\n";
return 1;
}
boost::asio::io_context io_context;
tcp::endpoint endpoint(tcp::v4(), std::atoi(argv[1]));
server server(io_context, endpoint);
io_context.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
This is client code.
//client.cpp
#include <iostream>
#include <thread>
#include <cstdlib>
#include <boost/asio.hpp>
#include "network/data/data.hpp"
using boost::asio::ip::tcp;
class client{
private:
boost::asio::io_context& io_context_;
tcp::socket socket_;
oper_data *data_;
void do_connect(const tcp::resolver::results_type& endpoints)
{
boost::asio::async_connect(socket_, endpoints,
[this](boost::system::error_code ec, tcp::endpoint)
{
if(!ec)
{
boost::asio::async_read(socket_,
boost::asio::buffer(data_, sizeof(oper_data)),
[this](boost::system::error_code ec, std::size_t)
{
if(!ec)
{
boost::asio::async_write(socket_,
boost::asio::buffer(data_,sizeof(oper_data)),
[this](boost::system::error_code ec, std::size_t)
{
});
}
else
{
socket_.close();
}
});
}
else
{
socket_.close();
}
});
}
public:
client(boost::asio::io_context& io_context,
const tcp::resolver::results_type& endpoints)
: io_context_(io_context),
socket_(io_context)
{
do_connect(endpoints);
}
void write(const oper_data& data)
{
boost::asio::post(io_context_,
[this, data]()
{
});
}
};
int main(int argc, char *argv[])
{
try
{
if(argc != 3)
{
std::cerr << "Usage: client <host> <port>\n";
return 1;
}
boost::asio::io_context io_context;
tcp::resolver resolver(io_context);
auto endpoints = resolver.resolve(argv[1], argv[2]);
client c(io_context, endpoints);
std::thread t([&io_context](){ io_context.run(); });
char line[128];
while (std::cin.getline(line, 128))
{
oper_data data;
//processing the line with deviding in 3 words.
}
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
this is sc_network.hpp
//sc_network.hpp
#include <boost/asio.hpp>
#include <memory>
#include <utility>
#include "data/data.hpp"
using boost::asio::ip::tcp;
class session
: public std::enable_shared_from_this<session>
{
private:
tcp::socket socket_;
data_proc data_proc_;
public:
session(tcp::socket socket)
: socket_(std::move(socket)){}
void start()
{
oper_data *input_data;
boost::asio::async_read(socket_,
boost::asio::buffer(input_data, sizeof(oper_data)),
[this, input_data](boost::system::error_code ec, std::size_t)
{
if(!ec)
{
data_proc_.set_data(*input_data);
data_proc_.oper_process();
start();
}
else
{
return;
}
});
}
};
class server
{
private:
tcp::acceptor acceptor_;
void do_accept()
{
acceptor_.async_accept(
[this](boost::system::error_code ec, tcp::socket socket)
{
if(!ec)
{
session ex_session(std::move(socket));
}
do_accept();
});
}
public:
server(boost::asio::io_context& io_context,
const tcp::endpoint& endpoint)
: acceptor_(io_context, endpoint)
{
do_accept();
}
};
this is data.hpp.
//data.hpp
#include <deque>
#include <cstring>
#include "favdew_utility.hpp"
#define max_oper_size 5
#define max_oper_buf max_oper_size + 1
struct oper_data {
char oper_[max_oper_buf] = "\0";
char *operand_;
char *oper_num_;
};
typedef struct oper_data oper_data;
class data_store {
private:
char *var_name_;
char *var_value_;
public:
data_store()
: var_name_(NULL), var_value_(NULL) {}
data_store(const char *var_name, const char *var_value)
{
std::size_t var_name_size = strlen(var_name) + 1;
var_name_ = new char[var_name_size];
strncpy(var_name_, var_name, strlen(var_name));
std::size_t var_value_size = strlen(var_value) + 1;
var_value_ = new char[var_value_size];
strncpy(var_value_, var_value, strlen(var_value));
}
char *var_name() { return var_name_; }
char *var_value() { return var_value_; }
void set_value(const char *var_value) {
var_value_ = new char[strlen(var_value) + 1];
strncpy(var_value_, var_value, strlen(var_value));
}
};
typedef std::deque<data_store> data_queue;
class data_proc {
private:
oper_data data_;
data_queue proc_queue;
void var()
{
if (data_store *var = this->get_var(data_.operand_)) {
var->set_value(data_.oper_num_);
}
else {
data_store input_data(data_.operand_, data_.oper_num_);
this->proc_queue.push_back(input_data);
}
}
bool sum()
{
data_store *var = this->get_var(data_.operand_);
if ( (var) && isNumber(var->var_value()))
{
const int input_data = std::atoi(var->var_value()) +
std::atoi(this->data_.oper_num_);
var->set_value(std::to_string(input_data).c_str());
return true;
}
else
return false;
}
bool dif()
{
data_store *var = this->get_var(data_.operand_);
if ((var) && isNumber(var->var_value()))
{
const int input_data = std::atoi(var->var_value()) -
std::atoi(this->data_.oper_num_);
var->set_value(std::to_string(input_data).c_str());
return true;
}
else
return false;
}
public:
data_proc()
{
oper_data input_data;
//<input_data.oper_> is already initialized with "\0"
std::memset(input_data.operand_, 0, sizeof(char *));
std::memset(input_data.oper_num_, 0, sizeof(char *));
}
data_proc(const char *oper, const char *operand, const char *oper_num)
{
strncpy(data_.oper_, oper, max_oper_size);
std::size_t operand_size = strlen(operand) + 1;
data_.operand_ = new char[operand_size];
strncpy(data_.operand_, operand, strlen(operand));
std::size_t oper_num_size = strlen(oper_num) + 1;
data_.oper_num_ = new char[oper_num_size];
strncpy(data_.oper_num_, oper_num, strlen(oper_num));
}
inline void set_data(oper_data data)
{
this->data_ = data;
}
void set_data(const char *oper, const char *operand, const char *oper_num)
{
strncpy(data_.oper_, oper, max_oper_size);
std::size_t operand_size = strlen(operand) + 1;
data_.operand_ = new char[operand_size];
strncpy(data_.operand_, operand, strlen(operand));
std::size_t oper_num_size = strlen(oper_num) + 1;
data_.oper_num_ = new char[oper_num_size];
strncpy(data_.oper_num_, oper_num, strlen(oper_num));
}
data_store *get_var(const char *var_name)
{
const std::size_t queue_size = this->proc_queue.size();
for (std::size_t i=0; i < queue_size; i++) {
if (!strcmp(this->proc_queue[i].var_name(), var_name)) {
return &proc_queue[i];
}
}
return NULL;
}
bool oper_process()
{
const char *oper = this->data_.oper_;
if (!strcmp(oper, "var")) {
var();
return true;
}
else if (!strcmp(oper, "sum")) {
sum();
return true;
}
else if (!strcmp(oper, "dif")) {
dif();
return true;
}
else {
return false;
}
}
};
this is favdew_utility.hpp
#include <string>
#include <cstdlib>
bool isNumber(const char *str)
{
std::size_t length = strlen(str);
for (std::size_t i = 0; i < length; i++)
{
if (!('0' < str[i] && str[i] < '9'))
return false;
continue;
}
return true;
}
bool isEmpty(void *buffer)
{
if (!buffer || *(char *)buffer == '\0')
return true;
else
return false;
}
There are many issues, just pointing out a few:
The declaration
session ex_session(std::move(socket));
This creates a local (stack) variable that inherits from enable_shared_from_this. Using shared_from_this will be Undefined Behaviour
Session gets immediately destructed and start() appears to be never called
If session::start() were called, it would fail because it starts an async operation without guarding the lifetime of the session instance:
boost::asio::async_read(socket_,
boost::asio::buffer(input_data, sizeof(oper_data)),
[this, input_data](boost::system::error_code ec, std::size_t) { ....
At the very least you need to capture the shared pointer to the session:
auto self = shared_from_this();
boost::asio::async_read(socket_,
boost::asio::buffer(input_data, sizeof(oper_data)),
[this, self, input_data](boost::system::error_code ec, std::size_t)
Even worse, input_data is never initialized. Again: Undefined Behaviour. Even if you did initialize it, you'd have to manage lifetime; why not make it a member of the session, instead of dynamically allocating (or forgetting to, as you have now)?
Caution: No, you cannot stack-allocate inside start() not even if you capture it in the lambda, because the async operations will not complete before start() exits.
Same in client: data_ is never initialized. Boom.
Even if you had it correctly allocated, using it as an asio::buffer() treats it as a POD.
Since, however, data_proc happily aggregates a data_queue which is std::deque<> it obviously IS NOT POD. More Undefined Behaviour.
What you probably need is to serialize your datastructures, instead of hoping that copying some bytes of memory is going to magically "work". It won't!
See e.g. sending/receiving a struct in boost::asio
Note While you're at is, use C++ instead of C? All the raw pointers and char* are complexity that you don't need, and it is handing your dozens of footguns or ends or rope that you're gonna hurt yourself more with.
In client.cpp you have:
std::thread t([&io_context](){ io_context.run(); });
char line[128];
while (std::cin.getline(line, 128))
{
oper_data data;
//processing the line with deviding in 3 words.
}
Soooo many things...
use std::getline, not std::istream::getline
the thread needs to be joined (https://en.cppreference.com/w/cpp/thread/thread/~thread)
if all you do is block for input, why have the thread?
io_context.run(); // replaces all of the above
data_store is also not POD, but it is also a living memory-leak. All the new-ed memory is never freed.
Note that, the way it's written, the struct might APPEAR to be POD, but logically it isn't (Rule Of Three). Basically, you wrote it in C, not C++. This foregoes all abstractions that C++ has, and now the compiler cannot tell that the struct refers to non-owned resources.
Mind you, this gives me the impression that oper_data might have similar issues (though at first I assumed that operand_ and _oper_num are supposed to point inside the fixed-size buffer oper_[])
Summarizing:
You're way ahead of yourself. Start much simpler. Use C++ (std::string, never use new/delete, actually use std::make_shared if you want to enable_shared_from_this).
You'll be much happier. Feel free to come back with simpler questions when you get stuck, ideally the SSCCE would be a (few) dozen or so lines.

Boost asio socket multicast to a specific ethernet interface

I thought I had found the answer in the following example, but not quite.
boost::asio::ip::udp::socket socket(io_service);
...
boost::asio::ip::address_v4 local_interface =
boost::asio::ip::address_v4::from_string("1.2.3.4");
boost::asio::ip::multicast::outbound_interface option(local_interface);
socket.set_option(option);
How do I map eth0 to the appropriate outbound_interface option?
The following code works fine on Windows and Mac OS X:
const ip::udp::resolver::query queryIF( ip::udp::v4(),
_description->getInterface(), "0" );
const ip::udp::resolver::iterator interfaceIP =
resolver.resolve( queryIF );
if( interfaceIP == end )
return false;
const ip::address ifAddr( ip::udp::endpoint( *interfaceIP ).address( ));
_read->set_option( ip::multicast::join_group( mcAddr.to_v4(),
ifAddr.to_v4( )));
_write->set_option( ip::multicast::outbound_interface( ifAddr.to_v4()));
EDIT: I had some issues on Linux, but did not look into it yet. My guess is the socket option is ignored in favor of the routing table.
I think the reason why your example and eile's example don't work is because you didn't set the SO_BINDTODEVICE socket option.
See this to know why it doesn't work: http://codingrelic.geekhold.com/2009/10/code-snippet-sobindtodevice.html
See this to know how to do it with boost::asio: http://permalink.gmane.org/gmane.comp.lib.boost.asio.user/2724
/**************************************************************************//**
\brief
\details
*******************************************************************************/
class UDPClient : public BoostSocketClient
{
public:
UDPClient ();
virtual ~UDPClient();
virtual ARLErrorCode_e open(int port_num, const char* network_type="ipv4", const char* ip_address="", uint32_t listen_interface=0);
virtual ARLErrorCode_e send(u8* message, u32 size);
virtual ARLErrorCode_e close();
virtual bool isOpen();
//virtual void onReceived(u8*, u32);
private:
void startReceive();
void handleReceive(const boost::system::error_code&, std::size_t);
void handleSend(const boost::system::error_code& error, std::size_t bytes_transferred);
private:
boost::asio::io_service send_ios_;
std::unique_ptr<boost::asio::io_service::work> send_worker_;
boost::asio::io_service receive_ios_;
std::unique_ptr<boost::asio::io_service::work> receive_worker_;
boost::thread send_thread_;
boost::thread receive_thread_;
boost::array<u8, 1024> _buffer;
boost::asio::ip::udp::endpoint send_endpoint_;
boost::asio::ip::udp::endpoint sender_endpoint_;
boost::asio::ip::udp::endpoint listen_endpoint_;
std::unique_ptr<boost::asio::ip::udp::socket> send_udp_socket_;
std::unique_ptr<boost::asio::ip::udp::socket> receive_udp_socket_;
};
#include <ACCompLib/Include/Typedefs.h>
#include <ACCompLib/Include/ARLErrorCodes.h>
#include <NetLib/Platform/Boost/cpp/UDPClient.h>
#include "Ws2tcpip.h"
#include "Iphlpapi.h"
using namespace std;
using namespace boost;
using namespace asio;
using namespace ip;
using namespace NetLib;
/***************************************************************************//**
\brief Constructor
\details
*******************************************************************************/
UDPClient::UDPClient()
{
receive_worker_.reset(new boost::asio::io_service::work(receive_ios_));
}
/***************************************************************************//**
\brief ctor
\details
*******************************************************************************/
UDPClient::~UDPClient()
{
try
{
receive_worker_.reset();
//send_worker_.reset();
if (send_thread_.joinable()) {
send_thread_.join();
}
if (receive_thread_.joinable()) {
receive_thread_.join();
}
}
catch (std::exception& e)
{
std::string str = e.what();
}
}
/***************************************************************************//**
\brief
\details
\note
\param[in]
*******************************************************************************/
ARLErrorCode_e UDPClient::open(int port_num, const char* network_type, const char* multicastAddress, uint32_t listen_interface)
{
try
{
struct in_addr in;
in.S_un.S_addr = listen_interface;
char* address_listen = inet_ntoa(in);
//const char* address_listen = "0.0.0.0";
std::string address_mcast = multicastAddress;
unsigned short address_port = port_num;
boost::system::error_code ec;
boost::asio::ip::address listen_addr = boost::asio::ip::address::from_string(address_listen, ec);
boost::asio::ip::address mcast_addr = boost::asio::ip::address::from_string(address_mcast, ec);
if (strcmp(network_type, "ipv4") == 0)
{
listen_endpoint_ = udp::endpoint(listen_addr, port_num);
send_endpoint_ = udp::endpoint(mcast_addr, port_num);
}
else if (strcmp(network_type, "ipv6") == 0)
{
}
else
return ES35_INVALID_SOCKET_CONNECTION;
send_udp_socket_.reset(new boost::asio::ip::udp::socket(send_ios_));
receive_udp_socket_.reset(new boost::asio::ip::udp::socket(receive_ios_));
send_udp_socket_->open(boost::asio::ip::udp::v4());
receive_udp_socket_->open(listen_endpoint_.protocol());
send_udp_socket_->set_option(boost::asio::ip::udp::socket::reuse_address(true));
receive_udp_socket_->set_option(boost::asio::ip::udp::socket::reuse_address(true));
boost::asio::ip::address_v4 local_interface =
boost::asio::ip::address_v4::from_string(address_listen);
boost::asio::ip::multicast::outbound_interface option(local_interface);
// Join the multicast group.
receive_udp_socket_->set_option(
boost::asio::ip::multicast::join_group(mcast_addr));
send_udp_socket_->set_option(option);
receive_udp_socket_->set_option(option);
boost::asio::ip::multicast::hops hops_option(3);
//send_udp_socket_->set_option(hops_option);
receive_udp_socket_->set_option(hops_option);
receive_udp_socket_->bind(listen_endpoint_);
startReceive();
receive_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &receive_ios_));
send_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &send_ios_));
return ES_NoError;
}
catch (std::exception& exp)
{
std::string str = exp.what();
return ES35_INVALID_SOCKET_CONNECTION;
}
}
/***************************************************************************//**
\brief
\details
*******************************************************************************/
ARLErrorCode_e UDPClient::close(void)
{
try {
boost::system::error_code ec;
//udp_socket_->cancel();
//udp_socket_.shutdown(socket_base::shutdown_both, ec);
if (ec)
{
return ES35_INVALID_SOCKET_CONNECTION;
}
if (send_udp_socket_->is_open())
{
send_udp_socket_->close();
}
if (receive_udp_socket_->is_open())
{
receive_udp_socket_->close();
}
receive_udp_socket_.reset();
send_udp_socket_.reset();
}
catch (std::exception& e)
{
std::string str = e.what();
return ES35_INVALID_SOCKET_CONNECTION;
}
return ES_NoError;
}
/***************************************************************************//**
\brief
\details
*******************************************************************************/
bool UDPClient::isOpen()
{
return send_udp_socket_->is_open() && receive_udp_socket_->is_open();
}
/***************************************************************************//**
\brief Send a message.
\details The message is sent asynchronously.
\param message
\param message size
*******************************************************************************/
ARLErrorCode_e UDPClient::send(u8* message, u32 size)
{
if (!isOpen()) {
return ES35_INVALID_SOCKET_CONNECTION;
}
std::string send_to_address = send_endpoint_.address().to_string();
send_udp_socket_->set_option(asio::ip::multicast::enable_loopback(false));
send_udp_socket_->async_send_to(
buffer(message, size),
send_endpoint_,
bind(
&UDPClient::handleSend,
this,
asio::placeholders::error,
asio::placeholders::bytes_transferred));
return ES_NoError;
}
/***************************************************************************//**
\brief Do nothing.
\details This function has the required signature to be used as an
asynchronous send completion handler.
\param not used
\param not used
*******************************************************************************/
void UDPClient::handleSend(const system::error_code& error, size_t)
{
if (error)
{
BoostSocketClient::onError(ES35_UDP_SEND_ERROR, (u8*)error.message().c_str(), error.message().size());
}
else
{
send_udp_socket_->set_option(asio::ip::multicast::enable_loopback(true));
}
}
/***************************************************************************//**
\brief Start an asynchronous receiver.
*******************************************************************************/
void NetLib::UDPClient::startReceive()
{
receive_udp_socket_->async_receive_from(
buffer(_buffer),
sender_endpoint_,
bind(
&UDPClient::handleReceive,
this,
asio::placeholders::error,
asio::placeholders::bytes_transferred));
std::string sender_address = sender_endpoint_.address().to_string();
}
/***************************************************************************//**
\brief Pass received data to the base class.
\details A new receiver is started.
\param error code
\param data size
*******************************************************************************/
void NetLib::UDPClient::handleReceive(const system::error_code& error, size_t size)
{
if (!error || error == error::message_size)
{
BoostSocketClient::onReceived(_buffer.data(), size);
startReceive();
}
else
{
BoostSocketClient::onError(ES35_UDP_RECEIVE_ERROR, (u8*)error.message().c_str(), error.message().size());
}
}
This code is not receiving response.please check
http://permalink.gmane.org/gmane.comp.lib.boost.asio.user/2724 is invalid.
The following code seems to be invalid:
boost::asio::ip::address_v4 local_interface =
boost::asio::ip::address_v4::from_string(ip);
boost::asio::ip::multicast::outbound_interface option(local_interface);
sock.set_option(option);

Resources