1/*
2 * Copyright 2016-2017, Rene Gollent, rene@gollent.com.
3 * Distributed under the terms of the MIT License.
4 */
5#include "TargetHostInterfaceRoster.h"
6
7#include <new>
8
9#include <AutoDeleter.h>
10#include <AutoLocker.h>
11
12#include "LocalTargetHostInterfaceInfo.h"
13#include "NetworkTargetHostInterfaceInfo.h"
14#include "TargetHostInterfaceInfo.h"
15
16
17/*static*/ TargetHostInterfaceRoster*
18	TargetHostInterfaceRoster::sDefaultInstance = NULL;
19
20
21TargetHostInterfaceRoster::TargetHostInterfaceRoster()
22	:
23	TargetHostInterface::Listener(),
24	fLock(),
25	fRunningTeamDebuggers(0),
26	fInterfaceInfos(20, false),
27	fActiveInterfaces(20, false),
28	fListener(NULL)
29{
30}
31
32
33TargetHostInterfaceRoster::~TargetHostInterfaceRoster()
34{
35	for (int32 i = 0; TargetHostInterfaceInfo* info
36			= fInterfaceInfos.ItemAt(i); i++) {
37		info->ReleaseReference();
38	}
39
40	for (int32 i = 0; TargetHostInterface* interface
41			= fActiveInterfaces.ItemAt(i); i++) {
42		if (interface->Lock())
43			interface->Quit();
44	}
45}
46
47
48/*static*/ TargetHostInterfaceRoster*
49TargetHostInterfaceRoster::Default()
50{
51	return sDefaultInstance;
52}
53
54
55/*static*/ status_t
56TargetHostInterfaceRoster::CreateDefault(Listener* listener)
57{
58	if (sDefaultInstance != NULL)
59		return B_OK;
60
61	TargetHostInterfaceRoster* roster
62		= new(std::nothrow) TargetHostInterfaceRoster;
63	if (roster == NULL)
64		return B_NO_MEMORY;
65	ObjectDeleter<TargetHostInterfaceRoster> rosterDeleter(roster);
66
67	status_t error = roster->Init(listener);
68	if (error != B_OK)
69		return error;
70
71	error = roster->RegisterInterfaceInfos();
72	if (error != B_OK)
73		return error;
74
75	sDefaultInstance = rosterDeleter.Detach();
76	return B_OK;
77}
78
79
80/*static*/ void
81TargetHostInterfaceRoster::DeleteDefault()
82{
83	TargetHostInterfaceRoster* roster = sDefaultInstance;
84	sDefaultInstance = NULL;
85	delete roster;
86}
87
88
89status_t
90TargetHostInterfaceRoster::Init(Listener* listener)
91{
92	fListener = listener;
93	return fLock.InitCheck();
94}
95
96
97status_t
98TargetHostInterfaceRoster::RegisterInterfaceInfos()
99{
100	TargetHostInterfaceInfo* info = NULL;
101	BReference<TargetHostInterfaceInfo> interfaceReference;
102
103	#undef REGISTER_INTERFACE_INFO
104	#define REGISTER_INTERFACE_INFO(type) \
105		info = new(std::nothrow) type##TargetHostInterfaceInfo; \
106		if (info == NULL) \
107			return B_NO_MEMORY; \
108		interfaceReference.SetTo(info, true); \
109		if (info->Init() != B_OK) \
110			return B_NO_MEMORY; \
111		if (!fInterfaceInfos.AddItem(info)) \
112			return B_NO_MEMORY; \
113		interfaceReference.Detach();
114
115	REGISTER_INTERFACE_INFO(Local)
116	REGISTER_INTERFACE_INFO(Network)
117
118	return B_OK;
119}
120
121
122int32
123TargetHostInterfaceRoster::CountInterfaceInfos() const
124{
125	return fInterfaceInfos.CountItems();
126}
127
128
129TargetHostInterfaceInfo*
130TargetHostInterfaceRoster::InterfaceInfoAt(int32 index) const
131{
132	return fInterfaceInfos.ItemAt(index);
133}
134
135
136status_t
137TargetHostInterfaceRoster::CreateInterface(TargetHostInterfaceInfo* info,
138	Settings* settings, TargetHostInterface*& _interface)
139{
140	// TODO: this should eventually verify that an active interface with
141	// matching settings/type doesn't already exist, and if so, return that
142	// directly rather than instantiating a new one, since i.e. the interface
143	// for the local host only requires one instance.
144	AutoLocker<TargetHostInterfaceRoster> locker(this);
145	TargetHostInterface* interface;
146	status_t error = info->CreateInterface(settings, interface);
147	if (error != B_OK)
148		return error;
149
150	error = interface->Run();
151	if (error < B_OK || !fActiveInterfaces.AddItem(interface)) {
152		delete interface;
153		return B_NO_MEMORY;
154	}
155
156	interface->AddListener(this);
157	_interface = interface;
158	return B_OK;
159}
160
161
162int32
163TargetHostInterfaceRoster::CountActiveInterfaces() const
164{
165	return fActiveInterfaces.CountItems();
166}
167
168
169TargetHostInterface*
170TargetHostInterfaceRoster::ActiveInterfaceAt(int32 index) const
171{
172	return fActiveInterfaces.ItemAt(index);
173}
174
175
176void
177TargetHostInterfaceRoster::TeamDebuggerStarted(TeamDebugger* debugger)
178{
179	fRunningTeamDebuggers++;
180	fListener->TeamDebuggerCountChanged(fRunningTeamDebuggers);
181}
182
183
184void
185TargetHostInterfaceRoster::TeamDebuggerQuit(TeamDebugger* debugger)
186{
187	fRunningTeamDebuggers--;
188	fListener->TeamDebuggerCountChanged(fRunningTeamDebuggers);
189}
190
191
192void
193TargetHostInterfaceRoster::TargetHostInterfaceQuit(
194	TargetHostInterface* interface)
195{
196	AutoLocker<TargetHostInterfaceRoster> locker(this);
197	fActiveInterfaces.RemoveItem(interface);
198
199}
200
201
202// #pragma mark - TargetHostInterfaceRoster::Listener
203
204
205TargetHostInterfaceRoster::Listener::~Listener()
206{
207}
208
209
210void
211TargetHostInterfaceRoster::Listener::TeamDebuggerCountChanged(int32 count)
212{
213}
214