Implemented report methods for interface and began first connection reports.

Added some changes.

Next tasks:
Up/Down()
Redial()


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4084 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Waldemar Kornewald
2003-07-26 17:34:45 +00:00
parent 1baf26bc47
commit cdb26db4b8
4 changed files with 231 additions and 69 deletions
+13 -7
View File
@@ -7,6 +7,7 @@
#include "KPPPStateMachine.h" #include "KPPPStateMachine.h"
#include "KPPPLCP.h" #include "KPPPLCP.h"
#include "KPPPReport.h"
#include "List.h" #include "List.h"
#include "LockerHelper.h" #include "LockerHelper.h"
@@ -27,6 +28,8 @@ class PPPInterface {
PPPInterface(driver_settings *settings, PPPInterface *parent = NULL); PPPInterface(driver_settings *settings, PPPInterface *parent = NULL);
~PPPInterface(); ~PPPInterface();
void Delete();
status_t InitCheck() const; status_t InitCheck() const;
driver_settings* Settings() driver_settings* Settings()
@@ -102,10 +105,12 @@ class PPPInterface {
bool Down(); bool Down();
bool IsUp() const; bool IsUp() const;
/* void EnableReports(PPP_REPORT type, thread_id thread, void EnableReports(PPP_REPORT_TYPE type, port_id port,
int32 flags); int32 flags = PPP_NO_REPORT_FLAGS);
void DisableReports(PPP_REPORT type, thread_id thread); void DisableReports(PPP_REPORT_TYPE type, port_id port);
bool DoesReport(PPP_REPORT type, thread_id thread); */ bool DoesReport(PPP_REPORT_TYPE type, port_id port);
bool Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length);
// returns false if reply was bad (or an error occured)
bool LoadModules(const driver_settings *settings, bool LoadModules(const driver_settings *settings,
int32 start, int32 count); int32 start, int32 count);
@@ -126,8 +131,6 @@ class PPPInterface {
// multilink methods // multilink methods
void SetParent(PPPInterface *parent) void SetParent(PPPInterface *parent)
{ fParent = parent; } { fParent = parent; }
// void Report(PPP_REPORT type, int32 code, void *data, int32 length);
private: private:
driver_parameter *fSettings; driver_parameter *fSettings;
@@ -153,8 +156,11 @@ class PPPInterface {
PPPEncapsulator *fFirstEncapsulator; PPPEncapsulator *fFirstEncapsulator;
List<PPPProtocol*> fProtocols; List<PPPProtocol*> fProtocols;
List<ppp_module_info*> fModules; List<ppp_module_info*> fModules;
List<ppp_report_request> fReportRequests;
BLocker& fGeneralLock; port_id fPort;
BLocker& fLock;
}; };
@@ -0,0 +1,56 @@
#ifndef _K_PPP_REPORT__H
#define _K_PPP_REPORT__H
#define PPP_REPORT_DATA_LIMIT 128
// how much optional data can be added to the report
#define PPP_REPORT_CODE '_3PR'
// the code field of read_port
// report flags
enum PPP_REPORT_FLAGS {
PPP_NO_REPORT_FLAGS = 0,
PPP_WAIT_FOR_REPLY = 0x1,
PPP_REMOVE_AFTER_REPORT = 0x2
};
// report types
enum PPP_REPORT_TYPE {
PPP_DESTRUCTION_REPORT = 0,
// the interface is being destroyed (no code is needed)
PPP_CONNECTION_REPORT = 1
};
// report codes (type-specific)
enum PPP_CONNECTION_REPORT_CODES {
PPP_UP_SUCCESSFUL = 1,
PPP_DOWN_SUCCESSFUL = 2,
PPP_UP_ABORTED = 3,
PPP_UP_FAILED = 4,
PPP_AUTHENTICATION_FAILED = 5,
PPP_CONNECTION_LOST = 6
};
typedef struct ppp_report_packet {
port_id port;
int32 type;
int32 code;
uint8 len;
char data[PPP_REPORT_DATA_LIMIT];
} ppp_report_packet;
//***********
// private
//***********
#define PPP_REPORT_TIMEOUT 10000
typedef struct ppp_report_request {
port_id port;
int32 type;
int32 flags;
} ppp_report_request;
#endif
+104 -13
View File
@@ -27,11 +27,13 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
: fSettings(dup_driver_settings(settings)), : fSettings(dup_driver_settings(settings)),
StateMachine(*this), LCP(*this), fIfnet(NULL), fLinkMTU(1500), StateMachine(*this), LCP(*this), fIfnet(NULL), fLinkMTU(1500),
fAccessing(0), fChildrenCount(0), fDevice(NULL), fFirstEncapsulator(NULL), fAccessing(0), fChildrenCount(0), fDevice(NULL), fFirstEncapsulator(NULL),
fGeneralLock(StateMachine().Locker()) fLock(StateMachine().Locker())
{ {
if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &fManager) != B_OK) if(get_module(PPP_MANAGER_MODULE_NAME, (module_info**) &fManager) != B_OK)
fManager = NULL; fManager = NULL;
fPort = create_port(0, "PPP: reply port");
// are we a multilink subinterface? // are we a multilink subinterface?
if(parent && parent->IsMultilink()) { if(parent && parent->IsMultilink()) {
fParent = parent; fParent = parent;
@@ -75,11 +77,14 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
PPPInterface::~PPPInterface() PPPInterface::~PPPInterface()
{ {
Report(PPP_DESTRUCTION_REPORT, 0, NULL, 0);
// tell all listeners that we are being destroyed
// TODO: // TODO:
// remove our iface, so that nobody will access it: // remove our iface, so that nobody will access it:
// go down if up // go down if up
// unregister from ppp_manager // unregister from ppp_manager
// delete children // delete children/remove from parent
// destroy and remove: // destroy and remove:
// device // device
// protocols // protocols
@@ -89,13 +94,21 @@ PPPInterface::~PPPInterface()
// put all modules (in fModules) // put all modules (in fModules)
put_module((module_info**) &fManager); put_module((module_info**) &fManager);
delete_port(fPort);
}
void
PPPInterface::Delete()
{
fManager->delete_interface(this);
} }
status_t status_t
PPPInterface::InitCheck() const PPPInterface::InitCheck() const
{ {
if(!fSettings || !fManager) if(!fSettings || !fManager || fPort < 0)
return B_ERROR; return B_ERROR;
// sub-interfaces should have a device // sub-interfaces should have a device
@@ -421,7 +434,7 @@ PPPInterface::SetAutoRedial(bool autoredial = true)
if(Mode() == PPP_CLIENT_MODE) if(Mode() == PPP_CLIENT_MODE)
return false; return false;
LockerHelper locker(fGeneralLock); LockerHelper locker(fLock);
fAutoRedial = autoredial; fAutoRedial = autoredial;
} }
@@ -433,7 +446,7 @@ PPPInterface::SetDialOnDemand(bool dialondemand = true)
if(Mode() != PPP_CLIENT_MODE) if(Mode() != PPP_CLIENT_MODE)
return false; return false;
LockerHelper locker(fGeneralLock); LockerHelper locker(fLock);
fDialOnDemand = dialondemand; fDialOnDemand = dialondemand;
@@ -493,33 +506,111 @@ PPPInterface::Down()
bool bool
PPPInterface::IsUp() const PPPInterface::IsUp() const
{ {
LockerHelper locker(fGeneralLock); LockerHelper locker(fLock);
return StateMachine().Phase() == PPP_ESTABLISHED_PHASE; return StateMachine().Phase() == PPP_ESTABLISHED_PHASE;
} }
/*
void void
PPPInterface::EnableReports(PPP_REPORT type, thread_id thread, PPPInterface::EnableReports(PPP_REPORT_TYPE type, port_id port,
bool needsVerification = false) int32 flags = PPP_NO_REPORT_FLAGS)
{ {
LockerHelper locker(fLock);
ppp_report_request request;
request.type = type;
request.port = port;
request.flags = flags;
fReportRequests.AddItem(request);
} }
void void
PPPInterface::DisableReports(PPP_REPORT type, thread_id thread) PPPInterface::DisableReports(PPP_REPORT_TYPE type, port_id port)
{ {
LockerHelper locker(fLock);
for(int32 i = 0; i < fReportRequests.CountItems(); i++) {
ppp_report_request& request = fReportRequests.ItemAt(i);
if(request.port != port)
continue;
if(report.type == type)
fReportRequest.RemoveItem(request);
}
} }
bool bool
PPPInterface::Reports(PPP_REPORT type, thread_id thread) PPPInterface::DoesReport(PPP_REPORT_TYPE type, port_id port)
{ {
LockerHelper locker(fLock);
for(int32 i = 0; i < fReportRequests.CountItems(); i++) {
ppp_report_request& request = fReportRequests.ItemAt(i);
if(request.port == port && request.type == type)
return true;
}
return false;
} }
*/
bool
PPPInterface::Report(PPP_REPORT_TYPE type, int32 code, void *data, int32 length)
{
if(length > PPP_REPORT_DATA_LIMIT || fPort < 0)
return false;
if(fReportRequests.CountItems() == 0)
return true;
if(!data)
length = 0;
LockerHelper locker(fLock);
int32 code, query, result;
bool successful = true;
report_packet report;
report.port = fPort;
report.type = type;
report.code = code;
report.length = length;
memcpy(report.data, data, length);
for(int32 index = 0; index < fReportRequests.CountItems(); index++) {
ppp_report_request& request = fReportRequests.ItemAt(index);
result = write_port_etc(request.port, PPP_REPORT_CODE, &report,
sizeof(report), B_TIMEOUT, PPP_REPORT_TIMEOUT);
if(result == B_BAD_PORT_ID) {
fReportRequests.RemoveItem(request);
--index;
continue;
} else if(result == B_OK) {
if(request.flags & PPP_WAIT_FOR_REPLY) {
result = read_port_etc(fPort, &code, NULL, 0,
B_TIMEOUT, PPP_REPORT_TIMEOUT);
if(result == 0 && code != B_OK)
successful = false;
}
}
if(request.flags & PPP_REMOVE_AFTER_REPORT) {
fReportRequests.RemoveItem(request);
--index;
}
}
return successful;
}
bool bool
+58 -49
View File
@@ -293,7 +293,7 @@ PPPStateMachine::UpFailedEvent()
switch(State()) { switch(State()) {
case PPP_STARTING_STATE: case PPP_STARTING_STATE:
// we must have called TLS() which sets establishment phase // TLSNotify() sets establishment phase
if(Phase() != PPP_ESTABLISHMENT_PHASE) { if(Phase() != PPP_ESTABLISHMENT_PHASE) {
// there must be a BUG in the device add-on or someone is trying to // there must be a BUG in the device add-on or someone is trying to
// fool us (UpEvent() is public) as we did not request the device // fool us (UpEvent() is public) as we did not request the device
@@ -303,9 +303,8 @@ PPPStateMachine::UpFailedEvent()
break; break;
} }
// TODO: Interface()->Report(PPP_CONNECTION_REPORT, PPP_UP_FAILED, NULL, 0);
// report that up failed
// Report(PPP_CONNECTION_REPORT, PPP_UP_FAILED, NULL, 0);
if(Interface()->Parent()) if(Interface()->Parent())
Interface()->Parent()->StateMachine().UpFailedEvent(Interface()); Interface()->Parent()->StateMachine().UpFailedEvent(Interface());
break; break;
@@ -373,8 +372,6 @@ PPPStateMachine::DownEvent()
{ {
LockerHelper locker(fLock); LockerHelper locker(fLock);
NewPhase(PPP_DOWN_PHASE);
switch(State()) { switch(State()) {
case PPP_CLOSED_STATE: case PPP_CLOSED_STATE:
case PPP_CLOSING_STATE: case PPP_CLOSING_STATE:
@@ -385,40 +382,14 @@ PPPStateMachine::DownEvent()
// The RFC says we should reconnect, but our implementation // The RFC says we should reconnect, but our implementation
// will only do this if auto-redial is enabled (only clients). // will only do this if auto-redial is enabled (only clients).
NewStatus(PPP_STARTING_STATE); NewStatus(PPP_STARTING_STATE);
// TODO:
// report that we lost the connection
// if fAuthStatus == FAILED || fPeerAuthStatus == FAILED
// Report(PPP_CONNECTION_REPORT, PPP_AUTH_FAILED, NULL, 0);
// else
// Report(PPP_CONNECTION_REPORT, PPP_CONNECTION_LOST, NULL, 0);
break; break;
case PPP_STOPPING_STATE: case PPP_STOPPING_STATE:
NewStatus(PPP_STARTING_STATE);
// TODO:
// report that we lost the connection
// Report(PPP_CONNECTION_REPORT, PPP_CONNECTION_LOST, NULL, 0);
break;
case PPP_REQ_SENT_STATE: case PPP_REQ_SENT_STATE:
case PPP_ACK_RCVD_STATE: case PPP_ACK_RCVD_STATE:
case PPP_ACK_SENT_STATE: case PPP_ACK_SENT_STATE:
NewStatus(PPP_STARTING_STATE);
// TODO:
// report that we lost the connection
// Report(PPP_CONNECTION_REPORT, PPP_CONNECTION_LOST, NULL, 0);
break;
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
// tld/1
NewStatus(PPP_STARTING_STATE); NewStatus(PPP_STARTING_STATE);
// TODO:
// report that we lost the connection
// Report(PPP_CONNECTION_REPORT, PPP_CONNECTION_LOST, NULL, 0);
break; break;
default: default:
@@ -430,19 +401,30 @@ PPPStateMachine::DownEvent()
// DownEncapsulators(); // DownEncapsulators();
// ResetOptionHandlers(); // ResetOptionHandlers();
NewPhase(PPP_DOWN_PHASE);
// maybe we need to redial // maybe we need to redial
if(State() == PPP_STARTING_STATE) { if(State() == PPP_STARTING_STATE) {
if(fAuthentiactionStatus == PPP_AUTHENTICATION_FAILED
|| fPeerAuthenticationStatus == PPP_AUTHENTICATION_FAILED)
Interface()->Report(PPP_CONNECTION_REPORT, PPP_AUTHENTICATION_FAILED,
NULL, 0);
else
Interface()->Report(PPP_CONNECTION_REPORT, PPP_CONNECTION_LOST,
NULL, 0);
if(Interface()->Parent())
Interface()->Parent()->StateMachine().UpFailedEvent(Interface());
NewState(PPP_INITIAL_STATE);
if(Interface()->DoesAutoRedial()) { if(Interface()->DoesAutoRedial()) {
NewState(PPP_INITIAL_STATE);
// TODO: // TODO:
// redial using a new thread (maybe interface manager will help us) // Redial()
} else { } else
if(Interface()->Parent()) Interface()->Delete();
Interface()->Parent()->StateMachine().UpFailedEvent(Interface()); } else
// TODO: Report(PPP_CONNECTION_REPORT, PPP_DOWN_SUCCESSFUL, NULL, 0);
// we must delete our interface
}
}
} }
@@ -674,6 +656,8 @@ PPPStateMachine::RCRBadEvent(mbuf *nak, mbuf *reject)
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
NewState(PPP_REQ_SENT_STATE); NewState(PPP_REQ_SENT_STATE);
NewPhase(PPP_ESTABLISHMENT_PHASE);
// tell handlers that we are reconfiguring
locker.UnlockNow(); locker.UnlockNow();
ThisLayerDown(); ThisLayerDown();
SendConfigureRequest(); SendConfigureRequest();
@@ -749,6 +733,8 @@ PPPStateMachine::RCAEvent(mbuf *packet)
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
NewState(PPP_REQ_SENT_STATE); NewState(PPP_REQ_SENT_STATE);
NewPhase(PPP_ESTABLISHMENT_PHASE);
// tell handlers that we are reconfiguring
locker.UnlockNow(); locker.UnlockNow();
ThisLayerDown(); ThisLayerDown();
SendConfigureRequest(); SendConfigureRequest();
@@ -808,6 +794,8 @@ PPPStateMachine::RCNEvent(mbuf *packet)
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
NewState(PPP_REQ_SENT_STATE); NewState(PPP_REQ_SENT_STATE);
NewPhase(PPP_ESTABLISHMENT_PHASE);
// tell handlers that we are reconfiguring
locker.UnlockNow(); locker.UnlockNow();
ThisLayerDown(); ThisLayerDown();
SendConfigureRequest(); SendConfigureRequest();
@@ -835,12 +823,16 @@ PPPStateMachine::RTREvent(mbuf *packet)
case PPP_ACK_RCVD_STATE: case PPP_ACK_RCVD_STATE:
case PPP_ACK_SENT_STATE: case PPP_ACK_SENT_STATE:
NewState(PPP_REQ_SENT_STATE); NewState(PPP_REQ_SENT_STATE);
NewPhase(PPP_TERMINATION_PHASE);
// tell handlers that we are terminating
locker.UnlockNow(); locker.UnlockNow();
SendTerminateAck(packet); SendTerminateAck(packet);
break; break;
case PPP_OPENED_STATE: case PPP_OPENED_STATE:
NewState(PPP_STOPPING_STATE); NewState(PPP_STOPPING_STATE);
NewPhase(PPP_TERMINATION_PHASE);
// tell handlers that we are terminating
ZeroRestartCount(); ZeroRestartCount();
locker.UnlockNow(); locker.UnlockNow();
ThisLayerDown(); ThisLayerDown();
@@ -848,6 +840,8 @@ PPPStateMachine::RTREvent(mbuf *packet)
break; break;
default: default:
NewPhase(PPP_TERMINATION_PHASE);
// tell handlers that we are terminating
locker.UnlockNow(); locker.UnlockNow();
SendTerminateAck(packet); SendTerminateAck(packet);
} }
@@ -1155,7 +1149,15 @@ PPPStateMachine::ThisLayerUp()
// We begin with authentication phase and wait until each phase is done. // We begin with authentication phase and wait until each phase is done.
// We stop when we reach established phase. // We stop when we reach established phase.
// Do not forget to check if we are going down.
if(Phase() != PPP_ESTABLISHMENT_PHASE)
return;
NewPhase(PPP_AUTHENTICATION_PHASE); NewPhase(PPP_AUTHENTICATION_PHASE);
locker.UnlockNow();
BringHandlersUp(); BringHandlersUp();
} }
@@ -1166,8 +1168,8 @@ PPPStateMachine::ThisLayerDown()
// TODO: // TODO:
// DownProtocols(); // DownProtocols();
// DownEncapsulators(); // DownEncapsulators();
// If there are protocols/encapsulators with PPP_DOWN_NEEDED flag
// wait until they report a DownEvent() (or until all of them are down). // PPPProtocol/Encapsulator::Down() should block if needed.
} }
@@ -1182,10 +1184,6 @@ PPPStateMachine::ThisLayerStarted()
void void
PPPStateMachine::ThisLayerFinished() PPPStateMachine::ThisLayerFinished()
{ {
// TODO:
// DownProtocols();
// DownEncapsulators();
if(Interface()->Device()) if(Interface()->Device())
Interface()->Device()->Down(); Interface()->Device()->Down();
} }
@@ -1326,11 +1324,15 @@ PPPStateMachine::SendEchoReply(mbuf *request)
void void
PPPStateMachine::BringHandlersUp() PPPStateMachine::BringHandlersUp()
{ {
while(Phase() <= PPP_ESTABLISHED_PHASE) { while(Phase() <= PPP_ESTABLISHED_PHASE && Phase() >= PPP_AUTHENTICATION_PHASE) {
if(BringPhaseUp() > 0) if(BringPhaseUp() > 0)
break; break;
if(Phase() == PPP_ESTABLISHED_PHASE) { fLock.Lock();
if(Phase() < PPP_AUTHENTICATION_PHASE)
return;
else if(Phase() == PPP_ESTABLISHED_PHASE) {
if(Interface()->Parent()) if(Interface()->Parent())
Interface()->Parent()->StateMachine().UpEvent(Interface()); Interface()->Parent()->StateMachine().UpEvent(Interface());
@@ -1340,6 +1342,8 @@ PPPStateMachine::BringHandlersUp()
Interface()->Ifnet()->if_flags |= IFF_RUNNING; Interface()->Ifnet()->if_flags |= IFF_RUNNING;
} else } else
NewPhase(Phase() + 1); NewPhase(Phase() + 1);
fLock.Unlock();
} }
} }
@@ -1348,6 +1352,11 @@ PPPStateMachine::BringHandlersUp()
uint32 uint32
PPPStateMachine::BringPhaseUp() PPPStateMachine::BringPhaseUp()
{ {
LockerHelper locker(fLock);
if(Phase() < PPP_AUTHENTICATION_PHASE)
return 0;
uint32 count = 0; uint32 count = 0;
PPPProtocol *protocol_handler; PPPProtocol *protocol_handler;
PPPEncapsulator *encapsulator_handler = Interface()->FirstEncapsulator(); PPPEncapsulator *encapsulator_handler = Interface()->FirstEncapsulator();