* Moved the network status replicant into its own application, similar to what
ProcessController and PowerStatus are doing. * Currently polls for info only - later, the stack should support listeners for interface related changes. * Also works under BONE (although it doesn't make much sense to use it there). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20655 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -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 ;
|
||||
|
||||
@@ -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
|
||||
;
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "NetworkStatus.h"
|
||||
#include "NetworkStatusWindow.h"
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Deskbar.h>
|
||||
#include <Entry.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef NETWORK_STATUS_H
|
||||
#define NETWORK_STATUS_H
|
||||
|
||||
|
||||
#include <image.h>
|
||||
|
||||
|
||||
extern const char* kSignature;
|
||||
extern const char* kDeskbarItemName;
|
||||
|
||||
status_t our_image(image_info& image);
|
||||
|
||||
#endif // NETWORK_STATUS_H
|
||||
@@ -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
|
||||
@@ -0,0 +1,469 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
* Hugo Santos, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "NetworkStatusView.h"
|
||||
|
||||
#include "NetworkStatus.h"
|
||||
#include "NetworkStatusIcons.h"
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Deskbar.h>
|
||||
#include <Dragger.h>
|
||||
#include <Drivers.h>
|
||||
#include <IconUtils.h>
|
||||
#include <MenuItem.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <Resources.h>
|
||||
#include <String.h>
|
||||
#include <TextView.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef NETWORK_STATUS_VIEW_H
|
||||
#define NETWORK_STATUS_VIEW_H
|
||||
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <View.h>
|
||||
|
||||
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<BString> fInterfaces;
|
||||
bool fInDeskbar;
|
||||
BBitmap* fBitmaps[kStatusCount];
|
||||
int32 fStatus;
|
||||
int fSocket;
|
||||
};
|
||||
|
||||
#endif // NETWORK_STATUS_VIEW_H
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include "NetworkStatusWindow.h"
|
||||
#include "NetworkStatusView.h"
|
||||
|
||||
#include <Application.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
#ifndef NETWORK_STATUS_WINDOW_H
|
||||
#define NETWORK_STATUS_WINDOW_H
|
||||
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
|
||||
class NetworkStatusWindow : public BWindow {
|
||||
public:
|
||||
NetworkStatusWindow();
|
||||
virtual ~NetworkStatusWindow();
|
||||
|
||||
virtual bool QuitRequested();
|
||||
};
|
||||
|
||||
#endif // NETWORK_STATUS_WINDOW_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:
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
+16
-130
@@ -11,7 +11,6 @@
|
||||
#include "NetServer.h"
|
||||
#include "Services.h"
|
||||
#include "Settings.h"
|
||||
#include "StatusReplicant.h"
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Deskbar.h>
|
||||
@@ -39,12 +38,10 @@
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
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<std::string, BLooper*> LooperMap;
|
||||
typedef std::map<std::string, int> 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 -
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <IconUtils.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Message.h>
|
||||
#include <Messenger.h>
|
||||
#include <Resources.h>
|
||||
#include <TextView.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -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 <PopUpMenu.h>
|
||||
#include <View.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
||||
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<std::string, int> InterfaceStatus;
|
||||
typedef std::vector<InterfaceStatus> 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
|
||||
Reference in New Issue
Block a user