User Manual, Developers Guide and API Documentation

ThreeWayHandshake.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-2007
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 16, D-52074 Aachen, Germany
00008  * phone: ++49-241-80-27910,
00009  * fax: ++49-241-80-22242
00010  * email: info@openwns.org
00011  * www: http://www.openwns.org
00012  * _____________________________________________________________________________
00013  *
00014  * openWNS is free software; you can redistribute it and/or modify it under the
00015  * terms of the GNU Lesser General Public License version 2 as published by the
00016  * Free Software Foundation;
00017  *
00018  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00019  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00020  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00021  * details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  *
00026  ******************************************************************************/
00027 
00028 #include <TCP/ThreeWayHandshake.hpp>
00029 #include <TCP/Service.hpp>
00030 #include <TCP/UpperConvergence.hpp>
00031 #include <TCP/ConnectionControl.hpp>
00032 #include <TCP/FiniteStateMachine.hpp>
00033 #include <TCP/HandshakeStrategyHandlerInterface.hpp>
00034 
00035 #include <WNS/ldk/Layer.hpp>
00036 #include <WNS/ldk/helper/FakePDU.hpp>
00037 #include <WNS/ldk/ControlServiceInterface.hpp>
00038 
00039 #include <WNS/node/Node.hpp>
00040 
00041 using namespace tcp;
00042 
00043 
00044 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00045     ThreeWayHandshake,
00046     wns::ldk::FunctionalUnit,
00047     "tcp.ThreeWayHandshake",
00048     wns::ldk::FUNConfigCreator
00049     );
00050 
00051 ThreeWayHandshake::ThreeWayHandshake(wns::ldk::fun::FUN* _fun, const wns::pyconfig::View& _pyco) :
00052     wns::ldk::CommandTypeSpecifier<>(_fun),
00053     wns::ldk::HasReceptor<>(),
00054     wns::ldk::HasConnector<>(),
00055     wns::ldk::HasDeliverer<>(),
00056     wns::Cloneable<ThreeWayHandshake>(),
00057     logger(_pyco.get("logger")),
00058     strategyHandler(NULL),
00059     pyco(_pyco),
00060     fsm(NULL),
00061     tcpHeaderFU(NULL),
00062     tcpHeaderReader(NULL)
00063 {
00064     MESSAGE_SINGLE(NORMAL, logger, "FU for 3-way-handshake created!");
00065 
00066     ConnectionVariables v;
00067 
00068     fsm = new FiniteStateMachine(v, logger);
00069 }
00070 
00071 ThreeWayHandshake::~ThreeWayHandshake()
00072 {
00073     delete fsm;
00074 }
00075 
00076 void
00077 ThreeWayHandshake::onFUNCreated()
00078 {
00079     tcpHeaderFU = getFUN()->findFriend<TCPHeader*>("tcp.tcpHeader");
00080     assure(tcpHeaderFU, "No FU for the TCP Header available!");
00081     tcpHeaderReader = getFUN()->getCommandReader("tcp.tcpHeader");
00082     assure(tcpHeaderReader, "No reader for the TCP Header available!");
00083 }
00084 
00085 void
00086 ThreeWayHandshake::doOnData(const wns::ldk::CompoundPtr& _compound)
00087 {
00088     assure(_compound, "doOnData called with an invalid compound.");
00089 
00090     assure(tcpHeaderReader, "No reader for the TCP Header available!");
00091     TCPCommand* tcpHeader = tcpHeaderReader->readCommand<TCPCommand>(
00092         _compound->getCommandPool());
00093 
00094     MESSAGE_SINGLE(NORMAL, logger, "ThreeWayHandshake::doOnData: incoming compound received!");
00095 
00096     if ((fsm->getVariables().activeOpen == false) && (strategyHandler == NULL))
00097     {
00098         // server in state closed, receives first compound (strategy handler not
00099         // assigned yet):
00100         // change to state listen
00101         assure(fsm->getStateName() == "tcp_fsm_closed", "Invalid transition: Currently not in state <closed>!");
00102         fsm->replaceState(fsm->createState<Listen>());
00103         this->flowID = tcpHeader->peer.flowID;
00104 
00105         strategyHandler = dynamic_cast<tcp::HandshakeStrategyHandlerInterface*>(
00106             getFUN()->getLayer()->getControlService<wns::ldk::ControlService>("fip"));
00107     }
00108 
00109 
00110     wns::ldk::helper::FakePDUPtr pdu;
00111     wns::ldk::CompoundPtr compound(new wns::ldk::Compound(getFUN()->getProxy()->createCommandPool(), pdu));
00112     assure(tcpHeaderFU, "No FU for the TCP Header available!");
00113     tcpHeaderFU->activateCommand(compound->getCommandPool());
00114 
00115     if (fsm->getVariables().activeOpen == false)
00116     {
00117         // server
00118         if (tcpHeader->peer.fin && tcpHeader->peer.ack)
00119         {
00120             // received fin_ack, send ack
00121             assure(fsm->getStateName() == "tcp_fsm_fin_wait_1", "Invalid transition: Currently not in state <fin_wait_1>!");
00122             fsm->ack();
00123             tcpFlagsToUpperCommand(compound);
00124             doSendData(compound);
00125         }
00126         else if (tcpHeader->peer.syn)
00127         {
00128             // received syn, send syn_ack
00129             assure(fsm->getStateName() == "tcp_fsm_listen", "Invalid transition: Currently not in state <listen>!");
00130             fsm->syn_ack();
00131             tcpFlagsToUpperCommand(compound);
00132             doSendData(compound);
00133             MESSAGE_SINGLE(NORMAL, logger, "ThreeWayHandshake: Syn rcvd, sent syn_ack for flowID " << this->flowID);
00134         }
00135         else if (tcpHeader->peer.ack)
00136         {
00137             // received ack
00138             // send nothing; either: syn_rcvd -> established
00139             //                    or closing -> closed (time_wait)
00140             //                    or last_ack -> closed
00141             assure(fsm->getStateName() == "tcp_fsm_syn_rcvd" or
00142                    fsm->getStateName() == "tcp_fsm_closing" or
00143                    fsm->getStateName() == "tcp_fsm_last_ack", "Invalid transition: Currently not in state <Syn_rcvd> or <Closing> or <Last_ack>!");
00144 
00145             if(fsm->getStateName() == "tcp_fsm_syn_rcvd")
00146             {
00147                 fsm->replaceState(fsm->createState<Established>());
00148                 MESSAGE_SINGLE(NORMAL, logger, "ThreeWayHandshake: 3WHS established for flowID " << this->flowID);
00149                 strategyHandler->passiveOpenConnection(this->flowID);
00150             }
00151             else if (fsm->getStateName() == "tcp_fsm_closing")
00152             {
00153                 fsm->replaceState(fsm->createState<Closed>());
00154             }
00155             else
00156             { // current state: last_ack
00157                 fsm->replaceState(fsm->createState<Closed>());
00158                 strategyHandler->passiveClosed(this->flowID);
00159             }
00160 
00161         }
00162         else if (tcpHeader->peer.rst)
00163         {
00164             // received rst, send nothing
00165             assure(fsm->getStateName() == "tcp_fsm_syn_rcvd", "Invalid transition: Currently not in state <syn_rcvd>!");
00166             fsm->replaceState(fsm->createState<Listen>());
00167         }
00168         else if (tcpHeader->peer.fin)
00169         {
00170             // Either: established -> close_wait
00171             //      or fin_wait_1 -> closing
00172             // received fin, send ack
00173             assure(fsm->getStateName() == "tcp_fsm_established" or
00174                    fsm->getStateName() == "tcp_fsm_fin_wait_1", "Invalid transition: Currently not in state <established> or <fin_wait_1>!");
00175             fsm->ack();
00176             tcpFlagsToUpperCommand(compound);
00177             doSendData(compound);
00178             closeConnection(this->flowID);
00179         }
00180     }
00181     else
00182     {
00183         // client
00184         if (tcpHeader->peer.syn && tcpHeader->peer.ack)
00185         {
00186             // state transition: syn_sent -> established
00187             assure(fsm->getStateName() == "tcp_fsm_syn_sent", "Invalid transition: Currently not in state <syn_sent>!" + fsm->getStateName());
00188             fsm->ack();
00189             strategyHandler->connectionEstablished(tcpHeader->peer.flowID);
00190             tcpFlagsToUpperCommand(compound);
00191             doSendData(compound);
00192         }
00193         else if (tcpHeader->peer.fin && tcpHeader->peer.ack)
00194         {
00195             // rcvd fin_ack, send ack to close connection
00196             assure(fsm->getStateName() == "tcp_fsm_fin_wait_1", "Invalid transition: Currently not in state <fin_wait_1>!");
00197             fsm->ack();
00198             tcpFlagsToUpperCommand(compound);
00199             doSendData(compound);
00200             strategyHandler->connectionClosed(this->flowID);
00201         }
00202         else if (tcpHeader->peer.ack)
00203         {
00204             // Either: fin_wait_1 -> fin_wait_2
00205             //     or  closing -> closed (time_wait)
00206             // send nothing
00207             assure(fsm->getStateName() == "tcp_fsm_fin_wait_1" or
00208                    fsm->getStateName() == "tcp_fsm_closing", "Invalid transition: Currently not in state <closing> or <fin_wait_1>!");
00209 
00210             if (fsm->getStateName() == "tcp_fsm_fin_wait_1")
00211             {
00212                 fsm->replaceState(fsm->createState<Fin_wait_2>());
00213             }
00214             else
00215             {
00216                 // current state: closing
00217                 fsm->replaceState(fsm->createState<Closed>());
00218                 strategyHandler->connectionClosed(this->flowID);
00219             }
00220         }
00221         else if (tcpHeader->peer.fin)
00222         {
00223             // Either: fin_wait_1 -> closing
00224             //     or: fin_wait_2 -> closed (time_wait)
00225             // At client side both transitions are equal!
00226             assure(fsm->getStateName() == "tcp_fsm_syn_rcvd" or
00227                    fsm->getStateName() == "tcp_fsm_fin_wait_2", "Invalid transition: Currently not in state <fin_wait_1> or <fin_wait_2>!");
00228             fsm->ack();
00229             tcpFlagsToUpperCommand(compound);
00230             doSendData(compound);
00231             // Additionally for fin_wait_2 (but now already in state closed!!!):
00232             if(fsm->getStateName() == "tcp_fsm_closed")
00233                 strategyHandler->connectionClosed(this->flowID);
00234         }
00235         else
00236         {
00237             throw(wns::Exception("Invalid signal received for client in state " + fsm->getStateName()));
00238         }
00239     }
00240 }
00241 
00242 void
00243 ThreeWayHandshake::doSendData(const wns::ldk::CompoundPtr& _compound)
00244 {
00245 
00246     if(isAccepting(_compound))
00247     {
00248         getConnector()->getAcceptor(_compound)->sendData(_compound);
00249     }
00250 }
00251 
00252 bool
00253 ThreeWayHandshake::doIsAccepting(const wns::ldk::CompoundPtr& /*_compound*/)
00254 {
00255     return true;
00256 }
00257 
00258 void
00259 ThreeWayHandshake::doWakeup()
00260 {
00261 }
00262 
00263 bool
00264 ThreeWayHandshake::doIsAccepting(const wns::ldk::CompoundPtr& /*_compound*/) const
00265 {
00266     return true;
00267 }
00268 
00269 void
00270 ThreeWayHandshake::activeOpen(const wns::service::tl::FlowID& _flowID)
00271 {
00272     assure(fsm->getStateName() == "tcp_fsm_closed", "Not in state closed!");
00273 
00274     this->flowID = _flowID;
00275 
00276     MESSAGE_SINGLE(NORMAL, logger, "ThreeWayHandshake::activeOpen() called for flowID " << _flowID);
00277 
00278     wns::ldk::helper::FakePDUPtr pdu;
00279     wns::ldk::CompoundPtr compound(new wns::ldk::Compound(getFUN()->getProxy()->createCommandPool(), pdu));
00280     assure(tcpHeaderFU, "No FU for the TCP Header available!");
00281     tcpHeaderFU->activateCommand(compound->getCommandPool());
00282 
00283     fsm->syn();
00284     tcpFlagsToUpperCommand(compound);
00285     fsm->getVariables().activeOpen = true;
00286 
00287     doSendData(compound);
00288 }
00289 
00290 void
00291 ThreeWayHandshake::passiveOpen(const wns::service::tl::FlowID& _flowID)
00292 {
00293     MESSAGE_SINGLE(NORMAL, logger, "ThreeWayHandshake::passiveOpen() called for flowID " << _flowID);
00294 
00295     strategyHandler->connectionEstablished(_flowID);
00296 }
00297 
00298 void
00299 ThreeWayHandshake::registerStrategyHandler(HandshakeStrategyHandlerInterface* _strategyHandler)
00300 {
00301     strategyHandler = _strategyHandler;
00302 }
00303 
00304 void
00305 ThreeWayHandshake::closeConnection(const wns::service::tl::FlowID& _flowID)
00306 {
00307     flowID = _flowID;
00308 
00309     assure(fsm->getStateName() == "tcp_fsm_established" // server
00310            or fsm->getStateName() == "tcp_fsm_syn_rcvd" // server/client
00311            or fsm->getStateName() == "tcp_fsm_syn_sent"
00312            or fsm->getStateName() == "tcp_fsm_close_wait", //client
00313            "Connection termination not initiated. Current state: " + fsm->getStateName());
00314 
00315     MESSAGE_SINGLE(NORMAL, logger, "Closing connection for flowID: " << flowID << " initiated.");
00316 
00317     wns::ldk::helper::FakePDUPtr pdu;
00318     wns::ldk::CompoundPtr compound(new wns::ldk::Compound(getFUN()->getProxy()->createCommandPool(), pdu));
00319     assure(tcpHeaderFU, "No FU for the TCP Header available!");
00320     tcpHeaderFU->activateCommand(compound->getCommandPool());
00321 
00322     fsm->fin();
00323 
00324     tcpFlagsToUpperCommand(compound);
00325 
00326     doSendData(compound);
00327 }
00328 
00329 void
00330 ThreeWayHandshake::tcpFlagsToUpperCommand(wns::ldk::CompoundPtr& _compound)
00331 {
00332     TCPCommand* tcpHeader = tcpHeaderReader->readCommand<TCPCommand>(
00333         _compound->getCommandPool());
00334 
00335     tcpHeader->peer.urg = fsm->getVariables().urg;
00336     tcpHeader->peer.ack = fsm->getVariables().ack;
00337     tcpHeader->peer.psh = fsm->getVariables().psh;
00338     tcpHeader->peer.rst = fsm->getVariables().rst;
00339     tcpHeader->peer.syn = fsm->getVariables().syn;
00340     tcpHeader->peer.fin = fsm->getVariables().fin;
00341 
00342     tcpHeader->peer.flowID = flowID;
00343 }

Generated on Sat May 26 03:32:17 2012 for openWNS by  doxygen 1.5.5