![]() |
User Manual, Developers Guide and API Documentation |
![]() |
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 }
1.5.5