提交 30842480 编写于 作者: C calincerchez

finished diameter base protocol

上级 fd7fc027
......@@ -50,7 +50,7 @@ void DiameterBase::handleMessage(cMessage *msg) {
DiameterPeer *peer = (DiameterPeer*)msg->getContextPointer();
peer->processTimer(msg);
} else { // handles SCTP messages
DiameterConnection *conn = conns.findConnectionFor(msg);
DiameterConnection *conn = conns.findConnection(msg);
if (!conn) {
// new connection -- create new socket object and server process
SCTPSocket *socket = new SCTPSocket(msg);
......@@ -58,7 +58,7 @@ void DiameterBase::handleMessage(cMessage *msg) {
conn = new DiameterConnection(this);
conn->setType(RESPONDER);
conn->setSocket(socket);
conns.addConnection(conn);
conns.insert(conn);
socket->setCallbackObject(conn);
socket->setOutboundStreams(outboundStreams);
......@@ -194,7 +194,7 @@ DiameterConnection *DiameterBase::createConnection(AddressVector addresses, int
conn->setAddresses(addresses);
conn->setPort(port);
conn->setType(INITIATOR);
conns.addConnection(conn);
conns.insert(conn);
return conn;
}
......
......@@ -124,7 +124,6 @@ public:
*/
DiameterConnection *createConnection(AddressVector addresses, int port);
DiameterPeer *createPeer(std::string dFQDN, std::string dRealm, DiameterConnection *conn, DiameterApplication *appl = NULL);
DiameterConnection *removeConnection(DiameterConnection *conn) { return conns.removeConnection(conn); }
DiameterSession *createSession(bool stType);
unsigned genSessionId() { return ++sessionIds; }
......@@ -133,6 +132,8 @@ public:
*/
DiameterPeer *findPeer(std::string dFQDN, std::string dRealm = "") { return peers.findPeer(dFQDN, dRealm); }
DiameterPeer *findPeer(unsigned applId) { return peers.findPeer(applId); }
void removeConnection(DiameterConnection *conn) { conns.erase(conn); }
};
#endif /* DIAMETERBASE_H_ */
......@@ -51,19 +51,24 @@ void DiameterConnection::socketDataArrived(int32 connId, void *yourPtr, cPacket
unsigned resCode = processOrigin(newPeer, dmsg);
if (peer == NULL) {
// enters only when the connection has no owner
if ((hdr.getCommandCode() == CapabilitiesExchange) && (hdr.getReqFlag() == true)) {
PeerEvent event = R_CONN_CER;
if (resCode == DIAMETER_MISSING_AVP) {
/* TODO */
} else {
if ((newPeer->getState() == R_OPEN)
|| (newPeer->getState() == I_OPEN)
|| (newPeer->getState() == WAIT_RETURNS)
|| (newPeer->getState() == WAIT_CONN_ACK_ELECT)) {
// if a peer with the same address info was found and it is one
// of this states reject the connection
shutdown();
newPeer->performStateTransition(event, dmsg);
return;
}
// new peer and if available old peer becomes the owner of this
// connection, election process will follow if necessary
newPeer->rConn = this;
this->setPeer(newPeer);
newPeer->performStateTransition(event, dmsg);
......@@ -144,6 +149,7 @@ void DiameterConnection::socketPeerClosed(int32 connId, void *yourPtr) {
EV << "Peer socket closed (Assoc Id = " << socket->getConnectionId() << ")\n";
if (peer != NULL) {
PeerEvent event;
// removes the connection from the peer
if (type == INITIATOR) {
event = I_PEER_DISC;
peer->iConn = NULL;
......@@ -151,27 +157,36 @@ void DiameterConnection::socketPeerClosed(int32 connId, void *yourPtr) {
event = R_PEER_DISC;
peer->rConn = NULL;
}
if (peer->getState() != CLOSED)
if (peer->getState() != CLOSED) {
// peer will be deleted during the state transition
peer->performStateTransition(event, NULL);
}
// removes the owner
peer = NULL;
}
// removes the connection
module->removeConnection(this);
}
void DiameterConnection::socketClosed(int32 connId, void *yourPtr) {
EV << "Socket closed (Assoc Id = " << socket->getConnectionId() << ")\n";
if (!ignore) {
// ignore is used because socketClosed is called twice
if (peer != NULL) {
PeerEvent event;
if ((peer->getState() == WAIT_CONN_ACK) || (peer->getState() == WAIT_CONN_ACK_ELECT))
event = I_RCV_CONN_NACK;
else
event = type == INITIATOR ? I_PEER_DISC : R_PEER_DISC;
if ((type == peer->getConnectionType()) && (peer->getState() != CLOSED))
if ((type == peer->getConnectionType()) && (peer->getState() != CLOSED)) {
// peer will be removed during state transition
peer->performStateTransition(event, NULL);
}
// removes the owner
peer = NULL;
}
module->removeConnection(this); // connection cleanup
// connection cleanup
module->removeConnection(this);
}
ignore = false;
}
......@@ -202,6 +217,16 @@ void DiameterConnection::connect() {
socket->connectx(addresses, port, 0);
}
void DiameterConnection::shutdown() {
EV << "Shutting down Assoc Id = " << socket->getConnectionId() << endl;
socket->shutdown();
}
void DiameterConnection::close() {
EV << "Closing Assoc Id = " << socket->getConnectionId() << endl;
socket->close();
}
unsigned DiameterConnection::processOrigin(DiameterPeer *&peer, DiameterMessage *msg) {
AVP *fqdn = msg->findAvp(AVP_OriginHost);
AVP *realm = msg->findAvp(AVP_OriginRealm);
......@@ -214,9 +239,11 @@ unsigned DiameterConnection::processOrigin(DiameterPeer *&peer, DiameterMessage
//module->printPeerList();
if ((peer = module->findPeer(dFQDN, dRealm)) != NULL) {
// enters if the peers are already open and the connection has owner
return DIAMETER_PEER_FOUND;
}
if (this->peer == NULL) {// only add another peer if this connection has no peer
if (this->peer == NULL) {
// only add another peer if this connection has no peer
type = RESPONDER;
peer = module->createPeer(dFQDN, dRealm, this);
}
......@@ -232,42 +259,35 @@ DiameterConnectionMap::~DiameterConnectionMap() {
// TODO Auto-generated destructor stub
}
DiameterConnection *DiameterConnectionMap::findConnectionFor(cMessage *msg) {
DiameterConnection *DiameterConnectionMap::findConnection(cMessage *msg) {
SCTPCommand *ind = dynamic_cast<SCTPCommand *>(msg->getControlInfo());
if (!ind)
opp_error("DiameterConnectionMap: findConnectionFor(): no SCTPCommand control info in message (not from SCTP?)");
opp_error("DiameterConnectionMap: findConnection(): no SCTPCommand control info in message (not from SCTP?)");
int assocId = ind->getAssocId();
ConnMap::iterator i = connMap.find(assocId);
ASSERT(i == connMap.end() || i->first == i->second->getConnectionId());
return (i == connMap.end()) ? NULL : i->second;
DiameterConnections::iterator i = conns.find(assocId);
ASSERT(i == conns.end() || i->first == i->second->getConnectionId());
return (i == conns.end()) ? NULL : i->second;
}
void DiameterConnectionMap::addConnection(DiameterConnection *conn) {
ASSERT(connMap.find(conn->getConnectionId()) == connMap.end());
connMap[conn->getConnectionId()] = conn;
void DiameterConnectionMap::insert(DiameterConnection *conn) {
ASSERT(conns.find(conn->getConnectionId()) == conns.end());
conns[conn->getConnectionId()] = conn;
}
DiameterConnection *DiameterConnectionMap::removeConnection(DiameterConnection *conn) {
ConnMap::iterator i = connMap.find(conn->getConnectionId());
if (i != connMap.end())
connMap.erase(i);
printConnectionMap();
return conn;
void DiameterConnectionMap::erase(DiameterConnection *conn) {
int connId = conn->getConnectionId();
ASSERT(conns.find(connId) != conns.end());
delete conns[connId];
conns.erase(connId);
}
/*
void DiameterConnectionMap::deleteConnections()
{
for (ConnMap::iterator i = connMap.begin(); i != connMap.end(); ++i)
delete i->second;
}
*/
void DiameterConnectionMap::printConnectionMap() {
void DiameterConnectionMap::print() {
EV << "=====================================================================\n"
<< "Connection Map:\n"
<< "-------------------------------------------------------------------------------\n"
<< "Conn Id\t| Local Addr\t| Local Port\t| Remote Addr\t| Remote Port\n"
<< "---------------------------------------------------------------------\n";
for (ConnMap::iterator i = connMap.begin(); i != connMap.end(); ++i)
for (DiameterConnections::iterator i = conns.begin(); i != conns.end(); ++i)
EV << (i->second)->getConnectionId() << endl;// << "\t| " << (i->second)->getLocalAddresses().at(0) << "\t| " << "" << "\t| " << "" << "\t| " << "" << endl;
EV << "=====================================================================\n";
}
......
......@@ -30,7 +30,8 @@ class DiameterPeer;
class DiameterBase;
/*
* Class for Diameter connection.
* Class for Diameter connection. The class is basically just a SCTP socket,
* that sends and receives messages for a Diameter peer (owner).
*/
class DiameterConnection : public SCTPSocket::CallbackInterface {
private:
......@@ -43,6 +44,10 @@ private:
AddressVector addresses;
int port;
/*
* Callback methods for SCTP socket. Message handling is done in the
* data arrived method.
*/
void socketEstablished(int32 connId, void *yourPtr, uint64 buffer);
void socketDataArrived(int32 connId, void *yourPtr, cPacket *msg, bool urgent);
void socketDataNotificationArrived(int32 connId, void *yourPtr, cPacket *msg);
......@@ -55,40 +60,85 @@ public:
DiameterConnection(DiameterBase *module);
virtual ~DiameterConnection();
void processMessage(cMessage *msg) { socket->processMessage(PK(msg)); }
unsigned processOrigin(DiameterPeer *&peer, DiameterMessage *msg);
void setPeer(DiameterPeer *peer) { this->peer = peer; }
/*
* Getter methods.
*/
bool getType() { return type; }
void setType(bool type) { this->type = type; }
// SCTPSocket *getSocket() { return socket; }
void setSocket(SCTPSocket *socket) { this->socket = socket; }
void setAddresses(AddressVector addresses) { this->addresses = addresses; }
void setPort(int port) { this->port = port; }
int getConnectionId() { return socket->getConnectionId(); }
void shutdown() { EV << "Shutting down Assoc Id = " << socket->getConnectionId() << endl; socket->shutdown(); }
void close() { EV << "Closing Assoc Id = " << socket->getConnectionId() << endl; socket->close(); }
void connect();
void send(DiameterMessage *msg, unsigned fqdnPos, unsigned realmPos); // adds also information about source identity
/*
* Setter methods.
*/
void setPeer(DiameterPeer *peer) { this->peer = peer; }
void setType(bool type) { this->type = type; }
void setSocket(SCTPSocket *socket) { this->socket = socket; }
void setAddresses(AddressVector addresses) { this->addresses = addresses; }
void setPort(int port) { this->port = port; }
/*
* Method for processing the origin of each message.
*/
unsigned processOrigin(DiameterPeer *&peer, DiameterMessage *msg);
int getConnectionId() { return socket->getConnectionId(); }
/*
* Utility methods for the socket.
*/
void shutdown();
void close();
void connect();
/*
* Method for sending Diameter messages. It will be used for all messages
* coming from the peer and it will add information regarding source
* identification.
*/
void send(DiameterMessage *msg, unsigned fqdnPos, unsigned realmPos);
/*
* Wrapper methods.
*/
void processMessage(cMessage *msg) { socket->processMessage(PK(msg)); }
};
/*
* Class for Diameter connection map. This class will hold all the
* connection for the Diameter base protocol model.
*/
class DiameterConnectionMap {
private:
typedef std::map<int,DiameterConnection*> ConnMap;
ConnMap connMap;
typedef std::map<int,DiameterConnection*> DiameterConnections;
DiameterConnections conns;
public:
DiameterConnectionMap();
virtual ~DiameterConnectionMap();
DiameterConnection *findConnectionFor(cMessage *msg);
void addConnection(DiameterConnection *conn);
DiameterConnection *removeConnection(DiameterConnection *conn);
unsigned int size() {return connMap.size();}
// void deleteConnections();
void printConnectionMap();
/*
* Method for finding a Diameter connection with a specific message based
* on the association id specified in the control info. The method
* returns the session if it is found, or NULL otherwise.
*/
DiameterConnection *findConnection(cMessage *msg);
/*
* Method for inserting a new connection in the map.
*/
void insert(DiameterConnection *conn);
/*
* Method for deleting a Diameter connection. The method calls first
* the destructor for the connection and removes it afterwards.
*/
void erase(DiameterConnection *conn);
/*
* Wrapper method.
*/
unsigned int size() {return conns.size();}
/*
* Method for printing the connection map.
*/
void print();
};
#endif /* DIAMETERCONNECTION_H_ */
......@@ -52,11 +52,6 @@ module DiameterNode
inout pppg[] @labels(PPPFrame-conn);
inout ethg[] @labels(EtherFrame-conn);
submodules:
namTrace: NAMTraceWriter {
parameters:
namid = namid;
@display("p=57,294");
}
notificationBoard: NotificationBoard {
parameters:
@display("p=57,54");
......@@ -73,35 +68,35 @@ module DiameterNode
@display("p=57,214");
}
sctp: SCTP {
@display("p=501,141;i=block/wheelbarrow");
@display("p=379,124;i=block/wheelbarrow");
}
pingApp: PingApp {
parameters:
@display("p=501,230");
@display("p=379,213");
}
networkLayer: NetworkLayer {
parameters:
proxyARP = false;
@display("p=336,230;q=queue");
@display("p=214,213;q=queue");
gates:
ifIn[sizeof(pppg)+sizeof(ethg)+numExtInterfaces];
ifOut[sizeof(pppg)+sizeof(ethg)+numExtInterfaces];
}
ppp[sizeof(pppg)]: PPPInterface {
parameters:
@display("p=186,390,row,90;q=txQueue");
@display("p=64,373,row,90;q=txQueue");
}
eth[sizeof(ethg)]: EthernetInterface {
parameters:
@display("p=336,390,row,90;q=txQueue");
@display("p=214,373,row,90;q=txQueue");
}
ext[numExtInterfaces]: ExtInterface {
parameters:
@display("p=501,390,row,90;q=txQueue;i=block/ifcard");
@display("p=379,373,row,90;q=txQueue;i=block/ifcard");
}
tcpdump: TCPDump {
parameters:
@display("p=336,302;i=abstract/cache_s");
@display("p=214,285;i=abstract/cache_s");
dumpFile = dumpFile;
gates:
ifIn[sizeof(pppg)+sizeof(ethg)+numExtInterfaces];
......@@ -112,12 +107,12 @@ module DiameterNode
diameter: <diameterAppType> like DiameterBase {
parameters:
configFile = configFile;
@display("p=501,71");
@display("p=379,54");
}
connections allowunconnected:
sctp.to_appl++ --> diameter.sctpIn;
diameter.sctpOut --> sctp.from_appl++;
sctp.to_ip --> networkLayer.sctpIn;
networkLayer.sctpOut --> sctp.from_ip;
......
......@@ -735,9 +735,9 @@ DiameterPeer *DiameterPeerTable::findPeer(unsigned applId) {
}
void DiameterPeerTable::erase(unsigned start, unsigned end) {
PeerTable::iterator first = peers.begin() + start;
PeerTable::iterator last = peers.begin() + end;
PeerTable::iterator i = first;
DiameterPeers::iterator first = peers.begin() + start;
DiameterPeers::iterator last = peers.begin() + end;
DiameterPeers::iterator i = first;
for (;i != last; ++i)
delete *i;
peers.erase(first, last);
......
......@@ -177,8 +177,8 @@ public:
*/
class DiameterPeerTable {
private:
typedef std::vector<DiameterPeer*>PeerTable;
PeerTable peers;
typedef std::vector<DiameterPeer*> DiameterPeers;
DiameterPeers peers;
public:
DiameterPeerTable();
virtual ~DiameterPeerTable();
......
......@@ -129,7 +129,7 @@ DiameterSessionTable::~DiameterSessionTable() {
// TODO Auto-generated destructor stub
}
DiameterSession *DiameterSessionTable::find(std::string id) {
DiameterSession *DiameterSessionTable::findSession(std::string id) {
for (unsigned i = 0; i < sessions.size(); i++) {
if (sessions.at(i)->getId() == id)
return sessions.at(i);
......@@ -138,9 +138,9 @@ DiameterSession *DiameterSessionTable::find(std::string id) {
}
void DiameterSessionTable::erase(unsigned start, unsigned end) {
SessionTable::iterator first = sessions.begin() + start;
SessionTable::iterator last = sessions.begin() + end;
SessionTable::iterator i = first;
DiameterSessions::iterator first = sessions.begin() + start;
DiameterSessions::iterator last = sessions.begin() + end;
DiameterSessions::iterator i = first;
for (;i != last; ++i)
delete *i;
sessions.erase(first, last);
......
......@@ -83,17 +83,17 @@ public:
*/
class DiameterSessionTable {
private:
typedef std::vector<DiameterSession*> SessionTable;
SessionTable sessions;
typedef std::vector<DiameterSession*> DiameterSessions;
DiameterSessions sessions;
public:
DiameterSessionTable();
virtual ~DiameterSessionTable();
/*
* Method for find a Diameter session with a specific id. The method
* Method for finding a Diameter session with a specific id. The method
* returns the session if it is found, or NULL otherwise.
*/
DiameterSession *find(std::string id);
DiameterSession *findSession(std::string id);
/*
* Method for deleting Diameter sessions. The method calls first
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册