xref: /haiku/src/apps/networkstatus/NetworkStatusView.cpp (revision 546208a53940a26c6379c48a7854ade1a8250fc5)
1f01106c3SAxel Dörfler /*
25c46b171SRene Gollent  * Copyright 2006-2012, Haiku, Inc. All rights reserved.
3f01106c3SAxel Dörfler  * Distributed under the terms of the MIT License.
4f01106c3SAxel Dörfler  *
5f01106c3SAxel Dörfler  * Authors:
63b41ad86SStephan Aßmus  *		Dario Casalinuovo
7937ca113SRene Gollent  *		Axel Dörfler, axeld@pinc-software.de
85c46b171SRene Gollent  *		Rene Gollent, rene@gollent.com
9937ca113SRene Gollent  *		Hugo Santos, hugosantos@gmail.com
10f01106c3SAxel Dörfler  */
11f01106c3SAxel Dörfler 
12f01106c3SAxel Dörfler 
13f01106c3SAxel Dörfler #include "NetworkStatusView.h"
14f01106c3SAxel Dörfler 
15440d0e61SAxel Dörfler #include <set>
16440d0e61SAxel Dörfler 
17195981bbSAxel Dörfler #include <arpa/inet.h>
18195981bbSAxel Dörfler #include <net/if.h>
19195981bbSAxel Dörfler #include <stdio.h>
20195981bbSAxel Dörfler #include <stdlib.h>
21195981bbSAxel Dörfler #include <string.h>
22195981bbSAxel Dörfler #include <sys/socket.h>
23195981bbSAxel Dörfler #include <sys/sockio.h>
24195981bbSAxel Dörfler #include <unistd.h>
25f01106c3SAxel Dörfler 
26f01106c3SAxel Dörfler #include <Alert.h>
27f01106c3SAxel Dörfler #include <Application.h>
28757e7059SAdrien Destugues #include <Catalog.h>
29f01106c3SAxel Dörfler #include <Bitmap.h>
30f01106c3SAxel Dörfler #include <Deskbar.h>
31f01106c3SAxel Dörfler #include <Dragger.h>
32f01106c3SAxel Dörfler #include <Drivers.h>
33f01106c3SAxel Dörfler #include <IconUtils.h>
34757e7059SAdrien Destugues #include <Locale.h>
35f01106c3SAxel Dörfler #include <MenuItem.h>
36f01106c3SAxel Dörfler #include <MessageRunner.h>
375fe97f21SAxel Dörfler #include <NetworkDevice.h>
385fe97f21SAxel Dörfler #include <NetworkInterface.h>
395fe97f21SAxel Dörfler #include <NetworkRoster.h>
40f01106c3SAxel Dörfler #include <PopUpMenu.h>
41f01106c3SAxel Dörfler #include <Resources.h>
42d5ba07a3SAxel Dörfler #include <Roster.h>
43f01106c3SAxel Dörfler #include <String.h>
44f01106c3SAxel Dörfler #include <TextView.h>
45f01106c3SAxel Dörfler 
46195981bbSAxel Dörfler #include "NetworkStatus.h"
47195981bbSAxel Dörfler #include "NetworkStatusIcons.h"
485fe97f21SAxel Dörfler #include "RadioView.h"
493ca00ffdSAxel Dörfler #include "WirelessNetworkMenuItem.h"
50195981bbSAxel Dörfler 
51f01106c3SAxel Dörfler 
52*546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
53*546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "NetworkStatusView"
54757e7059SAdrien Destugues 
55757e7059SAdrien Destugues 
56f01106c3SAxel Dörfler static const char *kStatusDescriptions[] = {
572ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("Unknown"),
582ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("No link"),
592ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("No stateful configuration"),
602ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("Configuring"),
612ee8f3f6SSiarzhuk Zharski 	B_TRANSLATE("Ready")
62f01106c3SAxel Dörfler };
63f01106c3SAxel Dörfler 
64f01106c3SAxel Dörfler extern "C" _EXPORT BView *instantiate_deskbar_item(void);
65f01106c3SAxel Dörfler 
66f01106c3SAxel Dörfler 
67f01106c3SAxel Dörfler const uint32 kMsgShowConfiguration = 'shcf';
68c1502c9aSStephan Aßmus const uint32 kMsgOpenNetworkPreferences = 'onwp';
692e1a6286SAxel Dörfler const uint32 kMsgJoinNetwork = 'join';
70f01106c3SAxel Dörfler 
71f01106c3SAxel Dörfler const uint32 kMinIconWidth = 16;
72f01106c3SAxel Dörfler const uint32 kMinIconHeight = 16;
73f01106c3SAxel Dörfler 
74195981bbSAxel Dörfler 
75195981bbSAxel Dörfler class SocketOpener {
76195981bbSAxel Dörfler public:
77195981bbSAxel Dörfler 	SocketOpener()
78195981bbSAxel Dörfler 	{
79195981bbSAxel Dörfler 		fSocket = socket(AF_INET, SOCK_DGRAM, 0);
80195981bbSAxel Dörfler 	}
81195981bbSAxel Dörfler 
82195981bbSAxel Dörfler 	~SocketOpener()
83195981bbSAxel Dörfler 	{
84195981bbSAxel Dörfler 		close(fSocket);
85195981bbSAxel Dörfler 	}
86195981bbSAxel Dörfler 
87195981bbSAxel Dörfler 	status_t InitCheck()
88195981bbSAxel Dörfler 	{
89195981bbSAxel Dörfler 		return fSocket >= 0 ? B_OK : B_ERROR;
90195981bbSAxel Dörfler 	}
91195981bbSAxel Dörfler 
92195981bbSAxel Dörfler 	operator int() const
93195981bbSAxel Dörfler 	{
94195981bbSAxel Dörfler 		return fSocket;
95195981bbSAxel Dörfler 	}
96195981bbSAxel Dörfler 
97195981bbSAxel Dörfler private:
98195981bbSAxel Dörfler 	int	fSocket;
99195981bbSAxel Dörfler };
100195981bbSAxel Dörfler 
101195981bbSAxel Dörfler 
102195981bbSAxel Dörfler //	#pragma mark -
103f01106c3SAxel Dörfler 
104f01106c3SAxel Dörfler 
105f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode,
106f01106c3SAxel Dörfler 		bool inDeskbar)
107f01106c3SAxel Dörfler 	: BView(frame, kDeskbarItemName, resizingMode,
108d5ba07a3SAxel Dörfler 		B_WILL_DRAW | B_FRAME_EVENTS),
1095c46b171SRene Gollent 	fInDeskbar(inDeskbar)
110f01106c3SAxel Dörfler {
111f01106c3SAxel Dörfler 	_Init();
112f01106c3SAxel Dörfler 
113f01106c3SAxel Dörfler 	if (!inDeskbar) {
114f01106c3SAxel Dörfler 		// we were obviously added to a standard window - let's add a dragger
115f01106c3SAxel Dörfler 		frame.OffsetTo(B_ORIGIN);
116f01106c3SAxel Dörfler 		frame.top = frame.bottom - 7;
117f01106c3SAxel Dörfler 		frame.left = frame.right - 7;
118f01106c3SAxel Dörfler 		BDragger* dragger = new BDragger(frame, this,
119f01106c3SAxel Dörfler 			B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
120f01106c3SAxel Dörfler 		AddChild(dragger);
121f01106c3SAxel Dörfler 	} else
122f01106c3SAxel Dörfler 		_Update();
123f01106c3SAxel Dörfler }
124f01106c3SAxel Dörfler 
125f01106c3SAxel Dörfler 
126f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BMessage* archive)
127d5ba07a3SAxel Dörfler 	: BView(archive),
128d5ba07a3SAxel Dörfler 	fInDeskbar(false)
129f01106c3SAxel Dörfler {
130d5ba07a3SAxel Dörfler 	app_info info;
131d5ba07a3SAxel Dörfler 	if (be_app->GetAppInfo(&info) == B_OK
132d5ba07a3SAxel Dörfler 		&& !strcasecmp(info.signature, "application/x-vnd.Be-TSKB"))
133d5ba07a3SAxel Dörfler 		fInDeskbar = true;
134d5ba07a3SAxel Dörfler 
135f01106c3SAxel Dörfler 	_Init();
136f01106c3SAxel Dörfler }
137f01106c3SAxel Dörfler 
138f01106c3SAxel Dörfler 
139f01106c3SAxel Dörfler NetworkStatusView::~NetworkStatusView()
140f01106c3SAxel Dörfler {
141f01106c3SAxel Dörfler }
142f01106c3SAxel Dörfler 
143f01106c3SAxel Dörfler 
144f01106c3SAxel Dörfler void
145f01106c3SAxel Dörfler NetworkStatusView::_Init()
146f01106c3SAxel Dörfler {
147f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
148e58807edSAlexander von Gluck IV 		fTrayIcons[i] = NULL;
149e58807edSAlexander von Gluck IV 		fNotifyIcons[i] = NULL;
150f01106c3SAxel Dörfler 	}
151f01106c3SAxel Dörfler 
152f01106c3SAxel Dörfler 	_UpdateBitmaps();
153f01106c3SAxel Dörfler }
154f01106c3SAxel Dörfler 
155f01106c3SAxel Dörfler 
156f01106c3SAxel Dörfler void
157f01106c3SAxel Dörfler NetworkStatusView::_UpdateBitmaps()
158f01106c3SAxel Dörfler {
159f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
160e58807edSAlexander von Gluck IV 		delete fTrayIcons[i];
161e58807edSAlexander von Gluck IV 		delete fNotifyIcons[i];
162e58807edSAlexander von Gluck IV 		fTrayIcons[i] = NULL;
163e58807edSAlexander von Gluck IV 		fNotifyIcons[i] = NULL;
164f01106c3SAxel Dörfler 	}
165f01106c3SAxel Dörfler 
166f01106c3SAxel Dörfler 	image_info info;
167f01106c3SAxel Dörfler 	if (our_image(info) != B_OK)
168f01106c3SAxel Dörfler 		return;
169f01106c3SAxel Dörfler 
170f01106c3SAxel Dörfler 	BFile file(info.name, B_READ_ONLY);
171f01106c3SAxel Dörfler 	if (file.InitCheck() < B_OK)
172f01106c3SAxel Dörfler 		return;
173f01106c3SAxel Dörfler 
174f01106c3SAxel Dörfler 	BResources resources(&file);
175f01106c3SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_HAIKU
176f01106c3SAxel Dörfler 	if (resources.InitCheck() < B_OK)
177f01106c3SAxel Dörfler 		return;
178f01106c3SAxel Dörfler #endif
179f01106c3SAxel Dörfler 
180f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
181f01106c3SAxel Dörfler 		const void* data = NULL;
182f01106c3SAxel Dörfler 		size_t size;
183f01106c3SAxel Dörfler 		data = resources.LoadResource(B_VECTOR_ICON_TYPE,
184f01106c3SAxel Dörfler 			kNetworkStatusNoDevice + i, &size);
185f01106c3SAxel Dörfler 		if (data != NULL) {
186e58807edSAlexander von Gluck IV 			// Scale main tray icon
187e58807edSAlexander von Gluck IV 			BBitmap* trayIcon = new BBitmap(Bounds(), B_RGBA32);
188e58807edSAlexander von Gluck IV 			if (trayIcon->InitCheck() == B_OK
189f01106c3SAxel Dörfler 				&& BIconUtils::GetVectorIcon((const uint8 *)data,
190e58807edSAlexander von Gluck IV 					size, trayIcon) == B_OK) {
191e58807edSAlexander von Gluck IV 				fTrayIcons[i] = trayIcon;
192f01106c3SAxel Dörfler 			} else
193e58807edSAlexander von Gluck IV 				delete trayIcon;
194e58807edSAlexander von Gluck IV 
195e58807edSAlexander von Gluck IV 			// Scale notification icon
196e58807edSAlexander von Gluck IV 			BBitmap* notifyIcon = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
197e58807edSAlexander von Gluck IV 			if (notifyIcon->InitCheck() == B_OK
198e58807edSAlexander von Gluck IV 				&& BIconUtils::GetVectorIcon((const uint8 *)data,
199e58807edSAlexander von Gluck IV 					size, notifyIcon) == B_OK) {
200e58807edSAlexander von Gluck IV 				fNotifyIcons[i] = notifyIcon;
201e58807edSAlexander von Gluck IV 			} else
202e58807edSAlexander von Gluck IV 				delete notifyIcon;
203f01106c3SAxel Dörfler 		}
204f01106c3SAxel Dörfler 	}
205f01106c3SAxel Dörfler }
206f01106c3SAxel Dörfler 
207f01106c3SAxel Dörfler 
208f01106c3SAxel Dörfler void
209f01106c3SAxel Dörfler NetworkStatusView::_Quit()
210f01106c3SAxel Dörfler {
211f01106c3SAxel Dörfler 	if (fInDeskbar) {
212f01106c3SAxel Dörfler 		BDeskbar deskbar;
213f01106c3SAxel Dörfler 		deskbar.RemoveItem(kDeskbarItemName);
214f01106c3SAxel Dörfler 	} else
215f01106c3SAxel Dörfler 		be_app->PostMessage(B_QUIT_REQUESTED);
216f01106c3SAxel Dörfler }
217f01106c3SAxel Dörfler 
218f01106c3SAxel Dörfler 
219f01106c3SAxel Dörfler NetworkStatusView *
220f01106c3SAxel Dörfler NetworkStatusView::Instantiate(BMessage* archive)
221f01106c3SAxel Dörfler {
222f01106c3SAxel Dörfler 	if (!validate_instantiation(archive, "NetworkStatusView"))
223f01106c3SAxel Dörfler 		return NULL;
224f01106c3SAxel Dörfler 
225f01106c3SAxel Dörfler 	return new NetworkStatusView(archive);
226f01106c3SAxel Dörfler }
227f01106c3SAxel Dörfler 
228f01106c3SAxel Dörfler 
229f01106c3SAxel Dörfler status_t
230f01106c3SAxel Dörfler NetworkStatusView::Archive(BMessage* archive, bool deep) const
231f01106c3SAxel Dörfler {
232f01106c3SAxel Dörfler 	status_t status = BView::Archive(archive, deep);
233f01106c3SAxel Dörfler 	if (status == B_OK)
234f01106c3SAxel Dörfler 		status = archive->AddString("add_on", kSignature);
235f01106c3SAxel Dörfler 	if (status == B_OK)
236f01106c3SAxel Dörfler 		status = archive->AddString("class", "NetworkStatusView");
237f01106c3SAxel Dörfler 
238f01106c3SAxel Dörfler 	return status;
239f01106c3SAxel Dörfler }
240f01106c3SAxel Dörfler 
241f01106c3SAxel Dörfler 
242f01106c3SAxel Dörfler void
243f01106c3SAxel Dörfler NetworkStatusView::AttachedToWindow()
244f01106c3SAxel Dörfler {
245f01106c3SAxel Dörfler 	BView::AttachedToWindow();
246f01106c3SAxel Dörfler 	if (Parent())
247f01106c3SAxel Dörfler 		SetViewColor(Parent()->ViewColor());
248f01106c3SAxel Dörfler 	else
249f01106c3SAxel Dörfler 		SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
250f01106c3SAxel Dörfler 
251f01106c3SAxel Dörfler 	SetLowColor(ViewColor());
252f01106c3SAxel Dörfler 
253195981bbSAxel Dörfler 	start_watching_network(
254195981bbSAxel Dörfler 		B_WATCH_NETWORK_INTERFACE_CHANGES | B_WATCH_NETWORK_LINK_CHANGES, this);
255f01106c3SAxel Dörfler 
256f01106c3SAxel Dörfler 	_Update();
257f01106c3SAxel Dörfler }
258f01106c3SAxel Dörfler 
259f01106c3SAxel Dörfler 
260f01106c3SAxel Dörfler void
261f01106c3SAxel Dörfler NetworkStatusView::DetachedFromWindow()
262f01106c3SAxel Dörfler {
263195981bbSAxel Dörfler 	stop_watching_network(this);
264f01106c3SAxel Dörfler }
265f01106c3SAxel Dörfler 
266f01106c3SAxel Dörfler 
267f01106c3SAxel Dörfler void
268f01106c3SAxel Dörfler NetworkStatusView::MessageReceived(BMessage* message)
269f01106c3SAxel Dörfler {
270f01106c3SAxel Dörfler 	switch (message->what) {
271195981bbSAxel Dörfler 		case B_NETWORK_MONITOR:
272f01106c3SAxel Dörfler 			_Update();
273f01106c3SAxel Dörfler 			break;
274f01106c3SAxel Dörfler 
275f01106c3SAxel Dörfler 		case kMsgShowConfiguration:
276f01106c3SAxel Dörfler 			_ShowConfiguration(message);
277f01106c3SAxel Dörfler 			break;
278f01106c3SAxel Dörfler 
279c1502c9aSStephan Aßmus 		case kMsgOpenNetworkPreferences:
2803b41ad86SStephan Aßmus 			_OpenNetworksPreferences();
2813b41ad86SStephan Aßmus 			break;
2823b41ad86SStephan Aßmus 
2832e1a6286SAxel Dörfler 		case kMsgJoinNetwork:
2842e1a6286SAxel Dörfler 		{
2852e1a6286SAxel Dörfler 			const char* deviceName;
2862e1a6286SAxel Dörfler 			const char* name;
2872e1a6286SAxel Dörfler 			if (message->FindString("device", &deviceName) == B_OK
2882e1a6286SAxel Dörfler 				&& message->FindString("name", &name) == B_OK) {
2892e1a6286SAxel Dörfler 				BNetworkDevice device(deviceName);
2902e1a6286SAxel Dörfler 				status_t status = device.JoinNetwork(name);
2912e1a6286SAxel Dörfler 				if (status != B_OK) {
2922e1a6286SAxel Dörfler 					BString text
2932e1a6286SAxel Dörfler 						= B_TRANSLATE("Could not join wireless network:\n");
2942e1a6286SAxel Dörfler 					text << strerror(status);
2952e1a6286SAxel Dörfler 					BAlert* alert = new BAlert(name, text.String(),
2962e1a6286SAxel Dörfler 						B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_AS_USUAL,
2972e1a6286SAxel Dörfler 						B_STOP_ALERT);
2982e1a6286SAxel Dörfler 					alert->Go(NULL);
2992e1a6286SAxel Dörfler 				}
3002e1a6286SAxel Dörfler 			}
3012e1a6286SAxel Dörfler 			break;
3022e1a6286SAxel Dörfler 		}
3032e1a6286SAxel Dörfler 
304f01106c3SAxel Dörfler 		case B_ABOUT_REQUESTED:
305f01106c3SAxel Dörfler 			_AboutRequested();
306f01106c3SAxel Dörfler 			break;
307f01106c3SAxel Dörfler 
308f01106c3SAxel Dörfler 		case B_QUIT_REQUESTED:
309f01106c3SAxel Dörfler 			_Quit();
310f01106c3SAxel Dörfler 			break;
311f01106c3SAxel Dörfler 
312f01106c3SAxel Dörfler 		default:
313f01106c3SAxel Dörfler 			BView::MessageReceived(message);
314f01106c3SAxel Dörfler 	}
315f01106c3SAxel Dörfler }
316f01106c3SAxel Dörfler 
317f01106c3SAxel Dörfler 
318f01106c3SAxel Dörfler void
319f01106c3SAxel Dörfler NetworkStatusView::FrameResized(float width, float height)
320f01106c3SAxel Dörfler {
321f01106c3SAxel Dörfler 	_UpdateBitmaps();
322d5ba07a3SAxel Dörfler 	Invalidate();
323f01106c3SAxel Dörfler }
324f01106c3SAxel Dörfler 
325f01106c3SAxel Dörfler 
326f01106c3SAxel Dörfler void
327f01106c3SAxel Dörfler NetworkStatusView::Draw(BRect updateRect)
328f01106c3SAxel Dörfler {
3295c46b171SRene Gollent 	int32 status = kStatusUnknown;
3305c46b171SRene Gollent 	for (std::map<BString, int32>::const_iterator it
3315c46b171SRene Gollent 		= fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) {
3325c46b171SRene Gollent 		if (it->second > status)
3335c46b171SRene Gollent 			status = it->second;
3345c46b171SRene Gollent 	}
3355c46b171SRene Gollent 
3365c46b171SRene Gollent 	if (fTrayIcons[status] == NULL)
337f01106c3SAxel Dörfler 		return;
338f01106c3SAxel Dörfler 
339f01106c3SAxel Dörfler 	SetDrawingMode(B_OP_ALPHA);
3405c46b171SRene Gollent 	DrawBitmap(fTrayIcons[status]);
341f01106c3SAxel Dörfler 	SetDrawingMode(B_OP_COPY);
342f01106c3SAxel Dörfler }
343f01106c3SAxel Dörfler 
344f01106c3SAxel Dörfler 
345f01106c3SAxel Dörfler void
346f01106c3SAxel Dörfler NetworkStatusView::_ShowConfiguration(BMessage* message)
347f01106c3SAxel Dörfler {
348f01106c3SAxel Dörfler 	static const struct information_entry {
349f01106c3SAxel Dörfler 		const char*	label;
350f01106c3SAxel Dörfler 		int32		control;
351f01106c3SAxel Dörfler 	} kInformationEntries[] = {
3522ee8f3f6SSiarzhuk Zharski 		{ B_TRANSLATE("Address"), SIOCGIFADDR },
3532ee8f3f6SSiarzhuk Zharski 		{ B_TRANSLATE("Broadcast"), SIOCGIFBRDADDR },
3542ee8f3f6SSiarzhuk Zharski 		{ B_TRANSLATE("Netmask"), SIOCGIFNETMASK },
355f01106c3SAxel Dörfler 		{ NULL }
356f01106c3SAxel Dörfler 	};
357f01106c3SAxel Dörfler 
358195981bbSAxel Dörfler 	SocketOpener socket;
359195981bbSAxel Dörfler 	if (socket.InitCheck() != B_OK)
360195981bbSAxel Dörfler 		return;
361195981bbSAxel Dörfler 
362f01106c3SAxel Dörfler 	const char* name;
363f01106c3SAxel Dörfler 	if (message->FindString("interface", &name) != B_OK)
364f01106c3SAxel Dörfler 		return;
365f01106c3SAxel Dörfler 
366f01106c3SAxel Dörfler 	ifreq request;
367f01106c3SAxel Dörfler 	if (!_PrepareRequest(request, name))
368f01106c3SAxel Dörfler 		return;
369f01106c3SAxel Dörfler 
3702ee8f3f6SSiarzhuk Zharski 	BString text(B_TRANSLATE("%ifaceName information:\n"));
3712ee8f3f6SSiarzhuk Zharski 	text.ReplaceFirst("%ifaceName", name);
372757e7059SAdrien Destugues 
373f01106c3SAxel Dörfler 	size_t boldLength = text.Length();
374f01106c3SAxel Dörfler 
375f01106c3SAxel Dörfler 	for (int i = 0; kInformationEntries[i].label; i++) {
376195981bbSAxel Dörfler 		if (ioctl(socket, kInformationEntries[i].control, &request,
377f01106c3SAxel Dörfler 				sizeof(request)) < 0) {
378f01106c3SAxel Dörfler 			continue;
379f01106c3SAxel Dörfler 		}
380f01106c3SAxel Dörfler 
381f01106c3SAxel Dörfler 		char address[32];
382f01106c3SAxel Dörfler 		sockaddr_in* inetAddress = NULL;
383f01106c3SAxel Dörfler 		switch (kInformationEntries[i].control) {
384f01106c3SAxel Dörfler 			case SIOCGIFNETMASK:
385f01106c3SAxel Dörfler 				inetAddress = (sockaddr_in*)&request.ifr_mask;
386f01106c3SAxel Dörfler 				break;
387f01106c3SAxel Dörfler 			default:
388f01106c3SAxel Dörfler 				inetAddress = (sockaddr_in*)&request.ifr_addr;
389f01106c3SAxel Dörfler 				break;
390f01106c3SAxel Dörfler 		}
391f01106c3SAxel Dörfler 
392f01106c3SAxel Dörfler 		if (inet_ntop(AF_INET, &inetAddress->sin_addr, address,
393f01106c3SAxel Dörfler 				sizeof(address)) == NULL) {
394f01106c3SAxel Dörfler 			return;
395f01106c3SAxel Dörfler 		}
396f01106c3SAxel Dörfler 
3972ee8f3f6SSiarzhuk Zharski 		text << "\n" << kInformationEntries[i].label << ": " << address;
398f01106c3SAxel Dörfler 	}
399f01106c3SAxel Dörfler 
400757e7059SAdrien Destugues 	BAlert* alert = new BAlert(name, text.String(), B_TRANSLATE("OK"));
401f01106c3SAxel Dörfler 	BTextView* view = alert->TextView();
402f01106c3SAxel Dörfler 	BFont font;
403f01106c3SAxel Dörfler 
404f01106c3SAxel Dörfler 	view->SetStylable(true);
405f01106c3SAxel Dörfler 	view->GetFont(&font);
406f01106c3SAxel Dörfler 	font.SetFace(B_BOLD_FACE);
407f01106c3SAxel Dörfler 	view->SetFontAndColor(0, boldLength, &font);
408f01106c3SAxel Dörfler 
409f01106c3SAxel Dörfler 	alert->Go(NULL);
410f01106c3SAxel Dörfler }
411f01106c3SAxel Dörfler 
412f01106c3SAxel Dörfler 
413f01106c3SAxel Dörfler void
414f01106c3SAxel Dörfler NetworkStatusView::MouseDown(BPoint point)
415f01106c3SAxel Dörfler {
416f01106c3SAxel Dörfler 	BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
417a31688d2SAxel Dörfler 	menu->SetAsyncAutoDestruct(true);
418f01106c3SAxel Dörfler 	menu->SetFont(be_plain_font);
4195c46b171SRene Gollent 	BString wifiInterface;
4205c46b171SRene Gollent 	BNetworkDevice wifiDevice;
421f01106c3SAxel Dörfler 
4225fe97f21SAxel Dörfler 	// Add interfaces
4235fe97f21SAxel Dörfler 
4245c46b171SRene Gollent 	for (std::map<BString, int32>::const_iterator it
4255c46b171SRene Gollent 		= fInterfaceStatuses.begin(); it != fInterfaceStatuses.end(); ++it) {
4265c46b171SRene Gollent 		const BString& name = it->first;
427f01106c3SAxel Dörfler 
428f01106c3SAxel Dörfler 		BString label = name;
429f01106c3SAxel Dörfler 		label += ": ";
430f01106c3SAxel Dörfler 		label += kStatusDescriptions[
431f01106c3SAxel Dörfler 			_DetermineInterfaceStatus(name.String())];
432f01106c3SAxel Dörfler 
433f01106c3SAxel Dörfler 		BMessage* info = new BMessage(kMsgShowConfiguration);
434f01106c3SAxel Dörfler 		info->AddString("interface", name.String());
435f01106c3SAxel Dörfler 		menu->AddItem(new BMenuItem(label.String(), info));
4365c46b171SRene Gollent 
4375c46b171SRene Gollent 		// We only show the networks of the first wireless device we find.
4385c46b171SRene Gollent 		if (wifiInterface.IsEmpty()) {
4395c46b171SRene Gollent 			wifiDevice.SetTo(name);
4405c46b171SRene Gollent 			if (wifiDevice.IsWireless())
4415c46b171SRene Gollent 				wifiInterface = name;
4425c46b171SRene Gollent 		}
443f01106c3SAxel Dörfler 	}
444f01106c3SAxel Dörfler 
4455c46b171SRene Gollent 	if (!fInterfaceStatuses.empty())
446f01106c3SAxel Dörfler 		menu->AddSeparatorItem();
4475fe97f21SAxel Dörfler 
4485fe97f21SAxel Dörfler 	// Add wireless networks, if any
4495fe97f21SAxel Dörfler 
4505c46b171SRene Gollent 	if (!wifiInterface.IsEmpty()) {
451440d0e61SAxel Dörfler 		std::set<BNetworkAddress> associated;
452440d0e61SAxel Dörfler 		BNetworkAddress address;
453440d0e61SAxel Dörfler 		uint32 cookie = 0;
4545c46b171SRene Gollent 		while (wifiDevice.GetNextAssociatedNetwork(cookie, address) == B_OK)
455440d0e61SAxel Dörfler 			associated.insert(address);
456440d0e61SAxel Dörfler 
4575fe97f21SAxel Dörfler 		wireless_network network;
4585fe97f21SAxel Dörfler 		int32 count = 0;
459440d0e61SAxel Dörfler 		cookie = 0;
4605c46b171SRene Gollent 		while (wifiDevice.GetNextNetwork(cookie, network) == B_OK) {
4612e1a6286SAxel Dörfler 			BMessage* message = new BMessage(kMsgJoinNetwork);
4625c46b171SRene Gollent 			message->AddString("device", wifiInterface);
4632e1a6286SAxel Dörfler 			message->AddString("name", network.name);
4642e1a6286SAxel Dörfler 
465440d0e61SAxel Dörfler 			BMenuItem* item = new WirelessNetworkMenuItem(network.name,
466440d0e61SAxel Dörfler 				network.signal_strength,
4672e1a6286SAxel Dörfler 				(network.flags & B_NETWORK_IS_ENCRYPTED) != 0, message);
468440d0e61SAxel Dörfler 			menu->AddItem(item);
469440d0e61SAxel Dörfler 			if (associated.find(network.address) != associated.end())
470440d0e61SAxel Dörfler 				item->SetMarked(true);
471440d0e61SAxel Dörfler 
4725fe97f21SAxel Dörfler 			count++;
4735fe97f21SAxel Dörfler 		}
4745fe97f21SAxel Dörfler 		if (count == 0) {
4755fe97f21SAxel Dörfler 			BMenuItem* item = new BMenuItem(
4765fe97f21SAxel Dörfler 				B_TRANSLATE("<no wireless networks found>"), NULL);
4775fe97f21SAxel Dörfler 			item->SetEnabled(false);
4785fe97f21SAxel Dörfler 			menu->AddItem(item);
4795fe97f21SAxel Dörfler 		}
4805fe97f21SAxel Dörfler 		menu->AddSeparatorItem();
4815fe97f21SAxel Dörfler 	}
4825fe97f21SAxel Dörfler 
483757e7059SAdrien Destugues 	menu->AddItem(new BMenuItem(B_TRANSLATE(
484757e7059SAdrien Destugues 		"Open network preferences" B_UTF8_ELLIPSIS),
485c1502c9aSStephan Aßmus 		new BMessage(kMsgOpenNetworkPreferences)));
4863b41ad86SStephan Aßmus 
4875fe97f21SAxel Dörfler 	if (fInDeskbar) {
488757e7059SAdrien Destugues 		menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
489757e7059SAdrien Destugues 			new BMessage(B_QUIT_REQUESTED)));
4905fe97f21SAxel Dörfler 	}
491f01106c3SAxel Dörfler 	menu->SetTargetForItems(this);
492f01106c3SAxel Dörfler 
493f01106c3SAxel Dörfler 	ConvertToScreen(&point);
494a31688d2SAxel Dörfler 	menu->Go(point, true, true, true);
495f01106c3SAxel Dörfler }
496f01106c3SAxel Dörfler 
497f01106c3SAxel Dörfler 
498f01106c3SAxel Dörfler void
499f01106c3SAxel Dörfler NetworkStatusView::_AboutRequested()
500f01106c3SAxel Dörfler {
5015fe97f21SAxel Dörfler 	BString about = B_TRANSLATE(
502757e7059SAdrien Destugues 		"NetworkStatus\n\twritten by %1 and Hugo Santos\n\t%2, Haiku, Inc.\n"
503757e7059SAdrien Destugues 		);
5045fe97f21SAxel Dörfler 	about.ReplaceFirst("%1", "Axel Dörfler");
505757e7059SAdrien Destugues 		// Append a new developer here
5065fe97f21SAxel Dörfler 	about.ReplaceFirst("%2", "Copyright 2007-2010");
507757e7059SAdrien Destugues 		// Append a new year here
5085fe97f21SAxel Dörfler 	BAlert* alert = new BAlert("about", about, B_TRANSLATE("OK"));
509f01106c3SAxel Dörfler 	BTextView *view = alert->TextView();
510f01106c3SAxel Dörfler 	BFont font;
511f01106c3SAxel Dörfler 
512f01106c3SAxel Dörfler 	view->SetStylable(true);
513f01106c3SAxel Dörfler 
514f01106c3SAxel Dörfler 	view->GetFont(&font);
515f01106c3SAxel Dörfler 	font.SetSize(18);
516f01106c3SAxel Dörfler 	font.SetFace(B_BOLD_FACE);
517f01106c3SAxel Dörfler 	view->SetFontAndColor(0, 13, &font);
518f01106c3SAxel Dörfler 
519f01106c3SAxel Dörfler 	alert->Go();
520f01106c3SAxel Dörfler }
521f01106c3SAxel Dörfler 
522f01106c3SAxel Dörfler 
523f01106c3SAxel Dörfler bool
524f01106c3SAxel Dörfler NetworkStatusView::_PrepareRequest(struct ifreq& request, const char* name)
525f01106c3SAxel Dörfler {
526f01106c3SAxel Dörfler 	if (strlen(name) > IF_NAMESIZE)
527f01106c3SAxel Dörfler 		return false;
528f01106c3SAxel Dörfler 
529f01106c3SAxel Dörfler 	strcpy(request.ifr_name, name);
530f01106c3SAxel Dörfler 	return true;
531f01106c3SAxel Dörfler }
532f01106c3SAxel Dörfler 
533f01106c3SAxel Dörfler 
534f01106c3SAxel Dörfler int32
5355c46b171SRene Gollent NetworkStatusView::_DetermineInterfaceStatus(
5365c46b171SRene Gollent 	const BNetworkInterface& interface)
537f01106c3SAxel Dörfler {
5385fe97f21SAxel Dörfler 	uint32 flags = interface.Flags();
539f01106c3SAxel Dörfler 	int32 status = kStatusNoLink;
540f01106c3SAxel Dörfler 
541f01106c3SAxel Dörfler 	// TODO: no kStatusLinkNoConfig yet
542f01106c3SAxel Dörfler 
543f01106c3SAxel Dörfler 	if (flags & IFF_CONFIGURING)
544f01106c3SAxel Dörfler 		status = kStatusConnecting;
5452a17be44SAxel Dörfler 	else if ((flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK))
546f01106c3SAxel Dörfler 		status = kStatusReady;
547f01106c3SAxel Dörfler 
548f01106c3SAxel Dörfler 	return status;
549f01106c3SAxel Dörfler }
550f01106c3SAxel Dörfler 
551f01106c3SAxel Dörfler 
552f01106c3SAxel Dörfler void
553f01106c3SAxel Dörfler NetworkStatusView::_Update(bool force)
554f01106c3SAxel Dörfler {
5555fe97f21SAxel Dörfler 	BNetworkRoster& roster = BNetworkRoster::Default();
5565fe97f21SAxel Dörfler 	BNetworkInterface interface;
5575fe97f21SAxel Dörfler 	uint32 cookie = 0;
5585fe97f21SAxel Dörfler 
5595fe97f21SAxel Dörfler 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
5605fe97f21SAxel Dörfler 		if ((interface.Flags() & IFF_LOOPBACK) == 0) {
5615c46b171SRene Gollent 			int32 oldStatus = kStatusUnknown;
5625c46b171SRene Gollent 			if (fInterfaceStatuses.find(interface.Name())
5635c46b171SRene Gollent 				!= fInterfaceStatuses.end()) {
5645c46b171SRene Gollent 				oldStatus = fInterfaceStatuses[interface.Name()];
565f01106c3SAxel Dörfler 			}
5665c46b171SRene Gollent 			int32 status = _DetermineInterfaceStatus(interface);
5675c46b171SRene Gollent 			if (oldStatus != status) {
568b44d24c0SAlexander von Gluck IV 				BNotification notification(B_INFORMATION_NOTIFICATION);
569b44d24c0SAlexander von Gluck IV 				notification.SetGroup(B_TRANSLATE("Network Status"));
570b44d24c0SAlexander von Gluck IV 				notification.SetTitle(interface.Name());
571b44d24c0SAlexander von Gluck IV 				notification.SetMessageID(interface.Name());
5725c46b171SRene Gollent 				notification.SetIcon(fNotifyIcons[status]);
5735c46b171SRene Gollent 				if (status == kStatusConnecting
5745c46b171SRene Gollent 					|| (status == kStatusReady
5755c46b171SRene Gollent 						&& oldStatus == kStatusConnecting)
5765c46b171SRene Gollent 					|| (status == kStatusNoLink
5775c46b171SRene Gollent 						&& oldStatus == kStatusReady)
5785c46b171SRene Gollent 					|| (status == kStatusNoLink
5795c46b171SRene Gollent 						&& oldStatus == kStatusConnecting)) {
58043c68287SAlexander von Gluck IV 					// A significant state change, raise notification.
5815c46b171SRene Gollent 					notification.SetContent(kStatusDescriptions[status]);
582b44d24c0SAlexander von Gluck IV 					notification.Send();
583b44d24c0SAlexander von Gluck IV 				}
584f01106c3SAxel Dörfler 				Invalidate();
585f01106c3SAxel Dörfler 			}
5865c46b171SRene Gollent 			fInterfaceStatuses[interface.Name()] = status;
5875c46b171SRene Gollent 		}
5885c46b171SRene Gollent 	}
589b44d24c0SAlexander von Gluck IV }
590f01106c3SAxel Dörfler 
591f01106c3SAxel Dörfler 
5923b41ad86SStephan Aßmus void
5933b41ad86SStephan Aßmus NetworkStatusView::_OpenNetworksPreferences()
5943b41ad86SStephan Aßmus {
595195981bbSAxel Dörfler 	status_t status = be_roster->Launch("application/x-vnd.Haiku-Network");
59646cac7f7SAlexandre Deckner 	if (status != B_OK && status != B_ALREADY_RUNNING) {
597757e7059SAdrien Destugues 		BString errorMessage(B_TRANSLATE("Launching the network preflet "
598757e7059SAdrien Destugues 			"failed.\n\nError: "));
599195981bbSAxel Dörfler 		errorMessage << strerror(status);
6003b41ad86SStephan Aßmus 		BAlert* alert = new BAlert("launch error", errorMessage.String(),
601757e7059SAdrien Destugues 			B_TRANSLATE("OK"));
602195981bbSAxel Dörfler 
603195981bbSAxel Dörfler 		// asynchronous alert in order to not block replicant host application
6043b41ad86SStephan Aßmus 		alert->Go(NULL);
6053b41ad86SStephan Aßmus 	}
6063b41ad86SStephan Aßmus }
6073b41ad86SStephan Aßmus 
6083b41ad86SStephan Aßmus 
609f01106c3SAxel Dörfler //	#pragma mark -
610f01106c3SAxel Dörfler 
611f01106c3SAxel Dörfler 
612f01106c3SAxel Dörfler extern "C" _EXPORT BView *
613f01106c3SAxel Dörfler instantiate_deskbar_item(void)
614f01106c3SAxel Dörfler {
61566eba86fSAxel Dörfler 	return new NetworkStatusView(BRect(0, 0, 15, 15),
61666eba86fSAxel Dörfler 		B_FOLLOW_LEFT | B_FOLLOW_TOP, true);
617f01106c3SAxel Dörfler }
618f01106c3SAxel Dörfler 
619