|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2008 Irene Ruengeler 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 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 //openCmd->setLocalAddr(localAddr); 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 //openCmd->setAssocId(assocId); 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 /*if (sockstate!=NOT_BOUND && sockstate!=CLOSED) 00170 opp_error( "SCTPSocket::connect(): connect() or listen() already called");*/ 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 //sctpEV3<<"Message cmd="<<&cmd<<"\n"; 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