SCTPSocket Class Reference

#include <SCTPSocket.h>

List of all members.

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)

Public Types

enum  State {
  NOT_BOUND, CLOSED, LISTENING, CONNECTING,
  CONNECTED, PEER_CLOSED, LOCALLY_CLOSED, SOCKERROR
}

Public Member Functions

 SCTPSocket ()
 SCTPSocket (cPacket *msg)
 ~SCTPSocket ()
int getConnectionId () const
int getState ()
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)
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 sockstate
IPvXAddress localAddr
AddressVector localAddresses
int localPrt
IPvXAddress remoteAddr
AddressVector remoteAddresses
int remotePrt
int fsmStatus
int inboundStreams
int outboundStreams
int lastStream
CallbackInterfacecb
void * yourPtr

Classes

class  CallbackInterface


Member Enumeration Documentation

Enumerator:
NOT_BOUND 
CLOSED 
LISTENING 
CONNECTING 
CONNECTED 
PEER_CLOSED 
LOCALLY_CLOSED 
SOCKERROR 


Constructor & Destructor Documentation

SCTPSocket::SCTPSocket (  ) 

Constructor. The connectionId() method returns a valid Id right after constructor call.

00025 {
00026         assocId = SCTP::getNewConnId();
00027         sockstate = NOT_BOUND;
00028         
00029         localPrt = remotePrt = 0;
00030         cb = NULL;
00031         yourPtr = NULL;
00032         
00033         gateToSctp = NULL;
00034         lastStream=-1;
00035         sctpEV3<<"sockstate="<<sockstate<<"\n";
00036 }

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

00040 {
00041         localAddresses.clear();
00042 }


Member Function Documentation

void SCTPSocket::sendToSCTP ( cPacket *  msg  )  [protected]

Referenced by abort(), close(), connect(), connectx(), listen(), requestStatus(), send(), sendNotification(), sendRequest(), and shutdown().

00064 {
00065         if (!gateToSctp)
00066                 opp_error("SCTPSocket: setOutputGate() must be invoked before socket can be used");
00067         check_and_cast<cSimpleModule *>(gateToSctp->getOwnerModule())->send(msg, gateToSctp);
00068 }

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().

00111 {return assocId;}

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().

00118 {return sockstate;}

const char * SCTPSocket::stateName ( int  state  )  [static]

Returns name of socket state code returned by state().

00045 {
00046 #define CASE(x) case x: s=#x; break
00047         const char *s = "unknown";
00048         switch (state)
00049         {
00050                 CASE(NOT_BOUND);
00051                 CASE(CLOSED);
00052                 CASE(LISTENING);
00053                 CASE(CONNECTING);
00054                 CASE(CONNECTED);
00055                 CASE(PEER_CLOSED);
00056                 CASE(LOCALLY_CLOSED);
00057                 CASE(SOCKERROR);
00058         }
00059         return s;
00060 #undef CASE
00061 }

AddressVector SCTPSocket::getLocalAddresses (  )  [inline]

00127 {return localAddresses;}

int SCTPSocket::getLocalPort (  )  [inline]

00128 {return localPrt;}

AddressVector SCTPSocket::getRemoteAddresses (  )  [inline]

00130 {return remoteAddresses;}

int SCTPSocket::getRemotePort (  )  [inline]

00131 {return remotePrt;}

IPvXAddress SCTPSocket::getRemoteAddr (  )  [inline]

00132 {return remoteAddr;}

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().

00142 {gateToSctp = toSctp;};

void SCTPSocket::setOutboundStreams ( int  streams  )  [inline]

void SCTPSocket::setInboundStreams ( int  streams  )  [inline]

00144 {inboundStreams = streams;};

int SCTPSocket::getOutboundStreams (  )  [inline]

00145 {return outboundStreams;};

int SCTPSocket::getLastStream (  )  [inline]

00146 {return lastStream;};

void SCTPSocket::bind ( int  localPort  ) 

Bind the socket to a local port number.

Referenced by SCTPServer::initialize(), SCTPPeer::initialize(), and SCTPClient::initialize().

00071 {
00072         if (sockstate!=NOT_BOUND)
00073                 opp_error("SCTPSocket::bind(): socket already bound");
00074         localAddresses.push_back(IPvXAddress("0.0.0.0"));
00075         localPrt = lPort;
00076         sockstate = CLOSED;
00077 }

void SCTPSocket::bind ( IPvXAddress  localAddr,
int  localPort 
)

Bind the socket to a local port number and IP address (useful with multi-homing).

00080 {
00081          
00082         sctpEV3<<"bind address "<<lAddr<<"\n";
00083         
00084         if (sockstate!=NOT_BOUND)
00085                 opp_error("SCTPSocket::bind(): socket already bound");
00086         localAddresses.push_back(lAddr);
00087         localPrt = lPort;
00088         sockstate = CLOSED;
00089 }

void SCTPSocket::bindx ( AddressVector  localAddr,
int  localPort 
)

Referenced by SCTPServer::initialize(), SCTPPeer::initialize(), and SCTPClient::initialize().

00098 {
00099         IPvXAddress lAddr;
00100         for (AddressVector::iterator i=lAddresses.begin(); i!=lAddresses.end(); ++i)
00101         {
00102                 ev<<"bindx: bind address "<<(*i)<<"\n";
00103                 localAddresses.push_back((*i));
00104         }
00105         localPrt = lPort;
00106         sockstate = CLOSED;
00107 }

void SCTPSocket::addAddress ( IPvXAddress  addr  ) 

00092 {
00093         sctpEV3<<"add address "<<addr<<"\n";
00094         localAddresses.push_back(addr);
00095 }

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().

00110 {
00111         if (sockstate!=CLOSED)
00112                 opp_error(sockstate==NOT_BOUND ? "SCTPSocket: must call bind() before listen()"
00113                                                : "SCTPSocket::listen(): connect() or listen() already called");
00114         
00115         cPacket *msg = new cPacket("PassiveOPEN", SCTP_C_OPEN_PASSIVE);
00116         
00117         SCTPOpenCommand *openCmd = new SCTPOpenCommand();
00118         //openCmd->setLocalAddr(localAddr);
00119         openCmd->setLocalAddresses(localAddresses);
00120         openCmd->setLocalPort(localPrt);
00121         openCmd->setAssocId(assocId);
00122         openCmd->setFork(fork);
00123         openCmd->setOutboundStreams(outboundStreams);
00124         openCmd->setNumRequests(requests);
00125         openCmd->setMessagesToPush(messagesToPush);
00126         msg->setControlInfo(openCmd);
00127          
00128         sctpEV3<<"Assoc "<<assocId<<"::send PassiveOPEN to SCTP from socket:listen \n";
00129         
00130         sendToSCTP(msg);
00131         sockstate = LISTENING;
00132 }

void SCTPSocket::connect ( IPvXAddress  remoteAddress,
int32  remotePort,
uint32  numRequests 
)

Active OPEN to the given remote socket.

Referenced by SCTPPeer::connect(), and SCTPClient::connect().

00135 {
00136 sctpEV3<<"Socket connect. Assoc="<<assocId<<", sockstate="<<sockstate<<"\n";     
00137         if (sockstate!=NOT_BOUND && sockstate!=CLOSED)
00138                 opp_error( "SCTPSocket::connect(): connect() or listen() already called");
00139         cPacket *msg = new cPacket("Associate", SCTP_C_ASSOCIATE);
00140         remoteAddr = remoteAddress;
00141         remotePrt = remotePort;
00142         SCTPOpenCommand *openCmd = new SCTPOpenCommand();
00143         openCmd->setAssocId(assocId);
00144         openCmd->setLocalAddresses(localAddresses);
00145         openCmd->setLocalPort(localPrt);
00146         openCmd->setRemoteAddr(remoteAddr);
00147         openCmd->setRemotePort(remotePrt);
00148         openCmd->setOutboundStreams(outboundStreams);
00149         openCmd->setNumRequests(numRequests);
00150         msg->setControlInfo(openCmd);
00151         sendToSCTP(msg);
00152         sockstate = CONNECTING;
00153 }

void SCTPSocket::connectx ( AddressVector  remoteAddresses,
int32  remotePort,
uint32  numRequests 
)

00156 {
00157         sctpEV3<<"Socket connectx. Assoc="<<assocId<<", sockstate="<<sockstate<<"\n";    
00158         if (sockstate!=NOT_BOUND && sockstate!=CLOSED)
00159                 opp_error( "SCTPSocket::connect(): connect() or listen() already called");
00160         cPacket *msg = new cPacket("Associate", SCTP_C_ASSOCIATE);
00161         remoteAddresses = remoteAddressList;
00162         remoteAddr = remoteAddresses.front();
00163         remotePrt = remotePort;
00164         SCTPOpenCommand *openCmd = new SCTPOpenCommand();
00165         openCmd->setAssocId(assocId);
00166         openCmd->setLocalAddresses(localAddresses);
00167         openCmd->setLocalPort(localPrt);
00168         openCmd->setRemoteAddr(remoteAddr);
00169         openCmd->setRemoteAddresses(remoteAddresses);
00170         openCmd->setRemotePort(remotePrt);
00171         openCmd->setOutboundStreams(outboundStreams);
00172         openCmd->setNumRequests(numRequests);
00173         msg->setControlInfo(openCmd);
00174         sendToSCTP(msg);
00175         sockstate = CONNECTING;
00176 }

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().

00179 {       
00180         if (sockstate!=CONNECTED && sockstate!=CONNECTING && sockstate!=PEER_CLOSED)
00181                 opp_error("SCTPSocket::send(): not connected or connecting");
00182         SCTPSendCommand *cmd = new SCTPSendCommand();   
00183         cmd->setAssocId(assocId);
00184         if (msg->getKind() == SCTP_C_SEND_ORDERED)
00185                 cmd->setSendUnordered(COMPLETE_MESG_ORDERED);
00186         else
00187                 cmd->setSendUnordered(COMPLETE_MESG_UNORDERED);
00188         lastStream=(lastStream+1)%outboundStreams;
00189         cmd->setSid(lastStream);
00190         cmd->setLast(last);
00191         cmd->setPrimary(primary);
00192         msg->setKind(SCTP_C_SEND);
00193         msg->setControlInfo(cmd);
00194         sendToSCTP(msg);
00195 }

void SCTPSocket::sendNotification ( cPacket *  msg  ) 

void SCTPSocket::sendRequest ( cPacket *  msg  ) 

Referenced by SCTPPeer::sendQueueRequest(), and SCTPClient::sendQueueRequest().

00206 {
00207         sendToSCTP(msg);
00208         
00209 }

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(), SCTPPeer::socketDataArrived(), and SCTPPeer::socketPeerClosed().

00212 {
00213         sctpEV3<<"SCTPSocket: close\n";
00214 
00215         cPacket *msg = new cPacket("CLOSE", SCTP_C_CLOSE);
00216         SCTPCommand *cmd = new SCTPCommand();
00217         cmd->setAssocId(assocId);
00218         msg->setControlInfo(cmd);
00219         sendToSCTP(msg);
00220         sockstate = sockstate==CONNECTED ? LOCALLY_CLOSED : CLOSED;
00221 }

void SCTPSocket::abort (  ) 

Aborts the association.

00235 {       
00236         if (sockstate!=NOT_BOUND && sockstate!=CLOSED && sockstate!=SOCKERROR)
00237         {
00238                 cPacket *msg = new cPacket("ABORT", SCTP_C_ABORT);
00239                 SCTPCommand *cmd = new SCTPCommand();
00240                  
00241                 //sctpEV3<<"Message cmd="<<&cmd<<"\n";
00242                 
00243                 cmd->setAssocId(assocId);
00244                 msg->setControlInfo(cmd);       
00245                 sendToSCTP(msg);
00246         }
00247         sockstate = CLOSED;
00248 }

void SCTPSocket::shutdown (  ) 

Referenced by SCTPClient::handleTimer(), SCTPPeer::sendRequestArrived(), SCTPClient::sendRequestArrived(), SCTPPeer::socketEstablished(), and SCTPClient::socketEstablished().

00224 {
00225         ev<<"SCTPSocket: shutdown\n";
00226 
00227         cPacket *msg = new cPacket("Shutdown", SCTP_C_SHUTDOWN);
00228         SCTPCommand *cmd = new SCTPCommand();
00229         cmd->setAssocId(assocId);
00230         msg->setControlInfo(cmd);
00231         sendToSCTP(msg);
00232 }

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.

00251 {
00252         cPacket *msg = new cPacket("STATUS", SCTP_C_STATUS);
00253         SCTPCommand *cmd = new SCTPCommand();   
00254         cmd->setAssocId(assocId);
00255         msg->setControlInfo(cmd);
00256         sendToSCTP(msg);
00257 }

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.)

00260 {  
00261         bool ret= dynamic_cast<SCTPCommand *>(msg->getControlInfo()) &&
00262            ((SCTPCommand *)(msg->getControlInfo()))->getAssocId()==assocId;
00263         sctpEV3<<"assoc="<<((SCTPCommand *)(msg->getControlInfo()))->getAssocId()<<"\n";
00264         return ret;
00265 }

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().)

00268 {
00269         return dynamic_cast<SCTPCommand *>(msg->getControlInfo());
00270 }

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().

00273 {
00274         cb = callback;
00275         yourPtr = yourPointer;
00276 }

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().

00279 {       
00280         SCTPStatusInfo *status;
00281         switch (msg->getKind())
00282         {
00283                 case SCTP_I_DATA:
00284                          
00285                         sctpEV3<<"SCTP_I_DATA\n";
00286                         
00287                         if (cb) 
00288                                 cb->socketDataArrived(assocId, yourPtr, msg, false);
00289                         break;
00290                 case SCTP_I_DATA_NOTIFICATION:
00291                          
00292                         sctpEV3<<"SCTP_I_NOTIFICATION\n";
00293                         
00294                         if (cb) 
00295                                 cb->socketDataNotificationArrived(assocId, yourPtr, msg);       
00296                         break;
00297                 case SCTP_I_SEND_MSG:
00298                         if (cb)
00299                                 cb->sendRequestArrived();
00300                         break;
00301                 case SCTP_I_ESTABLISHED:
00302                 {        
00303                         sockstate = CONNECTED;
00304                         SCTPConnectInfo *connectInfo = check_and_cast<SCTPConnectInfo *>(msg->removeControlInfo());
00305                         localAddr = connectInfo->getLocalAddr();
00306                         remoteAddr = connectInfo->getRemoteAddr();
00307                         localPrt = connectInfo->getLocalPort();
00308                         remotePrt = connectInfo->getRemotePort();;
00309                         fsmStatus = connectInfo->getStatus();
00310                         inboundStreams = connectInfo->getInboundStreams();
00311                         outboundStreams = connectInfo->getOutboundStreams();
00312                         
00313                         if (cb)
00314                                 cb->socketEstablished(assocId, yourPtr);
00315                         delete connectInfo;
00316                         break;
00317                 }
00318                 case SCTP_I_PEER_CLOSED:
00319                         sctpEV3<<"peer closed\n";
00320                         sockstate = sockstate==CONNECTED ? PEER_CLOSED : CLOSED;
00321 
00322                         if (cb)
00323                                 cb->socketPeerClosed(assocId, yourPtr);
00324                         break;
00325                 case SCTP_I_ABORT:
00326                 case SCTP_I_CONN_LOST:
00327                 case SCTP_I_CLOSED:
00328 
00329                         sockstate = CLOSED;
00330 
00331                         if (cb)
00332                                 cb->socketClosed(assocId, yourPtr);
00333                         break;
00334                 case SCTP_I_CONNECTION_REFUSED:
00335                 case SCTP_I_CONNECTION_RESET:
00336                 case SCTP_I_TIMED_OUT:
00337                         sockstate = SOCKERROR;
00338                         if (cb)
00339                                 cb->socketFailure(assocId, yourPtr, msg->getKind());
00340 
00341                         break;
00342                 case SCTP_I_STATUS:
00343                         status = check_and_cast<SCTPStatusInfo *>(msg->removeControlInfo());
00344 
00345                         if (cb)
00346                                 cb->socketStatusArrived(assocId, yourPtr, status);
00347                         delete status;
00348                         break;
00349                 case SCTP_I_SHUTDOWN_RECEIVED:
00350                         sctpEV3<<"SCTP_I_SHUTDOWN_RECEIVED\n";
00351                 if (cb)
00352                                 cb->shutdownReceivedArrived(assocId);
00353                         break;
00354                 case SCTP_I_SENDQUEUE_FULL:
00355                         if (cb)
00356                                 cb->sendqueueFullArrived(assocId);
00357                         break;
00358                 default:
00359                         opp_error("SCTPSocket: invalid msg kind %d, one of the SCTP_I_xxx constants expected", msg->getKind());
00360         }
00361 
00362         delete msg;
00363 }


Member Data Documentation

int SCTPSocket::assocId [protected]

int SCTPSocket::sockstate [protected]

Referenced by processMessage().

int SCTPSocket::localPrt [protected]

Referenced by connectx(), and getRemoteAddresses().

int SCTPSocket::remotePrt [protected]

int SCTPSocket::fsmStatus [protected]

Referenced by processMessage().

int SCTPSocket::inboundStreams [protected]

int SCTPSocket::outboundStreams [protected]

int SCTPSocket::lastStream [protected]

Referenced by getLastStream(), SCTPSocket(), and send().

void* SCTPSocket::yourPtr [protected]


The documentation for this class was generated from the following files:

Generated on Fri Mar 20 18:51:21 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5