From 3c39df3d0bf8f702c18504acfbc4e11fe39a20bc Mon Sep 17 00:00:00 2001 From: Waldemar Kornewald Date: Tue, 19 Aug 2003 10:40:45 +0000 Subject: [PATCH] Finished Up(). Redial needs one additional case to be complete. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4310 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kits/net/ppp/headers/KPPPInterface.h | 7 +- src/tests/kits/net/ppp/src/KPPPInterface.cpp | 177 ++++++++++++------ .../kits/net/ppp/src/KPPPStateMachine.cpp | 20 +- 3 files changed, 141 insertions(+), 63 deletions(-) diff --git a/src/tests/kits/net/ppp/headers/KPPPInterface.h b/src/tests/kits/net/ppp/headers/KPPPInterface.h index 7c7b8698b9..c643421907 100644 --- a/src/tests/kits/net/ppp/headers/KPPPInterface.h +++ b/src/tests/kits/net/ppp/headers/KPPPInterface.h @@ -128,6 +128,8 @@ class PPPInterface { void CalculateMRU(); + void Redial(); + // multilink methods void SetParent(PPPInterface *parent) { fParent = parent; } @@ -139,9 +141,8 @@ class PPPInterface { PPPReportManager fReportManager; ifnet *fIfnet; - thread_id fUpThread; - uint32 fRetry; - int32 fMaxRetries; + thread_id fUpThread, fRedialThread; + uint32 fDialRetry, fDialRetriesLimit; ppp_manager_info *fManager; diff --git a/src/tests/kits/net/ppp/src/KPPPInterface.cpp b/src/tests/kits/net/ppp/src/KPPPInterface.cpp index e9d22d211d..40d5abca8a 100644 --- a/src/tests/kits/net/ppp/src/KPPPInterface.cpp +++ b/src/tests/kits/net/ppp/src/KPPPInterface.cpp @@ -13,6 +13,7 @@ #include "settings_tools.h" #include +#include // TODO: @@ -23,12 +24,22 @@ // - maybe some protocols must go down instead of being reset -> add flag for this +// needed for redial: +typedef struct redial_info { + PPPInterface *interface; + thread_id *thread; +} redial_info; + +status_t redial_func(void *data); + + + PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NULL) : fSettings(dup_driver_settings(settings)), fStateMachine(*this), fLCP(*this), fReportManager(StateMachine().Locker()), - fIfnet(NULL), fUpThread(-1), fRetry(0), fMaxRetries(0), fLinkMTU(1500), - fAccessing(0), fChildrenCount(0), fDevice(NULL), fFirstEncapsulator(NULL), - fLock(StateMachine().Locker()) + fIfnet(NULL), fUpThread(-1), fRedialThread(-1), fDialRetry(0), + fDialRetriesLimit(0), 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) fManager = NULL; @@ -80,6 +91,7 @@ PPPInterface::~PPPInterface() // tell all listeners that we are being destroyed // TODO: + // kill (or wait for) fRedialThread // remove our iface, so that nobody will access it: // go down if up // unregister from ppp_manager @@ -345,7 +357,7 @@ PPPInterface::EncapsulatorFor(uint16 protocol, bool PPPInterface::AddChild(PPPInterface *child) { - if(!child || child->Mode() != Mode()) + if(!child) return false; LockerHelper locker(fLock); @@ -355,8 +367,6 @@ PPPInterface::AddChild(PPPInterface *child) child->SetParent(this); - CalculateMRU(); - return true; } @@ -433,47 +443,54 @@ PPPInterface::Up() 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_REPORT_GOING_UP) { - PPP_REPLY(sender, B_OK); - continue; - } else if(report.code == PPP_REPORT_UP_SUCCESSFUL) { - PPP_REPLY(sender, B_OK); - fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); - return true; - } else if(report.code == PPP_REPORT_DOWN_SUCCESSFUL - || report.code == PPP_REPORT_UP_ABORTED - || report.code == PPP_REPORT_AUTHENTICATION_FAILED) { - PPP_REPLY(sender, B_OK); - fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); - return false; - } else if(report.code == PPP_REPORT_DEVICE_UP_FAILED) { - // TODO: - // !!! check code (after vacation you sometimes forget things ;) !!! - if(fRetry >= fMaxRetries || fUpThread == -1) { + // fUpThread tells the state machine to go up + if(me == fUpThread) + StateMachine().OpenEvent(); + + while(true) { + if(IsUp()) { + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return true; + } + + if(receive_data(&sender, &report, sizeof(report)) != PPP_REPORT_CODE) + continue; + + if(IsUp()) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return true; + } + + + if(report.type == PPP_DESTRUCTION_REPORT) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return false; + } else if(report.type != PPP_CONNECTION_REPORT) { + PPP_REPLY(sender, B_OK); + continue; + } + + if(report.code == PPP_REPORT_GOING_UP) { + PPP_REPLY(sender, B_OK); + continue; + } else if(report.code == PPP_REPORT_UP_SUCCESSFUL) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return true; + } else if(report.code == PPP_REPORT_DOWN_SUCCESSFUL + || report.code == PPP_REPORT_UP_ABORTED + || report.code == PPP_REPORT_AUTHENTICATION_FAILED) { + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return false; + } + + if(me != fUpThread) { + // I am an observer + if(report.code == PPP_REPORT_DEVICE_UP_FAILED) { + if(fDialRetry >= fDialRetriesLimit || fUpThread == -1) { PPP_REPLY(sender, B_OK); fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); return false; @@ -482,8 +499,6 @@ PPPInterface::Up() continue; } } else if(report.code == PPP_REPORT_CONNECTION_LOST) { - // TODO: - // !!! check code (after vacation you sometimes forget things ;) !!! if(DoesAutoRedial()) { PPP_REPLY(sender, B_OK); continue; @@ -493,11 +508,37 @@ PPPInterface::Up() return false; } } - } - } else { - // I am the thread for the real task - while(true) { - + } else { + // I am the thread for the real task + if(report.code == PPP_REPORT_DEVICE_UP_FAILED) { + if(fDialRetry >= fDialRetriesLimit) { + fDialRetry = 0; + fUpThread = -1; + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return false; + } else { + ++fDialRetry; + PPP_REPLY(sender, B_OK); + StateMachine().OpenEvent(); + continue; + } + } else if(report.code == PPP_REPORT_CONNECTION_LOST) { + // the state machine knows that we are going up and leaves + // the redial task to us + if(DoesAutoRedial() && fDialRetry < fDialRetriesLimit) { + ++fDialRetry; + PPP_REPLY(sender, B_OK); + StateMachine().OpenEvent(); + continue; + } else { + fDialRetry = 0; + fUpThread = -1; + PPP_REPLY(sender, B_OK); + fReportManager.DisableReports(PPP_CONNECTION_REPORT, me); + return false; + } + } } } @@ -926,3 +967,31 @@ PPPInterface::CalculateMRU() if(Parent()) Parent()->CalculateMRU(); } + + +void +PPPInterface::Redial() +{ + if(fRedialThread != -1) + return; + + // start a new thread that calls our Up() method + redial_info *info = new redial_info; + info.interface = this; + info.thread = &fRedialThread; + + fRedialThread = spawn_thread(redial_func, "PPPInterface: redial_thread", + B_NORMAL_PRIORITY, info); +} + + +status_t +redial_func(void *data) +{ + redial_info *info = (redial_info*) data; + + info->interface->Up(); + *info->thread = -1; + + delete info; +} diff --git a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp index 41128e16ad..2218086fa4 100644 --- a/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp +++ b/src/tests/kits/net/ppp/src/KPPPStateMachine.cpp @@ -427,15 +427,23 @@ PPPStateMachine::DownEvent() // maybe we need to redial if(State() == PPP_STARTING_STATE) { + bool needsRedial = false; + if(fAuthentiactionStatus == PPP_AUTHENTICATION_FAILED || fAuthenticationStatus == PPP_AUTHENTICATING || fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED || fPeerAuthenticationStatus == PPP_AUTHENTICATING) Interface()->Report(PPP_CONNECTION_REPORT, PPP_REPORT_AUTHENTICATION_FAILED, NULL, 0); - else + else { + // if we are going up and lost connection the redial attempt becomes + // a dial retry which is managed by the main thread in Interface::Up() + if(Interface()->fUpThread == -1) + needsRedial = true; + Interface()->Report(PPP_CONNECTION_REPORT, PPP_REPORT_CONNECTION_LOST, NULL, 0); + } if(Interface()->Parent()) Interface()->Parent()->StateMachine().UpFailedEvent(Interface()); @@ -444,10 +452,9 @@ PPPStateMachine::DownEvent() if(Interface()->DoesAutoRedial()) { // TODO: - // redial if we have been connected - // problem: if we are reconfiguring we should redial, too -// if(oldState == PPP_OPENED_STATE) -// Interface()->Redial(); + // if we are reconfiguring we should redial, too + if(needsRedial) + Interface()->Redial(); } else if(!Interface()->DoesDialOnDemand()) Interface()->Delete(); } else { @@ -481,7 +488,8 @@ PPPStateMachine::OpenEvent() if(Interface()->IsMultilink() && !Interface()->Parent()) { NewPhase(PPP_ESTABLISHMENT_PHASE); for(int32 i = 0; i < Interface()->CountChildren(); i++) - Interface()->ChildAt(i)->StateMachine().OpenEvent(); + if(Interface()->ChildAt(i)->Mode() == Interface()->Mode()) + Interface()->ChildAt(i)->StateMachine().OpenEvent(); } else { locker.UnlockNow(); ThisLayerStarted();