INET Framework for OMNeT++/OMNEST
|
#include <SCTPSocket.h>
Classes | |
class | CallbackInterface |
Public Types | |
enum | State { NOT_BOUND, CLOSED, LISTENING, CONNECTING, CONNECTED, PEER_CLOSED, LOCALLY_CLOSED, SOCKERROR } |
Public Member Functions | |
SCTPSocket (bool type=true) | |
SCTPSocket (cPacket *msg) | |
~SCTPSocket () | |
int | getConnectionId () const |
int | getState () |
void | setState (int state) |
Getter functions | |
AddressVector | getLocalAddresses () |
int | getLocalPort () |
AddressVector | getRemoteAddresses () |
int | getRemotePort () |
IPvXAddress | getRemoteAddr () |
Opening and closing connections, sending data | |
void | setOutputGate (cGate *toSctp) |
void | setOutboundStreams (int streams) |
void | setInboundStreams (int streams) |
int | getOutboundStreams () |
int | getLastStream () |
void | bind (int localPort) |
void | bind (IPvXAddress localAddr, int localPort) |
void | bindx (AddressVector localAddr, int localPort) |
void | addAddress (IPvXAddress addr) |
void | listen (bool fork=false, uint32 requests=0, uint32 messagesToPush=0) |
void | connect (IPvXAddress remoteAddress, int32 remotePort, uint32 numRequests) |
void | connectx (AddressVector remoteAddresses, int32 remotePort, uint32 numRequests=0) |
void | send (cPacket *msg, bool last=true, bool primary=true) |
void | sendNotification (cPacket *msg) |
void | sendRequest (cPacket *msg) |
void | close () |
void | abort () |
void | shutdown () |
void | requestStatus () |
Static Public Member Functions | |
static const char * | stateName (int state) |
Public Attributes | |
cGate * | gateToSctp |
Protected Member Functions | |
void | sendToSCTP (cPacket *msg) |
Protected Attributes | |
int | assocId |
int | sockId |
int | sockstate |
bool | oneToOne |
IPvXAddress | localAddr |
AddressVector | localAddresses |
int | localPrt |
IPvXAddress | remoteAddr |
AddressVector | remoteAddresses |
int | remotePrt |
int | fsmStatus |
int | inboundStreams |
int | outboundStreams |
int | lastStream |
CallbackInterface * | cb |
void * | yourPtr |
Handling of messages arriving from SCTP | |
bool | belongsToSocket (cPacket *msg) |
void | setCallbackObject (CallbackInterface *cb, void *yourPtr=NULL) |
void | processMessage (cPacket *msg) |
static bool | belongsToAnySCTPSocket (cPacket *msg) |
enum SCTPSocket::State |
SCTPSocket::SCTPSocket | ( | bool | type = true | ) |
Constructor. The connectionId() method returns a valid Id right after constructor call.
{ sockstate = NOT_BOUND; localPrt = remotePrt = 0; cb = NULL; yourPtr = NULL; gateToSctp = NULL; lastStream=-1; oneToOne = type; if (oneToOne) assocId = SCTP::getNewConnId(); else assocId = 0; sctpEV3<<"sockstate="<<sockstate<<"\n"; }
SCTPSocket::SCTPSocket | ( | cPacket * | msg | ) |
Constructor, to be used with forked sockets (see listen()). The assocId will be picked up from the message: it should have arrived from SCTPMain and contain SCTPCommmand control info.
SCTPSocket::~SCTPSocket | ( | ) |
Destructor
{ localAddresses.clear(); }
void SCTPSocket::abort | ( | ) |
Aborts the association.
Referenced by SCTPClient::handleTimer().
void SCTPSocket::addAddress | ( | IPvXAddress | addr | ) |
{ sctpEV3<<"add address "<<addr<<"\n"; localAddresses.push_back(addr); }
bool SCTPSocket::belongsToAnySCTPSocket | ( | cPacket * | msg | ) | [static] |
Returns true if the message belongs to any SCTPSocket instance. (This basically checks if the message has a SCTPCommand attached to it as controlInfo().)
{ return dynamic_cast<SCTPCommand *>(msg->getControlInfo()); }
bool SCTPSocket::belongsToSocket | ( | cPacket * | msg | ) |
Returns true if the message belongs to this socket instance (message has a SCTPCommand as controlInfo(), and the assocId in it matches that of the socket.)
void SCTPSocket::bind | ( | int | localPort | ) |
Bind the socket to a local port number.
Referenced by SCTPServer::initialize(), SCTPPeer::initialize(), and SCTPClient::initialize().
{ if (sockstate!=NOT_BOUND) opp_error("SCTPSocket::bind(): socket already bound"); localAddresses.push_back(IPvXAddress("0.0.0.0")); localPrt = lPort; sockstate = CLOSED; }
void SCTPSocket::bind | ( | IPvXAddress | localAddr, |
int | localPort | ||
) |
void SCTPSocket::bindx | ( | AddressVector | localAddr, |
int | localPort | ||
) |
Referenced by SCTPServer::initialize(), SCTPPeer::initialize(), and SCTPClient::initialize().
{ IPvXAddress lAddr; for (AddressVector::iterator i=lAddresses.begin(); i!=lAddresses.end(); ++i) { ev<<"bindx: bind address "<<(*i)<<"\n"; localAddresses.push_back((*i)); } localPrt = lPort; sockstate = CLOSED; }
void SCTPSocket::close | ( | ) |
Closes the local end of the connection. With SCTP, a CLOSE operation means "I have no more data to send", and thus results in a one-way connection until the remote SCTP closes too (or the FIN_WAIT_1 timeout expires)
Referenced by SCTPClient::close(), SCTPClient::handleTimer(), SCTPPeer::socketDataArrived(), and SCTPPeer::socketPeerClosed().
{ sctpEV3<<"SCTPSocket: close\n"; cPacket *msg = new cPacket("CLOSE", SCTP_C_CLOSE); SCTPCommand *cmd = new SCTPCommand(); cmd->setAssocId(assocId); msg->setControlInfo(cmd); sendToSCTP(msg); sockstate = sockstate==CONNECTED ? LOCALLY_CLOSED : CLOSED; }
void SCTPSocket::connect | ( | IPvXAddress | remoteAddress, |
int32 | remotePort, | ||
uint32 | numRequests | ||
) |
Active OPEN to the given remote socket.
Referenced by SCTPPeer::connect(), and SCTPClient::connect().
{ sctpEV3<<"Socket connect. Assoc="<<assocId<<", sockstate="<<sockstate<<"\n"; if (oneToOne && sockstate!=NOT_BOUND && sockstate!=CLOSED) opp_error( "SCTPSocket::connect(): connect() or listen() already called"); else if (!oneToOne && sockstate!=LISTENING) opp_error( "SCTPSocket::connect: One-to-many style socket must be listening"); cPacket *msg = new cPacket("Associate", SCTP_C_ASSOCIATE); remoteAddr = remoteAddress; remotePrt = remotePort; SCTPOpenCommand *openCmd = new SCTPOpenCommand(); if (oneToOne) openCmd->setAssocId(assocId); else openCmd->setAssocId(SCTP::getNewConnId()); sctpEV3<<"Socket connect. Assoc="<<openCmd->getAssocId()<<", sockstate="<<stateName(sockstate)<<"\n"; //openCmd->setAssocId(assocId); openCmd->setLocalAddresses(localAddresses); openCmd->setLocalPort(localPrt); openCmd->setRemoteAddr(remoteAddr); openCmd->setRemotePort(remotePrt); openCmd->setOutboundStreams(outboundStreams); openCmd->setOutboundStreams(inboundStreams); openCmd->setNumRequests(numRequests); msg->setControlInfo(openCmd); sendToSCTP(msg); if (oneToOne) sockstate = CONNECTING; }
void SCTPSocket::connectx | ( | AddressVector | remoteAddresses, |
int32 | remotePort, | ||
uint32 | numRequests = 0 |
||
) |
{ sctpEV3<<"Socket connectx. sockstate="<<sockstate<<"\n"; /*if (sockstate!=NOT_BOUND && sockstate!=CLOSED) opp_error( "SCTPSocket::connect(): connect() or listen() already called");*/ if (oneToOne && sockstate!=NOT_BOUND && sockstate!=CLOSED) opp_error( "SCTPSocket::connect(): connect() or listen() already called"); else if (!oneToOne && sockstate!=LISTENING) opp_error( "SCTPSocket::connect: One-to-many style socket must be listening"); cPacket *msg = new cPacket("Associate", SCTP_C_ASSOCIATE); remoteAddresses = remoteAddressList; remoteAddr = remoteAddresses.front(); remotePrt = remotePort; SCTPOpenCommand *openCmd = new SCTPOpenCommand(); openCmd->setAssocId(assocId); openCmd->setLocalAddresses(localAddresses); openCmd->setLocalPort(localPrt); openCmd->setRemoteAddr(remoteAddr); openCmd->setRemoteAddresses(remoteAddresses); openCmd->setRemotePort(remotePrt); openCmd->setOutboundStreams(outboundStreams); openCmd->setNumRequests(numRequests); msg->setControlInfo(openCmd); sendToSCTP(msg); if (oneToOne) sockstate = CONNECTING; }
int SCTPSocket::getConnectionId | ( | ) | const [inline] |
Returns the internal connection Id. SCTP uses the (gate index, assocId) pair to identify the connection when it receives a command from the application (or SCTPSocket).
Referenced by SCTPPeer::connect(), SCTPPeer::sendQueueRequest(), SCTPClient::sendQueueRequest(), and SCTPClient::setPrimaryPath().
{return assocId;}
int SCTPSocket::getLastStream | ( | ) | [inline] |
{return lastStream;};
AddressVector SCTPSocket::getLocalAddresses | ( | ) | [inline] |
{return localAddresses;}
int SCTPSocket::getLocalPort | ( | ) | [inline] |
{return localPrt;}
int SCTPSocket::getOutboundStreams | ( | ) | [inline] |
{return outboundStreams;};
IPvXAddress SCTPSocket::getRemoteAddr | ( | ) | [inline] |
{return remoteAddr;}
AddressVector SCTPSocket::getRemoteAddresses | ( | ) | [inline] |
{return remoteAddresses;}
int SCTPSocket::getRemotePort | ( | ) | [inline] |
{return remotePrt;}
int SCTPSocket::getState | ( | ) | [inline] |
Returns the socket state, one of NOT_BOUND, CLOSED, LISTENING, CONNECTING, CONNECTED, etc. Messages received from SCTP must be routed through processMessage() in order to keep socket state up-to-date.
Referenced by SCTPPeer::handleMessage(), SCTPPeer::socketPeerClosed(), and SCTPClient::socketPeerClosed().
{return sockstate;}
void SCTPSocket::listen | ( | bool | fork = false , |
uint32 | requests = 0 , |
||
uint32 | messagesToPush = 0 |
||
) |
Initiates passive OPEN. If fork=true, you'll have to create a new SCTPSocket object for each incoming connection, and this socket will keep listening on the port. If fork=false, the first incoming connection will be accepted, and SCTP will refuse subsequent ones. See SCTPOpenCommand documentation (neddoc) for more info.
Referenced by SCTPServer::initialize(), and SCTPPeer::initialize().
{ if (sockstate!=CLOSED) opp_error(sockstate==NOT_BOUND ? "SCTPSocket: must call bind() before listen()" : "SCTPSocket::listen(): connect() or listen() already called"); cPacket *msg = new cPacket("PassiveOPEN", SCTP_C_OPEN_PASSIVE); SCTPOpenCommand *openCmd = new SCTPOpenCommand(); //openCmd->setLocalAddr(localAddr); openCmd->setLocalAddresses(localAddresses); openCmd->setLocalPort(localPrt); if (oneToOne) openCmd->setAssocId(assocId); else openCmd->setAssocId(SCTP::getNewConnId()); openCmd->setFork(fork); openCmd->setInboundStreams(inboundStreams); openCmd->setOutboundStreams(outboundStreams); openCmd->setNumRequests(requests); openCmd->setMessagesToPush(messagesToPush); msg->setControlInfo(openCmd); sctpEV3<<"Assoc "<<openCmd->getAssocId()<<"::send PassiveOPEN to SCTP from socket:listen \n"; sendToSCTP(msg); sockstate = LISTENING; }
void SCTPSocket::processMessage | ( | cPacket * | msg | ) |
Examines the message (which should have arrived from SCTPMain), updates socket state, and if there is a callback object installed (see setCallbackObject(), class CallbackInterface), dispatches to the appropriate method of it with the same yourPtr that you gave in the setCallbackObject() call.
The method deletes the message, unless (1) there is a callback object installed AND (2) the message is payload (message kind SCTP_I_DATA or SCTP_I_URGENT_DATA) when the responsibility of destruction is on the socketDataArrived() callback method.
IMPORTANT: for performance reasons, this method doesn't check that the message belongs to this socket, i.e. belongsToSocket(msg) would return true!
Referenced by SCTPPeer::handleMessage(), and SCTPClient::handleMessage().
{ SCTPStatusInfo *status; switch (msg->getKind()) { case SCTP_I_DATA: sctpEV3<<"SCTP_I_DATA\n"; if (cb) cb->socketDataArrived(assocId, yourPtr, msg, false); break; case SCTP_I_DATA_NOTIFICATION: sctpEV3<<"SCTP_I_NOTIFICATION\n"; if (cb) cb->socketDataNotificationArrived(assocId, yourPtr, msg); break; case SCTP_I_SEND_MSG: if (cb) cb->sendRequestArrived(); break; case SCTP_I_ESTABLISHED: { if (oneToOne) sockstate = CONNECTED; SCTPConnectInfo *connectInfo = check_and_cast<SCTPConnectInfo *>(msg->removeControlInfo()); localAddr = connectInfo->getLocalAddr(); remoteAddr = connectInfo->getRemoteAddr(); localPrt = connectInfo->getLocalPort(); remotePrt = connectInfo->getRemotePort();; fsmStatus = connectInfo->getStatus(); inboundStreams = connectInfo->getInboundStreams(); outboundStreams = connectInfo->getOutboundStreams(); if (cb) cb->socketEstablished(assocId, yourPtr, connectInfo->getNumMsgs()); delete connectInfo; break; } case SCTP_I_PEER_CLOSED: sctpEV3<<"peer closed\n"; if (oneToOne) sockstate = sockstate==CONNECTED ? PEER_CLOSED : CLOSED; if (cb) cb->socketPeerClosed(assocId, yourPtr); break; case SCTP_I_ABORT: case SCTP_I_CONN_LOST: case SCTP_I_CLOSED: sctpEV3<<"SCTP_I_CLOSED called\n"; sockstate = CLOSED; if (cb) cb->socketClosed(assocId, yourPtr); break; case SCTP_I_CONNECTION_REFUSED: case SCTP_I_CONNECTION_RESET: case SCTP_I_TIMED_OUT: sockstate = SOCKERROR; if (cb) cb->socketFailure(assocId, yourPtr, msg->getKind()); break; case SCTP_I_STATUS: status = check_and_cast<SCTPStatusInfo *>(msg->removeControlInfo()); if (cb) cb->socketStatusArrived(assocId, yourPtr, status); delete status; break; case SCTP_I_SHUTDOWN_RECEIVED: sctpEV3<<"SCTP_I_SHUTDOWN_RECEIVED\n"; if (cb) cb->shutdownReceivedArrived(assocId); break; case SCTP_I_SENDQUEUE_FULL: if (cb) cb->sendqueueFullArrived(assocId); break; case SCTP_I_SENDQUEUE_ABATED: { SCTPCommand *cmd = check_and_cast<SCTPCommand *>(msg->removeControlInfo()); if (cb) { cb->sendqueueAbatedArrived(assocId, cmd->getNumMsgs()); } delete cmd; break; } default: opp_error("SCTPSocket: invalid msg kind %d, one of the SCTP_I_xxx constants expected", msg->getKind()); } delete msg; }
void SCTPSocket::requestStatus | ( | ) |
Causes SCTP to reply with a fresh SCTPStatusInfo, attached to a dummy message as controlInfo(). The reply message can be recognized by its message kind SCTP_I_STATUS, or (if a callback object is used) the socketStatusArrived() method of the callback object will be called.
{ cPacket *msg = new cPacket("STATUS", SCTP_C_STATUS); SCTPCommand *cmd = new SCTPCommand(); cmd->setAssocId(assocId); msg->setControlInfo(cmd); sendToSCTP(msg); }
void SCTPSocket::send | ( | cPacket * | msg, |
bool | last = true , |
||
bool | primary = true |
||
) |
Sends data packet.
Referenced by SCTPPeer::sendRequest(), SCTPClient::sendRequest(), sendToSCTP(), SCTPPeer::socketDataArrived(), and SCTPClient::socketDataArrived().
{ if (oneToOne && sockstate!=CONNECTED && sockstate!=CONNECTING && sockstate!=PEER_CLOSED) { opp_error("SCTPSocket::send(): not connected or connecting"); } else if (!oneToOne && sockstate!=LISTENING) { opp_error( "SCTPSocket::send: One-to-many style socket must be listening"); } SCTPSendCommand *cmd = new SCTPSendCommand(); cmd->setAssocId(assocId); if (msg->getKind() == SCTP_C_SEND_ORDERED) cmd->setSendUnordered(COMPLETE_MESG_ORDERED); else cmd->setSendUnordered(COMPLETE_MESG_UNORDERED); lastStream=(lastStream+1)%outboundStreams; cmd->setSid(lastStream); cmd->setLast(last); cmd->setPrimary(primary); msg->setKind(SCTP_C_SEND); msg->setControlInfo(cmd); sendToSCTP(msg); }
void SCTPSocket::sendNotification | ( | cPacket * | msg | ) |
Referenced by SCTPClient::setPrimaryPath(), SCTPPeer::shutdownReceivedArrived(), SCTPClient::shutdownReceivedArrived(), SCTPPeer::socketDataNotificationArrived(), and SCTPClient::socketDataNotificationArrived().
{ if (oneToOne && sockstate!=CONNECTED && sockstate!=CONNECTING && sockstate!=PEER_CLOSED) { opp_error("SCTPSocket::sendNotification(%s): not connected or connecting", msg->getName()); } else if (!oneToOne && sockstate!=LISTENING) { opp_error( "SCTPSocket::send: One-to-many style socket must be listening"); } sendToSCTP(msg); }
void SCTPSocket::sendRequest | ( | cPacket * | msg | ) |
Referenced by SCTPPeer::sendQueueRequest(), and SCTPClient::sendQueueRequest().
{ sendToSCTP(msg); }
void SCTPSocket::sendToSCTP | ( | cPacket * | msg | ) | [protected] |
Referenced by abort(), close(), connect(), connectx(), listen(), requestStatus(), send(), sendNotification(), sendRequest(), and shutdown().
{ if (!gateToSctp) opp_error("SCTPSocket: setOutputGate() must be invoked before socket can be used"); check_and_cast<cSimpleModule *>(gateToSctp->getOwnerModule())->send(msg, gateToSctp); }
void SCTPSocket::setCallbackObject | ( | CallbackInterface * | cb, |
void * | yourPtr = NULL |
||
) |
Sets a callback object, to be used with processMessage(). This callback object may be your simple module itself (if it multiply inherits from CallbackInterface too, that is you declared it as
class MyAppModule : public cSimpleModule, public SCTPSocket::CallbackInterface
and redefined the necessary virtual functions; or you may use dedicated class (and objects) for this purpose.
SCTPSocket doesn't delete the callback object in the destructor or on any other occasion.
YourPtr is an optional pointer. It may contain any value you wish -- SCTPSocket will not look at it or do anything with it except passing it back to you in the CallbackInterface calls. You may find it useful if you maintain additional per-connection information: in that case you don't have to look it up by assocId in the callbacks, you can have it passed to you as yourPtr.
Referenced by SCTPPeer::initialize(), and SCTPClient::initialize().
void SCTPSocket::setInboundStreams | ( | int | streams | ) | [inline] |
Referenced by SCTPClient::connect(), and SCTPServer::initialize().
{inboundStreams = streams;};
void SCTPSocket::setOutboundStreams | ( | int | streams | ) | [inline] |
Referenced by SCTPPeer::connect(), SCTPClient::connect(), SCTPServer::initialize(), and SCTPPeer::initialize().
{outboundStreams = streams;};
void SCTPSocket::setOutputGate | ( | cGate * | toSctp | ) | [inline] |
Sets the gate on which to send to SCTP. Must be invoked before socket can be used. Example: socket.setOutputGate(gate("sctpOut"));
Referenced by SCTPServer::initialize(), SCTPPeer::initialize(), and SCTPClient::initialize().
{gateToSctp = toSctp;};
void SCTPSocket::setState | ( | int | state | ) | [inline] |
{sockstate = state; };
void SCTPSocket::shutdown | ( | ) |
Referenced by SCTPClient::handleTimer(), SCTPClient::sendqueueAbatedArrived(), SCTPPeer::sendRequestArrived(), SCTPClient::sendRequestArrived(), SCTPPeer::socketEstablished(), and SCTPClient::socketEstablished().
{ ev<<"SCTPSocket: shutdown\n"; cPacket *msg = new cPacket("Shutdown", SCTP_C_SHUTDOWN); SCTPCommand *cmd = new SCTPCommand(); cmd->setAssocId(assocId); msg->setControlInfo(cmd); sendToSCTP(msg); }
const char * SCTPSocket::stateName | ( | int | state | ) | [static] |
Returns name of socket state code returned by state().
Referenced by connect().
int SCTPSocket::assocId [protected] |
Referenced by abort(), belongsToSocket(), close(), connect(), connectx(), listen(), processMessage(), requestStatus(), SCTPSocket(), send(), and shutdown().
CallbackInterface* SCTPSocket::cb [protected] |
Referenced by processMessage(), SCTPSocket(), and setCallbackObject().
int SCTPSocket::fsmStatus [protected] |
Referenced by processMessage().
cGate* SCTPSocket::gateToSctp |
Referenced by SCTPSocket(), and sendToSCTP().
int SCTPSocket::inboundStreams [protected] |
Referenced by connect(), listen(), and processMessage().
int SCTPSocket::lastStream [protected] |
Referenced by SCTPSocket(), and send().
IPvXAddress SCTPSocket::localAddr [protected] |
Referenced by processMessage().
AddressVector SCTPSocket::localAddresses [protected] |
Referenced by addAddress(), bind(), bindx(), connect(), connectx(), listen(), and ~SCTPSocket().
int SCTPSocket::localPrt [protected] |
Referenced by bind(), bindx(), connect(), connectx(), listen(), processMessage(), and SCTPSocket().
bool SCTPSocket::oneToOne [protected] |
Referenced by connect(), connectx(), listen(), processMessage(), SCTPSocket(), send(), and sendNotification().
int SCTPSocket::outboundStreams [protected] |
Referenced by connect(), connectx(), listen(), processMessage(), and send().
IPvXAddress SCTPSocket::remoteAddr [protected] |
Referenced by connect(), connectx(), and processMessage().
AddressVector SCTPSocket::remoteAddresses [protected] |
Referenced by connectx().
int SCTPSocket::remotePrt [protected] |
Referenced by connect(), connectx(), processMessage(), and SCTPSocket().
int SCTPSocket::sockId [protected] |
int SCTPSocket::sockstate [protected] |
Referenced by abort(), bind(), bindx(), close(), connect(), connectx(), listen(), processMessage(), SCTPSocket(), send(), and sendNotification().
void* SCTPSocket::yourPtr [protected] |
Referenced by processMessage(), SCTPSocket(), and setCallbackObject().