SCTPSocket.cc

Go to the documentation of this file.
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