net_server: initial replicant version.
* Still picture-less and thus ugly. * It provides updated information on what the net_server is doing in terms of interface configuration. * It is also able to show simplistic address information for configured interfaces. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20523 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -40,6 +40,11 @@ AutoconfigLooper::~AutoconfigLooper()
|
||||
void
|
||||
AutoconfigLooper::_ReadyToRun()
|
||||
{
|
||||
BMessage interface(kMsgConfigureInterface);
|
||||
interface.AddString("device", fDevice.String());
|
||||
interface.AddInt32("net:status", kStatusPreparing);
|
||||
fTarget.SendMessage(&interface);
|
||||
|
||||
// start with DHCP
|
||||
|
||||
DHCPClient* client = new DHCPClient(fTarget, fDevice.String());
|
||||
@@ -57,8 +62,7 @@ AutoconfigLooper::_ReadyToRun()
|
||||
// TODO: have a look at zeroconf
|
||||
// TODO: this could also be done add-on based
|
||||
|
||||
BMessage interface;
|
||||
interface.AddString("device", fDevice.String());
|
||||
interface.ReplaceInt32("net:status", kStatusLinkNoConfig);
|
||||
|
||||
uint8 mac[6];
|
||||
uint8 last = 56;
|
||||
@@ -80,7 +84,7 @@ AutoconfigLooper::_ReadyToRun()
|
||||
address.AddString("gateway", "192.168.0.254");
|
||||
interface.AddMessage("address", &address);
|
||||
|
||||
fTarget.SendMessage(kMsgConfigureInterface, &interface);
|
||||
fTarget.SendMessage(&interface);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -474,6 +474,7 @@ DHCPClient::_Negotiate(dhcp_state state)
|
||||
|
||||
fConfiguration.MakeEmpty();
|
||||
fConfiguration.AddString("device", fDevice.String());
|
||||
fConfiguration.AddInt32("net:status", kStatusConnected);
|
||||
|
||||
BMessage address;
|
||||
address.AddString("family", "inet");
|
||||
|
||||
@@ -14,6 +14,7 @@ Server net_server :
|
||||
AutoconfigLooper.cpp
|
||||
DHCPClient.cpp
|
||||
Services.cpp
|
||||
StatusReplicant.cpp
|
||||
|
||||
: be libnetwork.so $(TARGET_LIBSTDC++)
|
||||
# for PPP
|
||||
|
||||
+129
-10
@@ -11,12 +11,15 @@
|
||||
#include "NetServer.h"
|
||||
#include "Services.h"
|
||||
#include "Settings.h"
|
||||
#include "StatusReplicant.h"
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Deskbar.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
#include <Roster.h>
|
||||
#include <Server.h>
|
||||
#include <TextView.h>
|
||||
|
||||
@@ -36,7 +39,12 @@
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
const char *kSignature = "application/x-vnd.haiku-net_server";
|
||||
static const char *kDeskbarSignature = "application/x-vnd.Be-TSKB";
|
||||
|
||||
|
||||
typedef std::map<std::string, BLooper*> LooperMap;
|
||||
typedef std::map<std::string, int> StatusMap;
|
||||
|
||||
|
||||
class NetServer : public BServer {
|
||||
@@ -61,10 +69,15 @@ 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;
|
||||
};
|
||||
|
||||
|
||||
@@ -236,7 +249,7 @@ get_mac_address(const char* device, uint8* address)
|
||||
|
||||
|
||||
NetServer::NetServer(status_t& error)
|
||||
: BServer("application/x-vnd.haiku-net_server", false, &error)
|
||||
: BServer(kSignature, false, &error)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -266,6 +279,13 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -305,18 +325,49 @@ NetServer::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
// we need a socket to talk to the networking stack
|
||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (socket < 0)
|
||||
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;
|
||||
|
||||
status_t status = _ConfigureInterface(socket, *message, true);
|
||||
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);
|
||||
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:
|
||||
{
|
||||
message->FindMessenger("messenger", &fStatusMessenger);
|
||||
_UpdateReplicantStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -732,6 +783,13 @@ 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;
|
||||
}
|
||||
|
||||
@@ -877,6 +935,67 @@ 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)
|
||||
{
|
||||
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("intf:name", it->first.c_str());
|
||||
message.AddInt32("intf:status", it->second);
|
||||
}
|
||||
|
||||
message.AddInt32("net:status", prevaling);
|
||||
|
||||
fStatusMessenger.SendMessage(&message);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,17 @@
|
||||
|
||||
|
||||
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);
|
||||
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Hugo Santos, hugosantos@gmail.com
|
||||
*/
|
||||
|
||||
#include "NetServer.h"
|
||||
#include "StatusReplicant.h"
|
||||
|
||||
#include <Alert.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Message.h>
|
||||
#include <Messenger.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 uint8 kStatusColors[kStatusCount][3] = {
|
||||
{ 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",
|
||||
};
|
||||
|
||||
|
||||
StatusReplicant::StatusReplicant()
|
||||
: BView(BRect(0, 0, 15, 15), kStatusReplicant, B_FOLLOW_ALL, 0),
|
||||
fPopup("", false, false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
StatusReplicant::StatusReplicant(BMessage *message)
|
||||
: BView(message), fPopup("", false, false)
|
||||
{
|
||||
// TODO: Load status bitmaps from resources
|
||||
for (int i = 0; i < kStatusCount; i++)
|
||||
fBitmaps[i] = NULL;
|
||||
}
|
||||
|
||||
|
||||
StatusReplicant::~StatusReplicant()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
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::MouseDown(BPoint point)
|
||||
{
|
||||
uint32 buttons;
|
||||
BPoint where;
|
||||
|
||||
GetMouse(&where, &buttons, true);
|
||||
where = ConvertToScreen(point);
|
||||
|
||||
fPopup.SetTargetForItems(this);
|
||||
fPopup.Go(where, true, true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusReplicant::UpdateFromMessage(BMessage *message)
|
||||
{
|
||||
int32 newStatus, intfStatus;
|
||||
|
||||
if (message->FindInt32("net:status", &newStatus) != B_OK
|
||||
|| newStatus < 0 || newStatus >= kStatusCount)
|
||||
return;
|
||||
|
||||
InterfaceStatusList status;
|
||||
int index = 0;
|
||||
while (message->FindInt32("intf:status", index, &intfStatus) == B_OK) {
|
||||
if (intfStatus < 0 || intfStatus >= kStatusCount)
|
||||
break;
|
||||
|
||||
const char *name;
|
||||
if (message->FindString("intf:name", index, &name) != B_OK)
|
||||
break;
|
||||
|
||||
status.push_back(InterfaceStatus(name, intfStatus));
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
ChangeStatus(newStatus);
|
||||
PrepareMenu(status);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StatusReplicant::ShowConfiguration(BMessage *message)
|
||||
{
|
||||
const char *device;
|
||||
if (message->FindString("intf:name", &device) != B_OK)
|
||||
return;
|
||||
|
||||
int32 status;
|
||||
if (message->FindInt32("intf:status", &status) != B_OK)
|
||||
return;
|
||||
|
||||
if (status != kStatusConnected && status != kStatusLinkNoConfig)
|
||||
return;
|
||||
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0)
|
||||
return;
|
||||
|
||||
if (strlen(device) > IF_NAMESIZE)
|
||||
return;
|
||||
|
||||
ifreq request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
strcpy(request.ifr_name, device);
|
||||
|
||||
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)
|
||||
{
|
||||
while (fPopup.RemoveItem((int32)0));
|
||||
|
||||
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("intf:name", i->first.c_str());
|
||||
message->AddInt32("intf: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 (fBitmaps[newStatus]) {
|
||||
SetViewColor(Parent()->ViewColor());
|
||||
SetViewBitmap(fBitmaps[newStatus]);
|
||||
} else {
|
||||
ClearViewBitmap();
|
||||
SetViewColor(kStatusColors[newStatus][0],
|
||||
kStatusColors[newStatus][1],
|
||||
kStatusColors[newStatus][2]);
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 *);
|
||||
virtual ~StatusReplicant();
|
||||
|
||||
static StatusReplicant *Instantiate(BMessage *);
|
||||
status_t Archive(BMessage *, bool deep) const;
|
||||
|
||||
void AttachedToWindow();
|
||||
void MessageReceived(BMessage *);
|
||||
|
||||
void MouseDown(BPoint point);
|
||||
|
||||
private:
|
||||
typedef std::pair<std::string, int> InterfaceStatus;
|
||||
typedef std::vector<InterfaceStatus> InterfaceStatusList;
|
||||
|
||||
void UpdateFromMessage(BMessage *);
|
||||
void ShowConfiguration(BMessage *);
|
||||
void PrepareMenu(const InterfaceStatusList &);
|
||||
void ChangeStatus(int newStatus);
|
||||
|
||||
BPopUpMenu fPopup;
|
||||
BBitmap *fBitmaps[kStatusCount];
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user