INET Framework for OMNeT++/OMNEST
SCTPPeer Class Reference

#include <SCTPPeer.h>

Inheritance diagram for SCTPPeer:
SCTPSocket::CallbackInterface

List of all members.

Classes

struct  pathStatus

Public Types

typedef std::map< IPvXAddress,
pathStatus
SCTPPathStatus

Public Member Functions

void initialize ()
void handleMessage (cMessage *msg)
void finish ()
void handleTimer (cMessage *msg)
void generateAndSend (SCTPConnectInfo *connectInfo)
void connect ()
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)
void setPrimaryPath ()
void sendRequestArrived ()
void sendQueueRequest ()
void shutdownReceivedArrived (int32 connId)
void sendqueueFullArrived (int32 connId)
void setStatusString (const char *s)
void addressAddedArrived (int32 assocId, IPvXAddress remoteAddr)

Public Attributes

SCTPPathStatus sctpPathStatus

Protected Types

typedef std::map< int32, long > RcvdPacketsPerAssoc
typedef std::map< int32, long > SentPacketsPerAssoc
typedef std::map< int32, long > RcvdBytesPerAssoc
typedef std::map< int32,
cOutVector * > 
BytesPerAssoc
typedef std::map< int32,
cDoubleHistogram * > 
HistEndToEndDelay
typedef std::map< int32,
cOutVector * > 
EndToEndDelay

Protected Member Functions

void sendOrSchedule (cPacket *msg)
void sendRequest (bool last=true)

Protected Attributes

int32 notifications
int32 serverAssocId
int32 clientAssocId
SCTPSocket clientSocket
double delay
double echoFactor
bool schedule
bool shutdownReceived
long bytesSent
int32 packetsSent
int32 packetsRcvd
int32 numSessions
int32 numRequestsToSend
bool ordered
int32 queueSize
cMessage * timeoutMsg
int32 outboundStreams
cMessage * timeMsg
cMessage * connectTimer
int32 bytesRcvd
int32 echoedBytesSent
int32 lastStream
bool sendAllowed
int32 numPacketsToReceive
RcvdPacketsPerAssoc rcvdPacketsPerAssoc
SentPacketsPerAssoc sentPacketsPerAssoc
RcvdBytesPerAssoc rcvdBytesPerAssoc
BytesPerAssoc bytesPerAssoc
HistEndToEndDelay histEndToEndDelay
EndToEndDelay endToEndDelay
int32 ssn

Member Typedef Documentation

typedef std::map<int32,cOutVector*> SCTPPeer::BytesPerAssoc [protected]
typedef std::map<int32,cOutVector*> SCTPPeer::EndToEndDelay [protected]
typedef std::map<int32,cDoubleHistogram*> SCTPPeer::HistEndToEndDelay [protected]
typedef std::map<int32,long> SCTPPeer::RcvdBytesPerAssoc [protected]
typedef std::map<int32,long> SCTPPeer::RcvdPacketsPerAssoc [protected]
typedef std::map<int32,long> SCTPPeer::SentPacketsPerAssoc [protected]

Member Function Documentation

void SCTPPeer::addressAddedArrived ( int32  assocId,
IPvXAddress  remoteAddr 
)
void SCTPPeer::connect ( )

Referenced by handleTimer().

{
    const char *connectAddress = par("connectAddress");
    int32 connectPort = par("connectPort");
    uint32 outStreams = par("outboundStreams");
    clientSocket.setOutboundStreams(outStreams);

    sctpEV3 << "issuing OPEN command\n";
    sctpEV3<<"Assoc "<<clientSocket.getConnectionId()<<"::connect to address "<<connectAddress<<", port "<<connectPort<<"\n";
    numSessions++;
    clientSocket.connect(IPAddressResolver().resolve(connectAddress, 1), connectPort, (uint32)par("numRequestsPerSession"));

}
void SCTPPeer::finish ( )
{
    delete timeoutMsg;
    delete connectTimer;
        ev << getFullPath() << ": opened " << numSessions << " sessions\n";
    ev << getFullPath() << ": sent " << bytesSent << " bytes in " << packetsSent << " packets\n";
    for (RcvdBytesPerAssoc::iterator l=rcvdBytesPerAssoc.begin(); l!=rcvdBytesPerAssoc.end(); l++)
    {
        ev << getFullPath() << ": received " << l->second << " bytes in assoc " << l->first<< "\n";
    }
    ev << getFullPath() << "Over all " << packetsRcvd << " packets received\n ";
    ev << getFullPath() << "Over all " << notifications << " notifications received\n ";
    for (BytesPerAssoc::iterator j = bytesPerAssoc.begin(); j!= bytesPerAssoc.end(); j++)
    {
        delete j->second;
        bytesPerAssoc.erase(j);
    }
    for (EndToEndDelay::iterator k = endToEndDelay.begin(); k!= endToEndDelay.end(); k++)
    {
        delete k->second;
        endToEndDelay.erase(k);
    }
    for (HistEndToEndDelay::iterator l = histEndToEndDelay.begin(); l!= histEndToEndDelay.end(); l++)
    {
        delete l->second;
        histEndToEndDelay.erase(l);
    }
    rcvdPacketsPerAssoc.clear();
    sentPacketsPerAssoc.clear();
    rcvdBytesPerAssoc.clear();
}
void SCTPPeer::generateAndSend ( SCTPConnectInfo *  connectInfo)

Referenced by handleMessage(), and handleTimer().

{
uint32 numBytes;
    cPacket* cmsg = new cPacket("CMSG");
    SCTPSimpleMessage* msg=new SCTPSimpleMessage("Server");
    numBytes=(long)par("requestLength");
    msg->setDataArraySize(numBytes);
    for (uint32 i=0; i<numBytes; i++)
    {
        msg->setData(i, 's');
    }
    msg->setDataLen(numBytes);
    msg->setByteLength(numBytes);
    cmsg->encapsulate(msg);
    SCTPSendCommand *cmd = new SCTPSendCommand();
    cmd->setAssocId(serverAssocId);
    if (ordered)
        cmd->setSendUnordered(COMPLETE_MESG_ORDERED);
    else
        cmd->setSendUnordered(COMPLETE_MESG_UNORDERED);
    lastStream=(lastStream+1)%outboundStreams;
    cmd->setSid(lastStream);
    cmd->setLast(true);
    cmsg->setKind(SCTP_C_SEND);
    cmsg->setControlInfo(cmd);
    packetsSent++;
    bytesSent+=msg->getBitLength()/8;
    sendOrSchedule(cmsg);
}
void SCTPPeer::handleMessage ( cMessage *  msg)
{
    int32 id;

    if (msg->isSelfMessage())
    {

        handleTimer(msg);
    }
    switch (msg->getKind())
    {
        case SCTP_I_PEER_CLOSED:
        case SCTP_I_ABORT:
        {
            SCTPCommand *ind = check_and_cast<SCTPCommand *>(msg->getControlInfo()->dup());
            cPacket* cmsg = new cPacket("Notification");
            SCTPSendCommand *cmd = new SCTPSendCommand();
            id = ind->getAssocId();
            cmd->setAssocId(id);
            cmd->setSid(ind->getSid());
            cmd->setNumMsgs(ind->getNumMsgs());
            cmsg->setControlInfo(cmd);
            delete ind;
            delete msg;
            cmsg->setKind(SCTP_C_ABORT);
            sendOrSchedule(cmsg);
            break;
        }
        case SCTP_I_ESTABLISHED:
        {
            if (clientSocket.getState()==SCTPSocket::CONNECTING)
                clientSocket.processMessage(PK(msg));
            else
            {
                int32 count=0;
                SCTPConnectInfo *connectInfo = dynamic_cast<SCTPConnectInfo *>(msg->removeControlInfo());
                numSessions++;
                serverAssocId = connectInfo->getAssocId();
                id = serverAssocId;
                outboundStreams = connectInfo->getOutboundStreams();
                rcvdPacketsPerAssoc[serverAssocId]= (long) par("numPacketsToReceivePerClient");
                sentPacketsPerAssoc[serverAssocId]= (long) par("numPacketsToSendPerClient");
                char text[30];
                sprintf(text, "App: Received Bytes of assoc %d",serverAssocId);
                bytesPerAssoc[serverAssocId] = new cOutVector(text);
                rcvdBytesPerAssoc[serverAssocId]= 0;
                sprintf(text, "App: EndToEndDelay of assoc %d",serverAssocId);
                endToEndDelay[serverAssocId] = new cOutVector(text);
                sprintf(text, "Hist: EndToEndDelay of assoc %d",serverAssocId);
                histEndToEndDelay[serverAssocId] = new cDoubleHistogram(text);

                //delete connectInfo;
                delete msg;
                if ((long) par("numPacketsToSendPerClient") > 0)
                {
                    SentPacketsPerAssoc::iterator i=sentPacketsPerAssoc.find(serverAssocId);
                    numRequestsToSend = i->second;
                    if ((simtime_t)par("thinkTime") > 0)
                    {
                        generateAndSend(connectInfo);
                        timeoutMsg->setKind(SCTP_C_SEND);
                        scheduleAt(simulation.getSimTime()+(simtime_t)par("thinkTime"), timeoutMsg);
                        numRequestsToSend--;
                        i->second = numRequestsToSend;
                    }
                    else
                    {
                        if (queueSize==0)
                        {
                            while (numRequestsToSend > 0)
                            {
                                generateAndSend(connectInfo);
                                numRequestsToSend--;
                                i->second = numRequestsToSend;
                            }
                        }
                        else if (queueSize>0)
                        {
                            while (numRequestsToSend > 0 && count++ < queueSize*2)
                            {
                                generateAndSend(connectInfo);
                                numRequestsToSend--;
                                i->second = numRequestsToSend;
                            }

                            cPacket* cmsg = new cPacket("Queue");
                            SCTPInfo* qinfo = new SCTPInfo();
                            qinfo->setText(queueSize);
                            cmsg->setKind(SCTP_C_QUEUE_MSGS_LIMIT);
                            qinfo->setAssocId(id);
                            cmsg->setControlInfo(qinfo);
                            sendOrSchedule(cmsg);
                        }

                        sctpEV3<<"!!!!!!!!!!!!!!!All data sent from Server !!!!!!!!!!\n";

                        RcvdPacketsPerAssoc::iterator j=rcvdPacketsPerAssoc.find(serverAssocId);
                        if (j->second == 0 && (simtime_t)par("waitToClose")>0)
                        {
                            char as[5];
                            sprintf(as, "%d",serverAssocId);
                            cMessage* abortMsg = new cMessage(as);
                            abortMsg->setKind(SCTP_I_ABORT);
                            scheduleAt(simulation.getSimTime()+(simtime_t)par("waitToClose"), abortMsg);
                        }
                        else
                        {
                            sctpEV3<<"no more packets to send, call shutdown for assoc "<<serverAssocId<<"\n";
                            cPacket* cmsg = new cPacket("ShutdownRequest");
                            SCTPCommand* cmd = new SCTPCommand();
                            cmsg->setKind(SCTP_C_SHUTDOWN);
                            cmd->setAssocId(serverAssocId);
                            cmsg->setControlInfo(cmd);
                            sendOrSchedule(cmsg);
                        }
                    }
                }
            }
            break;
        }
        case SCTP_I_DATA_NOTIFICATION:
        {
            notifications++;
            SCTPCommand *ind = check_and_cast<SCTPCommand *>(msg->removeControlInfo());
            cPacket* cmsg = new cPacket("Notification");
            SCTPSendCommand *cmd = new SCTPSendCommand();
            id = ind->getAssocId();
            cmd->setAssocId(id);
            cmd->setSid(ind->getSid());
            cmd->setNumMsgs(ind->getNumMsgs());
            cmsg->setKind(SCTP_C_RECEIVE);
            cmsg->setControlInfo(cmd);
            delete ind;
            delete msg;
            if (!cmsg->isScheduled() && schedule==false)
            {
                scheduleAt(simulation.getSimTime()+(simtime_t)par("delayFirstRead"), cmsg);
            }
            else if (schedule==true)
                sendOrSchedule(cmsg);
            break;
        }
        case SCTP_I_DATA:
        {
            SCTPCommand *ind = check_and_cast<SCTPCommand *>(msg->getControlInfo());
            id = ind->getAssocId();
            RcvdBytesPerAssoc::iterator j=rcvdBytesPerAssoc.find(id);
            if (j==rcvdBytesPerAssoc.end() && (clientSocket.getState()==SCTPSocket::CONNECTED))
                clientSocket.processMessage(PK(msg));
            else
            {
                j->second+= PK(msg)->getByteLength();
                BytesPerAssoc::iterator k=bytesPerAssoc.find(id);
                k->second->record(j->second);
                packetsRcvd++;
                if (echoFactor==0)
                {
                    if ((long)par("numPacketsToReceivePerClient")>0)
                    {
                        RcvdPacketsPerAssoc::iterator i=rcvdPacketsPerAssoc.find(id);
                        i->second--;
                        SCTPSimpleMessage *smsg=check_and_cast<SCTPSimpleMessage*>(msg);
                        EndToEndDelay::iterator j=endToEndDelay.find(id);
                        j->second->record(simulation.getSimTime()-smsg->getCreationTime());
                        HistEndToEndDelay::iterator k=histEndToEndDelay.find(id);
                        k->second->collect(simulation.getSimTime()-smsg->getCreationTime());
                        if (i->second == 0)
                        {
                            cPacket* cmsg = new cPacket("Request");
                            SCTPInfo* qinfo = new SCTPInfo();
                            cmsg->setKind(SCTP_C_NO_OUTSTANDING);
                            qinfo->setAssocId(id);
                            cmsg->setControlInfo(qinfo);
                            sendOrSchedule(cmsg);
                        }
                    }
                    delete msg;
                }
                else
                {
                    SCTPSendCommand *cmd = new SCTPSendCommand();
                    cmd->setAssocId(id);

                    SCTPSimpleMessage *smsg=check_and_cast<SCTPSimpleMessage*>(msg->dup());
                    EndToEndDelay::iterator j=endToEndDelay.find(id);
                    j->second->record(simulation.getSimTime()-smsg->getCreationTime());
                    HistEndToEndDelay::iterator k=histEndToEndDelay.find(id);
                    k->second->collect(simulation.getSimTime()-smsg->getCreationTime());
                    cPacket* cmsg = new cPacket("SVData");
                    bytesSent+=smsg->getByteLength();
                    cmd->setSendUnordered(cmd->getSendUnordered());
                    lastStream=(lastStream+1)%outboundStreams;
                    cmd->setSid(lastStream);
                    cmd->setLast(true);
                    cmsg->encapsulate(smsg);
                    cmsg->setKind(SCTP_C_SEND);
                    cmsg->setControlInfo(cmd);
                    packetsSent++;
                    delete msg;
                    sendOrSchedule(cmsg);
                }
            }

            break;
        }
        case SCTP_I_SHUTDOWN_RECEIVED:
        {
            SCTPCommand *command = check_and_cast<SCTPCommand *>(msg->removeControlInfo());
            id = command->getAssocId();
            sctpEV3<<"server: SCTP_I_SHUTDOWN_RECEIVED for assoc "<<id<<"\n";
            RcvdPacketsPerAssoc::iterator i=rcvdPacketsPerAssoc.find(id);
            if (i==rcvdPacketsPerAssoc.end()&& (clientSocket.getState()==SCTPSocket::CONNECTED))
                clientSocket.processMessage(PK(msg));
            else
            {
                if (i->second == 0)
                {
                    cPacket* cmsg = new cPacket("Request");
                    SCTPInfo* qinfo = new SCTPInfo();
                    cmsg->setKind(SCTP_C_NO_OUTSTANDING);
                    qinfo->setAssocId(id);
                    cmsg->setControlInfo(qinfo);
                    sendOrSchedule(cmsg);
                }
                delete command;
                shutdownReceived = true;
            }
            delete msg;
        }
        case SCTP_I_CLOSED: delete msg;
        break;
    }

    if (ev.isGUI())
    {
        char buf[32];
        RcvdBytesPerAssoc::iterator l=rcvdBytesPerAssoc.find(id);
        sprintf(buf, "rcvd: %ld bytes\nsent: %ld bytes", l->second, bytesSent);
        getDisplayString().setTagArg("t",0,buf);
    }
}
void SCTPPeer::handleTimer ( cMessage *  msg)

Referenced by handleMessage().

{
    cPacket* cmsg;
    SCTPCommand* cmd;
    int32 id;


    sctpEV3<<"SCTPPeer::handleTimer\n";

    SCTPConnectInfo *connectInfo = dynamic_cast<SCTPConnectInfo *>(msg->getControlInfo());
    switch (msg->getKind())
    {
        case MSGKIND_CONNECT:
            sctpEV3 << "starting session call connect\n";
            connect();
            break;
        case SCTP_C_SEND:

            if (numRequestsToSend>0)
            {
                generateAndSend(connectInfo);
                if ((simtime_t)par("thinkTime") > 0)
                    scheduleAt(simulation.getSimTime()+(simtime_t)par("thinkTime"), timeoutMsg);
                numRequestsToSend--;
            }
            break;
        case SCTP_I_ABORT:

            cmsg = new cPacket("CLOSE", SCTP_C_CLOSE);
            cmd = new SCTPCommand();
            id = atoi(msg->getName());
            cmd->setAssocId(id);
            cmsg->setControlInfo(cmd);
            sendOrSchedule(cmsg);
            break;
        case SCTP_C_RECEIVE:
            schedule = true;
            sendOrSchedule(PK(msg));
            break;
        default:

            break;
    }
}
void SCTPPeer::initialize ( )
{
    char * token;
    AddressVector addresses;

    numSessions = packetsSent = packetsRcvd = bytesSent = notifications = 0;
    WATCH(numSessions);
    WATCH(packetsSent);
    WATCH(packetsRcvd);
    WATCH(bytesSent);
    WATCH(numRequestsToSend);
    // parameters
    const char* address = par("address");

    token = strtok((char*)address,",");
    while (token != NULL)
    {
        addresses.push_back(IPvXAddress(token));
        token = strtok(NULL, ",");
    }
    int32 port = par("port");
    echoFactor = par("echoFactor");
    delay = par("echoDelay");
    outboundStreams = par("outboundStreams");
    ordered = (bool)par("ordered");
    queueSize = par("queueSize");
    lastStream = 0;
    timeoutMsg = new cMessage("SrvAppTimer");
    SCTPSocket* socket = new SCTPSocket();
    socket->setOutputGate(gate("sctpOut"));
    socket->setOutboundStreams(outboundStreams);
    if (strcmp(address,"")==0)
    {
        socket->bind(port);
        clientSocket.bind(port);
    }
    else
    {
        socket->bindx(addresses, port);
        clientSocket.bindx(addresses, port);
    }
    socket->listen(true, par("numPacketsToSendPerClient"));
    sctpEV3<<"SCTPPeer::initialized listen port="<<port<<"\n";
    clientSocket.setCallbackObject(this);
    clientSocket.setOutputGate(gate("sctpOut"));

    if ((simtime_t)par("startTime")>0)
    {
        connectTimer = new cMessage("ConnectTimer");
        connectTimer->setKind(MSGKIND_CONNECT);
        scheduleAt((simtime_t)par("startTime"), connectTimer);
    }
    schedule = false;
    shutdownReceived = false;
    sendAllowed = true;
}
void SCTPPeer::sendOrSchedule ( cPacket *  msg) [protected]

Referenced by generateAndSend(), handleMessage(), and handleTimer().

{
    if (delay==0)
    {
        send(msg, "sctpOut");
    }
    else
    {
        scheduleAt(simulation.getSimTime()+delay, msg);
    }
}
void SCTPPeer::sendqueueFullArrived ( int32  connId)
{
    sendAllowed = false;
}
void SCTPPeer::sendQueueRequest ( )

Referenced by socketEstablished().

{
    cPacket* cmsg = new cPacket("Queue");
    SCTPInfo* qinfo = new SCTPInfo();
    qinfo->setText(queueSize);
    cmsg->setKind(SCTP_C_QUEUE_MSGS_LIMIT);
    qinfo->setAssocId(clientSocket.getConnectionId());
    cmsg->setControlInfo(qinfo);
    clientSocket.sendRequest(cmsg);

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

Referenced by sendRequestArrived(), and socketEstablished().

{
    sctpEV3 << "sending request, " << numRequestsToSend-1 << " more to go\n";
    long numBytes = par("requestLength");
    if (numBytes < 1)
        numBytes=1;

    sctpEV3 << "SCTPClient: sending " << numBytes << " data bytes\n";

    cPacket* cmsg = new cPacket("AppData");
    SCTPSimpleMessage* msg=new SCTPSimpleMessage("data");

    msg->setDataArraySize(numBytes);
    for (int32 i=0; i<numBytes; i++)
    {
        msg->setData(i, 'a');
    }
    msg->setDataLen(numBytes);
    msg->setBitLength(numBytes * 8);
    msg->setCreationTime(simulation.getSimTime());
    cmsg->encapsulate(msg);
    if (ordered)
        cmsg->setKind(SCTP_C_SEND_ORDERED);
    else
        cmsg->setKind(SCTP_C_SEND_UNORDERED);
    // send SCTPMessage with SCTPSimpleMessage enclosed
    clientSocket.send(cmsg, last);
    bytesSent+=numBytes;
}
void SCTPPeer::sendRequestArrived ( ) [virtual]

Reimplemented from SCTPSocket::CallbackInterface.

{
int32 count = 0;

    sctpEV3<<"sendRequestArrived numRequestsToSend="<<numRequestsToSend<<"\n";
    while (numRequestsToSend > 0 && count++ < queueSize && sendAllowed)
    {
        numRequestsToSend--;
        if (count == queueSize || numRequestsToSend==0)
            sendRequest();
        else
            sendRequest(false);

        if (numRequestsToSend == 0)
        {
            sctpEV3<<"no more packets to send, call shutdown\n";
            clientSocket.shutdown();
        }
    }


}
void SCTPPeer::setPrimaryPath ( )
void SCTPPeer::setStatusString ( const char *  s)

Referenced by socketClosed(), socketDataArrived(), socketEstablished(), socketFailure(), and socketPeerClosed().

{
    if (ev.isGUI()) getDisplayString().setTagArg("t", 0, s);
}
void SCTPPeer::shutdownReceivedArrived ( int32  connId)
{
    if (numRequestsToSend==0)
    {
        cPacket* cmsg = new cPacket("Request");
        SCTPInfo* qinfo = new SCTPInfo();
        cmsg->setKind(SCTP_C_NO_OUTSTANDING);
        qinfo->setAssocId(connId);
        cmsg->setControlInfo(qinfo);
        clientSocket.sendNotification(cmsg);
    }
}
void SCTPPeer::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.

{
    // *redefine* to start another session etc.
    ev << "connection closed\n";
    setStatusString("closed");
}
void SCTPPeer::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.

{
    // *redefine* to perform or schedule next sending
    packetsRcvd++;

    sctpEV3<<"Client received packet Nr "<<packetsRcvd<<" from SCTP\n";

    SCTPCommand* ind = check_and_cast<SCTPCommand*>(msg->getControlInfo());

    bytesRcvd+=msg->getByteLength();

    if (echoFactor > 0)
    {
        SCTPSimpleMessage *smsg=check_and_cast<SCTPSimpleMessage*>(msg->dup());
        cPacket* cmsg = new cPacket("SVData");
        echoedBytesSent+=smsg->getBitLength()/8;
        cmsg->encapsulate(smsg);
        if (ind->getSendUnordered())
            cmsg->setKind(SCTP_C_SEND_UNORDERED);
        else
            cmsg->setKind(SCTP_C_SEND_ORDERED);
        packetsSent++;
        delete msg;
        clientSocket.send(cmsg,1);
    }
    if ((long)par("numPacketsToReceive")>0)
    {
        numPacketsToReceive--;
        if (numPacketsToReceive == 0)
        {
            setStatusString("closing");
            clientSocket.close();
        }
    }
}
void SCTPPeer::socketDataNotificationArrived ( int32  connId,
void *  yourPtr,
cPacket *  msg 
)
{
    SCTPCommand *ind = check_and_cast<SCTPCommand *>(msg->removeControlInfo());
    cPacket* cmsg = new cPacket("CMSG");
    SCTPSendCommand *cmd = new SCTPSendCommand();
    cmd->setAssocId(ind->getAssocId());
    cmd->setSid(ind->getSid());
    cmd->setNumMsgs(ind->getNumMsgs());
    cmsg->setKind(SCTP_C_RECEIVE);
    cmsg->setControlInfo(cmd);
    delete ind;
    clientSocket.sendNotification(cmsg);
}
void SCTPPeer::socketEstablished ( int32  connId,
void *  yourPtr 
)

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

{
    int32 count = 0;
     // *redefine* to perform or schedule first sending
    ev<<"SCTPClient: connected\n";
    setStatusString("connected");
    // determine number of requests in this session
    numRequestsToSend = (long) par("numRequestsPerSession");
    numPacketsToReceive = (long) par("numPacketsToReceive");
    if (numRequestsToSend<1)
        numRequestsToSend = 0;
    // perform first request (next one will be sent when reply arrives)
    if (numRequestsToSend>0)
    {
        if ((simtime_t)par("thinkTime") > 0)
        {
            if (sendAllowed)
            {
                sendRequest();
                numRequestsToSend--;
            }
            timeMsg->setKind(MSGKIND_SEND);
            scheduleAt(simulation.getSimTime()+(simtime_t)par("thinkTime"), timeMsg);

        }
        else
        {
            if (queueSize>0)
            {
                while (numRequestsToSend > 0 && count++ < queueSize*2 && sendAllowed)
                {
                    if (count == queueSize*2)
                        sendRequest();
                    else
                        sendRequest(false);
                    numRequestsToSend--;
                }
                if (numRequestsToSend>0 && sendAllowed)
                    sendQueueRequest();
            }
            else
            {
                while (numRequestsToSend > 0 && sendAllowed)
                {
                    sendRequest();
                    numRequestsToSend--;
                }
            }

            if (numPacketsToReceive == 0 && (simtime_t)par("waitToClose")>0)
            {
                timeMsg->setKind(MSGKIND_ABORT);
                scheduleAt(simulation.getSimTime()+(simtime_t)par("waitToClose"), timeMsg);
            }
            if (numRequestsToSend == 0 && (simtime_t)par("waitToClose")==0)
            {
                sctpEV3<<"socketEstablished:no more packets to send, call shutdown\n";
                clientSocket.shutdown();
            }
        }
    }
}
void SCTPPeer::socketFailure ( int32  connId,
void *  yourPtr,
int32  code 
)

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

{
    // subclasses may override this function, and add code try to reconnect after a delay.
    ev << "connection broken\n";
    setStatusString("broken");
    // reconnect after a delay
    timeMsg->setKind(MSGKIND_CONNECT);
    scheduleAt(simulation.getSimTime()+(simtime_t)par("reconnectInterval"), timeMsg);
}
void SCTPPeer::socketPeerClosed ( int32  connId,
void *  yourPtr 
)

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

{
    // close the connection (if not already closed)
    if (clientSocket.getState()==SCTPSocket::PEER_CLOSED)
    {
        ev << "remote SCTP closed, closing here as well\n";
        setStatusString("closing");
        clientSocket.close();
    }
}
void SCTPPeer::socketStatusArrived ( int32  connId,
void *  yourPtr,
SCTPStatusInfo *  status 
)

Redefine to handle incoming SCTPStatusInfo.

{
struct pathStatus ps;
    SCTPPathStatus::iterator i=sctpPathStatus.find(status->getPathId());
    if (i!=sctpPathStatus.end())
    {
        ps = i->second;
        ps.active=status->getActive();
    }
    else
    {
        ps.active = status->getActive();
        ps.primaryPath = false;
        sctpPathStatus[ps.pid]=ps;
    }
}

Member Data Documentation

int32 SCTPPeer::bytesRcvd [protected]

Referenced by socketDataArrived().

int32 SCTPPeer::clientAssocId [protected]
cMessage* SCTPPeer::connectTimer [protected]

Referenced by finish(), and initialize().

double SCTPPeer::delay [protected]

Referenced by initialize(), and sendOrSchedule().

int32 SCTPPeer::echoedBytesSent [protected]

Referenced by socketDataArrived().

double SCTPPeer::echoFactor [protected]
int32 SCTPPeer::lastStream [protected]
int32 SCTPPeer::notifications [protected]

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

int32 SCTPPeer::numSessions [protected]
bool SCTPPeer::ordered [protected]
bool SCTPPeer::schedule [protected]
int32 SCTPPeer::serverAssocId [protected]

Referenced by generateAndSend(), and handleMessage().

bool SCTPPeer::shutdownReceived [protected]

Referenced by handleMessage(), and initialize().

int32 SCTPPeer::ssn [protected]
cMessage* SCTPPeer::timeMsg [protected]

Referenced by socketEstablished(), and socketFailure().

cMessage* SCTPPeer::timeoutMsg [protected]

The documentation for this class was generated from the following files: