Files
scandocs/uni/masterarbeit/source/moversight/Moversight.cc
2014-06-30 13:58:10 +02:00

767 lines
25 KiB
C++

/*
* File: Moversight.cc
* Author: jgaebler
*
* Created on September 20, 2010, 1:30 PM
*/
#include "Moversight.h"
#include "Dispatcher.h"
#include "common/transport/MoversightMessageTypes.h"
#include "common/transport/TransportAddress.h"
#include "common/transport/msg/ExteriorMessage.h"
#include "common/validator/MessageValidator.h"
#include "ms/Peer.h"
#include "ms/msg/MSMessageFactory.h"
#include "mt/timer/MTTimer.h"
#include "mt/msg/MulticastMessage.h"
#include "fd/NetworkFailureDetectorType.h"
#if OMNETPP
#include "app/Application.h"
#include "app/ApplicationLevelMulticastTestApplication.h"
#include "app/MergeApplication.h"
#include "app/PeerplacingApplication.h"
#include "app/SplitApplication.h"
#include "app/TestApplication.h"
#include "app/PartitionApplication.h"
#include "app/PendingTestApplication.h"
#include "app/MaintanceApplication.h"
//omnet address related stuff
#include "IPvXAddressResolver.h"
#include "UDPControlInfo.h"
#include "InterfaceEntry.h"
#include "IInterfaceTable.h"
#include "IPvXAddress.h"
#include "IPv4InterfaceData.h"
#include "mobility/models/MovingMobilityBase.h"
#include "mobility/models/StationaryMobility.h"
#endif
namespace ubeeme {
namespace moversight {
#if OMNETPP
#define simulationTriggerTimeout 10
/**
* @brief Declares Moversight as omnetpp module.
*/
Define_Module(Moversight);
#else
Moversight::Moversight(MoversightCallback & callBack) : UDPNodeEventReceiver(0, false), infoObject(NULL), dispatcher(*this, callBack) {
#if 0
bool printDebugDIS;
bool printDebugNFD;
bool printDebugMT;
bool printDebugMS;
bool printDebugTC;
bool printDebugST;
bool printDebugCT;
bool printDebugAPP;
bool enableNFD;
bool enableMobilitySupport = default(true);
bool enableNetworkFailureDetector = default(true);
bool enableStreamTransfer = default(true);
#endif
setNFDEnabled(false);
initialize(0);
}
Moversight::~Moversight() {
}//End
#endif
/**
* @brief Returns the local address.
* @return The local address.
*/
TransportAddress &
Moversight::getLocalAddress() {
#if UBEEME
bool success = false;
if (infoObject.isNull()) {
success = initNetworkInfos();
}
if (success) {
PhysicalNetworkInterface::AddressEntryList addressList = infoObject->addressList;
PhysicalNetworkInterface::AddressEntryList::iterator it = addressList.begin();
if (it != addressList.end()) {
if (it->ip().protocol() == QAbstractSocket::IPv4Protocol) {
MOV_DEBUG << "Local: " << it->ip().toString();
localTA = TransportAddress(it->ip(), infoObject->boundPort);
}
}//End if
}
else {
localTA = TransportAddress();
}
#endif
return localTA;
}
#if OMNETPP
/**
* @brief Sets the local transport address of the current host
*/
void
Moversight::setLocalAddress() {
cModule *mod = getParentModule(); // get the MoversightPeer
IInterfaceTable* ift = IPvXAddressResolver().findInterfaceTableOf(mod);
//set the local address
if (ift && ift->getNumInterfaces() > 1) { //interface index 0 == loopback
InterfaceEntry *ie = ift->getInterface(1);
localTA = TransportAddress(ie->ipv4Data()->getIPAddress());
}
else {
localTA = TransportAddress();
}
//set the port
localTA.setPort(int(par("localPort")));
}
#endif
/**
* @brief Initialize the Moversight instance
*/
void
Moversight::initialize(int stage) {
#if OMNETPP
if (stage != 3) return;
setLocalAddress();
app = NULL;
visu = NULL;
dispatcher = NULL;
simulationTrigger = NULL;
//set Socket
socket.setOutputGate(gate("udpOut"));
socket.bind(localTA.getPort());
//read the simulation parameter and setup the module
peerPlacingStrategyType = PeerPlacingStrategyType(int (par("peerPlacingStrategy")));
peerPlacingStrategyMetricType = PeerPlacingStrategyMetricType(int (par("peerPlacingStrategyMetric")));
maintanceMomentMetricType = MaintanceMomentMetricType((int) (par("maintanceMomentMetricType")));
failureDetectorType = NetworkFailureDetectorType(int (par("failureDetectorType")));
peerResourcesValue = PeerResources(PeerResources::ResourceValue(par("peerResourceValue")));
//read max cluster
maxClusterCount = int(par("maxClusterCount"));
maxPeerCount = int(par("maxPeerCount"));
// // wireless Nodes register in category we want to listen with
// if (getParentModule()->getSubmodule("wlan", 0)) {
// notificationBoard = dynamic_cast<NotificationBoard *> (getParentModule()->getSubmodule("notificationBoard"));
// if (!notificationBoard)
// std::cerr << "Could not find NotificationBoard module with name 'notificationBoard' " << getParentModule() << endl;
// else {
// //categories we are interested in
// notificationBoard->subscribe(this, NF_L2_ASSOCIATED_NEWAP);
// notificationBoard->subscribe(this, NF_L2_BEACON_LOST);
// }
// }
app = NULL;
//load the proper test app
switch (int(par("testApp"))) {
case SPLIT_TEST_APPLICATION:
app = new SplitApplication(*this);
break;
case NFD_TEST_APPLICATION:
throw ParameterException("initialize - set up NFD_TEST_APPLICATION not implemented yet");
break;
case PEER_PLACING_TEST_APPLICATION:
app = new PeerplacingApplication(*this);
break;
case TEST_APPLICATION:
app = new TestApplication(*this);
break;
case MERGE_TEST_APPLICATION:
app = new MergeApplication(*this);
break;
case ALM_TEST_APPLICATION:
app = new ApplicationLevelMulticastTestApplication(*this);
break;
case PARTITION_APPLICATION:
app = new PartitionApplication(*this);
break;
case PENDING_TEST_APPLICATION:
app = new PendingTestApplication(*this);
break;
case MAINTANCE_APPLICATION:
app = new MaintanceApplication(*this);
break;
default:
throw ParameterException("initialize - no valid value for parameter \"application\" specified");
break;
}//end switch
enableRecordStats = par("recordStat").boolValue();
if(enableRecordStats){
numMessagesReceived = 0;
numMessagesSent = 0;;
}//end if
setNFDEnabled(par("enableNFD").boolValue());
//initialize print debug parameter
setPrintDebugAPP(par("printDebugAPP").boolValue());
setPrintDebugDIS(par("printDebugDIS").boolValue());
setPrintDebugNFD(par("printDebugNFD").boolValue());
setPrintDebugMT(par("printDebugMT").boolValue());
setPrintDebugMS(par("printDebugMS").boolValue());
setPrintDebugTC(par("printDebugTC").boolValue());
setPrintDebugST(par("printDebugST").boolValue());
setPrintDebugCT(par("printDebugCT").boolValue());
setPrintDebugUT(par("printDebugUT").boolValue());
setPrintDebugMOB(par("printDebugMOB").boolValue());
setPrintDebugVISU(par("printDebugVISU").boolValue());
setPrintDebugES(par("printDebugES").boolValue());
setPrintDebugUC(par("printDebugUC").boolValue());
setPrintDebugAC(par("printDebugAC").boolValue());
//start moversight
dispatcher = new Dispatcher(*this, *app);
//initialize the test application
app->setDispatcher(dispatcher);
app->initialise();
dispatcher->initialise();
simulationTrigger = new cMessage("simulationTrigger");
if (par("simulationTrigger").boolValue()) {
scheduleAt(simTime() + simulationTriggerTimeout, simulationTrigger);
}//End if
//start the visualization
visu = new MoversightSimulationPeerStateVisualization(*dispatcher);
visu->initialise();
updateSimUI();
#else
stage = stage;
//set up the peerplacing stuff
peerPlacingStrategyType = BALANCED_PEER_PLACING;
peerPlacingStrategyMetricType = OUCMETRIC_CLUSTERSIZE;
maintanceMomentMetricType = RESOURCEVALUEMOMENTMETRIC;
failureDetectorType = BERTIER_DETECTOR;
maxClusterCount = 12;
maxPeerCount = 6;
// setLocalAddress();
dispatcher.initialise();
#endif
}//End initialize
/**
* @brief Finish method. Is called during shutdown of moversight.
*/
void
Moversight::finish() {
#if OMNETPP
if(enableRecordStats){
recordScalar("messages_sent:count", numMessagesSent);
recordScalar("messages_received:count", numMessagesReceived);
}//End if
if (app != NULL) {
app->finalise();
delete app;
app = NULL;
}//End if
if (visu != NULL) {
delete visu;
visu = NULL;
}//End if
if (dispatcher != NULL) {
delete dispatcher;
dispatcher = NULL;
}//End if
if (simulationTrigger != NULL) {
cancelAndDelete(simulationTrigger);
simulationTrigger = NULL;
}//end if
#endif
}
#if OMNETPP
/**
* @brief Handles received messages (from the socket) and timers.
* @param msg The received message to handle.
*/
void
Moversight::handleMessage(cMessage *msg) {
// timer handling
if (msg->isSelfMessage()) {
cancelEvent(msg);
if (msg == simulationTrigger) {
handleSimulationTriggerTimer();
}//End if
else if (dynamic_cast<MoversightTimer *> (msg)) {
MoversightTimer* timer = dynamic_cast<MoversightTimer*> (msg);
timer->fire();
dispatcher->getEventService().process();
}//End else if
}//End if
// not a timer
else {
if(enableRecordStats) numMessagesReceived++;
MoversightMessage * mMsg = dynamic_cast<MoversightMessage *> (msg);
if (mMsg != NULL) {
GenericTime arrivalTime = GenericTime::currentTime();
mMsg->setArrivalTime(arrivalTime);
dispatcher->handleMessage(mMsg);
delete msg;
msg = NULL;
}
else {
MOV_DEBUG << "ERROR: handleMessage - unknown message type - drop message";
}
}//End else
}
/**
* @brief test code method
*/
void
Moversight::handleSimulationTriggerTimer() {
if (app != NULL) {
app->startTestCase(int(par("testCase")));
}
}
/**
* @brief This method updates the presentation of a peer within the omnett++ visualization. In particular, the
* icon of the peer is change depending on the role of the peer (master or slave).
*/
void
Moversight::updateSimUI() {
if (visu != NULL) {
visu->updateSimUI();
}
}
/**
* @brief Displays a message bubble at the omnet sim ui.
* @param msg
*/
void
Moversight::bubble(const char* msg) {
getParentModule()->bubble(msg);
}
/**
* @brief Schedules the simulation trigger timer.
* @param time The duration to the determined schedule.
*/
void
Moversight::scheduleTestCase(simtime_t time) {
cancelEvent(simulationTrigger);
scheduleAt((simTime() + time), simulationTrigger);
}
/**
* @brief receive notifications from notificationBoard
* @param category to identifiy the matter of changed Notification
*/
void
Moversight::receiveChangeNotification(int category, const cPolymorphic *details) {
switch (category) {
case NF_L2_ASSOCIATED_NEWAP:
std::cerr << dispatcher->getLocalPeer().getPeerID() << " Connection to an AP established " << endl;
//connectionEstablished();
break;
case NF_L2_BEACON_LOST:
std::cerr << dispatcher->getLocalPeer().getPeerID() << " Connection to an AP lost" << endl;
// dispatcher.signalConnectionLost();
break;
}
}
#endif
/**
* @brief Returns the user selected peer placing strategy type.
* @see PeerPlacingStrategy.h
* @return The selected strategy type.
*/
const PeerPlacingStrategyType &
Moversight::getPeerPlacingStrategyType() const {
return peerPlacingStrategyType;
}
const PeerPlacingStrategyMetricType &
Moversight::getPeerPlacingStrategyMetricType() const {
return peerPlacingStrategyMetricType;
}
const MaintanceMomentMetricType &
Moversight::getMaintanceMomentMetricType() const {
return maintanceMomentMetricType;
}
const PeerResources &
Moversight::getPeerResources() const {
return peerResourcesValue;
}
/**
* @brief Returns the user selected failure detector type.
* @see FailureDetectorType.h
* @return The selected failure detector type.
*/
const NetworkFailureDetectorType &
Moversight::getFailureDetectorType() const {
return failureDetectorType;
}
/**
* @brief Returns the maximal number of clusters
* @return number of clusters
*/
size_t
Moversight::getMaxClusterCount() {
return maxClusterCount;
}
/**
* @brief Returns the maximal number of peers in one cluster
* @return number of peers
*/
size_t
Moversight::getMaxPeerCount() {
return maxPeerCount;
}
/**
* @brief Sends a omnet message to a peer, identified by its transport address
* @param msg The message to send
* @param toPeerTA The destination address
*/
void
Moversight::sendToPeer( const MoversightMessage& msg, const TransportAddress & toPeerTA) {
#if OMNETPP
if(enableRecordStats) numMessagesSent++;
sendToUDP(msg, toPeerTA);
}
#else
void
Moversight::sendToPeer(MoversightMessage & msg, const TransportAddress & toPeerTA) {
delegateSend(msg, toPeerTA);
}
#endif
#if OMNETPP
/**
* @brief Sending the Message via UDP to the given TransportAddress
* @param packet The Message to send
* @param destAddr The destination transport address of the message
*/
void
Moversight::sendToUDP( const MoversightMessage& packet, const TransportAddress& destAddr) {
cPacket* msg = (cPacket *) packet.dup(); //without -> no local deletion of send message
// send message to UDP, with the appropriate control info attached
msg->setKind(UDP_C_DATA);
msg->setByteLength(sizeof packet);
socket.sendTo(msg, destAddr.getHostAddress(), destAddr.getPort());
}
#endif
/**
* @brief Assignment operator.
* @param other The instance to assign.
* @return A reference of the current object.
*/
Moversight & Moversight::operator =(Moversight const & other) {
if (this == &other) {
return *this;
}
BaseMoversight::operator=(other);
dispatcher = other.dispatcher;
#if OMNETPP
simulationTrigger = other.simulationTrigger;
app = other.app;
numMessagesReceived = other.numMessagesReceived;
numMessagesSent = other.numMessagesSent;
maxClusterCount = other.maxClusterCount;
maxPeerCount = other.maxPeerCount;
enableRecordStats = other.enableRecordStats;
socket = other.socket;
#endif
peerPlacingStrategyType = other.peerPlacingStrategyType;
peerPlacingStrategyMetricType = other.peerPlacingStrategyMetricType;
maintanceMomentMetricType = other.maintanceMomentMetricType;
failureDetectorType = other.failureDetectorType;
return *this;
}//End
#if UBEEME
/**
* @brief Delegates the data to the receiver
* @param buffer ByteArray of data
* @param from PeerID from the sender
*/
void
Moversight::delegateReceive(ByteArray const &buffer, PeerID const &from) {
DatagramInput<PeerID>::delegateReceive(buffer, from);
}
/**
* @brief Chains the given DatagramInput to this DatagramOutput. So it can be used for delegating.
* @param input Input to chain.
*/
void
Moversight::chainDown(DatagramInput<TransportAddress> *input) {
DatagramOutput<TransportAddress>::chainDown(input);
if (!initNetworkInfos()) {
MOV_DEBUG << "Cannot init network informations.";
}
dispatcher.initialise();
}
/**
* @brief Unchains the given input from this DatagramOutput.
* @param input Input to unchain.
*/
void
Moversight::unchainDown(DatagramInput<TransportAddress> *input) {
DatagramOutput<TransportAddress>::unchainDown(input);
infoObject.clear();
disconnectReceiver();
}
bool
Moversight::initNetworkInfos() {
DatagramInput<TransportAddress> *input = 0;
if (!inputList.empty()) {
input = inputList.front();
}
if (input && infoObject.isNull()) {
typedef std::list<QSharedPointer<UDPInfoObject> > UDPInfoObjectList;
UDPInfoObjectList objectList;
UDPInfoObjectList::iterator it;
UDPEndpoint *currentUDPEndpoint = 0;
InformationBroker::getInstance()->getInformationObjectList(objectList);
for (it = objectList.begin(); it != objectList.end(); ++it) {
currentUDPEndpoint = (*it)->getOwner();
if (input == currentUDPEndpoint || input->hasInputNodeInChain(currentUDPEndpoint)) {
infoObject = *it;
connectReceiver(currentUDPEndpoint);
connectAll();
return true;
}
}
}
return false;
}
/**
* @brief
* @param e The EventContainer
*/
void
Moversight::stateChanged(EventContainer e) {
UDPStateChangedEvent *changed = e.decapsulate<UDPStateChangedEvent > ();
if (changed) {
if (changed->getUDPState() == ubeeme::UDPEndpoint::UNCONNECTED_STATE) {
MOV_DEBUG << "UDP unconnected, delete information object.";
infoObject.clear();
disconnectReceiver();
initNetworkInfos();
}
dispatcher.initialise();
}
}
/**
* @brief Method checks whether the given DatagramInput is situated under the chain.
* Therefor bool NetworkOutput::hasNodeInChain(NETWORK_INPUT const *input) const is called.
* In case it's a DatagramOutput
*
* @param input searched DatagramInput
* @return if the DatagramInput searched for is below us
*/
bool
Moversight::hasInputNodeInChain(DatagramInput<PeerID> const * /*input*/) const {
return false;
}//End
/**
* @brief This is the callback, that gets called when the down linked node received data and forwards those to us.
* @param buffer all the received data
* @param from - sender of the data
* @param fromInput - reference to the linked node, from whom we got the data (can be ignored in most cases)
*/
void
Moversight::handleReceive(ByteArray const &buffer, TransportAddress const &from, DatagramInput<TransportAddress> const * /*fromInput*/) {
SharedPointer<NetworkMessage> received = factory.NetworkMessageFactory::createMessage(buffer, from);
if (!received.isNull()) {
dispatcher.handleMessage((MoversightMessage *) received.data());
}
}
/**
* @brief this is the callback, that gets called when the up linked node wants to send data to us
* @param buffer - the data to be send
* @param to - the receiver of the data
* @param fromOutput - reference to the linked node that wants to send the data to us (can be ignored in most cases)
* @return - true on successfull sending, otherwise false.
*/
bool
Moversight::handleSend(ByteArray const &buffer, PeerID const &/*to = 0*/, DatagramOutput<PeerID> const * /*fromOutput = 0 */) {
GroupData data; //("DT");
data.setData(buffer);
dispatcher.sendMessage(data);
return true;
}
/**
* @brief Invite a peer to the group
* @param destTa The transportAddress of the peer to invite
* @param pDesc the peerDescription
*/
void
Moversight::invitePeer(TransportAddress & destTa, PeerDescription & pDesc) {
dispatcher.invitePeer(destTa, pDesc);
}//End
/**
* @brief Cancel the invitation
* @param ta The transportAddress to send the cancellation
* @param reason Why the invitation is turned down
*/
void
Moversight::cancelInvitation(TransportAddress & ta, std::string reason) {
dispatcher.cancelInvitation(ta, reason);
}
/**
* @brief Accept the Invitation
* @param inv The invitation to accept
* @param comment A comment
* @param pDesc PeerDescription
*/
void
Moversight::acceptInvitation(Invitation & inv, std::string comment, PeerDescription & pDesc) {
dispatcher.acceptInvitation(inv, comment, pDesc);
}//End
/**
* @brief Reject the invitation
* @param inv The invitation to be rejected
* @param reason Why it's rejected
*/
void
Moversight::rejectInvitation(Invitation & inv, std::string reason) {
dispatcher.rejectInvitation(inv, reason);
}
/**
* @brief Leave the group
*/
void
Moversight::leaveGroup() {
dispatcher.leaveGroup();
}//End
/**
* @brief Start a split
* @param options The split options
* @param size The number of the splitting peers
* @param splitPeers PeerIDList of the splitting peers
*/
void
Moversight::splitGroup(unsigned char options, PeerIDList splitPeers) {
dispatcher.splitGroup(options, splitPeers);
}
/**
* @brief Start a group Merge
* @param destTa The other Mergedirector
*/
void
Moversight::mergeGroup(TransportAddress & destTa) {
dispatcher.mergeGroup(destTa);
}//End
/**
* @brief Accept the merge request
*/
void
Moversight::acceptGroupMerge() {
dispatcher.acceptGroupMerge();
}
/**
* @brief Reject the merge request
* @param reason Why it's rejected
*/
void
Moversight::rejectGroupMerge(std::string & reason) {
dispatcher.rejectGroupMerge(reason);
}
#endif
}
}