#include <SCTPClient.h>
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 |
SCTPAssociation * | assoc |
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 |
typedef std::map<IPvXAddress,pathStatus> SCTPClient::SCTPPathStatus |
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().
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 | |||
) |
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] |
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 | ) |
void SCTPClient::addressAddedArrived | ( | int32 | assocId, | |
IPvXAddress | remoteAddr | |||
) |
SCTPSocket SCTPClient::socket [protected] |
SCTPAssociation* SCTPClient::assoc [protected] |
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] |
Referenced by finish(), initialize(), and socketDataArrived().
uint64 SCTPClient::packetsRcvd [protected] |
Referenced by finish(), initialize(), and socketDataArrived().
uint64 SCTPClient::bytesSent [protected] |
Referenced by finish(), initialize(), and sendRequest().
uint64 SCTPClient::echoedBytesSent [protected] |
Referenced by initialize(), and socketDataArrived().
uint64 SCTPClient::bytesRcvd [protected] |
Referenced by finish(), initialize(), and socketDataArrived().
uint64 SCTPClient::numRequestsToSend [protected] |
Referenced by handleTimer(), initialize(), sendRequestArrived(), shutdownReceivedArrived(), and socketEstablished().
uint64 SCTPClient::numPacketsToReceive [protected] |
Referenced by initialize(), socketDataArrived(), and socketEstablished().
uint32 SCTPClient::numBytes [protected] |
Referenced by initialize(), and sendRequest().
int32 SCTPClient::echoFactor [protected] |
Referenced by initialize(), and socketDataArrived().
int32 SCTPClient::queueSize [protected] |
Referenced by initialize(), sendQueueRequest(), sendRequestArrived(), and socketEstablished().
bool SCTPClient::ordered [protected] |
Referenced by initialize(), and sendRequest().
bool SCTPClient::sendAllowed [protected] |
Referenced by handleTimer(), initialize(), sendqueueFullArrived(), sendRequestArrived(), and socketEstablished().
bool SCTPClient::timer [protected] |
Referenced by handleTimer(), initialize(), sendRequestArrived(), and socketEstablished().
cMessage* SCTPClient::timeMsg [protected] |
Referenced by finish(), handleTimer(), initialize(), sendRequestArrived(), socketEstablished(), and socketFailure().
cMessage* SCTPClient::stopTimer [protected] |
Referenced by finish(), and initialize().
Referenced by socketStatusArrived().