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