Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <omnetpp.h>
00019 #include "SCTPSocket.h"
00020 #include "SCTP.h"
00021 #include "SCTPAssociation.h"
00022
00023 SCTPSocket::SCTPSocket(bool type)
00024 {
00025 sockstate = NOT_BOUND;
00026 localPrt = remotePrt = 0;
00027 cb = NULL;
00028 yourPtr = NULL;
00029 gateToSctp = NULL;
00030 lastStream=-1;
00031 oneToOne = type;
00032 if (oneToOne)
00033 assocId = SCTP::getNewConnId();
00034 else
00035 assocId = 0;
00036 sctpEV3<<"sockstate="<<sockstate<<"\n";
00037 }
00038
00039 SCTPSocket:: ~SCTPSocket()
00040 {
00041 localAddresses.clear();
00042 }
00043
00044 const char *SCTPSocket::stateName(int 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 }
00062
00063 void SCTPSocket::sendToSCTP(cPacket *msg)
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 }
00069
00070 void SCTPSocket::bind(int lPort)
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 }
00078
00079 void SCTPSocket::bind(IPvXAddress lAddr, int lPort)
00080 {
00081 sctpEV3<<"bind address "<<lAddr<<"\n";
00082 if (sockstate!=NOT_BOUND)
00083 opp_error("SCTPSocket::bind(): socket already bound");
00084 localAddresses.push_back(lAddr);
00085 localPrt = lPort;
00086 sockstate = CLOSED;
00087 }
00088
00089 void SCTPSocket::addAddress(IPvXAddress addr)
00090 {
00091 sctpEV3<<"add address "<<addr<<"\n";
00092 localAddresses.push_back(addr);
00093 }
00094
00095 void SCTPSocket::bindx(AddressVector lAddresses, int lPort)
00096 {
00097 IPvXAddress lAddr;
00098 for (AddressVector::iterator i=lAddresses.begin(); i!=lAddresses.end(); ++i)
00099 {
00100 ev<<"bindx: bind address "<<(*i)<<"\n";
00101 localAddresses.push_back((*i));
00102 }
00103 localPrt = lPort;
00104 sockstate = CLOSED;
00105 }
00106
00107 void SCTPSocket::listen(bool fork, uint32 requests, uint32 messagesToPush)
00108 {
00109 if (sockstate!=CLOSED)
00110 opp_error(sockstate==NOT_BOUND ? "SCTPSocket: must call bind() before listen()"
00111 : "SCTPSocket::listen(): connect() or listen() already called");
00112
00113 cPacket *msg = new cPacket("PassiveOPEN", SCTP_C_OPEN_PASSIVE);
00114
00115 SCTPOpenCommand *openCmd = new SCTPOpenCommand();
00116
00117 openCmd->setLocalAddresses(localAddresses);
00118 openCmd->setLocalPort(localPrt);
00119 if (oneToOne)
00120 openCmd->setAssocId(assocId);
00121 else
00122 openCmd->setAssocId(SCTP::getNewConnId());
00123 openCmd->setFork(fork);
00124 openCmd->setInboundStreams(inboundStreams);
00125 openCmd->setOutboundStreams(outboundStreams);
00126 openCmd->setNumRequests(requests);
00127 openCmd->setMessagesToPush(messagesToPush);
00128 msg->setControlInfo(openCmd);
00129 sctpEV3<<"Assoc "<<openCmd->getAssocId()<<"::send PassiveOPEN to SCTP from socket:listen \n";
00130
00131 sendToSCTP(msg);
00132 sockstate = LISTENING;
00133 }
00134
00135 void SCTPSocket::connect(IPvXAddress remoteAddress, int32 remotePort, uint32 numRequests)
00136 {
00137 sctpEV3<<"Socket connect. Assoc="<<assocId<<", sockstate="<<sockstate<<"\n";
00138 if (oneToOne && sockstate!=NOT_BOUND && sockstate!=CLOSED)
00139 opp_error( "SCTPSocket::connect(): connect() or listen() already called");
00140 else if (!oneToOne && sockstate!=LISTENING)
00141 opp_error( "SCTPSocket::connect: One-to-many style socket must be listening");
00142 cPacket *msg = new cPacket("Associate", SCTP_C_ASSOCIATE);
00143 remoteAddr = remoteAddress;
00144 remotePrt = remotePort;
00145 SCTPOpenCommand *openCmd = new SCTPOpenCommand();
00146 if (oneToOne)
00147 openCmd->setAssocId(assocId);
00148 else
00149 openCmd->setAssocId(SCTP::getNewConnId());
00150 sctpEV3<<"Socket connect. Assoc="<<openCmd->getAssocId()<<", sockstate="<<stateName(sockstate)<<"\n";
00151
00152 openCmd->setLocalAddresses(localAddresses);
00153 openCmd->setLocalPort(localPrt);
00154 openCmd->setRemoteAddr(remoteAddr);
00155 openCmd->setRemotePort(remotePrt);
00156 openCmd->setOutboundStreams(outboundStreams);
00157 openCmd->setOutboundStreams(inboundStreams);
00158 openCmd->setNumRequests(numRequests);
00159 msg->setControlInfo(openCmd);
00160 sendToSCTP(msg);
00161 if (oneToOne)
00162 sockstate = CONNECTING;
00163 }
00164
00165
00166 void SCTPSocket::connectx(AddressVector remoteAddressList, int32 remotePort, uint32 numRequests)
00167 {
00168 sctpEV3<<"Socket connectx. sockstate="<<sockstate<<"\n";
00169
00170
00171 if (oneToOne && sockstate!=NOT_BOUND && sockstate!=CLOSED)
00172 opp_error( "SCTPSocket::connect(): connect() or listen() already called");
00173 else if (!oneToOne && sockstate!=LISTENING)
00174 opp_error( "SCTPSocket::connect: One-to-many style socket must be listening");
00175 cPacket *msg = new cPacket("Associate", SCTP_C_ASSOCIATE);
00176 remoteAddresses = remoteAddressList;
00177 remoteAddr = remoteAddresses.front();
00178 remotePrt = remotePort;
00179 SCTPOpenCommand *openCmd = new SCTPOpenCommand();
00180 openCmd->setAssocId(assocId);
00181 openCmd->setLocalAddresses(localAddresses);
00182 openCmd->setLocalPort(localPrt);
00183 openCmd->setRemoteAddr(remoteAddr);
00184 openCmd->setRemoteAddresses(remoteAddresses);
00185 openCmd->setRemotePort(remotePrt);
00186 openCmd->setOutboundStreams(outboundStreams);
00187 openCmd->setNumRequests(numRequests);
00188 msg->setControlInfo(openCmd);
00189 sendToSCTP(msg);
00190 if (oneToOne)
00191 sockstate = CONNECTING;
00192 }
00193
00194 void SCTPSocket::send(cPacket *msg, bool last, bool primary)
00195 {
00196 if (oneToOne && sockstate!=CONNECTED && sockstate!=CONNECTING && sockstate!=PEER_CLOSED) {
00197 opp_error("SCTPSocket::send(): not connected or connecting");
00198 }
00199 else if (!oneToOne && sockstate!=LISTENING) {
00200 opp_error( "SCTPSocket::send: One-to-many style socket must be listening");
00201 }
00202 SCTPSendCommand *cmd = new SCTPSendCommand();
00203 cmd->setAssocId(assocId);
00204 if (msg->getKind() == SCTP_C_SEND_ORDERED)
00205 cmd->setSendUnordered(COMPLETE_MESG_ORDERED);
00206 else
00207 cmd->setSendUnordered(COMPLETE_MESG_UNORDERED);
00208 lastStream=(lastStream+1)%outboundStreams;
00209 cmd->setSid(lastStream);
00210 cmd->setLast(last);
00211 cmd->setPrimary(primary);
00212 msg->setKind(SCTP_C_SEND);
00213 msg->setControlInfo(cmd);
00214 sendToSCTP(msg);
00215 }
00216
00217
00218 void SCTPSocket::sendNotification(cPacket *msg)
00219 {
00220 if (oneToOne && sockstate!=CONNECTED && sockstate!=CONNECTING && sockstate!=PEER_CLOSED) {
00221 opp_error("SCTPSocket::sendNotification(%s): not connected or connecting", msg->getName());
00222 }
00223 else if (!oneToOne && sockstate!=LISTENING) {
00224 opp_error( "SCTPSocket::send: One-to-many style socket must be listening");
00225 }
00226 sendToSCTP(msg);
00227 }
00228
00229 void SCTPSocket::sendRequest(cPacket *msg)
00230 {
00231 sendToSCTP(msg);
00232 }
00233
00234 void SCTPSocket::close()
00235 {
00236 sctpEV3<<"SCTPSocket: close\n";
00237
00238 cPacket *msg = new cPacket("CLOSE", SCTP_C_CLOSE);
00239 SCTPCommand *cmd = new SCTPCommand();
00240 cmd->setAssocId(assocId);
00241 msg->setControlInfo(cmd);
00242 sendToSCTP(msg);
00243 sockstate = sockstate==CONNECTED ? LOCALLY_CLOSED : CLOSED;
00244 }
00245
00246 void SCTPSocket::shutdown()
00247 {
00248 ev<<"SCTPSocket: shutdown\n";
00249
00250 cPacket *msg = new cPacket("Shutdown", SCTP_C_SHUTDOWN);
00251 SCTPCommand *cmd = new SCTPCommand();
00252 cmd->setAssocId(assocId);
00253 msg->setControlInfo(cmd);
00254 sendToSCTP(msg);
00255 }
00256
00257 void SCTPSocket::abort()
00258 {
00259 if (sockstate!=NOT_BOUND && sockstate!=CLOSED && sockstate!=SOCKERROR)
00260 {
00261 cPacket *msg = new cPacket("ABORT", SCTP_C_ABORT);
00262 SCTPCommand *cmd = new SCTPCommand();
00263
00264 cmd->setAssocId(assocId);
00265 msg->setControlInfo(cmd);
00266 sendToSCTP(msg);
00267 }
00268 sockstate = CLOSED;
00269 }
00270
00271 void SCTPSocket::requestStatus()
00272 {
00273 cPacket *msg = new cPacket("STATUS", SCTP_C_STATUS);
00274 SCTPCommand *cmd = new SCTPCommand();
00275 cmd->setAssocId(assocId);
00276 msg->setControlInfo(cmd);
00277 sendToSCTP(msg);
00278 }
00279
00280 bool SCTPSocket::belongsToSocket(cPacket *msg)
00281 {
00282 bool ret= dynamic_cast<SCTPCommand *>(msg->getControlInfo()) &&
00283 ((SCTPCommand *)(msg->getControlInfo()))->getAssocId()==assocId;
00284 sctpEV3<<"assoc="<<((SCTPCommand *)(msg->getControlInfo()))->getAssocId()<<"\n";
00285 return ret;
00286 }
00287
00288 bool SCTPSocket::belongsToAnySCTPSocket(cPacket *msg)
00289 {
00290 return dynamic_cast<SCTPCommand *>(msg->getControlInfo());
00291 }
00292
00293 void SCTPSocket::setCallbackObject(CallbackInterface *callback, void *yourPointer)
00294 {
00295 cb = callback;
00296 yourPtr = yourPointer;
00297 }
00298
00299 void SCTPSocket::processMessage(cPacket *msg)
00300 {
00301 SCTPStatusInfo *status;
00302 switch (msg->getKind())
00303 {
00304 case SCTP_I_DATA:
00305 sctpEV3<<"SCTP_I_DATA\n";
00306 if (cb)
00307 cb->socketDataArrived(assocId, yourPtr, msg, false);
00308 break;
00309 case SCTP_I_DATA_NOTIFICATION:
00310 sctpEV3<<"SCTP_I_NOTIFICATION\n";
00311 if (cb)
00312 cb->socketDataNotificationArrived(assocId, yourPtr, msg);
00313 break;
00314 case SCTP_I_SEND_MSG:
00315 if (cb)
00316 cb->sendRequestArrived();
00317 break;
00318 case SCTP_I_ESTABLISHED:
00319 {
00320 if (oneToOne)
00321 sockstate = CONNECTED;
00322 SCTPConnectInfo *connectInfo = check_and_cast<SCTPConnectInfo *>(msg->removeControlInfo());
00323 localAddr = connectInfo->getLocalAddr();
00324 remoteAddr = connectInfo->getRemoteAddr();
00325 localPrt = connectInfo->getLocalPort();
00326 remotePrt = connectInfo->getRemotePort();;
00327 fsmStatus = connectInfo->getStatus();
00328 inboundStreams = connectInfo->getInboundStreams();
00329 outboundStreams = connectInfo->getOutboundStreams();
00330
00331 if (cb)
00332 cb->socketEstablished(assocId, yourPtr, connectInfo->getNumMsgs());
00333 delete connectInfo;
00334 break;
00335 }
00336 case SCTP_I_PEER_CLOSED:
00337 sctpEV3<<"peer closed\n";
00338 if (oneToOne)
00339 sockstate = sockstate==CONNECTED ? PEER_CLOSED : CLOSED;
00340
00341 if (cb)
00342 cb->socketPeerClosed(assocId, yourPtr);
00343 break;
00344 case SCTP_I_ABORT:
00345 case SCTP_I_CONN_LOST:
00346 case SCTP_I_CLOSED:
00347 sctpEV3<<"SCTP_I_CLOSED called\n";
00348 sockstate = CLOSED;
00349
00350 if (cb)
00351 cb->socketClosed(assocId, yourPtr);
00352 break;
00353 case SCTP_I_CONNECTION_REFUSED:
00354 case SCTP_I_CONNECTION_RESET:
00355 case SCTP_I_TIMED_OUT:
00356 sockstate = SOCKERROR;
00357 if (cb)
00358 cb->socketFailure(assocId, yourPtr, msg->getKind());
00359
00360 break;
00361 case SCTP_I_STATUS:
00362 status = check_and_cast<SCTPStatusInfo *>(msg->removeControlInfo());
00363
00364 if (cb)
00365 cb->socketStatusArrived(assocId, yourPtr, status);
00366 delete status;
00367 break;
00368 case SCTP_I_SHUTDOWN_RECEIVED:
00369 sctpEV3<<"SCTP_I_SHUTDOWN_RECEIVED\n";
00370 if (cb)
00371 cb->shutdownReceivedArrived(assocId);
00372 break;
00373 case SCTP_I_SENDQUEUE_FULL:
00374 if (cb)
00375 cb->sendqueueFullArrived(assocId);
00376 break;
00377 case SCTP_I_SENDQUEUE_ABATED:
00378 {
00379 SCTPCommand *cmd = check_and_cast<SCTPCommand *>(msg->removeControlInfo());
00380 if (cb)
00381 {
00382 cb->sendqueueAbatedArrived(assocId, cmd->getNumMsgs());
00383 }
00384 delete cmd;
00385 break;
00386 }
00387 default:
00388 opp_error("SCTPSocket: invalid msg kind %d, one of the SCTP_I_xxx constants expected", msg->getKind());
00389 }
00390
00391 delete msg;
00392 }
00393
00394