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

View File

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

View File

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

View File

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

View File

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