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