#include "PPPInterfaceListener.h"
#include "PPPInterface.h"
#include <Messenger.h>
#include <Handler.h>
#include <LockerHelper.h>
#include <KPPPUtils.h>
static const int32 kCodeQuitReportThread = 'QUIT';
static
status_t
report_thread(void *data)
{
PPPInterfaceListener *listener = static_cast<PPPInterfaceListener*>(data);
ppp_report_packet report;
ppp_interface_id *interfaceID;
int32 code;
thread_id sender;
BMessage message;
while (true) {
code = receive_data(&sender, &report, sizeof(report));
if (code == kCodeQuitReportThread)
break;
else if (code != PPP_REPORT_CODE)
continue;
BMessenger messenger(listener->Target());
if (messenger.IsValid()) {
message.MakeEmpty();
message.what = PPP_REPORT_MESSAGE;
message.AddInt32("type", report.type);
message.AddInt32("code", report.code);
if (report.length >= sizeof(ppp_interface_id)
&& ((report.type == PPP_MANAGER_REPORT
&& report.code == PPP_REPORT_INTERFACE_CREATED)
|| report.type >= PPP_INTERFACE_REPORT_TYPE_MIN)) {
interfaceID = reinterpret_cast<ppp_interface_id*>(report.data);
message.AddInt32("interface", static_cast<int32>(*interfaceID));
}
messenger.SendMessage(&message, (BHandler*) NULL, 100000);
}
}
return B_OK;
}
PPPInterfaceListener::PPPInterfaceListener(BHandler *target)
: fTarget(target),
fIsWatching(false),
fInterface(PPP_UNDEFINED_INTERFACE_ID)
{
Construct();
}
PPPInterfaceListener::PPPInterfaceListener(const PPPInterfaceListener& copy)
: fTarget(copy.Target()),
fIsWatching(false),
fInterface(PPP_UNDEFINED_INTERFACE_ID)
{
Construct();
}
PPPInterfaceListener::~PPPInterfaceListener()
{
StopWatchingInterface();
StopWatchingManager();
send_data(fReportThread, kCodeQuitReportThread, NULL, 0);
int32 tmp;
wait_for_thread(fReportThread, &tmp);
}
status_t
PPPInterfaceListener::InitCheck() const
{
if (fReportThread < 0)
return B_ERROR;
return Manager().InitCheck();
}
void
PPPInterfaceListener::SetTarget(BHandler *target)
{
fTarget = target;
}
bool
PPPInterfaceListener::WatchInterface(ppp_interface_id ID)
{
if (ID == fInterface)
return true;
StopWatchingInterface();
if (ID == PPP_UNDEFINED_INTERFACE_ID)
return true;
PPPInterface interface(ID);
if (interface.InitCheck() != B_OK)
return false;
if (!interface.EnableReports(PPP_CONNECTION_REPORT, fReportThread, PPP_NO_FLAGS))
return false;
fIsWatching = true;
fInterface = ID;
return true;
}
void
PPPInterfaceListener::WatchManager()
{
Manager().EnableReports(PPP_MANAGER_REPORT, fReportThread, PPP_NO_FLAGS);
}
void
PPPInterfaceListener::StopWatchingInterface()
{
if (!fIsWatching)
return;
PPPInterface interface(fInterface);
interface.DisableReports(PPP_ALL_REPORTS, fReportThread);
fIsWatching = false;
fInterface = PPP_UNDEFINED_INTERFACE_ID;
}
void
PPPInterfaceListener::StopWatchingManager()
{
Manager().DisableReports(PPP_ALL_REPORTS, fReportThread);
}
void
PPPInterfaceListener::Construct()
{
fReportThread = spawn_thread(report_thread, "report_thread", B_NORMAL_PRIORITY,
this);
resume_thread(fReportThread);
}