⛏️ index : haiku.git

/*
 * Copyright 2016-2017, Rene Gollent, rene@gollent.com.
 * Distributed under the terms of the MIT License.
 */
#include "TargetHostInterfaceRoster.h"

#include <new>

#include <AutoDeleter.h>
#include <AutoLocker.h>

#include "LocalTargetHostInterfaceInfo.h"
#include "NetworkTargetHostInterfaceInfo.h"
#include "TargetHostInterfaceInfo.h"


/*static*/ TargetHostInterfaceRoster*
	TargetHostInterfaceRoster::sDefaultInstance = NULL;


TargetHostInterfaceRoster::TargetHostInterfaceRoster()
	:
	TargetHostInterface::Listener(),
	fLock(),
	fRunningTeamDebuggers(0),
	fInterfaceInfos(20),
	fActiveInterfaces(20),
	fListener(NULL)
{
}


TargetHostInterfaceRoster::~TargetHostInterfaceRoster()
{
	for (int32 i = 0; TargetHostInterfaceInfo* info
			= fInterfaceInfos.ItemAt(i); i++) {
		info->ReleaseReference();
	}

	for (int32 i = 0; TargetHostInterface* interface
			= fActiveInterfaces.ItemAt(i); i++) {
		if (interface->Lock())
			interface->Quit();
	}
}


/*static*/ TargetHostInterfaceRoster*
TargetHostInterfaceRoster::Default()
{
	return sDefaultInstance;
}


/*static*/ status_t
TargetHostInterfaceRoster::CreateDefault(Listener* listener)
{
	if (sDefaultInstance != NULL)
		return B_OK;

	TargetHostInterfaceRoster* roster
		= new(std::nothrow) TargetHostInterfaceRoster;
	if (roster == NULL)
		return B_NO_MEMORY;
	ObjectDeleter<TargetHostInterfaceRoster> rosterDeleter(roster);

	status_t error = roster->Init(listener);
	if (error != B_OK)
		return error;

	error = roster->RegisterInterfaceInfos();
	if (error != B_OK)
		return error;

	sDefaultInstance = rosterDeleter.Detach();
	return B_OK;
}


/*static*/ void
TargetHostInterfaceRoster::DeleteDefault()
{
	TargetHostInterfaceRoster* roster = sDefaultInstance;
	sDefaultInstance = NULL;
	delete roster;
}


status_t
TargetHostInterfaceRoster::Init(Listener* listener)
{
	fListener = listener;
	return fLock.InitCheck();
}


status_t
TargetHostInterfaceRoster::RegisterInterfaceInfos()
{
	TargetHostInterfaceInfo* info = NULL;
	BReference<TargetHostInterfaceInfo> interfaceReference;

	#undef REGISTER_INTERFACE_INFO
	#define REGISTER_INTERFACE_INFO(type) \
		info = new(std::nothrow) type##TargetHostInterfaceInfo; \
		if (info == NULL) \
			return B_NO_MEMORY; \
		interfaceReference.SetTo(info, true); \
		if (info->Init() != B_OK) \
			return B_NO_MEMORY; \
		if (!fInterfaceInfos.AddItem(info)) \
			return B_NO_MEMORY; \
		interfaceReference.Detach();

	REGISTER_INTERFACE_INFO(Local)
	REGISTER_INTERFACE_INFO(Network)

	return B_OK;
}


int32
TargetHostInterfaceRoster::CountInterfaceInfos() const
{
	return fInterfaceInfos.CountItems();
}


TargetHostInterfaceInfo*
TargetHostInterfaceRoster::InterfaceInfoAt(int32 index) const
{
	return fInterfaceInfos.ItemAt(index);
}


status_t
TargetHostInterfaceRoster::CreateInterface(TargetHostInterfaceInfo* info,
	Settings* settings, TargetHostInterface*& _interface)
{
	// TODO: this should eventually verify that an active interface with
	// matching settings/type doesn't already exist, and if so, return that
	// directly rather than instantiating a new one, since i.e. the interface
	// for the local host only requires one instance.
	AutoLocker<TargetHostInterfaceRoster> locker(this);
	TargetHostInterface* interface;
	status_t error = info->CreateInterface(settings, interface);
	if (error != B_OK)
		return error;

	error = interface->Run();
	if (error < B_OK || !fActiveInterfaces.AddItem(interface)) {
		delete interface;
		return B_NO_MEMORY;
	}

	interface->AddListener(this);
	_interface = interface;
	return B_OK;
}


int32
TargetHostInterfaceRoster::CountActiveInterfaces() const
{
	return fActiveInterfaces.CountItems();
}


TargetHostInterface*
TargetHostInterfaceRoster::ActiveInterfaceAt(int32 index) const
{
	return fActiveInterfaces.ItemAt(index);
}


void
TargetHostInterfaceRoster::TeamDebuggerStarted(TeamDebugger* debugger)
{
	fRunningTeamDebuggers++;
	fListener->TeamDebuggerCountChanged(fRunningTeamDebuggers);
}


void
TargetHostInterfaceRoster::TeamDebuggerQuit(TeamDebugger* debugger)
{
	fRunningTeamDebuggers--;
	fListener->TeamDebuggerCountChanged(fRunningTeamDebuggers);
}


void
TargetHostInterfaceRoster::TargetHostInterfaceQuit(
	TargetHostInterface* interface)
{
	AutoLocker<TargetHostInterfaceRoster> locker(this);
	fActiveInterfaces.RemoveItem(interface);

}


// #pragma mark - TargetHostInterfaceRoster::Listener


TargetHostInterfaceRoster::Listener::~Listener()
{
}


void
TargetHostInterfaceRoster::Listener::TeamDebuggerCountChanged(int32 count)
{
}