xref: /haiku/src/apps/networkstatus/NetworkStatusView.cpp (revision 5fe97f21b69ac7d689925611cfdf8a1b2cae8ad1)
1f01106c3SAxel Dörfler /*
27974d3dcSStephan Aßmus  * Copyright 2006-2009, 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 
14195981bbSAxel Dörfler #include <arpa/inet.h>
15195981bbSAxel Dörfler #include <net/if.h>
16195981bbSAxel Dörfler #include <stdio.h>
17195981bbSAxel Dörfler #include <stdlib.h>
18195981bbSAxel Dörfler #include <string.h>
19195981bbSAxel Dörfler #include <sys/socket.h>
20195981bbSAxel Dörfler #include <sys/sockio.h>
21195981bbSAxel Dörfler #include <unistd.h>
22f01106c3SAxel Dörfler 
23f01106c3SAxel Dörfler #include <Alert.h>
24f01106c3SAxel Dörfler #include <Application.h>
25757e7059SAdrien Destugues #include <Catalog.h>
26f01106c3SAxel Dörfler #include <Bitmap.h>
27f01106c3SAxel Dörfler #include <Deskbar.h>
28f01106c3SAxel Dörfler #include <Dragger.h>
29f01106c3SAxel Dörfler #include <Drivers.h>
30f01106c3SAxel Dörfler #include <IconUtils.h>
31757e7059SAdrien Destugues #include <Locale.h>
32f01106c3SAxel Dörfler #include <MenuItem.h>
33f01106c3SAxel Dörfler #include <MessageRunner.h>
34*5fe97f21SAxel Dörfler #include <NetworkDevice.h>
35*5fe97f21SAxel Dörfler #include <NetworkInterface.h>
36*5fe97f21SAxel Dörfler #include <NetworkRoster.h>
37f01106c3SAxel Dörfler #include <PopUpMenu.h>
38f01106c3SAxel Dörfler #include <Resources.h>
39d5ba07a3SAxel Dörfler #include <Roster.h>
40f01106c3SAxel Dörfler #include <String.h>
41f01106c3SAxel Dörfler #include <TextView.h>
42f01106c3SAxel Dörfler 
43195981bbSAxel Dörfler #include "NetworkStatus.h"
44195981bbSAxel Dörfler #include "NetworkStatusIcons.h"
45*5fe97f21SAxel Dörfler #include "RadioView.h"
46195981bbSAxel Dörfler 
47f01106c3SAxel Dörfler 
48757e7059SAdrien Destugues #undef B_TRANSLATE_CONTEXT
49757e7059SAdrien Destugues #define B_TRANSLATE_CONTEXT "NetworkStatusView"
50757e7059SAdrien Destugues 
51757e7059SAdrien Destugues 
52f01106c3SAxel Dörfler static const char *kStatusDescriptions[] = {
53757e7059SAdrien Destugues 	B_TRANSLATE_MARK("Unknown"),
54757e7059SAdrien Destugues 	B_TRANSLATE_MARK("No link"),
55757e7059SAdrien Destugues 	B_TRANSLATE_MARK("No stateful configuration"),
56757e7059SAdrien Destugues 	B_TRANSLATE_MARK("Configuring"),
57757e7059SAdrien Destugues 	B_TRANSLATE_MARK("Ready")
58f01106c3SAxel Dörfler };
59f01106c3SAxel Dörfler 
60f01106c3SAxel Dörfler extern "C" _EXPORT BView *instantiate_deskbar_item(void);
61f01106c3SAxel Dörfler 
62f01106c3SAxel Dörfler 
63f01106c3SAxel Dörfler const uint32 kMsgShowConfiguration = 'shcf';
64c1502c9aSStephan Aßmus const uint32 kMsgOpenNetworkPreferences = 'onwp';
65f01106c3SAxel Dörfler 
66f01106c3SAxel Dörfler const uint32 kMinIconWidth = 16;
67f01106c3SAxel Dörfler const uint32 kMinIconHeight = 16;
68f01106c3SAxel Dörfler 
69195981bbSAxel Dörfler 
70*5fe97f21SAxel Dörfler class WirelessNetworkMenuItem : public BMenuItem {
71*5fe97f21SAxel Dörfler public:
72*5fe97f21SAxel Dörfler 								WirelessNetworkMenuItem(const char* name,
73*5fe97f21SAxel Dörfler 									int32 signalQuality, bool encrypted,
74*5fe97f21SAxel Dörfler 									BMessage* message);
75*5fe97f21SAxel Dörfler 	virtual						~WirelessNetworkMenuItem();
76*5fe97f21SAxel Dörfler 
77*5fe97f21SAxel Dörfler 			void				SetSignalQuality(int32 quality);
78*5fe97f21SAxel Dörfler 			int32				SignalQuality() const
79*5fe97f21SAxel Dörfler 									{ return fQuality; }
80*5fe97f21SAxel Dörfler 			bool				IsEncrypted() const
81*5fe97f21SAxel Dörfler 									{ return fIsEncrypted; }
82*5fe97f21SAxel Dörfler 
83*5fe97f21SAxel Dörfler protected:
84*5fe97f21SAxel Dörfler 	virtual	void				DrawContent();
85*5fe97f21SAxel Dörfler 	virtual	void				Highlight(bool isHighlighted);
86*5fe97f21SAxel Dörfler 	virtual	void				GetContentSize(float* width, float* height);
87*5fe97f21SAxel Dörfler 			void				DrawRadioIcon();
88*5fe97f21SAxel Dörfler 
89*5fe97f21SAxel Dörfler private:
90*5fe97f21SAxel Dörfler 			int32				fQuality;
91*5fe97f21SAxel Dörfler 			bool				fIsEncrypted;
92*5fe97f21SAxel Dörfler };
93*5fe97f21SAxel Dörfler 
94*5fe97f21SAxel Dörfler 
95195981bbSAxel Dörfler class SocketOpener {
96195981bbSAxel Dörfler public:
97195981bbSAxel Dörfler 	SocketOpener()
98195981bbSAxel Dörfler 	{
99195981bbSAxel Dörfler 		fSocket = socket(AF_INET, SOCK_DGRAM, 0);
100195981bbSAxel Dörfler 	}
101195981bbSAxel Dörfler 
102195981bbSAxel Dörfler 	~SocketOpener()
103195981bbSAxel Dörfler 	{
104195981bbSAxel Dörfler 		close(fSocket);
105195981bbSAxel Dörfler 	}
106195981bbSAxel Dörfler 
107195981bbSAxel Dörfler 	status_t InitCheck()
108195981bbSAxel Dörfler 	{
109195981bbSAxel Dörfler 		return fSocket >= 0 ? B_OK : B_ERROR;
110195981bbSAxel Dörfler 	}
111195981bbSAxel Dörfler 
112195981bbSAxel Dörfler 	operator int() const
113195981bbSAxel Dörfler 	{
114195981bbSAxel Dörfler 		return fSocket;
115195981bbSAxel Dörfler 	}
116195981bbSAxel Dörfler 
117195981bbSAxel Dörfler private:
118195981bbSAxel Dörfler 	int	fSocket;
119195981bbSAxel Dörfler };
120195981bbSAxel Dörfler 
121195981bbSAxel Dörfler 
122*5fe97f21SAxel Dörfler // #pragma mark - WirelessNetworkMenuItem
123*5fe97f21SAxel Dörfler 
124*5fe97f21SAxel Dörfler 
125*5fe97f21SAxel Dörfler WirelessNetworkMenuItem::WirelessNetworkMenuItem(const char* name,
126*5fe97f21SAxel Dörfler 	int32 signalQuality, bool encrypted, BMessage* message)
127*5fe97f21SAxel Dörfler 	:
128*5fe97f21SAxel Dörfler 	BMenuItem(name, message),
129*5fe97f21SAxel Dörfler 	fQuality(signalQuality),
130*5fe97f21SAxel Dörfler 	fIsEncrypted(encrypted)
131*5fe97f21SAxel Dörfler {
132*5fe97f21SAxel Dörfler }
133*5fe97f21SAxel Dörfler 
134*5fe97f21SAxel Dörfler 
135*5fe97f21SAxel Dörfler WirelessNetworkMenuItem::~WirelessNetworkMenuItem()
136*5fe97f21SAxel Dörfler {
137*5fe97f21SAxel Dörfler }
138*5fe97f21SAxel Dörfler 
139*5fe97f21SAxel Dörfler 
140*5fe97f21SAxel Dörfler void
141*5fe97f21SAxel Dörfler WirelessNetworkMenuItem::SetSignalQuality(int32 quality)
142*5fe97f21SAxel Dörfler {
143*5fe97f21SAxel Dörfler 	fQuality = quality;
144*5fe97f21SAxel Dörfler }
145*5fe97f21SAxel Dörfler 
146*5fe97f21SAxel Dörfler 
147*5fe97f21SAxel Dörfler void
148*5fe97f21SAxel Dörfler WirelessNetworkMenuItem::DrawContent()
149*5fe97f21SAxel Dörfler {
150*5fe97f21SAxel Dörfler 	DrawRadioIcon();
151*5fe97f21SAxel Dörfler 	BMenuItem::DrawContent();
152*5fe97f21SAxel Dörfler }
153*5fe97f21SAxel Dörfler 
154*5fe97f21SAxel Dörfler 
155*5fe97f21SAxel Dörfler void
156*5fe97f21SAxel Dörfler WirelessNetworkMenuItem::Highlight(bool isHighlighted)
157*5fe97f21SAxel Dörfler {
158*5fe97f21SAxel Dörfler 	BMenuItem::Highlight(isHighlighted);
159*5fe97f21SAxel Dörfler }
160*5fe97f21SAxel Dörfler 
161*5fe97f21SAxel Dörfler 
162*5fe97f21SAxel Dörfler void
163*5fe97f21SAxel Dörfler WirelessNetworkMenuItem::GetContentSize(float* width, float* height)
164*5fe97f21SAxel Dörfler {
165*5fe97f21SAxel Dörfler 	BMenuItem::GetContentSize(width, height);
166*5fe97f21SAxel Dörfler 	*width += *height + 4;
167*5fe97f21SAxel Dörfler }
168*5fe97f21SAxel Dörfler 
169*5fe97f21SAxel Dörfler 
170*5fe97f21SAxel Dörfler void
171*5fe97f21SAxel Dörfler WirelessNetworkMenuItem::DrawRadioIcon()
172*5fe97f21SAxel Dörfler {
173*5fe97f21SAxel Dörfler 	BRect bounds = Frame();
174*5fe97f21SAxel Dörfler 	bounds.left = bounds.right - 4 - bounds.Height();
175*5fe97f21SAxel Dörfler 	bounds.right -= 4;
176*5fe97f21SAxel Dörfler 	bounds.bottom -= 2;
177*5fe97f21SAxel Dörfler 
178*5fe97f21SAxel Dörfler 	RadioView::Draw(Menu(), bounds, fQuality, RadioView::DefaultMax());
179*5fe97f21SAxel Dörfler }
180*5fe97f21SAxel Dörfler 
181*5fe97f21SAxel Dörfler 
182195981bbSAxel Dörfler //	#pragma mark -
183f01106c3SAxel Dörfler 
184f01106c3SAxel Dörfler 
185f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode,
186f01106c3SAxel Dörfler 		bool inDeskbar)
187f01106c3SAxel Dörfler 	: BView(frame, kDeskbarItemName, resizingMode,
188d5ba07a3SAxel Dörfler 		B_WILL_DRAW | B_FRAME_EVENTS),
189f01106c3SAxel Dörfler 	fInDeskbar(inDeskbar),
190f01106c3SAxel Dörfler 	fStatus(kStatusUnknown)
191f01106c3SAxel Dörfler {
192f01106c3SAxel Dörfler 	_Init();
193f01106c3SAxel Dörfler 
194f01106c3SAxel Dörfler 	if (!inDeskbar) {
195f01106c3SAxel Dörfler 		// we were obviously added to a standard window - let's add a dragger
196f01106c3SAxel Dörfler 		frame.OffsetTo(B_ORIGIN);
197f01106c3SAxel Dörfler 		frame.top = frame.bottom - 7;
198f01106c3SAxel Dörfler 		frame.left = frame.right - 7;
199f01106c3SAxel Dörfler 		BDragger* dragger = new BDragger(frame, this,
200f01106c3SAxel Dörfler 			B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
201f01106c3SAxel Dörfler 		AddChild(dragger);
202f01106c3SAxel Dörfler 	} else
203f01106c3SAxel Dörfler 		_Update();
204f01106c3SAxel Dörfler }
205f01106c3SAxel Dörfler 
206f01106c3SAxel Dörfler 
207f01106c3SAxel Dörfler NetworkStatusView::NetworkStatusView(BMessage* archive)
208d5ba07a3SAxel Dörfler 	: BView(archive),
209d5ba07a3SAxel Dörfler 	fInDeskbar(false)
210f01106c3SAxel Dörfler {
211d5ba07a3SAxel Dörfler 	app_info info;
212d5ba07a3SAxel Dörfler 	if (be_app->GetAppInfo(&info) == B_OK
213d5ba07a3SAxel Dörfler 		&& !strcasecmp(info.signature, "application/x-vnd.Be-TSKB"))
214d5ba07a3SAxel Dörfler 		fInDeskbar = true;
215d5ba07a3SAxel Dörfler 
216f01106c3SAxel Dörfler 	_Init();
217f01106c3SAxel Dörfler }
218f01106c3SAxel Dörfler 
219f01106c3SAxel Dörfler 
220f01106c3SAxel Dörfler NetworkStatusView::~NetworkStatusView()
221f01106c3SAxel Dörfler {
222f01106c3SAxel Dörfler }
223f01106c3SAxel Dörfler 
224f01106c3SAxel Dörfler 
225f01106c3SAxel Dörfler void
226f01106c3SAxel Dörfler NetworkStatusView::_Init()
227f01106c3SAxel Dörfler {
228f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
229f01106c3SAxel Dörfler 		fBitmaps[i] = NULL;
230f01106c3SAxel Dörfler 	}
231f01106c3SAxel Dörfler 
232f01106c3SAxel Dörfler 	_UpdateBitmaps();
233f01106c3SAxel Dörfler }
234f01106c3SAxel Dörfler 
235f01106c3SAxel Dörfler 
236f01106c3SAxel Dörfler void
237f01106c3SAxel Dörfler NetworkStatusView::_UpdateBitmaps()
238f01106c3SAxel Dörfler {
239f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
240f01106c3SAxel Dörfler 		delete fBitmaps[i];
241f01106c3SAxel Dörfler 		fBitmaps[i] = NULL;
242f01106c3SAxel Dörfler 	}
243f01106c3SAxel Dörfler 
244f01106c3SAxel Dörfler 	image_info info;
245f01106c3SAxel Dörfler 	if (our_image(info) != B_OK)
246f01106c3SAxel Dörfler 		return;
247f01106c3SAxel Dörfler 
248f01106c3SAxel Dörfler 	BFile file(info.name, B_READ_ONLY);
249f01106c3SAxel Dörfler 	if (file.InitCheck() < B_OK)
250f01106c3SAxel Dörfler 		return;
251f01106c3SAxel Dörfler 
252f01106c3SAxel Dörfler 	BResources resources(&file);
253f01106c3SAxel Dörfler #ifdef HAIKU_TARGET_PLATFORM_HAIKU
254f01106c3SAxel Dörfler 	if (resources.InitCheck() < B_OK)
255f01106c3SAxel Dörfler 		return;
256f01106c3SAxel Dörfler #endif
257f01106c3SAxel Dörfler 
258f01106c3SAxel Dörfler 	for (int i = 0; i < kStatusCount; i++) {
259f01106c3SAxel Dörfler 		const void* data = NULL;
260f01106c3SAxel Dörfler 		size_t size;
261f01106c3SAxel Dörfler 		data = resources.LoadResource(B_VECTOR_ICON_TYPE,
262f01106c3SAxel Dörfler 			kNetworkStatusNoDevice + i, &size);
263f01106c3SAxel Dörfler 		if (data != NULL) {
2644c28a737SStephan Aßmus 			BBitmap* icon = new BBitmap(Bounds(), B_RGBA32);
265f01106c3SAxel Dörfler 			if (icon->InitCheck() == B_OK
266f01106c3SAxel Dörfler 				&& BIconUtils::GetVectorIcon((const uint8 *)data,
267f01106c3SAxel Dörfler 					size, icon) == B_OK) {
268f01106c3SAxel Dörfler 				fBitmaps[i] = icon;
269f01106c3SAxel Dörfler 			} else
270f01106c3SAxel Dörfler 				delete icon;
271f01106c3SAxel Dörfler 		}
272f01106c3SAxel Dörfler 	}
273f01106c3SAxel Dörfler }
274f01106c3SAxel Dörfler 
275f01106c3SAxel Dörfler 
276f01106c3SAxel Dörfler void
277f01106c3SAxel Dörfler NetworkStatusView::_Quit()
278f01106c3SAxel Dörfler {
279f01106c3SAxel Dörfler 	if (fInDeskbar) {
280f01106c3SAxel Dörfler 		BDeskbar deskbar;
281f01106c3SAxel Dörfler 		deskbar.RemoveItem(kDeskbarItemName);
282f01106c3SAxel Dörfler 	} else
283f01106c3SAxel Dörfler 		be_app->PostMessage(B_QUIT_REQUESTED);
284f01106c3SAxel Dörfler }
285f01106c3SAxel Dörfler 
286f01106c3SAxel Dörfler 
287f01106c3SAxel Dörfler NetworkStatusView *
288f01106c3SAxel Dörfler NetworkStatusView::Instantiate(BMessage* archive)
289f01106c3SAxel Dörfler {
290f01106c3SAxel Dörfler 	if (!validate_instantiation(archive, "NetworkStatusView"))
291f01106c3SAxel Dörfler 		return NULL;
292f01106c3SAxel Dörfler 
293f01106c3SAxel Dörfler 	return new NetworkStatusView(archive);
294f01106c3SAxel Dörfler }
295f01106c3SAxel Dörfler 
296f01106c3SAxel Dörfler 
297f01106c3SAxel Dörfler status_t
298f01106c3SAxel Dörfler NetworkStatusView::Archive(BMessage* archive, bool deep) const
299f01106c3SAxel Dörfler {
300f01106c3SAxel Dörfler 	status_t status = BView::Archive(archive, deep);
301f01106c3SAxel Dörfler 	if (status == B_OK)
302f01106c3SAxel Dörfler 		status = archive->AddString("add_on", kSignature);
303f01106c3SAxel Dörfler 	if (status == B_OK)
304f01106c3SAxel Dörfler 		status = archive->AddString("class", "NetworkStatusView");
305f01106c3SAxel Dörfler 
306f01106c3SAxel Dörfler 	return status;
307f01106c3SAxel Dörfler }
308f01106c3SAxel Dörfler 
309f01106c3SAxel Dörfler 
310f01106c3SAxel Dörfler void
311f01106c3SAxel Dörfler NetworkStatusView::AttachedToWindow()
312f01106c3SAxel Dörfler {
313f01106c3SAxel Dörfler 	BView::AttachedToWindow();
314f01106c3SAxel Dörfler 	if (Parent())
315f01106c3SAxel Dörfler 		SetViewColor(Parent()->ViewColor());
316f01106c3SAxel Dörfler 	else
317f01106c3SAxel Dörfler 		SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
318f01106c3SAxel Dörfler 
319f01106c3SAxel Dörfler 	SetLowColor(ViewColor());
320f01106c3SAxel Dörfler 
321195981bbSAxel Dörfler 	start_watching_network(
322195981bbSAxel Dörfler 		B_WATCH_NETWORK_INTERFACE_CHANGES | B_WATCH_NETWORK_LINK_CHANGES, this);
323f01106c3SAxel Dörfler 
324f01106c3SAxel Dörfler 	_Update();
325f01106c3SAxel Dörfler }
326f01106c3SAxel Dörfler 
327f01106c3SAxel Dörfler 
328f01106c3SAxel Dörfler void
329f01106c3SAxel Dörfler NetworkStatusView::DetachedFromWindow()
330f01106c3SAxel Dörfler {
331195981bbSAxel Dörfler 	stop_watching_network(this);
332f01106c3SAxel Dörfler }
333f01106c3SAxel Dörfler 
334f01106c3SAxel Dörfler 
335f01106c3SAxel Dörfler void
336f01106c3SAxel Dörfler NetworkStatusView::MessageReceived(BMessage* message)
337f01106c3SAxel Dörfler {
338f01106c3SAxel Dörfler 	switch (message->what) {
339195981bbSAxel Dörfler 		case B_NETWORK_MONITOR:
340f01106c3SAxel Dörfler 			_Update();
341f01106c3SAxel Dörfler 			break;
342f01106c3SAxel Dörfler 
343f01106c3SAxel Dörfler 		case kMsgShowConfiguration:
344f01106c3SAxel Dörfler 			_ShowConfiguration(message);
345f01106c3SAxel Dörfler 			break;
346f01106c3SAxel Dörfler 
347c1502c9aSStephan Aßmus 		case kMsgOpenNetworkPreferences:
3483b41ad86SStephan Aßmus 			_OpenNetworksPreferences();
3493b41ad86SStephan Aßmus 			break;
3503b41ad86SStephan Aßmus 
351f01106c3SAxel Dörfler 		case B_ABOUT_REQUESTED:
352f01106c3SAxel Dörfler 			_AboutRequested();
353f01106c3SAxel Dörfler 			break;
354f01106c3SAxel Dörfler 
355f01106c3SAxel Dörfler 		case B_QUIT_REQUESTED:
356f01106c3SAxel Dörfler 			_Quit();
357f01106c3SAxel Dörfler 			break;
358f01106c3SAxel Dörfler 
359f01106c3SAxel Dörfler 		default:
360f01106c3SAxel Dörfler 			BView::MessageReceived(message);
361f01106c3SAxel Dörfler 	}
362f01106c3SAxel Dörfler }
363f01106c3SAxel Dörfler 
364f01106c3SAxel Dörfler 
365f01106c3SAxel Dörfler void
366f01106c3SAxel Dörfler NetworkStatusView::FrameResized(float width, float height)
367f01106c3SAxel Dörfler {
368f01106c3SAxel Dörfler 	_UpdateBitmaps();
369d5ba07a3SAxel Dörfler 	Invalidate();
370f01106c3SAxel Dörfler }
371f01106c3SAxel Dörfler 
372f01106c3SAxel Dörfler 
373f01106c3SAxel Dörfler void
374f01106c3SAxel Dörfler NetworkStatusView::Draw(BRect updateRect)
375f01106c3SAxel Dörfler {
376f01106c3SAxel Dörfler 	if (fBitmaps[fStatus] == NULL)
377f01106c3SAxel Dörfler 		return;
378f01106c3SAxel Dörfler 
379f01106c3SAxel Dörfler 	SetDrawingMode(B_OP_ALPHA);
380f01106c3SAxel Dörfler 	DrawBitmap(fBitmaps[fStatus]);
381f01106c3SAxel Dörfler 	SetDrawingMode(B_OP_COPY);
382f01106c3SAxel Dörfler }
383f01106c3SAxel Dörfler 
384f01106c3SAxel Dörfler 
385f01106c3SAxel Dörfler void
386f01106c3SAxel Dörfler NetworkStatusView::_ShowConfiguration(BMessage* message)
387f01106c3SAxel Dörfler {
388f01106c3SAxel Dörfler 	static const struct information_entry {
389f01106c3SAxel Dörfler 		const char*	label;
390f01106c3SAxel Dörfler 		int32		control;
391f01106c3SAxel Dörfler 	} kInformationEntries[] = {
392f01106c3SAxel Dörfler 		{ "Address", SIOCGIFADDR },
393f01106c3SAxel Dörfler 		{ "Broadcast", SIOCGIFBRDADDR },
394f01106c3SAxel Dörfler 		{ "Netmask", SIOCGIFNETMASK },
395f01106c3SAxel Dörfler 		{ NULL }
396f01106c3SAxel Dörfler 	};
397f01106c3SAxel Dörfler 
398195981bbSAxel Dörfler 	SocketOpener socket;
399195981bbSAxel Dörfler 	if (socket.InitCheck() != B_OK)
400195981bbSAxel Dörfler 		return;
401195981bbSAxel Dörfler 
402f01106c3SAxel Dörfler 	const char* name;
403f01106c3SAxel Dörfler 	if (message->FindString("interface", &name) != B_OK)
404f01106c3SAxel Dörfler 		return;
405f01106c3SAxel Dörfler 
406f01106c3SAxel Dörfler 	ifreq request;
407f01106c3SAxel Dörfler 	if (!_PrepareRequest(request, name))
408f01106c3SAxel Dörfler 		return;
409f01106c3SAxel Dörfler 
410757e7059SAdrien Destugues 	BString text = NULL;
411757e7059SAdrien Destugues 	if (strncmp("Address", name, strlen(name)) == 0)
412757e7059SAdrien Destugues 		text = B_TRANSLATE("Address information:\n");
413757e7059SAdrien Destugues 
414757e7059SAdrien Destugues 	if (strncmp("Broadcast", name, strlen(name)) == 0)
415757e7059SAdrien Destugues 		text = B_TRANSLATE("Broadcast information:\n");
416757e7059SAdrien Destugues 
417757e7059SAdrien Destugues 	if (strncmp("Netmask", name, strlen(name)) == 0)
418757e7059SAdrien Destugues 		text = B_TRANSLATE("Netmask information:\n");
419757e7059SAdrien Destugues 
420f01106c3SAxel Dörfler 	size_t boldLength = text.Length();
421f01106c3SAxel Dörfler 
422f01106c3SAxel Dörfler 	for (int i = 0; kInformationEntries[i].label; i++) {
423195981bbSAxel Dörfler 		if (ioctl(socket, kInformationEntries[i].control, &request,
424f01106c3SAxel Dörfler 				sizeof(request)) < 0) {
425f01106c3SAxel Dörfler 			continue;
426f01106c3SAxel Dörfler 		}
427f01106c3SAxel Dörfler 
428f01106c3SAxel Dörfler 		char address[32];
429f01106c3SAxel Dörfler 		sockaddr_in* inetAddress = NULL;
430f01106c3SAxel Dörfler 		switch (kInformationEntries[i].control) {
431f01106c3SAxel Dörfler 			case SIOCGIFNETMASK:
432f01106c3SAxel Dörfler 				inetAddress = (sockaddr_in*)&request.ifr_mask;
433f01106c3SAxel Dörfler 				break;
434f01106c3SAxel Dörfler 			default:
435f01106c3SAxel Dörfler 				inetAddress = (sockaddr_in*)&request.ifr_addr;
436f01106c3SAxel Dörfler 				break;
437f01106c3SAxel Dörfler 		}
438f01106c3SAxel Dörfler 
439f01106c3SAxel Dörfler 		if (inet_ntop(AF_INET, &inetAddress->sin_addr, address,
440f01106c3SAxel Dörfler 				sizeof(address)) == NULL) {
441f01106c3SAxel Dörfler 			return;
442f01106c3SAxel Dörfler 		}
443f01106c3SAxel Dörfler 
444f01106c3SAxel Dörfler 		text += "\n";
445757e7059SAdrien Destugues 
446757e7059SAdrien Destugues 		if (strncmp("Address", kInformationEntries[i].label,
447757e7059SAdrien Destugues 			strlen(kInformationEntries[i].label)) == 0)
448757e7059SAdrien Destugues 			text += B_TRANSLATE("Address");
449757e7059SAdrien Destugues 
450757e7059SAdrien Destugues 		if (strncmp("Broadcast", kInformationEntries[i].label,
451757e7059SAdrien Destugues 			strlen(kInformationEntries[i].label)) == 0)
452757e7059SAdrien Destugues 			text += B_TRANSLATE("Broadcast");
453757e7059SAdrien Destugues 
454757e7059SAdrien Destugues 		if (strncmp("Netmask", kInformationEntries[i].label,
455757e7059SAdrien Destugues 			strlen(kInformationEntries[i].label)) == 0)
456757e7059SAdrien Destugues 			text += B_TRANSLATE("Netmask");
457757e7059SAdrien Destugues 
458f01106c3SAxel Dörfler 		text += ": ";
459f01106c3SAxel Dörfler 		text += address;
460f01106c3SAxel Dörfler 	}
461f01106c3SAxel Dörfler 
462757e7059SAdrien Destugues 	BAlert* alert = new BAlert(name, text.String(), B_TRANSLATE("OK"));
463f01106c3SAxel Dörfler 	BTextView* view = alert->TextView();
464f01106c3SAxel Dörfler 	BFont font;
465f01106c3SAxel Dörfler 
466f01106c3SAxel Dörfler 	view->SetStylable(true);
467f01106c3SAxel Dörfler 	view->GetFont(&font);
468f01106c3SAxel Dörfler 	font.SetFace(B_BOLD_FACE);
469f01106c3SAxel Dörfler 	view->SetFontAndColor(0, boldLength, &font);
470f01106c3SAxel Dörfler 
471f01106c3SAxel Dörfler 	alert->Go(NULL);
472f01106c3SAxel Dörfler }
473f01106c3SAxel Dörfler 
474f01106c3SAxel Dörfler 
475f01106c3SAxel Dörfler void
476f01106c3SAxel Dörfler NetworkStatusView::MouseDown(BPoint point)
477f01106c3SAxel Dörfler {
478f01106c3SAxel Dörfler 	BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
479a31688d2SAxel Dörfler 	menu->SetAsyncAutoDestruct(true);
480f01106c3SAxel Dörfler 	menu->SetFont(be_plain_font);
481f01106c3SAxel Dörfler 
482*5fe97f21SAxel Dörfler 	// Add interfaces
483*5fe97f21SAxel Dörfler 
484f01106c3SAxel Dörfler 	for (int32 i = 0; i < fInterfaces.CountItems(); i++) {
485f01106c3SAxel Dörfler 		BString& name = *fInterfaces.ItemAt(i);
486f01106c3SAxel Dörfler 
487f01106c3SAxel Dörfler 		BString label = name;
488f01106c3SAxel Dörfler 		label += ": ";
489f01106c3SAxel Dörfler 		label += kStatusDescriptions[
490f01106c3SAxel Dörfler 			_DetermineInterfaceStatus(name.String())];
491f01106c3SAxel Dörfler 
492f01106c3SAxel Dörfler 		BMessage* info = new BMessage(kMsgShowConfiguration);
493f01106c3SAxel Dörfler 		info->AddString("interface", name.String());
494f01106c3SAxel Dörfler 		menu->AddItem(new BMenuItem(label.String(), info));
495f01106c3SAxel Dörfler 	}
496f01106c3SAxel Dörfler 
497f01106c3SAxel Dörfler 	menu->AddSeparatorItem();
498*5fe97f21SAxel Dörfler 
499*5fe97f21SAxel Dörfler 	// Add wireless networks, if any
500*5fe97f21SAxel Dörfler 
501*5fe97f21SAxel Dörfler 	for (int32 i = 0; i < fInterfaces.CountItems(); i++) {
502*5fe97f21SAxel Dörfler 		BNetworkDevice device(fInterfaces.ItemAt(i)->String());
503*5fe97f21SAxel Dörfler 		if (!device.IsWireless())
504*5fe97f21SAxel Dörfler 			continue;
505*5fe97f21SAxel Dörfler 
506*5fe97f21SAxel Dörfler 		wireless_network network;
507*5fe97f21SAxel Dörfler 		int32 count = 0;
508*5fe97f21SAxel Dörfler 		for (int32 i = 0; device.GetScanResultAt(i, network) == B_OK; i++) {
509*5fe97f21SAxel Dörfler 			printf("%s: noise %u : rssi %u\n", network.name,
510*5fe97f21SAxel Dörfler 				network.noise_level, network.signal_strength);
511*5fe97f21SAxel Dörfler 			menu->AddItem(new WirelessNetworkMenuItem(network.name,
512*5fe97f21SAxel Dörfler 				network.signal_strength, false, NULL));
513*5fe97f21SAxel Dörfler 			count++;
514*5fe97f21SAxel Dörfler 		}
515*5fe97f21SAxel Dörfler 		if (count == 0) {
516*5fe97f21SAxel Dörfler 			BMenuItem* item = new BMenuItem(
517*5fe97f21SAxel Dörfler 				B_TRANSLATE("<no wireless networks found>"), NULL);
518*5fe97f21SAxel Dörfler 			item->SetEnabled(false);
519*5fe97f21SAxel Dörfler 			menu->AddItem(item);
520*5fe97f21SAxel Dörfler 		}
521*5fe97f21SAxel Dörfler 		menu->AddSeparatorItem();
522*5fe97f21SAxel Dörfler 
523*5fe97f21SAxel Dörfler 		// We only show the networks of the first wireless device we find.
524*5fe97f21SAxel Dörfler 		break;
525*5fe97f21SAxel Dörfler 	}
526*5fe97f21SAxel Dörfler 
527757e7059SAdrien Destugues 	menu->AddItem(new BMenuItem(B_TRANSLATE(
528757e7059SAdrien Destugues 		"Open network preferences" B_UTF8_ELLIPSIS),
529c1502c9aSStephan Aßmus 		new BMessage(kMsgOpenNetworkPreferences)));
5303b41ad86SStephan Aßmus 
531*5fe97f21SAxel Dörfler 	if (fInDeskbar) {
532757e7059SAdrien Destugues 		menu->AddItem(new BMenuItem(B_TRANSLATE("Quit"),
533757e7059SAdrien Destugues 			new BMessage(B_QUIT_REQUESTED)));
534*5fe97f21SAxel Dörfler 	}
535f01106c3SAxel Dörfler 	menu->SetTargetForItems(this);
536f01106c3SAxel Dörfler 
537f01106c3SAxel Dörfler 	ConvertToScreen(&point);
538a31688d2SAxel Dörfler 	menu->Go(point, true, true, true);
539f01106c3SAxel Dörfler }
540f01106c3SAxel Dörfler 
541f01106c3SAxel Dörfler 
542f01106c3SAxel Dörfler void
543f01106c3SAxel Dörfler NetworkStatusView::_AboutRequested()
544f01106c3SAxel Dörfler {
545*5fe97f21SAxel Dörfler 	BString about = B_TRANSLATE(
546757e7059SAdrien Destugues 		"NetworkStatus\n\twritten by %1 and Hugo Santos\n\t%2, Haiku, Inc.\n"
547757e7059SAdrien Destugues 		);
548*5fe97f21SAxel Dörfler 	about.ReplaceFirst("%1", "Axel Dörfler");
549757e7059SAdrien Destugues 		// Append a new developer here
550*5fe97f21SAxel Dörfler 	about.ReplaceFirst("%2", "Copyright 2007-2010");
551757e7059SAdrien Destugues 		// Append a new year here
552*5fe97f21SAxel Dörfler 	BAlert* alert = new BAlert("about", about, B_TRANSLATE("OK"));
553f01106c3SAxel Dörfler 	BTextView *view = alert->TextView();
554f01106c3SAxel Dörfler 	BFont font;
555f01106c3SAxel Dörfler 
556f01106c3SAxel Dörfler 	view->SetStylable(true);
557f01106c3SAxel Dörfler 
558f01106c3SAxel Dörfler 	view->GetFont(&font);
559f01106c3SAxel Dörfler 	font.SetSize(18);
560f01106c3SAxel Dörfler 	font.SetFace(B_BOLD_FACE);
561f01106c3SAxel Dörfler 	view->SetFontAndColor(0, 13, &font);
562f01106c3SAxel Dörfler 
563f01106c3SAxel Dörfler 	alert->Go();
564f01106c3SAxel Dörfler }
565f01106c3SAxel Dörfler 
566f01106c3SAxel Dörfler 
567f01106c3SAxel Dörfler bool
568f01106c3SAxel Dörfler NetworkStatusView::_PrepareRequest(struct ifreq& request, const char* name)
569f01106c3SAxel Dörfler {
570f01106c3SAxel Dörfler 	if (strlen(name) > IF_NAMESIZE)
571f01106c3SAxel Dörfler 		return false;
572f01106c3SAxel Dörfler 
573f01106c3SAxel Dörfler 	strcpy(request.ifr_name, name);
574f01106c3SAxel Dörfler 	return true;
575f01106c3SAxel Dörfler }
576f01106c3SAxel Dörfler 
577f01106c3SAxel Dörfler 
578f01106c3SAxel Dörfler int32
579f01106c3SAxel Dörfler NetworkStatusView::_DetermineInterfaceStatus(const char* name)
580f01106c3SAxel Dörfler {
581*5fe97f21SAxel Dörfler 	BNetworkInterface interface(name);
582*5fe97f21SAxel Dörfler 	uint32 flags = interface.Flags();
583f01106c3SAxel Dörfler 	int32 status = kStatusNoLink;
584f01106c3SAxel Dörfler 
585f01106c3SAxel Dörfler 	// TODO: no kStatusLinkNoConfig yet
586f01106c3SAxel Dörfler 
587f01106c3SAxel Dörfler 	if (flags & IFF_CONFIGURING)
588f01106c3SAxel Dörfler 		status = kStatusConnecting;
5892a17be44SAxel Dörfler 	else if ((flags & (IFF_UP | IFF_LINK)) == (IFF_UP | IFF_LINK))
590f01106c3SAxel Dörfler 		status = kStatusReady;
591f01106c3SAxel Dörfler 
592f01106c3SAxel Dörfler 	return status;
593f01106c3SAxel Dörfler }
594f01106c3SAxel Dörfler 
595f01106c3SAxel Dörfler 
596f01106c3SAxel Dörfler void
597f01106c3SAxel Dörfler NetworkStatusView::_Update(bool force)
598f01106c3SAxel Dörfler {
599f01106c3SAxel Dörfler 	int32 oldStatus = fStatus;
600f01106c3SAxel Dörfler 	fStatus = kStatusUnknown;
601f01106c3SAxel Dörfler 	fInterfaces.MakeEmpty();
602f01106c3SAxel Dörfler 
603*5fe97f21SAxel Dörfler 	BNetworkRoster& roster = BNetworkRoster::Default();
604*5fe97f21SAxel Dörfler 	BNetworkInterface interface;
605*5fe97f21SAxel Dörfler 	uint32 cookie = 0;
606*5fe97f21SAxel Dörfler 
607*5fe97f21SAxel Dörfler 	while (roster.GetNextInterface(&cookie, interface) == B_OK) {
608*5fe97f21SAxel Dörfler 		if ((interface.Flags() & IFF_LOOPBACK) == 0) {
609*5fe97f21SAxel Dörfler 			fInterfaces.AddItem(new BString(interface.Name()));
610*5fe97f21SAxel Dörfler 			int32 status = _DetermineInterfaceStatus(interface.Name());
611f01106c3SAxel Dörfler 			if (status > fStatus)
612f01106c3SAxel Dörfler 				fStatus = status;
613f01106c3SAxel Dörfler 		}
614f01106c3SAxel Dörfler 	}
615f01106c3SAxel Dörfler 
616f01106c3SAxel Dörfler 	if (fStatus != oldStatus)
617f01106c3SAxel Dörfler 		Invalidate();
618f01106c3SAxel Dörfler }
619f01106c3SAxel Dörfler 
620f01106c3SAxel Dörfler 
6213b41ad86SStephan Aßmus void
6223b41ad86SStephan Aßmus NetworkStatusView::_OpenNetworksPreferences()
6233b41ad86SStephan Aßmus {
624195981bbSAxel Dörfler 	status_t status = be_roster->Launch("application/x-vnd.Haiku-Network");
62546cac7f7SAlexandre Deckner 	if (status != B_OK && status != B_ALREADY_RUNNING) {
626757e7059SAdrien Destugues 		BString errorMessage(B_TRANSLATE("Launching the network preflet "
627757e7059SAdrien Destugues 			"failed.\n\nError: "));
628195981bbSAxel Dörfler 		errorMessage << strerror(status);
6293b41ad86SStephan Aßmus 		BAlert* alert = new BAlert("launch error", errorMessage.String(),
630757e7059SAdrien Destugues 			B_TRANSLATE("OK"));
631195981bbSAxel Dörfler 
632195981bbSAxel Dörfler 		// asynchronous alert in order to not block replicant host application
6333b41ad86SStephan Aßmus 		alert->Go(NULL);
6343b41ad86SStephan Aßmus 	}
6353b41ad86SStephan Aßmus }
6363b41ad86SStephan Aßmus 
6373b41ad86SStephan Aßmus 
638f01106c3SAxel Dörfler //	#pragma mark -
639f01106c3SAxel Dörfler 
640f01106c3SAxel Dörfler 
641f01106c3SAxel Dörfler extern "C" _EXPORT BView *
642f01106c3SAxel Dörfler instantiate_deskbar_item(void)
643f01106c3SAxel Dörfler {
64466eba86fSAxel Dörfler 	return new NetworkStatusView(BRect(0, 0, 15, 15),
64566eba86fSAxel Dörfler 		B_FOLLOW_LEFT | B_FOLLOW_TOP, true);
646f01106c3SAxel Dörfler }
647f01106c3SAxel Dörfler 
648