xref: /haiku/src/apps/networkstatus/NetworkStatusView.cpp (revision 4c28a7375dd0df1768e4fdeb6d01251fb06e7133)
1f01106c3SAxel Dörfler /*
2f01106c3SAxel Dörfler  * Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
3f01106c3SAxel Dörfler  * Distributed under the terms of the MIT License.
4f01106c3SAxel Dörfler  *
5f01106c3SAxel Dörfler  * Authors:
6f01106c3SAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
7f01106c3SAxel Dörfler  *		Hugo Santos, hugosantos@gmail.com
83b41ad86SStephan Aßmus  *		Dario Casalinuovo
9f01106c3SAxel Dörfler  */
10f01106c3SAxel Dörfler 
11f01106c3SAxel Dörfler 
12f01106c3SAxel Dörfler #include "NetworkStatusView.h"
13f01106c3SAxel Dörfler 
14f01106c3SAxel Dörfler #include "NetworkStatus.h"
15f01106c3SAxel Dörfler #include "NetworkStatusIcons.h"
16f01106c3SAxel Dörfler 
17f01106c3SAxel Dörfler #include <Alert.h>
18f01106c3SAxel Dörfler #include <Application.h>
19f01106c3SAxel Dörfler #include <Bitmap.h>
20f01106c3SAxel Dörfler #include <Deskbar.h>
21f01106c3SAxel Dörfler #include <Dragger.h>
22f01106c3SAxel Dörfler #include <Drivers.h>
23f01106c3SAxel Dörfler #include <IconUtils.h>
24f01106c3SAxel Dörfler #include <MenuItem.h>
25f01106c3SAxel Dörfler #include <MessageRunner.h>
26f01106c3SAxel Dörfler #include <PopUpMenu.h>
27f01106c3SAxel Dörfler #include <Resources.h>
28d5ba07a3SAxel Dörfler #include <Roster.h>
29f01106c3SAxel Dörfler #include <String.h>
30f01106c3SAxel Dörfler #include <TextView.h>
31f01106c3SAxel Dörfler 
32f01106c3SAxel Dörfler #include <arpa/inet.h>
33f01106c3SAxel Dörfler #include <net/if.h>
34f01106c3SAxel Dörfler #include <stdio.h>
35f01106c3SAxel Dörfler #include <stdlib.h>
36f01106c3SAxel Dörfler #include <string.h>
37f01106c3SAxel Dörfler #include <sys/socket.h>
38f01106c3SAxel Dörfler #include <sys/sockio.h>
39f01106c3SAxel Dörfler #include <unistd.h>
40f01106c3SAxel Dörfler 
41f01106c3SAxel Dörfler #ifndef HAIKU_TARGET_PLATFORM_HAIKU
42f01106c3SAxel Dörfler // BONE compatibility
43f01106c3SAxel Dörfler #	define IF_NAMESIZE IFNAMSIZ
44f01106c3SAxel Dörfler #	define IFF_LINK 0
45f01106c3SAxel Dörfler #	define IFF_CONFIGURING 0
46f01106c3SAxel Dörfler #	define ifc_value ifc_val
47f01106c3SAxel Dörfler #endif
48f01106c3SAxel Dörfler 
49f01106c3SAxel Dörfler static const char *kStatusDescriptions[] = {
50f01106c3SAxel Dörfler 	"Unknown",
51f01106c3SAxel Dörfler 	"No Link",
52f01106c3SAxel Dörfler 	"No stateful configuration",
53f01106c3SAxel Dörfler 	"Configuring",
54f01106c3SAxel Dörfler 	"Ready"
55f01106c3SAxel Dörfler };
56f01106c3SAxel Dörfler 
57f01106c3SAxel Dörfler extern "C" _EXPORT BView *instantiate_deskbar_item(void);
58f01106c3SAxel Dörfler 
59f01106c3SAxel Dörfler 
60f01106c3SAxel Dörfler const uint32 kMsgUpdate = 'updt';
61f01106c3SAxel Dörfler const uint32 kMsgShowConfiguration = 'shcf';
62c1502c9aSStephan Aßmus const uint32 kMsgOpenNetworkPreferences = 'onwp';
63f01106c3SAxel Dörfler 
64f01106c3SAxel Dörfler const uint32 kMinIconWidth = 16;
65f01106c3SAxel Dörfler const uint32 kMinIconHeight = 16;
66f01106c3SAxel Dörfler 
67f01106c3SAxel Dörfler const bigtime_t kUpdateInterval = 1000000;
68f01106c3SAxel Dörfler 	// every second
69f01106c3SAxel Dörfler 
70f01106c3SAxel Dörfler 
71f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode,
72f01106c3SAxel Dörfler 		bool inDeskbar)
73f01106c3SAxel Dörfler 	: BView(frame, kDeskbarItemName, resizingMode,
74d5ba07a3SAxel Dörfler 		B_WILL_DRAW | B_FRAME_EVENTS),
75f01106c3SAxel Dörfler 	fInDeskbar(inDeskbar),
76f01106c3SAxel Dörfler 	fStatus(kStatusUnknown)
77f01106c3SAxel Dörfler {
78f01106c3SAxel Dörfler 	_Init();
79f01106c3SAxel Dörfler 
80f01106c3SAxel Dörfler 	if (!inDeskbar) {
81f01106c3SAxel Dörfler 		// we were obviously added to a standard window - let's add a dragger
82f01106c3SAxel Dörfler 		frame.OffsetTo(B_ORIGIN);
83f01106c3SAxel Dörfler 		frame.top = frame.bottom - 7;
84f01106c3SAxel Dörfler 		frame.left = frame.right - 7;
85f01106c3SAxel Dörfler 		BDragger* dragger = new BDragger(frame, this,
86f01106c3SAxel Dörfler 			B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
87f01106c3SAxel Dörfler 		AddChild(dragger);
88f01106c3SAxel Dörfler 	} else
89f01106c3SAxel Dörfler 		_Update();
90f01106c3SAxel Dörfler }
91f01106c3SAxel Dörfler 
92f01106c3SAxel Dörfler 
93f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BMessage* archive)
94d5ba07a3SAxel Dörfler 	: BView(archive),
95d5ba07a3SAxel Dörfler 	fInDeskbar(false)
96f01106c3SAxel Dörfler {
97d5ba07a3SAxel Dörfler 	app_info info;
98d5ba07a3SAxel Dörfler 	if (be_app->GetAppInfo(&info) == B_OK
99d5ba07a3SAxel Dörfler 		&& !strcasecmp(info.signature, "application/x-vnd.Be-TSKB"))
100d5ba07a3SAxel Dörfler 		fInDeskbar = true;
101d5ba07a3SAxel Dörfler 
102f01106c3SAxel Dörfler 	_Init();
103f01106c3SAxel Dörfler }
104f01106c3SAxel Dörfler 
105f01106c3SAxel Dörfler 
106f01106c3SAxel Dörfler NetworkStatusView::~NetworkStatusView()
107f01106c3SAxel Dörfler {
108f01106c3SAxel Dörfler }
109f01106c3SAxel Dörfler 
110f01106c3SAxel Dörfler 
111f01106c3SAxel Dörfler void
112f01106c3SAxel Dörfler NetworkStatusView::_Init()
113f01106c3SAxel Dörfler {
114f01106c3SAxel Dörfler 	fMessageRunner = NULL;
115f01106c3SAxel Dörfler 
116f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
117f01106c3SAxel Dörfler 		fBitmaps[i] = NULL;
118f01106c3SAxel Dörfler 	}
119f01106c3SAxel Dörfler 
120f01106c3SAxel Dörfler 	_UpdateBitmaps();
121f01106c3SAxel Dörfler }
122f01106c3SAxel Dörfler 
123f01106c3SAxel Dörfler 
124f01106c3SAxel Dörfler void
125f01106c3SAxel Dörfler NetworkStatusView::_UpdateBitmaps()
126f01106c3SAxel Dörfler {
127f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
128f01106c3SAxel Dörfler 		delete fBitmaps[i];
129f01106c3SAxel Dörfler 		fBitmaps[i] = NULL;
130f01106c3SAxel Dörfler 	}
131f01106c3SAxel Dörfler 
132f01106c3SAxel Dörfler 	image_info info;
133f01106c3SAxel Dörfler 	if (our_image(info) != B_OK)
134f01106c3SAxel Dörfler 		return;
135f01106c3SAxel Dörfler 
136f01106c3SAxel Dörfler 	BFile file(info.name, B_READ_ONLY);
137f01106c3SAxel Dörfler 	if (file.InitCheck() < B_OK)
138f01106c3SAxel Dörfler 		return;
139f01106c3SAxel Dörfler 
140f01106c3SAxel Dörfler 	BResources resources(&file);
141f01106c3SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_HAIKU
142f01106c3SAxel Dörfler 	if (resources.InitCheck() < B_OK)
143f01106c3SAxel Dörfler 		return;
144f01106c3SAxel Dörfler #endif
145f01106c3SAxel Dörfler 
146f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
147f01106c3SAxel Dörfler 		const void* data = NULL;
148f01106c3SAxel Dörfler 		size_t size;
149f01106c3SAxel Dörfler 		data = resources.LoadResource(B_VECTOR_ICON_TYPE,
150f01106c3SAxel Dörfler 			kNetworkStatusNoDevice + i, &size);
151f01106c3SAxel Dörfler 		if (data != NULL) {
152*4c28a737SStephan Aßmus 			BBitmap* icon = new BBitmap(Bounds(), B_RGBA32);
153f01106c3SAxel Dörfler 			if (icon->InitCheck() == B_OK
154f01106c3SAxel Dörfler 				&& BIconUtils::GetVectorIcon((const uint8 *)data,
155f01106c3SAxel Dörfler 					size, icon) == B_OK) {
156f01106c3SAxel Dörfler 				fBitmaps[i] = icon;
157f01106c3SAxel Dörfler 			} else
158f01106c3SAxel Dörfler 				delete icon;
159f01106c3SAxel Dörfler 		}
160f01106c3SAxel Dörfler 	}
161f01106c3SAxel Dörfler }
162f01106c3SAxel Dörfler 
163f01106c3SAxel Dörfler 
164f01106c3SAxel Dörfler void
165f01106c3SAxel Dörfler NetworkStatusView::_Quit()
166f01106c3SAxel Dörfler {
167f01106c3SAxel Dörfler 	if (fInDeskbar) {
168f01106c3SAxel Dörfler 		BDeskbar deskbar;
169f01106c3SAxel Dörfler 		deskbar.RemoveItem(kDeskbarItemName);
170f01106c3SAxel Dörfler 	} else
171f01106c3SAxel Dörfler 		be_app->PostMessage(B_QUIT_REQUESTED);
172f01106c3SAxel Dörfler }
173f01106c3SAxel Dörfler 
174f01106c3SAxel Dörfler 
175f01106c3SAxel Dörfler NetworkStatusView *
176f01106c3SAxel Dörfler NetworkStatusView::Instantiate(BMessage* archive)
177f01106c3SAxel Dörfler {
178f01106c3SAxel Dörfler 	if (!validate_instantiation(archive, "NetworkStatusView"))
179f01106c3SAxel Dörfler 		return NULL;
180f01106c3SAxel Dörfler 
181f01106c3SAxel Dörfler 	return new NetworkStatusView(archive);
182f01106c3SAxel Dörfler }
183f01106c3SAxel Dörfler 
184f01106c3SAxel Dörfler 
185f01106c3SAxel Dörfler status_t
186f01106c3SAxel Dörfler NetworkStatusView::Archive(BMessage* archive, bool deep) const
187f01106c3SAxel Dörfler {
188f01106c3SAxel Dörfler 	status_t status = BView::Archive(archive, deep);
189f01106c3SAxel Dörfler 	if (status == B_OK)
190f01106c3SAxel Dörfler 		status = archive->AddString("add_on", kSignature);
191f01106c3SAxel Dörfler 	if (status == B_OK)
192f01106c3SAxel Dörfler 		status = archive->AddString("class", "NetworkStatusView");
193f01106c3SAxel Dörfler 
194f01106c3SAxel Dörfler 	return status;
195f01106c3SAxel Dörfler }
196f01106c3SAxel Dörfler 
197f01106c3SAxel Dörfler 
198f01106c3SAxel Dörfler void
199f01106c3SAxel Dörfler NetworkStatusView::AttachedToWindow()
200f01106c3SAxel Dörfler {
201f01106c3SAxel Dörfler 	BView::AttachedToWindow();
202f01106c3SAxel Dörfler 	if (Parent())
203f01106c3SAxel Dörfler 		SetViewColor(Parent()->ViewColor());
204f01106c3SAxel Dörfler 	else
205f01106c3SAxel Dörfler 		SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
206f01106c3SAxel Dörfler 
207f01106c3SAxel Dörfler 	SetLowColor(ViewColor());
208f01106c3SAxel Dörfler 
209f01106c3SAxel Dörfler 	BMessage update(kMsgUpdate);
210f01106c3SAxel Dörfler 	fMessageRunner = new BMessageRunner(this, &update, kUpdateInterval);
211f01106c3SAxel Dörfler 
212f01106c3SAxel Dörfler 	fSocket = socket(AF_INET, SOCK_DGRAM, 0);
213f01106c3SAxel Dörfler 	_Update();
214f01106c3SAxel Dörfler }
215f01106c3SAxel Dörfler 
216f01106c3SAxel Dörfler 
217f01106c3SAxel Dörfler void
218f01106c3SAxel Dörfler NetworkStatusView::DetachedFromWindow()
219f01106c3SAxel Dörfler {
220f01106c3SAxel Dörfler 	delete fMessageRunner;
221f01106c3SAxel Dörfler 	close(fSocket);
222f01106c3SAxel Dörfler }
223f01106c3SAxel Dörfler 
224f01106c3SAxel Dörfler 
225f01106c3SAxel Dörfler void
226f01106c3SAxel Dörfler NetworkStatusView::MessageReceived(BMessage* message)
227f01106c3SAxel Dörfler {
228f01106c3SAxel Dörfler 	switch (message->what) {
229f01106c3SAxel Dörfler 		case kMsgUpdate:
230f01106c3SAxel Dörfler 			_Update();
231f01106c3SAxel Dörfler 			break;
232f01106c3SAxel Dörfler 
233f01106c3SAxel Dörfler 		case kMsgShowConfiguration:
234f01106c3SAxel Dörfler 			_ShowConfiguration(message);
235f01106c3SAxel Dörfler 			break;
236f01106c3SAxel Dörfler 
237c1502c9aSStephan Aßmus 		case kMsgOpenNetworkPreferences:
2383b41ad86SStephan Aßmus 			_OpenNetworksPreferences();
2393b41ad86SStephan Aßmus 			break;
2403b41ad86SStephan Aßmus 
241f01106c3SAxel Dörfler 		case B_ABOUT_REQUESTED:
242f01106c3SAxel Dörfler 			_AboutRequested();
243f01106c3SAxel Dörfler 			break;
244f01106c3SAxel Dörfler 
245f01106c3SAxel Dörfler 		case B_QUIT_REQUESTED:
246f01106c3SAxel Dörfler 			_Quit();
247f01106c3SAxel Dörfler 			break;
248f01106c3SAxel Dörfler 
249f01106c3SAxel Dörfler 		default:
250f01106c3SAxel Dörfler 			BView::MessageReceived(message);
251f01106c3SAxel Dörfler 	}
252f01106c3SAxel Dörfler }
253f01106c3SAxel Dörfler 
254f01106c3SAxel Dörfler 
255f01106c3SAxel Dörfler void
256f01106c3SAxel Dörfler NetworkStatusView::FrameResized(float width, float height)
257f01106c3SAxel Dörfler {
258f01106c3SAxel Dörfler 	_UpdateBitmaps();
259d5ba07a3SAxel Dörfler 	Invalidate();
260f01106c3SAxel Dörfler }
261f01106c3SAxel Dörfler 
262f01106c3SAxel Dörfler 
263f01106c3SAxel Dörfler void
264f01106c3SAxel Dörfler NetworkStatusView::Draw(BRect updateRect)
265f01106c3SAxel Dörfler {
266f01106c3SAxel Dörfler 	if (fBitmaps[fStatus] == NULL)
267f01106c3SAxel Dörfler 		return;
268f01106c3SAxel Dörfler 
269f01106c3SAxel Dörfler 	SetDrawingMode(B_OP_ALPHA);
270f01106c3SAxel Dörfler 	DrawBitmap(fBitmaps[fStatus]);
271f01106c3SAxel Dörfler 	SetDrawingMode(B_OP_COPY);
272f01106c3SAxel Dörfler }
273f01106c3SAxel Dörfler 
274f01106c3SAxel Dörfler 
275f01106c3SAxel Dörfler void
276f01106c3SAxel Dörfler NetworkStatusView::_ShowConfiguration(BMessage* message)
277f01106c3SAxel Dörfler {
278f01106c3SAxel Dörfler 	static const struct information_entry {
279f01106c3SAxel Dörfler 		const char *label;
280f01106c3SAxel Dörfler 		int32 control;
281f01106c3SAxel Dörfler 	} kInformationEntries[] = {
282f01106c3SAxel Dörfler 		{ "Address", SIOCGIFADDR },
283f01106c3SAxel Dörfler 		{ "Broadcast", SIOCGIFBRDADDR },
284f01106c3SAxel Dörfler 		{ "Netmask", SIOCGIFNETMASK },
285f01106c3SAxel Dörfler 		{ NULL }
286f01106c3SAxel Dörfler 	};
287f01106c3SAxel Dörfler 
288f01106c3SAxel Dörfler 	const char *name;
289f01106c3SAxel Dörfler 	if (message->FindString("interface", &name) != B_OK)
290f01106c3SAxel Dörfler 		return;
291f01106c3SAxel Dörfler 
292f01106c3SAxel Dörfler 	ifreq request;
293f01106c3SAxel Dörfler 	if (!_PrepareRequest(request, name))
294f01106c3SAxel Dörfler 		return;
295f01106c3SAxel Dörfler 
296f01106c3SAxel Dörfler 	BString text = name;
297f01106c3SAxel Dörfler 	text += " information:\n";
298f01106c3SAxel Dörfler 	size_t boldLength = text.Length();
299f01106c3SAxel Dörfler 
300f01106c3SAxel Dörfler 	for (int i = 0; kInformationEntries[i].label; i++) {
301f01106c3SAxel Dörfler 		if (ioctl(fSocket, kInformationEntries[i].control, &request,
302f01106c3SAxel Dörfler 				sizeof(request)) < 0) {
303f01106c3SAxel Dörfler 			continue;
304f01106c3SAxel Dörfler 		}
305f01106c3SAxel Dörfler 
306f01106c3SAxel Dörfler 		char address[32];
307f01106c3SAxel Dörfler 		sockaddr_in* inetAddress = NULL;
308f01106c3SAxel Dörfler 		switch (kInformationEntries[i].control) {
309f01106c3SAxel Dörfler 			case SIOCGIFNETMASK:
310f01106c3SAxel Dörfler 				inetAddress = (sockaddr_in*)&request.ifr_mask;
311f01106c3SAxel Dörfler 				break;
312f01106c3SAxel Dörfler 			default:
313f01106c3SAxel Dörfler 				inetAddress = (sockaddr_in*)&request.ifr_addr;
314f01106c3SAxel Dörfler 				break;
315f01106c3SAxel Dörfler 		}
316f01106c3SAxel Dörfler 
317f01106c3SAxel Dörfler 		if (inet_ntop(AF_INET, &inetAddress->sin_addr, address,
318f01106c3SAxel Dörfler 				sizeof(address)) == NULL) {
319f01106c3SAxel Dörfler 			return;
320f01106c3SAxel Dörfler 		}
321f01106c3SAxel Dörfler 
322f01106c3SAxel Dörfler 		text += "\n";
323f01106c3SAxel Dörfler 		text += kInformationEntries[i].label;
324f01106c3SAxel Dörfler 		text += ": ";
325f01106c3SAxel Dörfler 		text += address;
326f01106c3SAxel Dörfler 	}
327f01106c3SAxel Dörfler 
328f01106c3SAxel Dörfler 	BAlert* alert = new BAlert(name, text.String(), "Ok");
329f01106c3SAxel Dörfler 	BTextView* view = alert->TextView();
330f01106c3SAxel Dörfler 	BFont font;
331f01106c3SAxel Dörfler 
332f01106c3SAxel Dörfler 	view->SetStylable(true);
333f01106c3SAxel Dörfler 	view->GetFont(&font);
334f01106c3SAxel Dörfler 	font.SetFace(B_BOLD_FACE);
335f01106c3SAxel Dörfler 	view->SetFontAndColor(0, boldLength, &font);
336f01106c3SAxel Dörfler 
337f01106c3SAxel Dörfler 	alert->Go(NULL);
338f01106c3SAxel Dörfler }
339f01106c3SAxel Dörfler 
340f01106c3SAxel Dörfler 
341f01106c3SAxel Dörfler void
342f01106c3SAxel Dörfler NetworkStatusView::MouseDown(BPoint point)
343f01106c3SAxel Dörfler {
344f01106c3SAxel Dörfler 	BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
345f01106c3SAxel Dörfler 	menu->SetFont(be_plain_font);
346f01106c3SAxel Dörfler 
347f01106c3SAxel Dörfler 	for (int32 i = 0; i < fInterfaces.CountItems(); i++) {
348f01106c3SAxel Dörfler 		BString& name = *fInterfaces.ItemAt(i);
349f01106c3SAxel Dörfler 
350f01106c3SAxel Dörfler 		BString label = name;
351f01106c3SAxel Dörfler 		label += ": ";
352f01106c3SAxel Dörfler 		label += kStatusDescriptions[
353f01106c3SAxel Dörfler 			_DetermineInterfaceStatus(name.String())];
354f01106c3SAxel Dörfler 
355f01106c3SAxel Dörfler 		BMessage* info = new BMessage(kMsgShowConfiguration);
356f01106c3SAxel Dörfler 		info->AddString("interface", name.String());
357f01106c3SAxel Dörfler 		menu->AddItem(new BMenuItem(label.String(), info));
358f01106c3SAxel Dörfler 	}
359f01106c3SAxel Dörfler 
360f01106c3SAxel Dörfler 	menu->AddSeparatorItem();
36166eba86fSAxel Dörfler 	menu->AddItem(new BMenuItem("About NetworkStatus" B_UTF8_ELLIPSIS,
362f01106c3SAxel Dörfler 		new BMessage(B_ABOUT_REQUESTED)));
3633b41ad86SStephan Aßmus 	menu->AddItem(new BMenuItem("Open Networks Preferences" B_UTF8_ELLIPSIS,
364c1502c9aSStephan Aßmus 		new BMessage(kMsgOpenNetworkPreferences)));
3653b41ad86SStephan Aßmus 
366f01106c3SAxel Dörfler 	if (fInDeskbar)
367f01106c3SAxel Dörfler 		menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED)));
368f01106c3SAxel Dörfler 	menu->SetTargetForItems(this);
369f01106c3SAxel Dörfler 
370f01106c3SAxel Dörfler 	ConvertToScreen(&point);
371f01106c3SAxel Dörfler 	menu->Go(point, true, false, true);
372f01106c3SAxel Dörfler }
373f01106c3SAxel Dörfler 
374f01106c3SAxel Dörfler 
375f01106c3SAxel Dörfler void
376f01106c3SAxel Dörfler NetworkStatusView::_AboutRequested()
377f01106c3SAxel Dörfler {
378f01106c3SAxel Dörfler 	BAlert *alert = new BAlert("about", "NetworkStatus\n"
379f01106c3SAxel Dörfler 		"\twritten by Axel Dörfler and Hugo Santos\n"
380f01106c3SAxel Dörfler 		"\tCopyright 2007, Haiku, Inc.\n", "Ok");
381f01106c3SAxel Dörfler 	BTextView *view = alert->TextView();
382f01106c3SAxel Dörfler 	BFont font;
383f01106c3SAxel Dörfler 
384f01106c3SAxel Dörfler 	view->SetStylable(true);
385f01106c3SAxel Dörfler 
386f01106c3SAxel Dörfler 	view->GetFont(&font);
387f01106c3SAxel Dörfler 	font.SetSize(18);
388f01106c3SAxel Dörfler 	font.SetFace(B_BOLD_FACE);
389f01106c3SAxel Dörfler 	view->SetFontAndColor(0, 13, &font);
390f01106c3SAxel Dörfler 
391f01106c3SAxel Dörfler 	alert->Go();
392f01106c3SAxel Dörfler }
393f01106c3SAxel Dörfler 
394f01106c3SAxel Dörfler 
395f01106c3SAxel Dörfler bool
396f01106c3SAxel Dörfler NetworkStatusView::_PrepareRequest(struct ifreq& request, const char* name)
397f01106c3SAxel Dörfler {
398f01106c3SAxel Dörfler 	if (strlen(name) > IF_NAMESIZE)
399f01106c3SAxel Dörfler 		return false;
400f01106c3SAxel Dörfler 
401f01106c3SAxel Dörfler 	strcpy(request.ifr_name, name);
402f01106c3SAxel Dörfler 	return true;
403f01106c3SAxel Dörfler }
404f01106c3SAxel Dörfler 
405f01106c3SAxel Dörfler 
406f01106c3SAxel Dörfler int32
407f01106c3SAxel Dörfler NetworkStatusView::_DetermineInterfaceStatus(const char* name)
408f01106c3SAxel Dörfler {
409f01106c3SAxel Dörfler 	ifreq request;
410f01106c3SAxel Dörfler 	if (!_PrepareRequest(request, name))
411f01106c3SAxel Dörfler 		return kStatusUnknown;
412f01106c3SAxel Dörfler 
413f01106c3SAxel Dörfler 	uint32 flags = 0;
414f01106c3SAxel Dörfler 	if (ioctl(fSocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0)
415f01106c3SAxel Dörfler 		flags = request.ifr_flags;
416f01106c3SAxel Dörfler 
417f01106c3SAxel Dörfler 	int32 status = kStatusNoLink;
418f01106c3SAxel Dörfler 
419f01106c3SAxel Dörfler 	// TODO: no kStatusLinkNoConfig yet
420f01106c3SAxel Dörfler 
421f01106c3SAxel Dörfler 	if (flags & IFF_CONFIGURING)
422f01106c3SAxel Dörfler 		status = kStatusConnecting;
4232a17be44SAxel Dörfler 	else if ((flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK))
424f01106c3SAxel Dörfler 		status = kStatusReady;
425f01106c3SAxel Dörfler 
426f01106c3SAxel Dörfler 	return status;
427f01106c3SAxel Dörfler }
428f01106c3SAxel Dörfler 
429f01106c3SAxel Dörfler 
430f01106c3SAxel Dörfler void
431f01106c3SAxel Dörfler NetworkStatusView::_Update(bool force)
432f01106c3SAxel Dörfler {
433f01106c3SAxel Dörfler 	// iterate over all interfaces and retrieve minimal status
434f01106c3SAxel Dörfler 
435f01106c3SAxel Dörfler 	ifconf config;
436f01106c3SAxel Dörfler 	config.ifc_len = sizeof(config.ifc_value);
437f01106c3SAxel Dörfler 	if (ioctl(fSocket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
438f01106c3SAxel Dörfler 		return;
439f01106c3SAxel Dörfler 
440f01106c3SAxel Dörfler 	uint32 count = (uint32)config.ifc_value;
441f01106c3SAxel Dörfler 	if (count == 0)
442f01106c3SAxel Dörfler 		return;
443f01106c3SAxel Dörfler 
444f01106c3SAxel Dörfler 	void *buffer = malloc(count * sizeof(struct ifreq));
445f01106c3SAxel Dörfler 	if (buffer == NULL)
446f01106c3SAxel Dörfler 		return;
447f01106c3SAxel Dörfler 
448f01106c3SAxel Dörfler 	config.ifc_len = count * sizeof(struct ifreq);
449f01106c3SAxel Dörfler 	config.ifc_buf = buffer;
450f01106c3SAxel Dörfler 	if (ioctl(fSocket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
451f01106c3SAxel Dörfler 		return;
452f01106c3SAxel Dörfler 
453f01106c3SAxel Dörfler 	ifreq *interface = (ifreq *)buffer;
454f01106c3SAxel Dörfler 
455f01106c3SAxel Dörfler 	int32 oldStatus = fStatus;
456f01106c3SAxel Dörfler 	fStatus = kStatusUnknown;
457f01106c3SAxel Dörfler 	fInterfaces.MakeEmpty();
458f01106c3SAxel Dörfler 
459f01106c3SAxel Dörfler 	for (uint32 i = 0; i < count; i++) {
460f01106c3SAxel Dörfler 		if (strncmp(interface->ifr_name, "loop", 4) && interface->ifr_name[0]) {
461f01106c3SAxel Dörfler 			fInterfaces.AddItem(new BString(interface->ifr_name));
462f01106c3SAxel Dörfler 			int32 status = _DetermineInterfaceStatus(interface->ifr_name);
463f01106c3SAxel Dörfler 			if (status > fStatus)
464f01106c3SAxel Dörfler 				fStatus = status;
465f01106c3SAxel Dörfler 		}
466f01106c3SAxel Dörfler 
467f01106c3SAxel Dörfler 		interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
468f01106c3SAxel Dörfler 			+ interface->ifr_addr.sa_len);
469f01106c3SAxel Dörfler 	}
470f01106c3SAxel Dörfler 
471f01106c3SAxel Dörfler 	free(buffer);
472f01106c3SAxel Dörfler 
473f01106c3SAxel Dörfler 	if (fStatus != oldStatus)
474f01106c3SAxel Dörfler 		Invalidate();
475f01106c3SAxel Dörfler }
476f01106c3SAxel Dörfler 
477f01106c3SAxel Dörfler 
4783b41ad86SStephan Aßmus void
4793b41ad86SStephan Aßmus NetworkStatusView::_OpenNetworksPreferences()
4803b41ad86SStephan Aßmus {
4813b41ad86SStephan Aßmus 	status_t ret = be_roster->Launch("application/x-vnd.Haiku-Network");
4823b41ad86SStephan Aßmus 	if (ret < B_OK) {
4833b41ad86SStephan Aßmus 		BString errorMessage("Launching the Network preflet failed.\n\n"
4843b41ad86SStephan Aßmus 			"Error: ");
4853b41ad86SStephan Aßmus 		errorMessage << strerror(ret);
4863b41ad86SStephan Aßmus 		BAlert* alert = new BAlert("launch error", errorMessage.String(),
4873b41ad86SStephan Aßmus 			"Ok");
4883b41ad86SStephan Aßmus 		// asynchronous alert in order to not block replicant host
4893b41ad86SStephan Aßmus 		// application
4903b41ad86SStephan Aßmus 		alert->Go(NULL);
4913b41ad86SStephan Aßmus 	}
4923b41ad86SStephan Aßmus }
4933b41ad86SStephan Aßmus 
4943b41ad86SStephan Aßmus 
495f01106c3SAxel Dörfler //	#pragma mark -
496f01106c3SAxel Dörfler 
497f01106c3SAxel Dörfler 
498f01106c3SAxel Dörfler extern "C" _EXPORT BView *
499f01106c3SAxel Dörfler instantiate_deskbar_item(void)
500f01106c3SAxel Dörfler {
50166eba86fSAxel Dörfler 	return new NetworkStatusView(BRect(0, 0, 15, 15),
50266eba86fSAxel Dörfler 		B_FOLLOW_LEFT | B_FOLLOW_TOP, true);
503f01106c3SAxel Dörfler }
504f01106c3SAxel Dörfler 
505