//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//
#include "AE.h"
Define_Module(AE);
AE::AE() :
Irm(NULL), Cdap(NULL)
{
FlowObject = NULL;
connectionState = NIL;
}
AE::~AE() {
connectionState = NIL;
FlowObject = NULL;
Irm = NULL;
Cdap = NULL;
}
void AE::initSignalsAndListeners() {
cModule* catcher1 = this->getParentModule();
cModule* catcher2 = this->getParentModule()->getParentModule()->getParentModule();
//Signals that this module is emitting
sigAEAllocReq = registerSignal(SIG_AE_AllocateRequest);
sigAEDeallocReq = registerSignal(SIG_AE_DeallocateRequest);
sigAESendData = registerSignal(SIG_AE_DataSend);
sigAEAllocResPosi = registerSignal(SIG_AERIBD_AllocateResponsePositive);
sigAEAllocResNega = registerSignal(SIG_AERIBD_AllocateResponseNegative);
sigAEConReq = registerSignal(SIG_AE_ConnectionRequest);
sigAERelReq = registerSignal(SIG_AE_ReleaseRequest);
//Signals that this module is processing
lisAERcvData = new LisAEReceiveData(this);
catcher1->subscribe(SIG_CDAP_DateReceive, lisAERcvData);
// AllocationRequest from FAI
lisAEAllReqFromFai = new LisAEAllReqFromFai(this);
catcher2->subscribe(SIG_FAI_AllocateRequest, lisAEAllReqFromFai);
// DeallocationRequest from FAI
lisAEDeallReqFromFai = new LisAEDeallReqFromFai(this);
catcher2->subscribe(SIG_FAI_DeallocateRequest, lisAEDeallReqFromFai);
lisAEDeallResFromFai = new LisAEDeallReqFromFai(this);
catcher2->subscribe(SIG_FAI_DeallocateResponse, lisAEDeallResFromFai);
lisAEAllResPosi = new LisAEAllResPosi(this);
catcher2->subscribe(SIG_FAI_AllocateResponsePositive, lisAEAllResPosi);
lisAEAllResNega = new LisAEAllResNega(this);
catcher2->subscribe(SIG_FAI_AllocateResponseNegative, lisAEAllResNega);
lisAEConResPosi = new LisAEConResPosi(this);
catcher1->subscribe(SIG_CACE_ConnectionResponsePositive, lisAEConResPosi);
lisAEConResNega = new LisAEConResNega(this);
catcher1->subscribe(SIG_CACE_ConnectionResponseNegative, lisAEConResNega);
lisAERelRes = new LisAERelRes(this);
catcher1->subscribe(SIG_CACE_ReleaseResponse, lisAERelRes);
}
void AE::initialize() {
//Init pointers
initPointers();
//Source info
initNamingInfo();
//Setup signals
initSignalsAndListeners();
//Watchers
//WATCH_LIST(flows);
WATCH(FlowObject);
WATCH(connectionState);
}
void AE::handleMessage(cMessage* msg) {
}
bool AE::createBindings(Flow& flow) {
EV << this->getFullPath() << " created bindings and registered a new flow" << endl;
//Create new gates
cGate* gIrmIn;
cGate* gIrmOut;
Irm->getOrCreateFirstUnconnectedGatePair(GATE_AEIO, false, true, *&gIrmIn, *&gIrmOut);
cModule* IrmMod = Irm->getParentModule();
cGate* gIrmModIn;
cGate* gIrmModOut;
IrmMod->getOrCreateFirstUnconnectedGatePair(GATE_NORTHIO, false, true, *&gIrmModIn, *&gIrmModOut);
cModule* ApMon = this->getParentModule()->getParentModule();
cGate* gApIn;
cGate* gApOut;
ApMon->getOrCreateFirstUnconnectedGatePair(GATE_SOUTHIO, false, true, *&gApIn, *&gApOut);
//Get AE gates
cGate* gAeIn = this->getParentModule()->gateHalf(GATE_AEIO, cGate::INPUT);
cGate* gAeOut = this->getParentModule()->gateHalf(GATE_AEIO, cGate::OUTPUT);
//CDAPParent Module gates
cGate* gCdapParentIn = Cdap->gateHalf(GATE_SOUTHIO, cGate::INPUT);
cGate* gCdapParentOut = Cdap->gateHalf(GATE_SOUTHIO, cGate::OUTPUT);
//Connect gates together
gIrmOut->connectTo(gIrmModOut);
gIrmModOut->connectTo(gApIn);
gApIn->connectTo(gAeIn);
gAeIn->connectTo(gCdapParentIn);
gCdapParentOut->connectTo(gAeOut);
gAeOut->connectTo(gApOut);
gApOut->connectTo(gIrmModIn);
gIrmModIn->connectTo(gIrmIn);
//Set north-half of the routing in ConnectionTable
Irm->setNorthGates(&flow, gIrmIn, gIrmOut);
//Return true if all dynamically created gates have same index
return gIrmIn->isConnected()
&& gAeIn->isConnected()
&& gIrmModIn->isConnected()
&& gApIn->isConnected();
}
void AE::initPointers() {
Irm = dynamic_cast<IRM*>(this->getParentModule()->getParentModule()->getParentModule()->getSubmodule(MOD_IPCRESMANAGER)->getSubmodule(MOD_IRM));
Cdap = this->getParentModule()->getSubmodule(MOD_CDAP);
if (!Irm || !Cdap)
error("Pointers to Irm or ConnectionTable or Cdap are not initialized!");
}
void AE::insertFlow() {
//Add a new flow to
//Prepare flow
Irm->newFlow(FlowObject);
//Interconnect IRM and AE
bool status = createBindings(*FlowObject);
if (!status) {
error("Gate inconsistency during creation of a new flow!");
}
}
void AE::signalizeAllocateRequest(Flow* flow) {
emit(sigAEAllocReq, flow);
}
void AE::signalizeDeallocateRequest(Flow* flow) {
emit(sigAEDeallocReq, flow);
}
void AE::receiveData(CDAPMessage* msg) {
Enter_Method("receiveData()");
//M_READ_Request
if (dynamic_cast<CDAP_M_Read*>(msg)) {
processMRead(msg);
}
//M_READ_Response
else if (dynamic_cast<CDAP_M_Read_R*>(msg)) {
processMReadR(msg);
}
delete msg;
}
void AE::receiveAllocationRequestFromFAI(Flow* flow) {
Enter_Method("receiveAllocationRequestFromFai()");
//EV << this->getFullPath() << " received AllocationRequest from FAI" << endl;
//TODO: Vesely - More sophisticated decission
if (QoSRequirements.countFeasibilityScore(flow->getQosParameters()) > 0) {
//Initialize flow within AE
FlowObject = flow;
insertFlow();
//EV << "======================" << endl << flow->info() << endl;
//Interconnect IRM and IPC
Irm->receiveAllocationResponsePositiveFromIpc(flow) ?
Irm->changeStatus(FlowObject, ConnectionTableEntry::CON_CONNECTPENDING)
:
Irm->changeStatus(FlowObject, ConnectionTableEntry::CON_ERROR);
//Change connection status
changeConStatus(CONNECTION_PENDING);
this->signalizeAllocateResponsePositive(FlowObject);
}
else {
this->signalizeAllocateResponseNegative(FlowObject);
}
}
void AE::signalizeSendData(cMessage* msg) {
EV << "Emits SendData signal for message " << msg->getName() << endl;
emit(sigAESendData, msg);
}
void AE::signalizeAllocateResponsePositive(Flow* flow) {
emit(sigAEAllocResPosi, flow);
}
void AE::receiveAllocationResponseNegative(Flow* flow) {
Enter_Method("receiveAllocationResponseNegative()");
//Change allocation status
Irm->changeStatus(flow, ConnectionTableEntry::CON_ERROR);
deleteBindings(*FlowObject);
//Change connection status
changeConStatus(NIL);
}
void AE::receiveAllocationResponsePositive(Flow* flow) {
Enter_Method("receiveAllocationResponsePositive()");
//Interconnect IRM and IPC
Irm->receiveAllocationResponsePositiveFromIpc(flow);
//Change allocation status
Irm->changeStatus(flow, ConnectionTableEntry::CON_CONNECTPENDING);
//Change connection status
changeConStatus(CONNECTION_PENDING);
}
void AE::sendAllocationRequest(Flow* flow) {
//TODO: Vesely - Substitute with signal
Irm->receiveAllocationRequestFromAe(flow);
//Change connection status
changeConStatus(FLOW_PENDING);
}
void AE::sendDeallocationRequest(Flow* flow) {
//TODO: Vesely - Substitute with signal
Irm->receiveDeallocationRequestFromAe(flow);
}
void AE::signalizeAllocateResponseNegative(Flow* flow) {
emit(sigAEAllocResNega, flow);
}
void AE::sendData(Flow* flow, CDAPMessage* msg) {
//Retrieve handle from ConTab record
int handle = Irm->getIrmGateHandle(flow);
if (handle != VAL_UNDEF_HANDLE) {
//Pass Data to CDAP
//Connection/Release or send data msg
if (dynamic_cast<CDAP_M_Connect*>(msg) != NULL &&
getConStatus() == CONNECTION_PENDING){
signalizeConnectionRequest(msg);
}
else if(dynamic_cast<CDAP_M_Release*>(msg) != NULL){
signalizeReleaseRequest(msg);
changeConStatus(RELEASING);
}
else if(getConStatus() == ESTABLISHED
//TODO: Vesely - Ugly hack to support old AE wo Establishment. Should be removed sooner or later
|| getConStatus() == CONNECTION_PENDING
){
signalizeSendData(msg);
}
}
else {
EV << "Sending data before flow is allocated!" << endl;
delete msg;
}
}
void AE::processMRead(CDAPMessage* msg) {
}
void AE::receiveDeallocationRequestFromFAI(Flow* flow) {
Enter_Method("receiveDeallocationRequestFromFai()");
bool status;
status = deleteBindings(*flow);
if (!status) {
EV << "deleteBindings() failed during DeallocateRequest processing!" << endl;
return;
}
status = Irm->deleteBindings(flow);
if (!status) {
EV << "IRM.deleteBindings() failed during DeallocateRequest processing!" << endl;
return;
}
//EV << "Statusak> " << status;
}
bool AE::deleteBindings(Flow& flow) {
EV << this->getFullPath() << " deleted bindings" << endl;
int handle1 = Irm->getIrmGateHandle(&flow);
int handle2 = Irm->getApGateHandle(&flow);
if (handle1 == VAL_UNDEF_HANDLE)
error("Delete gates before flow allocation is impossible!");
//Disconnect gates
cGate* gIrmIn = Irm->gateHalf(GATE_AEIO, cGate::INPUT, handle1);
cGate* gIrmOut = Irm->gateHalf(GATE_AEIO, cGate::OUTPUT, handle1);
cModule* IrmMod = Irm->getParentModule();
cGate* gIrmModIn = IrmMod->gateHalf(GATE_NORTHIO,cGate::INPUT, handle1);
cGate* gIrmModOut = IrmMod->gateHalf(GATE_NORTHIO,cGate::OUTPUT, handle1);
cModule* ApMon = this->getParentModule()->getParentModule();
cGate* gApIn = ApMon->gateHalf(GATE_SOUTHIO,cGate::INPUT, handle2);
cGate* gApOut = ApMon->gateHalf(GATE_SOUTHIO,cGate::OUTPUT, handle2);
//Get AE gates
cGate* gAeIn = this->getParentModule()->gateHalf(GATE_AEIO, cGate::INPUT);
cGate* gAeOut = this->getParentModule()->gateHalf(GATE_AEIO, cGate::OUTPUT);
//CDAPParent Module gates
cGate* gCdapParentIn = Cdap->gateHalf(GATE_SOUTHIO, cGate::INPUT);
cGate* gCdapParentOut = Cdap->gateHalf(GATE_SOUTHIO, cGate::OUTPUT);
//Disconnect gates
gIrmOut->disconnect();
gIrmModOut->disconnect();
gApIn->disconnect();
gAeIn->disconnect();
gCdapParentIn->disconnect();
gCdapParentOut->disconnect();
gAeOut->disconnect();
gApOut->disconnect();
gIrmModIn->disconnect();
gIrmIn->disconnect();
//Return true if all dynamically created gates are disconnected
return !gIrmIn->isConnected() && !gIrmOut->isConnected()
&& !gAeIn->isConnected() && !gAeOut->isConnected()
&& !gCdapParentIn->isConnected() && !gCdapParentOut->isConnected();
}
void AE::processMReadR(CDAPMessage* msg) {
}
void AE::signalizeConnectionRequest(CDAPMessage* msg){
emit(sigAEConReq, msg);
}
void AE::signalizeReleaseRequest(CDAPMessage* msg){
emit(sigAERelReq, msg);
}