SCTPClient Class Reference

#include <SCTPClient.h>

Inheritance diagram for SCTPClient:

SCTPSocket::CallbackInterface

List of all members.

Public Types

typedef std::map< IPvXAddress,
pathStatus
SCTPPathStatus

Public Member Functions

void initialize ()
void handleMessage (cMessage *msg)
void finish ()
void handleTimer (cMessage *msg)
void setAssociation (SCTPAssociation *_assoc)
void setPrimaryPath (const char *addr)
void sendRequestArrived ()
void sendQueueRequest ()
void shutdownReceivedArrived (int32 connId)
void sendqueueFullArrived (int32 connId)
void addressAddedArrived (int32 assocId, IPvXAddress remoteAddr)
Utility functions


void connect ()
void close ()
void setStatusString (const char *s)
SCTPSocket::CallbackInterface callback methods


void socketEstablished (int32 connId, void *yourPtr)
void socketDataArrived (int32 connId, void *yourPtr, cPacket *msg, bool urgent)
void socketDataNotificationArrived (int32 connId, void *yourPtr, cPacket *msg)
void socketPeerClosed (int32 connId, void *yourPtr)
void socketClosed (int32 connId, void *yourPtr)
void socketFailure (int32 connId, void *yourPtr, int32 code)
void socketStatusArrived (int32 connId, void *yourPtr, SCTPStatusInfo *status)

Public Attributes

SCTPPathStatus sctpPathStatus

Protected Member Functions

void sendRequest (bool last=true)

Protected Attributes

SCTPSocket socket
SCTPAssociationassoc
int32 numSessions
int32 numBroken
uint64 packetsSent
uint64 packetsRcvd
uint64 bytesSent
uint64 echoedBytesSent
uint64 bytesRcvd
uint64 numRequestsToSend
uint64 numPacketsToReceive
uint32 numBytes
int32 echoFactor
int32 queueSize
bool ordered
bool sendAllowed
bool timer
cMessage * timeMsg
cMessage * stopTimer

Classes

struct  pathStatus


Member Typedef Documentation


Member Function Documentation

void SCTPClient::sendRequest ( bool  last = true  )  [protected]

Utility: sends a request to the server

Referenced by handleTimer(), sendRequestArrived(), and socketEstablished().

00285 {
00286         uint32 i;
00287         
00288         if (numBytes < 1)
00289                 numBytes=1;
00290          
00291         cPacket* cmsg = new cPacket("AppData");
00292         SCTPSimpleMessage* msg=new SCTPSimpleMessage("data");
00293 
00294         msg->setDataArraySize(numBytes);
00295         for (i=0; i<numBytes; i++)
00296         {
00297                 msg->setData(i, 'a');
00298         }
00299         msg->setDataLen(numBytes);
00300         msg->setBitLength(numBytes * 8);
00301         msg->setCreationTime(simulation.getSimTime());
00302         cmsg->encapsulate(msg);
00303         if (ordered)
00304                 cmsg->setKind(SCTP_C_SEND_ORDERED);
00305         else
00306                 cmsg->setKind(SCTP_C_SEND_UNORDERED);
00307         // send SCTPMessage with SCTPSimpleMessage enclosed
00308         socket.send(cmsg, last);
00309         bytesSent+=numBytes;
00310 }

void SCTPClient::initialize (  ) 

Initialization.

00033 {
00034         const char * address;
00035         char* token;
00036         AddressVector addresses;
00037         sctpEV3<<"initialize SCTP Client\n";    
00038         numSessions = numBroken = packetsSent = packetsRcvd = bytesSent = echoedBytesSent = bytesRcvd = 0;
00039         WATCH(numSessions);
00040         WATCH(numBroken);
00041         WATCH(packetsSent);
00042         WATCH(packetsRcvd);
00043         WATCH(bytesSent);
00044         WATCH(bytesRcvd);
00045         
00046         // parameters
00047         address=par("address");
00048 
00049         token = strtok((char*)address,",");
00050         while (token != NULL)
00051         {
00052                 addresses.push_back(IPvXAddress(token));
00053                 token = strtok(NULL, ",");
00054         }
00055         int32 port = par("port");
00056         echoFactor = par("echoFactor");
00057         if (!echoFactor) echoFactor = false;
00058         ordered = (bool)par("ordered");
00059         if (strcmp(address,"")==0)
00060         {
00061                 socket.bind(port);
00062         }
00063         else
00064         {
00065                 socket.bindx(addresses, port);
00066         } 
00067         
00068         socket.setCallbackObject(this);
00069         socket.setOutputGate(gate("sctpOut"));
00070         setStatusString("waiting");
00071 
00072         timeMsg = new cMessage("CliAppTimer");
00073         numRequestsToSend = 0;
00074         numPacketsToReceive = 0;
00075         queueSize = par("queueSize");
00076         WATCH(numRequestsToSend);
00077         numBytes = par("requestLength");
00078         recordScalar("ums", numBytes);
00079         timeMsg->setKind(MSGKIND_CONNECT);
00080         scheduleAt((simtime_t)par("startTime"), timeMsg);
00081         sendAllowed = true;
00082         if ((simtime_t)par("stopTime")!=0)
00083         {
00084                 stopTimer = new cMessage("StopTimer");
00085                 stopTimer->setKind(MSGKIND_STOP);
00086                 scheduleAt((simtime_t)par("stopTime"), stopTimer);
00087                 timer = true;
00088         }
00089         else
00090         {
00091                 timer = false;
00092                 stopTimer = NULL;
00093         }
00094         if ((simtime_t)par("primaryTime")!=0)
00095         {
00096                 cMessage* cmsg = new cMessage("PrimaryTime");
00097                 cmsg->setKind(MSGKIND_PRIMARY);
00098                 scheduleAt((simtime_t)par("primaryTime"), cmsg);
00099         }
00100 }

void SCTPClient::handleMessage ( cMessage *  msg  ) 

For self-messages it invokes handleTimer(); messages arriving from SCTP will get dispatched to the socketXXX() functions.

00103 {
00104         if (msg->isSelfMessage())
00105                 handleTimer(msg);
00106         else
00107         {
00108                 socket.processMessage(PK(msg));
00109         }
00110 }

void SCTPClient::finish (  ) 

Records basic statistics: numSessions, packetsSent, packetsRcvd, bytesSent, bytesRcvd. Redefine to record different or more statistics at the end of the simulation.

00480 {
00481         if (timeMsg->isScheduled())
00482                 cancelEvent(timeMsg);
00483         delete timeMsg;
00484         if (stopTimer)
00485         {
00486                 cancelEvent(stopTimer);
00487                 delete stopTimer;
00488         }
00489         ev << getFullPath() << ": opened " << numSessions << " sessions\n";
00490         ev << getFullPath() << ": sent " << bytesSent << " bytes in " << packetsSent << " packets\n";
00491         ev << getFullPath() << ": received " << bytesRcvd << " bytes in " << packetsRcvd << " packets\n";
00492         sctpEV3<<"Client finished\n";
00493 }

void SCTPClient::connect (  ) 

Issues an active OPEN to the address/port given as module parameters

Referenced by handleTimer().

00113 {
00114         const char *connectAddress = par("connectAddress");
00115         int32 connectPort = par("connectPort");
00116         uint32 outStreams = par("outboundStreams");
00117         socket.setOutboundStreams(outStreams);
00118         ev << "issuing OPEN command\n";
00119         setStatusString("connecting");
00120         ev<<"connect to address "<<connectAddress<<"\n";
00121         socket.connect(IPAddressResolver().resolve(connectAddress, 1), connectPort, (uint32)par("numRequestsPerSession"));
00122 
00123 numSessions++;
00124 }

void SCTPClient::close (  ) 

Issues CLOSE command

Referenced by handleTimer(), socketDataArrived(), and socketPeerClosed().

00127 {
00128         setStatusString("closing");
00129         socket.close();
00130 }

void SCTPClient::setStatusString ( const char *  s  ) 

Sends a GenericAppMsg of the given length When running under GUI, it displays the given string next to the icon

Referenced by close(), connect(), initialize(), socketClosed(), socketEstablished(), and socketFailure().

00134 {
00135         if (ev.isGUI()) getDisplayString().setTagArg("t", 0, s);
00136 }

void SCTPClient::handleTimer ( cMessage *  msg  ) 

Invoked from handleMessage(). Should be redefined to handle self-messages.

Referenced by handleMessage().

00313 {
00314         
00315         switch (msg->getKind())
00316         {
00317                 case MSGKIND_CONNECT:
00318                         ev << "starting session call connect\n";
00319                         connect();
00320                         break;
00321         
00322                 case MSGKIND_SEND:
00323                         
00324                         if ((!timer && numRequestsToSend>0 || timer))
00325                         {
00326                                 if (sendAllowed)
00327                                 {
00328                                         sendRequest();
00329                                         if (!timer)
00330                                                 numRequestsToSend--;
00331                                 }
00332                                 if ((simtime_t)par("thinkTime") > 0)
00333                                         scheduleAt(simulation.getSimTime()+(simtime_t)par("thinkTime"), timeMsg);
00334                                 
00335                                 if ((!timer && numRequestsToSend == 0) && (simtime_t)par("waitToClose")==0)
00336                                 {
00337                                         socket.shutdown();
00338                                         if (timeMsg->isScheduled())
00339                                                 cancelEvent(timeMsg);
00340                                 }       
00341                         }
00342                         else if ((!timer && numRequestsToSend == 0) && (simtime_t)par("waitToClose")==0)
00343                         {
00344                                         socket.shutdown();
00345                                         if (timeMsg->isScheduled())
00346                                                 cancelEvent(timeMsg);
00347                         }       
00348                         break;
00349                 case MSGKIND_ABORT:
00350                         close();
00351                         break;
00352                 case MSGKIND_PRIMARY:
00353                         setPrimaryPath((const char*)par("newPrimary"));
00354                         break;
00355                 case MSGKIND_STOP:
00356                         numRequestsToSend=0;
00357                         sendAllowed = false;
00358                         socket.shutdown();
00359                         if (timeMsg->isScheduled())
00360                                 cancelEvent(timeMsg);
00361                         //socket.close();
00362                         break;
00363                 default:
00364                         ev<<"MsgKind ="<<msg->getKind()<<" unknown\n";
00365                         break;
00366         }
00367 }

void SCTPClient::socketEstablished ( int32  connId,
void *  yourPtr 
)

Does nothing but update statistics/status. Redefine to perform or schedule first sending.

00139 {
00140         int32 count = 0;
00141         ev<<"SCTPClient: connected\n";
00142         setStatusString("connected");
00143         // determine number of requests in this session
00144         numRequestsToSend = (long) par("numRequestsPerSession");
00145         numPacketsToReceive = (long) par("numPacketsToReceive");
00146         if (numRequestsToSend<1) 
00147                 numRequestsToSend = 0;
00148         // perform first request (next one will be sent when reply arrives)
00149         if ((numRequestsToSend>0 && !timer) || timer)
00150         {
00151                 if ((simtime_t)par("thinkTime") > 0)
00152                 {
00153                         if (sendAllowed)
00154                         {
00155                                 sendRequest();
00156                                 if (!timer)
00157                                         numRequestsToSend--;
00158                         }
00159                         timeMsg->setKind(MSGKIND_SEND);
00160                         scheduleAt(simulation.getSimTime()+(simtime_t)par("thinkTime"), timeMsg);
00161                         
00162                 }
00163                 else
00164                 {
00165                         if (queueSize>0)
00166                         {
00167                                 while (((!timer && numRequestsToSend > 0) || timer) && count++ < queueSize*2 && sendAllowed)
00168                                 {
00169                                         if (count == queueSize*2)
00170                                                 sendRequest();
00171                                         else
00172                                                 sendRequest(false);
00173                                         if (!timer)
00174                                         {
00175                                                 if (--numRequestsToSend == 0)
00176                                                         sendAllowed = false;
00177                                         }
00178 
00179                                 }
00180                                 if ((!timer && numRequestsToSend>0 || timer) && sendAllowed)
00181                                         sendQueueRequest();
00182                         }
00183                         else
00184                         {
00185                                 while ((!timer && numRequestsToSend>0 || timer) && sendAllowed)
00186                                 {
00187                                         if (!timer && numRequestsToSend==1)
00188                                                 sendRequest(true);
00189                                         else
00190                                                 sendRequest(false);
00191                                         if (!timer)
00192                                                 numRequestsToSend--;
00193                                 }
00194                         }
00195                         
00196                         if ((!timer && numPacketsToReceive == 0) && (simtime_t)par("waitToClose")>0)
00197                         {       
00198                                 timeMsg->setKind(MSGKIND_ABORT);
00199                                 scheduleAt(simulation.getSimTime()+(simtime_t)par("waitToClose"), timeMsg);
00200                         }
00201                         if ((!timer && numRequestsToSend == 0) && (simtime_t)par("waitToClose")==0)
00202                         {
00203                                 sctpEV3<<"socketEstablished:no more packets to send, call shutdown\n";
00204                                 socket.shutdown();
00205                                 if (timeMsg->isScheduled())
00206                                         cancelEvent(timeMsg);
00207                         }       
00208                 }
00209         }
00210 }

void SCTPClient::socketDataArrived ( int32  connId,
void *  yourPtr,
cPacket *  msg,
bool  urgent 
)

Does nothing but update statistics/status. Redefine to perform or schedule next sending. Beware: this funcion deletes the incoming message, which might not be what you want.

00252 {
00253         packetsRcvd++;
00254          
00255         sctpEV3<<"Client received packet Nr "<<packetsRcvd<<" from SCTP\n";
00256         SCTPCommand* ind = check_and_cast<SCTPCommand*>(msg->removeControlInfo());
00257         bytesRcvd+=msg->getByteLength();
00258         if (echoFactor > 0)
00259         {
00260                 SCTPSimpleMessage *smsg=check_and_cast<SCTPSimpleMessage*>(msg->dup());
00261                 cPacket* cmsg = new cPacket("SVData");  
00262                 echoedBytesSent+=smsg->getBitLength()/8;
00263                 cmsg->encapsulate(smsg);
00264                 if (ind->getSendUnordered())
00265                         cmsg->setKind(SCTP_C_SEND_UNORDERED);
00266                 else
00267                         cmsg->setKind(SCTP_C_SEND_ORDERED);
00268                 packetsSent++;
00269                 delete msg;
00270                 socket.send(cmsg, 1);
00271         }
00272         if ((long)par("numPacketsToReceive")>0)
00273         {
00274                 numPacketsToReceive--;
00275                 if (numPacketsToReceive == 0)
00276                 {
00277                         close();
00278                 }
00279         }
00280         delete ind;
00281 }

void SCTPClient::socketDataNotificationArrived ( int32  connId,
void *  yourPtr,
cPacket *  msg 
)

00371 {
00372         SCTPCommand *ind = check_and_cast<SCTPCommand *>(msg->removeControlInfo());
00373         cPacket* cmsg = new cPacket("CMSG");
00374         SCTPSendCommand *cmd = new SCTPSendCommand();
00375         cmd->setAssocId(ind->getAssocId());
00376         cmd->setSid(ind->getSid());
00377         cmd->setNumMsgs(ind->getNumMsgs());
00378         cmsg->setKind(SCTP_C_RECEIVE);
00379         cmsg->setControlInfo(cmd);  
00380         delete ind;
00381         socket.sendNotification(cmsg);
00382 }

void SCTPClient::socketPeerClosed ( int32  connId,
void *  yourPtr 
)

Since remote SCTP closed, invokes close(). Redefine if you want to do something else.

00398 {
00399         // close the connection (if not already closed)
00400         if (socket.getState()==SCTPSocket::PEER_CLOSED)
00401         {
00402                 ev << "remote SCTP closed, closing here as well\n";
00403                 close();
00404         }
00405 }

void SCTPClient::socketClosed ( int32  connId,
void *  yourPtr 
)

Does nothing but update statistics/status. Redefine if you want to do something else, such as opening a new connection.

00408 {
00409         // *redefine* to start another session etc.
00410         ev << "connection closed\n";
00411         setStatusString("closed");
00412 }

void SCTPClient::socketFailure ( int32  connId,
void *  yourPtr,
int32  code 
)

Does nothing but update statistics/status. Redefine if you want to try reconnecting after a delay.

00415 {
00416         // subclasses may override this function, and add code try to reconnect after a delay.
00417         ev << "connection broken\n";
00418         setStatusString("broken");
00419         
00420         numBroken++;
00421         
00422         // reconnect after a delay
00423         timeMsg->setKind(MSGKIND_CONNECT);
00424         scheduleAt(simulation.getSimTime()+(simtime_t)par("reconnectInterval"), timeMsg);
00425 }

void SCTPClient::socketStatusArrived ( int32  connId,
void *  yourPtr,
SCTPStatusInfo *  status 
)

Redefine to handle incoming SCTPStatusInfo.

00428 {
00429 struct pathStatus ps;
00430         SCTPPathStatus::iterator i=sctpPathStatus.find(status->getPathId());
00431         if (i!=sctpPathStatus.end())
00432         {
00433                 ps = i->second;
00434                 ps.active=status->getActive();
00435         }
00436         else
00437         {
00438                 ps.active = status->getActive();
00439                 ps.pid = status->getPathId();
00440                 ps.primaryPath = false;
00441                 sctpPathStatus[ps.pid]=ps;
00442         }
00443 }

void SCTPClient::setAssociation ( SCTPAssociation _assoc  )  [inline]

00128 {assoc = _assoc;};

void SCTPClient::setPrimaryPath ( const char *  addr  ) 

Referenced by handleTimer().

00446 {
00447 
00448         cPacket* cmsg = new cPacket("CMSG");
00449         SCTPPathInfo *pinfo = new SCTPPathInfo();
00450         if (strcmp(str,"")!=0)
00451         {
00452                 pinfo->setRemoteAddress(IPvXAddress(str));
00453         }
00454         else
00455         {
00456                 str = (const char*)par("primaryPath");
00457                 if (strcmp(str, "")!=0)
00458                         pinfo->setRemoteAddress(IPvXAddress(str));
00459         }
00460 
00461         pinfo->setAssocId(socket.getConnectionId());
00462         cmsg->setKind(SCTP_C_PRIMARY);
00463         cmsg->setControlInfo(pinfo);  
00464         socket.sendNotification(cmsg);
00465 }

void SCTPClient::sendRequestArrived (  )  [virtual]

Reimplemented from SCTPSocket::CallbackInterface.

00225 {
00226 int32 count = 0;
00227 
00228         sctpEV3<<"sendRequestArrived numRequestsToSend="<<numRequestsToSend<<"\n";
00229         while ((!timer && numRequestsToSend > 0 || timer) && count++ < queueSize && sendAllowed)
00230         {
00231                 if (count == queueSize)
00232                         sendRequest();
00233                 else
00234                         sendRequest(false);
00235 
00236                 if (!timer)
00237                         numRequestsToSend--;
00238                 
00239                 if ((!timer && numRequestsToSend == 0))
00240                 {
00241                         sctpEV3<<"no more packets to send, call shutdown\n";
00242                         socket.shutdown();
00243                         if (timeMsg->isScheduled())
00244                                 cancelEvent(timeMsg);
00245                 }       
00246         }
00247         
00248         
00249 }

void SCTPClient::sendQueueRequest (  ) 

Referenced by socketEstablished().

00213 {
00214         cPacket* cmsg = new cPacket("Queue");
00215         SCTPInfo* qinfo = new SCTPInfo();
00216         qinfo->setText(queueSize);
00217         cmsg->setKind(SCTP_C_QUEUE);
00218         qinfo->setAssocId(socket.getConnectionId());
00219         cmsg->setControlInfo(qinfo);  
00220         socket.sendRequest(cmsg);
00221         
00222 }

void SCTPClient::shutdownReceivedArrived ( int32  connId  ) 

00385 {
00386         if (numRequestsToSend==0)
00387         {
00388                 cPacket* cmsg = new cPacket("Request");
00389                 SCTPInfo* qinfo = new SCTPInfo();
00390                 cmsg->setKind(SCTP_C_NO_OUTSTANDING);
00391                 qinfo->setAssocId(connId);
00392                 cmsg->setControlInfo(qinfo);  
00393                 socket.sendNotification(cmsg);
00394         }
00395 }

void SCTPClient::sendqueueFullArrived ( int32  connId  ) 

00471 {
00472         sendAllowed = false;
00473 }

void SCTPClient::addressAddedArrived ( int32  assocId,
IPvXAddress  remoteAddr 
)

00476 {
00477 }


Member Data Documentation

Referenced by setAssociation().

int32 SCTPClient::numSessions [protected]

Referenced by connect(), finish(), and initialize().

int32 SCTPClient::numBroken [protected]

Referenced by initialize(), and socketFailure().

uint64 SCTPClient::packetsSent [protected]

uint64 SCTPClient::packetsRcvd [protected]

uint64 SCTPClient::bytesSent [protected]

Referenced by finish(), initialize(), and sendRequest().

uint64 SCTPClient::echoedBytesSent [protected]

Referenced by initialize(), and socketDataArrived().

uint64 SCTPClient::bytesRcvd [protected]

uint64 SCTPClient::numRequestsToSend [protected]

uint64 SCTPClient::numPacketsToReceive [protected]

uint32 SCTPClient::numBytes [protected]

Referenced by initialize(), and sendRequest().

int32 SCTPClient::echoFactor [protected]

Referenced by initialize(), and socketDataArrived().

int32 SCTPClient::queueSize [protected]

bool SCTPClient::ordered [protected]

Referenced by initialize(), and sendRequest().

bool SCTPClient::sendAllowed [protected]

bool SCTPClient::timer [protected]

cMessage* SCTPClient::timeMsg [protected]

cMessage* SCTPClient::stopTimer [protected]

Referenced by finish(), and initialize().

Referenced by socketStatusArrived().


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