From 4d1fb4b669c3bb296e6bd099a601c20c5c2af5a2 Mon Sep 17 00:00:00 2001 From: Waldemar Kornewald Date: Sun, 27 Jul 2003 11:54:35 +0000 Subject: [PATCH] PPPReportManager had some old port code. Added checking for sender to report system. Worked on StateMachine and added cases where the interface should be deleted. Added some flags (report and protocol) and report codes. Started implementing Up(). Some minor changes (comments, multilink). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4108 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/tests/kits/net/ppp/headers/KPPPDefs.h | 4 +- src/tests/kits/net/ppp/headers/KPPPDevice.h | 1 + .../kits/net/ppp/headers/KPPPInterface.h | 3 + .../kits/net/ppp/headers/KPPPReportDefs.h | 4 +- .../kits/net/ppp/headers/KPPPReportManager.h | 2 + src/tests/kits/net/ppp/src/KPPPInterface.cpp | 85 +++++++++++++++--- .../kits/net/ppp/src/KPPPReportManager.cpp | 19 +++- .../kits/net/ppp/src/KPPPStateMachine.cpp | 87 +++++++++++++------ 8 files changed, 163 insertions(+), 42 deletions(-) diff --git a/src/tests/kits/net/ppp/headers/KPPPDefs.h b/src/tests/kits/net/ppp/headers/KPPPDefs.h index dc9fbe488b..39c4f2fa3f 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDefs.h +++ b/src/tests/kits/net/ppp/headers/KPPPDefs.h @@ -65,10 +65,12 @@ enum { PPP_NO_FLAGS = 0x00, PPP_ALWAYS_ALLOWED = 0x01, // protocol may send/receive in PPP_ESTABLISHMENT_PHASE - PPP_NEEDS_DOWN = 0x02 + PPP_NEEDS_DOWN = 0x02, // protocol needs a Down() in addition to a Reset() to // terminate the connection properly (losing the connection // still results in a Reset() only) + PPP_NOT_IMPORTANT = 0x03 + // if this protocol fails to go up we do not disconnect }; // phase when the protocol is brought up diff --git a/src/tests/kits/net/ppp/headers/KPPPDevice.h b/src/tests/kits/net/ppp/headers/KPPPDevice.h index 3e4ce0d4a4..1f1d80990c 100644 --- a/src/tests/kits/net/ppp/headers/KPPPDevice.h +++ b/src/tests/kits/net/ppp/headers/KPPPDevice.h @@ -29,6 +29,7 @@ class PPPDevice { { return fMTU; } virtual uint32 PreferredMTU() const = 0; + // these calls must not block virtual void Up() = 0; virtual void Down() = 0; virtual void Listen() = 0; diff --git a/src/tests/kits/net/ppp/headers/KPPPInterface.h b/src/tests/kits/net/ppp/headers/KPPPInterface.h index b40c7d8815..c9f14e1c8a 100644 --- a/src/tests/kits/net/ppp/headers/KPPPInterface.h +++ b/src/tests/kits/net/ppp/headers/KPPPInterface.h @@ -19,6 +19,8 @@ class PPPOptionHandler; class PPPInterface { + friend class PPPStateMachine; + private: // copies are not allowed! PPPInterface(const PPPInterface& copy); @@ -136,6 +138,7 @@ class PPPInterface { PPPLCP fLCP; PPPReportManager fReportManager; ifnet *fIfnet; + thread_id fUpThread; ppp_manager_info *fManager; diff --git a/src/tests/kits/net/ppp/headers/KPPPReportDefs.h b/src/tests/kits/net/ppp/headers/KPPPReportDefs.h index 0846158b0e..99fc3a944f 100644 --- a/src/tests/kits/net/ppp/headers/KPPPReportDefs.h +++ b/src/tests/kits/net/ppp/headers/KPPPReportDefs.h @@ -11,7 +11,8 @@ enum PPP_REPORT_FLAGS { PPP_NO_REPORT_FLAGS = 0, PPP_WAIT_FOR_REPLY = 0x1, - PPP_REMOVE_AFTER_REPORT = 0x2 + PPP_REMOVE_AFTER_REPORT = 0x2, + PPP_NO_REPLY_TIMEOUT = 0x4 }; // report types @@ -23,6 +24,7 @@ enum PPP_REPORT_TYPE { // report codes (type-specific) enum PPP_CONNECTION_REPORT_CODES { + PPP_GOING_UP = 0, PPP_UP_SUCCESSFUL = 1, PPP_DOWN_SUCCESSFUL = 2, PPP_UP_ABORTED = 3, diff --git a/src/tests/kits/net/ppp/headers/KPPPReportManager.h b/src/tests/kits/net/ppp/headers/KPPPReportManager.h index 0321d69f9b..7bdc37c1fa 100644 --- a/src/tests/kits/net/ppp/headers/KPPPReportManager.h +++ b/src/tests/kits/net/ppp/headers/KPPPReportManager.h @@ -7,6 +7,8 @@ #include "LockerHelper.h" +#define PPP_REPLY(sender, value) send_data_with_timeout((sender), (value), NULL, 0, B_REPORT_TIMEOUT) + class PPPReportManager { public: PPPReportManager(BLocker& lock); diff --git a/src/tests/kits/net/ppp/src/KPPPInterface.cpp b/src/tests/kits/net/ppp/src/KPPPInterface.cpp index 94c5203661..0b0d739274 100644 --- a/src/tests/kits/net/ppp/src/KPPPInterface.cpp +++ b/src/tests/kits/net/ppp/src/KPPPInterface.cpp @@ -26,7 +26,7 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NULL) : fSettings(dup_driver_settings(settings)), fStateMachine(*this), fLCP(*this), fReportManager(StateMachine().Locker()), - fIfnet(NULL), fLinkMTU(1500), fAccessing(0), fChildrenCount(0), + fIfnet(NULL), fUpThread(-1), fLinkMTU(1500), fAccessing(0), fChildrenCount(0), fDevice(NULL), fFirstEncapsulator(NULL), fLock(StateMachine().Locker()) { if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &fManager) != B_OK) @@ -344,6 +344,9 @@ PPPInterface::EncapsulatorFor(uint16 protocol, bool PPPInterface::AddChild(PPPInterface *child) { + if(!child || child->Mode() != Mode()) + return false; + LockerHelper locker(fLock); if(fChildren.HasItem(child) || !fChildren.AddItem(child)) @@ -402,28 +405,88 @@ PPPInterface::SetDialOnDemand(bool dialondemand = true) // check if we need to register/unregister if(!Ifnet() && fDialOnDemand) RegisterInterface(); - else if(Ifnet() && !fDialOnDemand && Phase() == PPP_DOWN_PHASE) + else if(Ifnet() && !fDialOnDemand && Phase() == PPP_DOWN_PHASE) { UnregisterInterface(); + Delete(); + } } bool PPPInterface::Up() { - // ToDo: - // instead of waiting for state change we should wait until - // all retries are done - - if(!InitCheck() || Phase() != PPP_DOWN_PHASE) + if(!InitCheck() || Phase() == PPP_TERMINATION_PHASE) return false; if(IsUp()) return true; - // TODO: - // Add one-time connection report request and wait - // for results. If we lost the connection we should - // consider redialing. + ppp_report_packet report; + thread_id me = find_thread(NULL), sender; + + // one thread has to do the real task while all other threads are observers + fLock.Lock(); + if(fUpThread == -1) + fUpThread = me; + + fReportManager.EnableReports(PPP_CONNECTION_REPORT, me, PPP_WAIT_FOR_REPLY); + fLock.Unlock(); + + if(me != fUpThread) { + // I am an observer + while(true) { + if(IsUp()) { + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return true; + } + + if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE) { + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return true; + } + + if(IsUp()) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return true; + } + + if(report.type != PPP_CONNECTION_REPORT) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + } + + if(report.code == PPP_GOING_UP) { + PPP_REPLY(sender, B_OK); + continue; + } else if(report.code == PPP_UP_SUCCESSFUL) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return true; + } else if(report.code == PPP_DOWN_SUCCESSFUL + || report.code == PPP_UP_ABORTED) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return false; + } else if(report.code == PPP_UP_FAILED) { + // TODO: + // if maximum number of retries is reached we return false + // otherwise we wait for the next dial-attempt + } else if(report.code == PPP_AUTHENTICATION_FAILED) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return false; + } else if(report.code == PPP_CONNECTION_LOST) { + // TODO: + // if autoredial is enabled wait for redial attemts (just continue) + } + } + } else { + // I am the thread for the real task + while(true) { + + } + } return false; } diff --git a/src/tests/kits/net/ppp/src/KPPPReportManager.cpp b/src/tests/kits/net/ppp/src/KPPPReportManager.cpp index 0ccb69d278..b44e760cb9 100644 --- a/src/tests/kits/net/ppp/src/KPPPReportManager.cpp +++ b/src/tests/kits/net/ppp/src/KPPPReportManager.cpp @@ -82,7 +82,7 @@ PPPReportManager::Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 len for(int32 index = 0; index < fReportRequests.CountItems(); index++) { ppp_report_request& request = fReportRequests.ItemAt(index); - result = send_data_with_timeout(request.port, PPP_REPORT_CODE, &report, + result = send_data_with_timeout(request.thread, PPP_REPORT_CODE, &report, sizeof(report), PPP_REPORT_TIMEOUT); if(result == B_BAD_THREAD_ID || result == B_NO_MEMORY) { @@ -91,10 +91,21 @@ PPPReportManager::Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 len continue; } else if(result == B_OK) { if(request.flags & PPP_WAIT_FOR_REPLY) { - result = receive_data_with_timeout(fPort, &code, NULL, 0, - PPP_REPORT_TIMEOUT); + if(request.flags & PPP_NO_REPLY_TIMEOUT) { + sender = -1; + while(sender != request.thread) + code = receive_data(&sender, NULL, 0); + result = B_OK; + } else { + sender = -1; + result = B_OK; + while(sender != request.thread && result == B_OK) + result = receive_data_with_timeout(&sender, &code, NULL, 0, + PPP_REPORT_TIMEOUT); + } + if(result == B_OK && code != B_OK) - successful = false; + acceptable = false; } } diff --git a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp index cecea663b7..f0319697dd 100644 --- a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp +++ b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp @@ -2,7 +2,11 @@ // TODO: -// do not forget to reset authentication status when needed +// do not forget to reset authentication status when: +// - connection is lost +// - reconfiguring? +// - terminating +// - ... PPPStateMachine::PPPStateMachine(PPPInterface& interface) : fInterface(&interface), fPhase(PPP_DOWN_PHASE), @@ -49,8 +53,16 @@ PPPStateMachine::NewPhase(PPP_PHASE next) { // Report a down event to parent if we are not usable anymore. // The report threads get their notification later. - if(Phase() == PPP_ESTABLISHED_PHASE && Interface()->Parent()) - Interface()->Parent()->StateMachine().DownEvent(Interface()); + if(Phase() == PPP_ESTABLISHED_PHASE && next != Phase()) { + if(Interface()->Ifnet()) + Interface()->Ifnet()->if_flags &= ~IFF_RUNNING; + + if(!Interface()->DoesDialOnDemand()) + Interface()->UnregisterInterface(); + + if(Interface()->Parent()) + Interface()->Parent()->StateMachine().DownEvent(Interface()); + } // there is nothing after established phase and nothing before down phase if(next > PPP_ESTABLISHED_PHASE) @@ -161,13 +173,14 @@ PPPStateMachine::UpEvent(PPPInterface *interface) LockerHelper locker(fLock); if(Phase() <= PPP_TERMINATION_PHASE || State() != PPP_STARTING_STATE) { - interface->Down(); + interface->StateMachine().CloseEvent(); return; } NewState(PPP_OPENED_STATE); if(Phase() == PPP_ESTABLISHMENT_PHASE) { NewPhase(PPP_AUTHENTICATION_PHASE); + locker.UnlockNow(); ThisLayerUp(); } } @@ -189,8 +202,10 @@ PPPStateMachine::DownEvent(PPPInterface *interface) ++count; } - if(count == 0 && Interface()->Ifnet()) - Interface()->Ifnet()->if_flags &= ~IFF_RUNNING; + if(count == 0) { + locker.UnlockNow(); + DownEvent(); + } } } @@ -198,8 +213,8 @@ PPPStateMachine::DownEvent(PPPInterface *interface) void PPPStateMachine::UpFailedEvent(PPPProtocol *protocol) { - // All protocols must go up. - CloseEvent(); + if(protocol->Flags() & PPP_NOT_IMPORTANT) + CloseEvent(); } @@ -222,8 +237,8 @@ PPPStateMachine::DownEvent(PPPProtocol *protocol) void PPPStateMachine::UpFailedEvent(PPPEncapsulator *encapsulator) { - // All encapsulators must go up. - CloseEvent(); + if(encapsulator->Flags() & PPP_NOT_IMPORTANT) + CloseEvent(); } @@ -337,9 +352,15 @@ PPPStateMachine::UpEvent() NewState(PPP_CLOSED_STATE); locker.UnlockNow(); ThisLayerFinished(); + + return; } // TODO: handle server-up! + NewState(PPP_REQ_SENT_STATE); + InitializeRestartCount(); + locker.UnlockNow(); + SendConfigureRequest(); break; case PPP_STARTING_STATE: @@ -381,7 +402,7 @@ PPPStateMachine::DownEvent() case PPP_STOPPED_STATE: // The RFC says we should reconnect, but our implementation // will only do this if auto-redial is enabled (only clients). - NewStatus(PPP_STARTING_STATE); + NewState(PPP_STARTING_STATE); break; case PPP_STOPPING_STATE: @@ -389,7 +410,7 @@ PPPStateMachine::DownEvent() case PPP_ACK_RCVD_STATE: case PPP_ACK_SENT_STATE: case PPP_OPENED_STATE: - NewStatus(PPP_STARTING_STATE); + NewState(PPP_STARTING_STATE); break; default: @@ -406,7 +427,9 @@ PPPStateMachine::DownEvent() // maybe we need to redial if(State() == PPP_STARTING_STATE) { if(fAuthentiactionStatus == PPP_AUTHENTICATION_FAILED - || fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED) + || fAuthenticationStatus == PPP_AUTHENTICATING + || fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED + || fPeerAuthenticationStatus == PPP_AUTHENTICATING) Interface()->Report(PPP_CONNECTION_REPORT, PPP_AUTHENTICATION_FAILED, NULL, 0); else @@ -421,10 +444,14 @@ PPPStateMachine::DownEvent() if(Interface()->DoesAutoRedial()) { // TODO: // Redial() - } else + } else if(!Interface()->DoesDialOnDemand()) Interface()->Delete(); - } else - Report(PPP_CONNECTION_REPORT, PPP_DOWN_SUCCESSFUL, NULL, 0); + } else { + Interface()->Report(PPP_CONNECTION_REPORT, PPP_DOWN_SUCCESSFUL, NULL, 0); + + if(!Interface()->DoesDialOnDemand()) + Interface()->Delete(); + } } @@ -436,11 +463,21 @@ PPPStateMachine::OpenEvent() switch(State()) { case PPP_INITIAL_STATE: - NewState(PPP_STARTING_STATE); + if(!Interface()->Report(PPP_CONNECTION_REPORT, PPP_GOING_UP, NULL, 0)) + return; + + if(Interface()->Mode() == PPP_SERVER_MODE) { + NewPhase(PPP_ESTABLISHMENT_PHASE); + + if(Interface()->Device()) + Interface()->Device()->Listen(); + } else + NewState(PPP_STARTING_STATE); + if(Interface()->IsMultilink() && !Interface()->Parent()) { NewPhase(PPP_ESTABLISHMENT_PHASE); for(int32 i = 0; i < Interface()->CountChildren(); i++) - Interface()->ChildAt(i)->Up(); + Interface()->ChildAt(i)->StateMachine().OpenEvent(); } else { locker.UnlockNow(); ThisLayerStarted(); @@ -473,12 +510,14 @@ PPPStateMachine::CloseEvent() if(Interface()->IsMultilink() && !Interface()->Parent()) { NewState(PPP_INITIAL_STATE); - NewPhase(PPP_DOWN_PHASE); + + if(Phase() != PPP_DOWN_PHASE) + NewPhase(PPP_TERMINATION_PHASE); ThisLayerDown(); for(int32 i = 0; i < Interface()->CountChildren(); i++) - Interface()->ChildAt(i)->Down(); + Interface()->ChildAt(i)->StateMachine().CloseEvent(); return; } @@ -1328,7 +1367,7 @@ PPPStateMachine::BringHandlersUp() if(BringPhaseUp() > 0) break; - fLock.Lock(); + LockerHelper locker(fLock); if(Phase() < PPP_AUTHENTICATION_PHASE) return; @@ -1336,14 +1375,12 @@ PPPStateMachine::BringHandlersUp() if(Interface()->Parent()) Interface()->Parent()->StateMachine().UpEvent(Interface()); - // TODO: - // Report(PPP_CONNECTION_REPORT, PPP_UP_SUCCESSFUL, NULL, 0); if(Interface()->Ifnet()) Interface()->Ifnet()->if_flags |= IFF_RUNNING; + + Interface()->Report(PPP_CONNECTION_REPORT, PPP_UP_SUCCESSFUL, NULL, 0); } else NewPhase(Phase() + 1); - - fLock.Unlock(); } }