diff --git a/src/apps/Jamfile b/src/apps/Jamfile index ebd6fb4d25..db2cee9766 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -17,6 +17,7 @@ SubInclude HAIKU_TOP src apps magnify ; SubInclude HAIKU_TOP src apps mail ; SubInclude HAIKU_TOP src apps mediaplayer ; SubInclude HAIKU_TOP src apps midiplayer ; +SubInclude HAIKU_TOP src apps networkstatus ; SubInclude HAIKU_TOP src apps people ; SubInclude HAIKU_TOP src apps poorman ; SubInclude HAIKU_TOP src apps powerstatus ; diff --git a/src/apps/networkstatus/Jamfile b/src/apps/networkstatus/Jamfile new file mode 100644 index 0000000000..b0fb960fa7 --- /dev/null +++ b/src/apps/networkstatus/Jamfile @@ -0,0 +1,19 @@ +SubDir HAIKU_TOP src apps networkstatus ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders shared ; +UseLibraryHeaders agg icon ; + +local icon_libs ; +if $(TARGET) != haiku { + icon_libs = libicon.a libagg.a ; +} + +Application NetworkStatus : + NetworkStatusWindow.cpp + NetworkStatusView.cpp + NetworkStatus.cpp + : be $(icon_libs) $(NETWORK_LIBS) + : NetworkStatus.rdef NetworkStatusIcons.rdef + ; diff --git a/src/apps/networkstatus/NetworkStatus.cpp b/src/apps/networkstatus/NetworkStatus.cpp new file mode 100644 index 0000000000..f02d011a4e --- /dev/null +++ b/src/apps/networkstatus/NetworkStatus.cpp @@ -0,0 +1,135 @@ +/* + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "NetworkStatus.h" +#include "NetworkStatusWindow.h" + +#include +#include +#include +#include + +#include +#include +#include + + +class NetworkStatus : public BApplication { + public: + NetworkStatus(); + virtual ~NetworkStatus(); + + virtual void ReadyToRun(); + virtual void AboutRequested(); +}; + + +const char* kSignature = "application/x-vnd.Haiku-NetworkStatus"; +const char* kDeskbarSignature = "application/x-vnd.Be-TSKB"; +const char* kDeskbarItemName = "NetworkStatus"; + + +status_t +our_image(image_info& image) +{ + int32 cookie = 0; + while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) { + if ((char *)our_image >= (char *)image.text + && (char *)our_image <= (char *)image.text + image.text_size) + return B_OK; + } + + return B_ERROR; +} + + +// #pragma mark - + + +NetworkStatus::NetworkStatus() + : BApplication(kSignature) +{ +} + + +NetworkStatus::~NetworkStatus() +{ +} + + +void +NetworkStatus::ReadyToRun() +{ + bool isInstalled = false; + bool isDeskbarRunning = true; + + { + // if the Deskbar is not alive at this point, it might be after having + // acknowledged the requester below + BDeskbar deskbar; +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + isDeskbarRunning = deskbar.IsRunning(); +#endif + isInstalled = deskbar.HasItem(kDeskbarItemName); + } + + if (isDeskbarRunning && !isInstalled) { + BAlert* alert = new BAlert("", "Do you want NetworkStatus to live in the Deskbar?", + "Don't", "Install", NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); + alert->SetShortcut(0, B_ESCAPE); + + if (alert->Go()) { + image_info info; + entry_ref ref; + + if (our_image(info) == B_OK + && get_ref_for_path(info.name, &ref) == B_OK) { + BDeskbar deskbar; + deskbar.AddItem(&ref); + } + + Quit(); + return; + } + } + + BWindow* window = new NetworkStatusWindow(); + window->Show(); +} + + +void +NetworkStatus::AboutRequested() +{ + BWindow* window = WindowAt(0); + if (window == NULL) + return; + + BView* view = window->FindView(kDeskbarItemName); + if (view == NULL) + return; + + BMessenger target((BHandler*)view); + BMessage about(B_ABOUT_REQUESTED); + target.SendMessage(&about); +} + + +// #pragma mark - + + +int +main(int, char**) +{ + NetworkStatus app; + app.Run(); + + return 0; +} + diff --git a/src/apps/networkstatus/NetworkStatus.h b/src/apps/networkstatus/NetworkStatus.h new file mode 100644 index 0000000000..739358256b --- /dev/null +++ b/src/apps/networkstatus/NetworkStatus.h @@ -0,0 +1,20 @@ +/* + * Copyright 2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef NETWORK_STATUS_H +#define NETWORK_STATUS_H + + +#include + + +extern const char* kSignature; +extern const char* kDeskbarItemName; + +status_t our_image(image_info& image); + +#endif // NETWORK_STATUS_H diff --git a/src/apps/networkstatus/NetworkStatus.rdef b/src/apps/networkstatus/NetworkStatus.rdef new file mode 100644 index 0000000000..2f18682c9f --- /dev/null +++ b/src/apps/networkstatus/NetworkStatus.rdef @@ -0,0 +1,42 @@ + +resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.Haiku-NetworkStatus"; + +resource app_flags B_SINGLE_LAUNCH; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + + variety = B_APPV_DEVELOPMENT, + internal = 0, + + short_info = "NetworkStatus", + long_info = "NetworkStatus ©2007 Haiku" +}; + +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + +resource vector_icon { + $"6E63696608050005B8020016023A692E36692FBA2ECD3E2ECD4B89A449631800" + $"5CFF8305E7020106023C00000000000000003C00004680004680000029B6FFFF" + $"035492020106023C00000000000000003C0000468000468000009FF699FF049A" + $"4304016E020006023959B6382F60BA2F603B59B647C1424B11D30056FF22FF05" + $"D0050C0A044C60516060505C4E02043334BD6E34B7B534263926BBDC26BE0F33" + $"3EB7B53EBD6E3E403940BE0F40BBDC0A06513A5A3D5A504C5E425842440A044C" + $"484C5E425842440A04513A5A3D4C4842440A044C485A3D5A504C5E0404BE404A" + $"3246324A323E4236423C42323A3202042E22BB3722B5F022222E22B5F022BB37" + $"2E3AB5F03ABB373A3A2E3ABB373AB5F00608BFDBB506B560B506B560B443B639" + $"222E22B75822BAB3B718BD20B52EBC80B718BD20283628322A34263024302E28" + $"28282A2826060CA2EBAF2E28B98632263428302E302C303036323436BBB3BC32" + $"BBB3BC32BCB7BB523A2E3ABA063AB668B9EEB3FDBBE9B493B9EEB3FD2E243026" + $"0614BFDDAFABE82E22B90C22B72B22B506B560B5E6B468B506B5602828282628" + $"2A242E30283226302A3436B718BD20B718BD20B78FBD462E3AB80F3AB9C53ABB" + $"B3BC32BADCBCECBBB3BC3234363632302E3030302C34283226B953282E30262E" + $"24B9EEB3FDB9EEB3FDB980B3DD02042A50B84D50B5AA50B49756B497C732B497" + $"C9D52A5CB5AA5CB84D5C305630C9D530C732090A06020001000A000306020710" + $"01178400040A010103000A030104000A020105000A04010A000A05020809000A" + $"00010B1001178800040A07010B00" +}; + +#endif diff --git a/src/servers/net/NetworkStatusIcons.h b/src/apps/networkstatus/NetworkStatusIcons.h similarity index 100% rename from src/servers/net/NetworkStatusIcons.h rename to src/apps/networkstatus/NetworkStatusIcons.h diff --git a/src/servers/net/NetworkStatusIcons.rdef b/src/apps/networkstatus/NetworkStatusIcons.rdef similarity index 100% rename from src/servers/net/NetworkStatusIcons.rdef rename to src/apps/networkstatus/NetworkStatusIcons.rdef diff --git a/src/apps/networkstatus/NetworkStatusView.cpp b/src/apps/networkstatus/NetworkStatusView.cpp new file mode 100644 index 0000000000..c27b5be990 --- /dev/null +++ b/src/apps/networkstatus/NetworkStatusView.cpp @@ -0,0 +1,469 @@ +/* + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + * Hugo Santos, hugosantos@gmail.com + */ + + +#include "NetworkStatusView.h" + +#include "NetworkStatus.h" +#include "NetworkStatusIcons.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef HAIKU_TARGET_PLATFORM_HAIKU +// BONE compatibility +# define IF_NAMESIZE IFNAMSIZ +# define IFF_LINK 0 +# define IFF_CONFIGURING 0 +# define ifc_value ifc_val +#endif + +static const char *kStatusDescriptions[] = { + "Unknown", + "No Link", + "No stateful configuration", + "Configuring", + "Ready" +}; + +extern "C" _EXPORT BView *instantiate_deskbar_item(void); + + +const uint32 kMsgUpdate = 'updt'; +const uint32 kMsgShowConfiguration = 'shcf'; + +const uint32 kMinIconWidth = 16; +const uint32 kMinIconHeight = 16; + +const bigtime_t kUpdateInterval = 1000000; + // every second + + +NetworkStatusView::NetworkStatusView(BRect frame, int32 resizingMode, + bool inDeskbar) + : BView(frame, kDeskbarItemName, resizingMode, + B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE), + fInDeskbar(inDeskbar), + fStatus(kStatusUnknown) +{ + _Init(); + + if (!inDeskbar) { + // we were obviously added to a standard window - let's add a dragger + frame.OffsetTo(B_ORIGIN); + frame.top = frame.bottom - 7; + frame.left = frame.right - 7; + BDragger* dragger = new BDragger(frame, this, + B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + AddChild(dragger); + } else + _Update(); +} + + +NetworkStatusView::NetworkStatusView(BMessage* archive) + : BView(archive) +{ + _Init(); +} + + +NetworkStatusView::~NetworkStatusView() +{ +} + + +void +NetworkStatusView::_Init() +{ + fMessageRunner = NULL; + + for (int i = 0; i < kStatusCount; i++) { + fBitmaps[i] = NULL; + } + + _UpdateBitmaps(); +} + + +void +NetworkStatusView::_UpdateBitmaps() +{ + for (int i = 0; i < kStatusCount; i++) { + delete fBitmaps[i]; + fBitmaps[i] = NULL; + } + + image_info info; + if (our_image(info) != B_OK) + return; + + BFile file(info.name, B_READ_ONLY); + if (file.InitCheck() < B_OK) + return; + + BResources resources(&file); +#ifdef HAIKU_TARGET_PLATFORM_HAIKU + if (resources.InitCheck() < B_OK) + return; +#endif + + for (int i = 0; i < kStatusCount; i++) { + const void* data = NULL; + size_t size; + data = resources.LoadResource(B_VECTOR_ICON_TYPE, + kNetworkStatusNoDevice + i, &size); + if (data != NULL) { + BBitmap* icon = new BBitmap(Bounds(), B_RGB32); + if (icon->InitCheck() == B_OK + && BIconUtils::GetVectorIcon((const uint8 *)data, + size, icon) == B_OK) { + fBitmaps[i] = icon; + } else + delete icon; + } + } +} + + +void +NetworkStatusView::_Quit() +{ + if (fInDeskbar) { + BDeskbar deskbar; + deskbar.RemoveItem(kDeskbarItemName); + } else + be_app->PostMessage(B_QUIT_REQUESTED); +} + + +NetworkStatusView * +NetworkStatusView::Instantiate(BMessage* archive) +{ + if (!validate_instantiation(archive, "NetworkStatusView")) + return NULL; + + return new NetworkStatusView(archive); +} + + +status_t +NetworkStatusView::Archive(BMessage* archive, bool deep) const +{ + status_t status = BView::Archive(archive, deep); + if (status == B_OK) + status = archive->AddString("add_on", kSignature); + if (status == B_OK) + status = archive->AddString("class", "NetworkStatusView"); + + return status; +} + + +void +NetworkStatusView::AttachedToWindow() +{ + BView::AttachedToWindow(); + if (Parent()) + SetViewColor(Parent()->ViewColor()); + else + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + SetLowColor(ViewColor()); + + BMessage update(kMsgUpdate); + fMessageRunner = new BMessageRunner(this, &update, kUpdateInterval); + + fSocket = socket(AF_INET, SOCK_DGRAM, 0); + _Update(); +} + + +void +NetworkStatusView::DetachedFromWindow() +{ + delete fMessageRunner; + close(fSocket); +} + + +void +NetworkStatusView::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgUpdate: + _Update(); + break; + + case kMsgShowConfiguration: + _ShowConfiguration(message); + break; + + case B_ABOUT_REQUESTED: + _AboutRequested(); + break; + + case B_QUIT_REQUESTED: + _Quit(); + break; + + default: + BView::MessageReceived(message); + } +} + + +void +NetworkStatusView::FrameResized(float width, float height) +{ + _UpdateBitmaps(); +} + + +void +NetworkStatusView::Draw(BRect updateRect) +{ + if (fBitmaps[fStatus] == NULL) + return; + + SetDrawingMode(B_OP_ALPHA); + DrawBitmap(fBitmaps[fStatus]); + SetDrawingMode(B_OP_COPY); +} + + +void +NetworkStatusView::_ShowConfiguration(BMessage* message) +{ + static const struct information_entry { + const char *label; + int32 control; + } kInformationEntries[] = { + { "Address", SIOCGIFADDR }, + { "Broadcast", SIOCGIFBRDADDR }, + { "Netmask", SIOCGIFNETMASK }, + { NULL } + }; + + const char *name; + if (message->FindString("interface", &name) != B_OK) + return; + + ifreq request; + if (!_PrepareRequest(request, name)) + return; + + BString text = name; + text += " information:\n"; + size_t boldLength = text.Length(); + + for (int i = 0; kInformationEntries[i].label; i++) { + if (ioctl(fSocket, kInformationEntries[i].control, &request, + sizeof(request)) < 0) { + continue; + } + + char address[32]; + sockaddr_in* inetAddress = NULL; + switch (kInformationEntries[i].control) { + case SIOCGIFNETMASK: + inetAddress = (sockaddr_in*)&request.ifr_mask; + break; + default: + inetAddress = (sockaddr_in*)&request.ifr_addr; + break; + } + + if (inet_ntop(AF_INET, &inetAddress->sin_addr, address, + sizeof(address)) == NULL) { + return; + } + + text += "\n"; + text += kInformationEntries[i].label; + text += ": "; + text += address; + } + + BAlert* alert = new BAlert(name, text.String(), "Ok"); + BTextView* view = alert->TextView(); + BFont font; + + view->SetStylable(true); + view->GetFont(&font); + font.SetFace(B_BOLD_FACE); + view->SetFontAndColor(0, boldLength, &font); + + alert->Go(NULL); +} + + +void +NetworkStatusView::MouseDown(BPoint point) +{ + BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false); + menu->SetFont(be_plain_font); + + for (int32 i = 0; i < fInterfaces.CountItems(); i++) { + BString& name = *fInterfaces.ItemAt(i); + + BString label = name; + label += ": "; + label += kStatusDescriptions[ + _DetermineInterfaceStatus(name.String())]; + + BMessage* info = new BMessage(kMsgShowConfiguration); + info->AddString("interface", name.String()); + menu->AddItem(new BMenuItem(label.String(), info)); + } + + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("About" B_UTF8_ELLIPSIS, + new BMessage(B_ABOUT_REQUESTED))); + if (fInDeskbar) + menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED))); + menu->SetTargetForItems(this); + + ConvertToScreen(&point); + menu->Go(point, true, false, true); +} + + +void +NetworkStatusView::_AboutRequested() +{ + BAlert *alert = new BAlert("about", "NetworkStatus\n" + "\twritten by Axel Dörfler and Hugo Santos\n" + "\tCopyright 2007, Haiku, Inc.\n", "Ok"); + BTextView *view = alert->TextView(); + BFont font; + + view->SetStylable(true); + + view->GetFont(&font); + font.SetSize(18); + font.SetFace(B_BOLD_FACE); + view->SetFontAndColor(0, 13, &font); + + alert->Go(); +} + + +bool +NetworkStatusView::_PrepareRequest(struct ifreq& request, const char* name) +{ + if (strlen(name) > IF_NAMESIZE) + return false; + + strcpy(request.ifr_name, name); + return true; +} + + +int32 +NetworkStatusView::_DetermineInterfaceStatus(const char* name) +{ + ifreq request; + if (!_PrepareRequest(request, name)) + return kStatusUnknown; + + uint32 flags = 0; + if (ioctl(fSocket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) + flags = request.ifr_flags; + + int32 status = kStatusNoLink; + + // TODO: no kStatusLinkNoConfig yet + + if (flags & IFF_CONFIGURING) + status = kStatusConnecting; + else if (flags & (IFF_UP | IFF_LINK) == IFF_UP | IFF_LINK) + status = kStatusReady; + + return status; +} + + +void +NetworkStatusView::_Update(bool force) +{ + // iterate over all interfaces and retrieve minimal status + + ifconf config; + config.ifc_len = sizeof(config.ifc_value); + if (ioctl(fSocket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) + return; + + uint32 count = (uint32)config.ifc_value; + if (count == 0) + return; + + void *buffer = malloc(count * sizeof(struct ifreq)); + if (buffer == NULL) + return; + + config.ifc_len = count * sizeof(struct ifreq); + config.ifc_buf = buffer; + if (ioctl(fSocket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) + return; + + ifreq *interface = (ifreq *)buffer; + + int32 oldStatus = fStatus; + fStatus = kStatusUnknown; + fInterfaces.MakeEmpty(); + + for (uint32 i = 0; i < count; i++) { + if (strncmp(interface->ifr_name, "loop", 4) && interface->ifr_name[0]) { + fInterfaces.AddItem(new BString(interface->ifr_name)); + int32 status = _DetermineInterfaceStatus(interface->ifr_name); + if (status > fStatus) + fStatus = status; + } + + interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + + interface->ifr_addr.sa_len); + } + + free(buffer); + + if (fStatus != oldStatus) + Invalidate(); +} + + +// #pragma mark - + + +extern "C" _EXPORT BView * +instantiate_deskbar_item(void) +{ + return new NetworkStatusView(BRect(0, 0, 15, 15), B_FOLLOW_NONE, true); +} + diff --git a/src/apps/networkstatus/NetworkStatusView.h b/src/apps/networkstatus/NetworkStatusView.h new file mode 100644 index 0000000000..5cf2fc951d --- /dev/null +++ b/src/apps/networkstatus/NetworkStatusView.h @@ -0,0 +1,65 @@ +/* + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef NETWORK_STATUS_VIEW_H +#define NETWORK_STATUS_VIEW_H + + +#include +#include + +class BMessageRunner; + + +enum { + kStatusUnknown = 0, + kStatusNoLink, + kStatusLinkNoConfig, + kStatusConnecting, + kStatusReady, + + kStatusCount +}; + +class NetworkStatusView : public BView { + public: + NetworkStatusView(BRect frame, int32 resizingMode, + bool inDeskbar = false); + NetworkStatusView(BMessage* archive); + virtual ~NetworkStatusView(); + + static NetworkStatusView* Instantiate(BMessage* archive); + virtual status_t Archive(BMessage* archive, bool deep = true) const; + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + virtual void MessageReceived(BMessage* message); + virtual void FrameResized(float width, float height); + virtual void MouseDown(BPoint where); + virtual void Draw(BRect updateRect); + + private: + void _AboutRequested(); + void _Quit(); + void _Init(); + void _UpdateBitmaps(); + void _ShowConfiguration(BMessage* message); + bool _PrepareRequest(struct ifreq& request, + const char* name); + int32 _DetermineInterfaceStatus(const char* name); + void _Update(bool force = false); + + BMessageRunner* fMessageRunner; + BObjectList fInterfaces; + bool fInDeskbar; + BBitmap* fBitmaps[kStatusCount]; + int32 fStatus; + int fSocket; +}; + +#endif // NETWORK_STATUS_VIEW_H diff --git a/src/apps/networkstatus/NetworkStatusWindow.cpp b/src/apps/networkstatus/NetworkStatusWindow.cpp new file mode 100644 index 0000000000..e57056f19b --- /dev/null +++ b/src/apps/networkstatus/NetworkStatusWindow.cpp @@ -0,0 +1,41 @@ +/* + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "NetworkStatusWindow.h" +#include "NetworkStatusView.h" + +#include + + +NetworkStatusWindow::NetworkStatusWindow() + : BWindow(BRect(150, 150, 249, 249), "NetworkStatus", B_TITLED_WINDOW, + B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS) +{ + BView* topView = new BView(Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW); + topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(topView); + + SetSizeLimits(25, 265, 25, 265); + + topView->AddChild(new NetworkStatusView(Bounds().InsetByCopy(5, 5), + B_FOLLOW_ALL)); +} + + +NetworkStatusWindow::~NetworkStatusWindow() +{ +} + + +bool +NetworkStatusWindow::QuitRequested() +{ + be_app->PostMessage(B_QUIT_REQUESTED); + return true; +} diff --git a/src/apps/networkstatus/NetworkStatusWindow.h b/src/apps/networkstatus/NetworkStatusWindow.h new file mode 100644 index 0000000000..5b259d73fd --- /dev/null +++ b/src/apps/networkstatus/NetworkStatusWindow.h @@ -0,0 +1,23 @@ +/* + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ +#ifndef NETWORK_STATUS_WINDOW_H +#define NETWORK_STATUS_WINDOW_H + + +#include + + +class NetworkStatusWindow : public BWindow { + public: + NetworkStatusWindow(); + virtual ~NetworkStatusWindow(); + + virtual bool QuitRequested(); +}; + +#endif // NETWORK_STATUS_WINDOW_H diff --git a/src/servers/net/AutoconfigLooper.cpp b/src/servers/net/AutoconfigLooper.cpp index 0c4554fc9d..7bf3e8b20b 100644 --- a/src/servers/net/AutoconfigLooper.cpp +++ b/src/servers/net/AutoconfigLooper.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -40,10 +40,22 @@ AutoconfigLooper::~AutoconfigLooper() void AutoconfigLooper::_ReadyToRun() { - BMessage interface(kMsgConfigureInterface); - interface.AddString("device", fDevice.String()); - interface.AddInt32("net:status", kStatusPreparing); - fTarget.SendMessage(&interface); + ifreq request; + if (!prepare_request(request, fDevice.String())) + return; + + // set IFF_CONFIGURING flag on interface + + int socket = ::socket(AF_LINK, SOCK_DGRAM, 0); + if (socket < 0) + return; + + if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0) { + request.ifr_flags |= IFF_CONFIGURING; + ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)); + } + + close(socket); // start with DHCP @@ -62,7 +74,9 @@ AutoconfigLooper::_ReadyToRun() // TODO: have a look at zeroconf // TODO: this could also be done add-on based - interface.ReplaceInt32("net:status", kStatusLinkNoConfig); + BMessage interface(kMsgConfigureInterface); + interface.AddString("device", fDevice.String()); + interface.AddBool("auto", true); uint8 mac[6]; uint8 last = 56; diff --git a/src/servers/net/DHCPClient.cpp b/src/servers/net/DHCPClient.cpp index c5e92a3bf2..af7fb0a971 100644 --- a/src/servers/net/DHCPClient.cpp +++ b/src/servers/net/DHCPClient.cpp @@ -474,7 +474,7 @@ DHCPClient::_Negotiate(dhcp_state state) fConfiguration.MakeEmpty(); fConfiguration.AddString("device", fDevice.String()); - fConfiguration.AddInt32("net:status", kStatusConnected); + fConfiguration.AddBool("auto", true); BMessage address; address.AddString("family", "inet"); diff --git a/src/servers/net/Jamfile b/src/servers/net/Jamfile index 8223371bed..ddc948e077 100644 --- a/src/servers/net/Jamfile +++ b/src/servers/net/Jamfile @@ -1,13 +1,12 @@ SubDir HAIKU_TOP src servers net ; UsePrivateHeaders app net ; -UseLibraryHeaders icon ; #UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libppp headers ] ; #UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ; #UseHeaders [ FDirName $(HAIKU_TOP) src tests kits net DialUpPreflet ] ; -AddResources net_server : net_server.rdef NetworkStatusIcons.rdef ; +AddResources net_server : net_server.rdef ; Server net_server : NetServer.cpp @@ -15,7 +14,6 @@ Server net_server : AutoconfigLooper.cpp DHCPClient.cpp Services.cpp - StatusReplicant.cpp : be libnetwork.so $(TARGET_LIBSTDC++) # for PPP diff --git a/src/servers/net/NetServer.cpp b/src/servers/net/NetServer.cpp index 9b6ec6c468..de2b38d765 100644 --- a/src/servers/net/NetServer.cpp +++ b/src/servers/net/NetServer.cpp @@ -11,7 +11,6 @@ #include "NetServer.h" #include "Services.h" #include "Settings.h" -#include "StatusReplicant.h" #include #include @@ -39,12 +38,10 @@ #include -const char *kSignature = "application/x-vnd.haiku-net_server"; -static const char *kDeskbarSignature = "application/x-vnd.Be-TSKB"; +static const char *kSignature = "application/x-vnd.haiku-net_server"; typedef std::map LooperMap; -typedef std::map StatusMap; class NetServer : public BServer { @@ -69,15 +66,10 @@ class NetServer : public BServer { void _ConfigureInterfaces(int socket, BMessage* _missingDevice = NULL); void _BringUpInterfaces(); void _StartServices(); - status_t _AddStatusReplicant(bool force); - void _UpdateDeviceStatus(const char *device, int status); - void _UpdateReplicantStatus(); Settings fSettings; LooperMap fDeviceMap; - StatusMap fStatusMap; BMessenger fServices; - BMessenger fStatusMessenger; }; @@ -279,13 +271,6 @@ NetServer::ReadyToRun() fSettings.StartMonitoring(this); _BringUpInterfaces(); _StartServices(); - - // we have to wait for Deskbar to show up before - // adding the status replicant - be_roster->StartWatching(BMessenger(this), B_REQUEST_LAUNCHED); - // but possibly the Deskbar is already running - // so add immediatly - _AddStatusReplicant(true); } @@ -325,49 +310,18 @@ NetServer::MessageReceived(BMessage* message) break; } - status_t status = B_OK; - if (message->GetInfo("address", NULL) != B_NAME_NOT_FOUND) { - // we need a socket to talk to the networking stack - int socket = ::socket(AF_INET, SOCK_DGRAM, 0); - if (socket < 0) - break; + // we need a socket to talk to the networking stack + int socket = ::socket(AF_INET, SOCK_DGRAM, 0); + if (socket < 0) + break; - status = _ConfigureInterface(socket, *message, true); + status_t status = _ConfigureInterface(socket, *message, true); - BMessage reply(B_REPLY); - reply.AddInt32("status", status); - message->SendReply(&reply); + BMessage reply(B_REPLY); + reply.AddInt32("status", status); + message->SendReply(&reply); - close(socket); - } - - if (status == B_OK) { - const char *device; - int32 net_status; - if (message->FindInt32("net:status", &net_status) == B_OK && - message->FindString("device", &device) == B_OK) { - _UpdateDeviceStatus(device, net_status); - } - } - - break; - } - - case B_SOME_APP_LAUNCHED: - { - // check if Deskbar was launched - const char *signature; - if (message->FindString("be:signature", &signature) == B_OK) { - if (strcmp(signature, kDeskbarSignature) == 0) - _AddStatusReplicant(true); - } - break; - } - - case kRegisterStatusReplicant: - { - if (message->FindMessenger("messenger", &fStatusMessenger) == B_OK) - _UpdateReplicantStatus(); + close(socket); break; } @@ -544,7 +498,11 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface, bool fromMessage int32 flags; if (interface.FindInt32("flags", &flags) < B_OK) flags = IFF_UP; - + + bool autoConfigured; + if (interface.FindBool("auto", &autoConfigured) == B_OK && autoConfigured) + flags |= IFF_AUTO_CONFIGURED; + int32 mtu; if (interface.FindInt32("mtu", &mtu) < B_OK) mtu = -1; @@ -783,13 +741,6 @@ NetServer::_QuitLooperForDevice(const char* device) iterator->second->Quit(); fDeviceMap.erase(iterator); - - StatusMap::iterator it = fStatusMap.find(device); - if (it != fStatusMap.end()) { - fStatusMap.erase(it); - _UpdateReplicantStatus(); - } - return true; } @@ -873,8 +824,7 @@ NetServer::_ConfigureInterfaces(int socket, BMessage* _missingDevice) } } - if (_ConfigureInterface(socket, interface) == B_OK) - _UpdateDeviceStatus(device, kStatusConnected); + _ConfigureInterface(socket, interface); } } @@ -936,70 +886,6 @@ NetServer::_StartServices() } -status_t -NetServer::_AddStatusReplicant(bool force) -{ - BDeskbar deskbar; - status_t status; - - if (deskbar.HasItem(kStatusReplicant)) { - if (force) { - status = deskbar.RemoveItem(kStatusReplicant); - if (status != B_OK) - return status; - } else { - return B_OK; - } - } - - StatusReplicant *replicant = new StatusReplicant(); - status = deskbar.AddItem(replicant); - delete replicant; - - return status; -} - - -void -NetServer::_UpdateDeviceStatus(const char *device, int status) -{ - if (strcmp(device, "loop") == 0) - return; - - StatusMap::iterator it = fStatusMap.find(device); - if (it != fStatusMap.end() && it->second == status) - return; - - fStatusMap[device] = status; - _UpdateReplicantStatus(); -} - - -void -NetServer::_UpdateReplicantStatus() -{ - if (!fStatusMessenger.IsValid()) - return; - - int prevaling = kStatusUnknown; - - BMessage message(kStatusUpdate); - - for (StatusMap::iterator it = fStatusMap.begin(); - it != fStatusMap.end(); ++it) { - if (it->second > prevaling) - prevaling = it->second; - - message.AddString("interface:name", it->first.c_str()); - message.AddInt32("interface:status", it->second); - } - - message.AddInt32("net:status", prevaling); - - fStatusMessenger.SendMessage(&message); -} - - // #pragma mark - diff --git a/src/servers/net/NetServer.h b/src/servers/net/NetServer.h index f161fd8bc6..1dff4d8821 100644 --- a/src/servers/net/NetServer.h +++ b/src/servers/net/NetServer.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -15,17 +15,7 @@ static const uint32 kMsgConfigureInterface = 'COif'; -extern const char *kSignature; -enum { - kStatusUnknown = 0, - kStatusNoLink, - kStatusLinkNoConfig, - kStatusConnected, - kStatusPreparing, - - kStatusCount -}; extern bool get_family_index(const char* name, int32& familyIndex); extern int family_at_index(int32 index); diff --git a/src/servers/net/StatusReplicant.cpp b/src/servers/net/StatusReplicant.cpp deleted file mode 100644 index 3715c4d607..0000000000 --- a/src/servers/net/StatusReplicant.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright 2007, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Hugo Santos, hugosantos@gmail.com - */ - - -#include "StatusReplicant.h" - -#include "NetServer.h" -#include "NetworkStatusIcons.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -const char *kStatusReplicant = "NetStatusView"; -static const uint32 kShowConfiguration = 'shcf'; - -static const rgb_color kStatusColors[kStatusCount] = { - { 0, 0, 0 }, // Unknown - { 255, 0, 0 }, // NoLink - { 0, 0, 255 }, // LinkNoConfig - { 0, 255, 0 }, // Connected - { 255, 255, 0 }, // Preparing -}; - -struct information_entry { - const char *label; - int ioc; -}; - -static const information_entry kInformationEntries[] = { - { "Address", SIOCGIFADDR }, - { "Broadcast", SIOCGIFBRDADDR }, - { "Netmask", SIOCGIFNETMASK }, - { NULL } -}; - -static const char *kStatusDescriptions[] = { - "Unknown", - "No Link", - "No stateful configuration", - "Ready", - "Configuring", -}; - - -static status_t -our_image(image_info *image) -{ - int32 cookie = 0; - while (get_next_image_info(B_CURRENT_TEAM, &cookie, image) == B_OK) { - if ((char *)our_image >= (char *)image->text && - (char *)our_image <= (char *)image->text + image->text_size) - return B_OK; - } - - return B_ERROR; -} - - -// #pragma mark - - - -StatusReplicant::StatusReplicant() - : BView(BRect(0, 0, 15, 15), kStatusReplicant, B_FOLLOW_ALL, B_WILL_DRAW), - fPopUp("", false, false), - fStatus(kStatusUnknown) -{ - _Init(false); -} - - -StatusReplicant::StatusReplicant(BMessage *message) - : BView(message), - fPopUp("", false, false), - fStatus(kStatusUnknown) -{ - _Init(); -} - - -StatusReplicant::~StatusReplicant() -{ - for (int32 i = 0; i < kStatusCount; i++) { - delete fBitmaps[i]; - } -} - - -StatusReplicant * -StatusReplicant::Instantiate(BMessage *data) -{ - if (validate_instantiation(data, kStatusReplicant)) - return new StatusReplicant(data); - - return NULL; -} - - -status_t -StatusReplicant::Archive(BMessage *data, bool deep) const -{ - BView::Archive(data, deep); - data->AddString("add_on", kSignature); - data->AddString("class", kStatusReplicant); - return B_OK; -} - - -void -StatusReplicant::AttachedToWindow() -{ - BMessage message(kRegisterStatusReplicant); - message.AddMessenger("messenger", BMessenger(this)); - - if (BMessenger(kSignature).SendMessage(&message) != B_OK) { - // TODO: Remove myself from Deskbar - } - - _ChangeStatus(kStatusUnknown); - _PrepareMenu(InterfaceStatusList()); -} - - -void -StatusReplicant::MessageReceived(BMessage *message) -{ - switch (message->what) { - case kStatusUpdate: - _UpdateFromMessage(message); - break; - case kShowConfiguration: - _ShowConfiguration(message); - break; - - default: - BView::MessageReceived(message); - break; - } -} - - -void -StatusReplicant::Draw(BRect updateRect) -{ - if (fBitmaps[fStatus] == NULL) - return; - - SetDrawingMode(B_OP_ALPHA); - DrawBitmap(fBitmaps[fStatus]); - SetDrawingMode(B_OP_COPY); -} - - -void -StatusReplicant::MouseDown(BPoint point) -{ - uint32 buttons; - BPoint where; - - GetMouse(&where, &buttons, true); - where = ConvertToScreen(point); - - fPopUp.SetTargetForItems(this); - fPopUp.Go(where, true, true); -} - - -void -StatusReplicant::_Init(bool isReplicant) -{ - // Load status bitmaps from resources - - for (int i = 0; i < kStatusCount; i++) { - fBitmaps[i] = NULL; - } - - if (!isReplicant) - return; - - image_info info; - if (our_image(&info) != B_OK) - return; - - BFile file(info.name, B_READ_ONLY); - if (file.InitCheck() < B_OK) - return; - - BResources resources(&file); - if (resources.InitCheck() < B_OK) - return; - - for (int i = 0; i < kStatusCount; i++) { - const void* data = NULL; - size_t size; - data = resources.LoadResource(B_VECTOR_ICON_TYPE, - kNetworkStatusNoDevice + i, &size); - if (data != NULL) { - BBitmap* icon = new BBitmap(Bounds(), B_RGB32); - if (icon->InitCheck() == B_OK - && BIconUtils::GetVectorIcon((const uint8 *)data, - size, icon) == B_OK) { - fBitmaps[i] = icon; - } else - delete icon; - } - } -} - - -void -StatusReplicant::_UpdateFromMessage(BMessage *message) -{ - int32 newStatus; - if (message->FindInt32("net:status", &newStatus) != B_OK - || newStatus < 0 || newStatus >= kStatusCount) - return; - - InterfaceStatusList status; - int32 interfaceStatus; - - for (uint32 index = 0; message->FindInt32("interface:status", index, - &interfaceStatus) == B_OK; index++) { - if (interfaceStatus < 0 || interfaceStatus >= kStatusCount) - break; - - const char *name; - if (message->FindString("interface:name", index, &name) != B_OK) - break; - - status.push_back(InterfaceStatus(name, interfaceStatus)); - } - - _ChangeStatus(newStatus); - _PrepareMenu(status); -} - - -void -StatusReplicant::_ShowConfiguration(BMessage *message) -{ - const char *device; - if (message->FindString("interface:name", &device) != B_OK) - return; - - int32 status; - if (message->FindInt32("interface:status", &status) != B_OK) - return; - - if (status != kStatusConnected && status != kStatusLinkNoConfig) - return; - - if (strlen(device) > IF_NAMESIZE) - return; - - int sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) - return; - - ifreq request; - memset(&request, 0, sizeof(request)); - strcpy(request.ifr_name, device); - - std::string text = device; - text += " information:\n"; - size_t boldLength = text.size(); - - for (int i = 0; kInformationEntries[i].label; i++) { - if (ioctl(sock, kInformationEntries[i].ioc, &request, - sizeof(request)) < 0) { - close(sock); - return; - } - - char address[32]; - if (inet_ntop(AF_INET, &((sockaddr_in *)&request.ifr_addr)->sin_addr, - address, sizeof(address)) == NULL) { - close(sock); - return; - } - - text += "\n"; - text += kInformationEntries[i].label; - text += ": "; - text += address; - } - - close(sock); - - BAlert *info = new BAlert(device, text.c_str(), "Ok"); - BTextView *view = info->TextView(); - BFont font; - - view->SetStylable(true); - view->GetFont(&font); - font.SetSize(12); - font.SetFace(B_BOLD_FACE); - view->SetFontAndColor(0, boldLength, &font); - - info->Go(NULL); -} - - -void -StatusReplicant::_PrepareMenu(const InterfaceStatusList &status) -{ - fPopUp.RemoveItems(0, fPopUp.CountItems(), true); - - if (status.empty()) { - fPopUp.AddItem(new BMenuItem("No interfaces available.", NULL)); - fPopUp.ItemAt(0)->SetEnabled(false); - } else { - for (InterfaceStatusList::const_iterator i = status.begin(); - i != status.end(); ++i) { - std::string label = i->first; - label += ": "; - label += kStatusDescriptions[i->second]; - - BMessage *message = new BMessage(kShowConfiguration); - message->AddString("interface:name", i->first.c_str()); - message->AddInt32("interface:status", i->second); - - BMenuItem *item = new BMenuItem(label.c_str(), message); - if (i->second != kStatusConnected && - i->second != kStatusLinkNoConfig) - item->SetEnabled(false); - fPopUp.AddItem(item); - } - } -} - - -void -StatusReplicant::_ChangeStatus(int newStatus) -{ - if (fStatus == newStatus) - return; - - fStatus = newStatus; - - if (fBitmaps[newStatus]) - SetViewColor(Parent()->ViewColor()); - else - SetViewColor(kStatusColors[newStatus]); - - Invalidate(); -} diff --git a/src/servers/net/StatusReplicant.h b/src/servers/net/StatusReplicant.h deleted file mode 100644 index f7295ea9a9..0000000000 --- a/src/servers/net/StatusReplicant.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2007, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Hugo Santos, hugosantos@gmail.com - */ -#ifndef _STATUS_REPLICANT_H -#define _STATUS_REPLICANT_H - - -#include "NetServer.h" - -#include -#include - -#include -#include -#include - - -static const uint32 kRegisterStatusReplicant = 'rnsr'; -static const uint32 kStatusUpdate = 'stup'; -extern const char *kStatusReplicant; - - -class StatusReplicant : public BView { - public: - StatusReplicant(); - StatusReplicant(BMessage *archive); - virtual ~StatusReplicant(); - - static StatusReplicant *Instantiate(BMessage *archive); - virtual status_t Archive(BMessage *archive, bool deep) const; - - virtual void AttachedToWindow(); - virtual void MessageReceived(BMessage *message); - virtual void Draw(BRect updateRect); - virtual void MouseDown(BPoint point); - - private: - typedef std::pair InterfaceStatus; - typedef std::vector InterfaceStatusList; - - void _Init(bool isReplicant = true); - void _UpdateFromMessage(BMessage *message); - void _ShowConfiguration(BMessage *message); - void _PrepareMenu(const InterfaceStatusList &list); - void _ChangeStatus(int newStatus); - - BPopUpMenu fPopUp; - BBitmap* fBitmaps[kStatusCount]; - int32 fStatus; -}; - -#endif // _STATUS_REPLICANT_H