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
This commit is contained in:
Waldemar Kornewald
2003-08-19 10:40:45 +00:00
parent 434690369e
commit 3c39df3d0b
3 changed files with 141 additions and 63 deletions
@@ -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;
+123 -54
View File
@@ -13,6 +13,7 @@
#include "settings_tools.h"
#include <cstring>
#include <new.h>
// 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;
}
@@ -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();