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
This commit is contained in:
Waldemar Kornewald 2003-07-27 11:54:35 +00:00
parent ebf34d2339
commit 4d1fb4b669
8 changed files with 163 additions and 42 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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();
}
}