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:
parent
1baf26bc47
commit
cdb26db4b8
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "KPPPStateMachine.h"
|
||||
#include "KPPPLCP.h"
|
||||
#include "KPPPReport.h"
|
||||
|
||||
#include "List.h"
|
||||
#include "LockerHelper.h"
|
||||
|
@ -27,6 +28,8 @@ class PPPInterface {
|
|||
PPPInterface(driver_settings *settings, PPPInterface *parent = NULL);
|
||||
~PPPInterface();
|
||||
|
||||
void Delete();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
driver_settings* Settings()
|
||||
|
@ -102,10 +105,12 @@ class PPPInterface {
|
|||
bool Down();
|
||||
bool IsUp() const;
|
||||
|
||||
/* void EnableReports(PPP_REPORT type, thread_id thread,
|
||||
int32 flags);
|
||||
void DisableReports(PPP_REPORT type, thread_id thread);
|
||||
bool DoesReport(PPP_REPORT type, thread_id thread); */
|
||||
void EnableReports(PPP_REPORT_TYPE type, port_id port,
|
||||
int32 flags = PPP_NO_REPORT_FLAGS);
|
||||
void DisableReports(PPP_REPORT_TYPE type, port_id port);
|
||||
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,
|
||||
int32 start, int32 count);
|
||||
|
@ -126,8 +131,6 @@ class PPPInterface {
|
|||
// multilink methods
|
||||
void SetParent(PPPInterface *parent)
|
||||
{ fParent = parent; }
|
||||
|
||||
// void Report(PPP_REPORT type, int32 code, void *data, int32 length);
|
||||
|
||||
private:
|
||||
driver_parameter *fSettings;
|
||||
|
@ -153,8 +156,11 @@ class PPPInterface {
|
|||
PPPEncapsulator *fFirstEncapsulator;
|
||||
List<PPPProtocol*> fProtocols;
|
||||
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
|
|
@ -27,11 +27,13 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
|
|||
: fSettings(dup_driver_settings(settings)),
|
||||
StateMachine(*this), LCP(*this), fIfnet(NULL), fLinkMTU(1500),
|
||||
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)
|
||||
fManager = NULL;
|
||||
|
||||
fPort = create_port(0, "PPP: reply port");
|
||||
|
||||
// are we a multilink subinterface?
|
||||
if(parent && parent->IsMultilink()) {
|
||||
fParent = parent;
|
||||
|
@ -75,11 +77,14 @@ PPPInterface::PPPInterface(driver_settings *settings, PPPInterface *parent = NUL
|
|||
|
||||
PPPInterface::~PPPInterface()
|
||||
{
|
||||
Report(PPP_DESTRUCTION_REPORT, 0, NULL, 0);
|
||||
// tell all listeners that we are being destroyed
|
||||
|
||||
// TODO:
|
||||
// remove our iface, so that nobody will access it:
|
||||
// go down if up
|
||||
// unregister from ppp_manager
|
||||
// delete children
|
||||
// delete children/remove from parent
|
||||
// destroy and remove:
|
||||
// device
|
||||
// protocols
|
||||
|
@ -89,13 +94,21 @@ PPPInterface::~PPPInterface()
|
|||
// put all modules (in fModules)
|
||||
|
||||
put_module((module_info**) &fManager);
|
||||
delete_port(fPort);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PPPInterface::Delete()
|
||||
{
|
||||
fManager->delete_interface(this);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PPPInterface::InitCheck() const
|
||||
{
|
||||
if(!fSettings || !fManager)
|
||||
if(!fSettings || !fManager || fPort < 0)
|
||||
return B_ERROR;
|
||||
|
||||
// sub-interfaces should have a device
|
||||
|
@ -421,7 +434,7 @@ PPPInterface::SetAutoRedial(bool autoredial = true)
|
|||
if(Mode() == PPP_CLIENT_MODE)
|
||||
return false;
|
||||
|
||||
LockerHelper locker(fGeneralLock);
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
fAutoRedial = autoredial;
|
||||
}
|
||||
|
@ -433,7 +446,7 @@ PPPInterface::SetDialOnDemand(bool dialondemand = true)
|
|||
if(Mode() != PPP_CLIENT_MODE)
|
||||
return false;
|
||||
|
||||
LockerHelper locker(fGeneralLock);
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
fDialOnDemand = dialondemand;
|
||||
|
||||
|
@ -493,33 +506,111 @@ PPPInterface::Down()
|
|||
bool
|
||||
PPPInterface::IsUp() const
|
||||
{
|
||||
LockerHelper locker(fGeneralLock);
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
return StateMachine().Phase() == PPP_ESTABLISHED_PHASE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
void
|
||||
PPPInterface::EnableReports(PPP_REPORT type, thread_id thread,
|
||||
bool needsVerification = false)
|
||||
PPPInterface::EnableReports(PPP_REPORT_TYPE type, port_id port,
|
||||
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
|
||||
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
|
||||
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
|
||||
|
|
|
@ -293,7 +293,7 @@ PPPStateMachine::UpFailedEvent()
|
|||
|
||||
switch(State()) {
|
||||
case PPP_STARTING_STATE:
|
||||
// we must have called TLS() which sets establishment phase
|
||||
// TLSNotify() sets establishment phase
|
||||
if(Phase() != PPP_ESTABLISHMENT_PHASE) {
|
||||
// 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
|
||||
|
@ -303,9 +303,8 @@ PPPStateMachine::UpFailedEvent()
|
|||
break;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// report that up failed
|
||||
// Report(PPP_CONNECTION_REPORT, PPP_UP_FAILED, NULL, 0);
|
||||
Interface()->Report(PPP_CONNECTION_REPORT, PPP_UP_FAILED, NULL, 0);
|
||||
|
||||
if(Interface()->Parent())
|
||||
Interface()->Parent()->StateMachine().UpFailedEvent(Interface());
|
||||
break;
|
||||
|
@ -373,8 +372,6 @@ PPPStateMachine::DownEvent()
|
|||
{
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
NewPhase(PPP_DOWN_PHASE);
|
||||
|
||||
switch(State()) {
|
||||
case PPP_CLOSED_STATE:
|
||||
case PPP_CLOSING_STATE:
|
||||
|
@ -385,40 +382,14 @@ PPPStateMachine::DownEvent()
|
|||
// The RFC says we should reconnect, but our implementation
|
||||
// will only do this if auto-redial is enabled (only clients).
|
||||
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;
|
||||
|
||||
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_ACK_RCVD_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:
|
||||
// tld/1
|
||||
NewStatus(PPP_STARTING_STATE);
|
||||
|
||||
// TODO:
|
||||
// report that we lost the connection
|
||||
// Report(PPP_CONNECTION_REPORT, PPP_CONNECTION_LOST, NULL, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -430,19 +401,30 @@ PPPStateMachine::DownEvent()
|
|||
// DownEncapsulators();
|
||||
// ResetOptionHandlers();
|
||||
|
||||
NewPhase(PPP_DOWN_PHASE);
|
||||
|
||||
// maybe we need to redial
|
||||
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()) {
|
||||
NewState(PPP_INITIAL_STATE);
|
||||
// TODO:
|
||||
// redial using a new thread (maybe interface manager will help us)
|
||||
} else {
|
||||
if(Interface()->Parent())
|
||||
Interface()->Parent()->StateMachine().UpFailedEvent(Interface());
|
||||
// TODO:
|
||||
// we must delete our interface
|
||||
}
|
||||
}
|
||||
// Redial()
|
||||
} else
|
||||
Interface()->Delete();
|
||||
} else
|
||||
Report(PPP_CONNECTION_REPORT, PPP_DOWN_SUCCESSFUL, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -674,6 +656,8 @@ PPPStateMachine::RCRBadEvent(mbuf *nak, mbuf *reject)
|
|||
|
||||
case PPP_OPENED_STATE:
|
||||
NewState(PPP_REQ_SENT_STATE);
|
||||
NewPhase(PPP_ESTABLISHMENT_PHASE);
|
||||
// tell handlers that we are reconfiguring
|
||||
locker.UnlockNow();
|
||||
ThisLayerDown();
|
||||
SendConfigureRequest();
|
||||
|
@ -749,6 +733,8 @@ PPPStateMachine::RCAEvent(mbuf *packet)
|
|||
|
||||
case PPP_OPENED_STATE:
|
||||
NewState(PPP_REQ_SENT_STATE);
|
||||
NewPhase(PPP_ESTABLISHMENT_PHASE);
|
||||
// tell handlers that we are reconfiguring
|
||||
locker.UnlockNow();
|
||||
ThisLayerDown();
|
||||
SendConfigureRequest();
|
||||
|
@ -808,6 +794,8 @@ PPPStateMachine::RCNEvent(mbuf *packet)
|
|||
|
||||
case PPP_OPENED_STATE:
|
||||
NewState(PPP_REQ_SENT_STATE);
|
||||
NewPhase(PPP_ESTABLISHMENT_PHASE);
|
||||
// tell handlers that we are reconfiguring
|
||||
locker.UnlockNow();
|
||||
ThisLayerDown();
|
||||
SendConfigureRequest();
|
||||
|
@ -835,12 +823,16 @@ PPPStateMachine::RTREvent(mbuf *packet)
|
|||
case PPP_ACK_RCVD_STATE:
|
||||
case PPP_ACK_SENT_STATE:
|
||||
NewState(PPP_REQ_SENT_STATE);
|
||||
NewPhase(PPP_TERMINATION_PHASE);
|
||||
// tell handlers that we are terminating
|
||||
locker.UnlockNow();
|
||||
SendTerminateAck(packet);
|
||||
break;
|
||||
|
||||
case PPP_OPENED_STATE:
|
||||
NewState(PPP_STOPPING_STATE);
|
||||
NewPhase(PPP_TERMINATION_PHASE);
|
||||
// tell handlers that we are terminating
|
||||
ZeroRestartCount();
|
||||
locker.UnlockNow();
|
||||
ThisLayerDown();
|
||||
|
@ -848,6 +840,8 @@ PPPStateMachine::RTREvent(mbuf *packet)
|
|||
break;
|
||||
|
||||
default:
|
||||
NewPhase(PPP_TERMINATION_PHASE);
|
||||
// tell handlers that we are terminating
|
||||
locker.UnlockNow();
|
||||
SendTerminateAck(packet);
|
||||
}
|
||||
|
@ -1155,7 +1149,15 @@ PPPStateMachine::ThisLayerUp()
|
|||
|
||||
// We begin with authentication phase and wait until each phase is done.
|
||||
// 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);
|
||||
|
||||
locker.UnlockNow();
|
||||
|
||||
BringHandlersUp();
|
||||
}
|
||||
|
||||
|
@ -1166,8 +1168,8 @@ PPPStateMachine::ThisLayerDown()
|
|||
// TODO:
|
||||
// DownProtocols();
|
||||
// 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
|
||||
PPPStateMachine::ThisLayerFinished()
|
||||
{
|
||||
// TODO:
|
||||
// DownProtocols();
|
||||
// DownEncapsulators();
|
||||
|
||||
if(Interface()->Device())
|
||||
Interface()->Device()->Down();
|
||||
}
|
||||
|
@ -1326,11 +1324,15 @@ PPPStateMachine::SendEchoReply(mbuf *request)
|
|||
void
|
||||
PPPStateMachine::BringHandlersUp()
|
||||
{
|
||||
while(Phase() <= PPP_ESTABLISHED_PHASE) {
|
||||
while(Phase() <= PPP_ESTABLISHED_PHASE && Phase() >= PPP_AUTHENTICATION_PHASE) {
|
||||
if(BringPhaseUp() > 0)
|
||||
break;
|
||||
|
||||
if(Phase() == PPP_ESTABLISHED_PHASE) {
|
||||
fLock.Lock();
|
||||
|
||||
if(Phase() < PPP_AUTHENTICATION_PHASE)
|
||||
return;
|
||||
else if(Phase() == PPP_ESTABLISHED_PHASE) {
|
||||
if(Interface()->Parent())
|
||||
Interface()->Parent()->StateMachine().UpEvent(Interface());
|
||||
|
||||
|
@ -1340,6 +1342,8 @@ PPPStateMachine::BringHandlersUp()
|
|||
Interface()->Ifnet()->if_flags |= IFF_RUNNING;
|
||||
} else
|
||||
NewPhase(Phase() + 1);
|
||||
|
||||
fLock.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1348,6 +1352,11 @@ PPPStateMachine::BringHandlersUp()
|
|||
uint32
|
||||
PPPStateMachine::BringPhaseUp()
|
||||
{
|
||||
LockerHelper locker(fLock);
|
||||
|
||||
if(Phase() < PPP_AUTHENTICATION_PHASE)
|
||||
return 0;
|
||||
|
||||
uint32 count = 0;
|
||||
PPPProtocol *protocol_handler;
|
||||
PPPEncapsulator *encapsulator_handler = Interface()->FirstEncapsulator();
|
||||
|
|
Loading…
Reference in New Issue