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:
parent
ebf34d2339
commit
4d1fb4b669
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user