Avoid deadlock.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41278 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin
2011-04-23 01:52:16 +00:00
parent 302a7082ba
commit 9ff5266f3a
4 changed files with 82 additions and 47 deletions
+8 -10
View File
@@ -58,21 +58,19 @@ AutoconfigLooper::_RemoveClient()
void void
AutoconfigLooper::_Configure() AutoconfigLooper::_Configure()
{ {
// start with DHCP
if (fCurrentClient == NULL) {
fCurrentClient = new DHCPClient(fTarget, fDevice.String());
AddHandler(fCurrentClient);
}
// set IFF_CONFIGURING flag on interface // set IFF_CONFIGURING flag on interface
BNetworkInterface interface(fDevice.String()); BNetworkInterface interface(fDevice.String());
int32 flags = interface.Flags() & ~IFF_AUTO_CONFIGURED; int32 flags = interface.Flags() & ~IFF_AUTO_CONFIGURED;
interface.SetFlags(flags | IFF_CONFIGURING); interface.SetFlags(flags | IFF_CONFIGURING);
// remove current handler
_RemoveClient();
// start with DHCP
fCurrentClient = new DHCPClient(fTarget, fDevice.String());
AddHandler(fCurrentClient);
if (fCurrentClient->Initialize() == B_OK) if (fCurrentClient->Initialize() == B_OK)
return; return;
@@ -91,7 +89,7 @@ AutoconfigLooper::_Configure()
BMessage message(kMsgConfigureInterface); BMessage message(kMsgConfigureInterface);
message.AddString("device", fDevice.String()); message.AddString("device", fDevice.String());
message.AddBool("auto", true); message.AddBool("auto_configured", true);
BNetworkAddress link; BNetworkAddress link;
uint8 last = 56; uint8 last = 56;
+63 -27
View File
@@ -422,6 +422,7 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
fConfiguration(kMsgConfigureInterface), fConfiguration(kMsgConfigureInterface),
fResolverConfiguration(kMsgConfigureResolver), fResolverConfiguration(kMsgConfigureResolver),
fRunner(NULL), fRunner(NULL),
fAssignedAddress(0),
fServer(AF_INET, NULL, DHCP_SERVER_PORT), fServer(AF_INET, NULL, DHCP_SERVER_PORT),
fLeaseTime(0) fLeaseTime(0)
{ {
@@ -436,6 +437,18 @@ DHCPClient::DHCPClient(BMessenger target, const char* device)
memcpy(fMAC, link.LinkLevelAddress(), sizeof(fMAC)); memcpy(fMAC, link.LinkLevelAddress(), sizeof(fMAC));
if ((interface.Flags() & IFF_AUTO_CONFIGURED) != 0) {
// Check for interface previous auto-configured address, if any.
BNetworkInterfaceAddress interfaceAddress;
int index = interface.FindFirstAddress(AF_INET);
if (index >= 0
&& interface.GetAddressAt(index, interfaceAddress) == B_OK) {
BNetworkAddress address = interfaceAddress.Address();
const sockaddr_in& addr = (sockaddr_in&)address.SockAddr();
fAssignedAddress = addr.sin_addr.s_addr;
}
}
openlog_thread("DHCP", 0, LOG_DAEMON); openlog_thread("DHCP", 0, LOG_DAEMON);
} }
@@ -466,8 +479,8 @@ DHCPClient::~DHCPClient()
status_t status_t
DHCPClient::Initialize() DHCPClient::Initialize()
{ {
fStatus = _Negotiate(INIT); fStatus = _Negotiate(fAssignedAddress == 0 ? INIT : INIT_REBOOT);
syslog(LOG_DEBUG, "DHCP for %s, status: %s\n", Device(), strerror(fStatus)); syslog(LOG_DEBUG, "%s: DHCP status = %s\n", Device(), strerror(fStatus));
return fStatus; return fStatus;
} }
@@ -527,13 +540,15 @@ DHCPClient::_Negotiate(dhcp_state state)
// send discover/request message // send discover/request message
_SendMessage(socket, state == INIT ? discover : request, _SendMessage(socket, state == INIT ? discover : request,
state != RENEWAL ? broadcast : fServer); state != RENEWING ? broadcast : fServer);
// no need to check the status; in case of an error we'll just send // no need to check the status; in case of an error we'll just send
// the message again // the message again
// receive loop until we've got an offer and acknowledged it // receive loop until we've got an offer and acknowledged it
while (state != ACKNOWLEDGED) { while (state != BOUND) {
printf("DHCPClient::_Negotiate(%d)\n", (int)state);
char buffer[2048]; char buffer[2048];
struct sockaddr_in from; struct sockaddr_in from;
socklen_t fromLength = sizeof(from); socklen_t fromLength = sizeof(from);
@@ -546,12 +561,8 @@ DHCPClient::_Negotiate(dhcp_state state)
return B_TIMED_OUT; return B_TIMED_OUT;
} }
if (state == INIT) _SendMessage(socket, state == INIT ? discover : request,
_SendMessage(socket, discover, broadcast); state != RENEWING ? broadcast : fServer);
else {
_SendMessage(socket, request,
state != RENEWAL ? broadcast : fServer);
}
continue; continue;
} else if (bytesReceived < 0) } else if (bytesReceived < 0)
@@ -566,9 +577,15 @@ DHCPClient::_Negotiate(dhcp_state state)
continue; continue;
} }
syslog(LOG_DEBUG, "Received %s from %s for %s\n", // advance from startup state
dhcp_message::TypeToString(message->Type()), if (state == INIT)
_AddressToString(from.sin_addr.s_addr).String(), Device()); state = SELECTING;
else if (state == INIT_REBOOT)
state = REBOOTING;
syslog(LOG_DEBUG, "%s: Received %s from %s\n",
Device(), dhcp_message::TypeToString(message->Type()),
_AddressToString(from.sin_addr.s_addr).String());
switch (message->Type()) { switch (message->Type()) {
case DHCP_NONE: case DHCP_NONE:
@@ -579,7 +596,7 @@ DHCPClient::_Negotiate(dhcp_state state)
case DHCP_OFFER: case DHCP_OFFER:
{ {
// first offer wins // first offer wins
if (state != INIT) if (state != SELECTING)
break; break;
// collect interface options // collect interface options
@@ -590,7 +607,7 @@ DHCPClient::_Negotiate(dhcp_state state)
fConfiguration.MakeEmpty(); fConfiguration.MakeEmpty();
fConfiguration.AddString("device", Device()); fConfiguration.AddString("device", Device());
fConfiguration.AddBool("auto", true); fConfiguration.AddBool("auto_configured", true);
BMessage address; BMessage address;
address.AddString("family", "inet"); address.AddString("family", "inet");
@@ -614,8 +631,10 @@ DHCPClient::_Negotiate(dhcp_state state)
case DHCP_ACK: case DHCP_ACK:
{ {
if (state != REQUESTING && state != REBINDING if (state != REQUESTING
&& state != RENEWAL) && state != REBOOTING
&& state != REBINDING
&& state != RENEWING)
continue; continue;
// TODO: we might want to configure the stuff, don't we? // TODO: we might want to configure the stuff, don't we?
@@ -626,7 +645,7 @@ DHCPClient::_Negotiate(dhcp_state state)
// way // way
// our address request has been acknowledged // our address request has been acknowledged
state = ACKNOWLEDGED; state = BOUND;
// configure interface // configure interface
BMessage reply; BMessage reply;
@@ -644,9 +663,18 @@ DHCPClient::_Negotiate(dhcp_state state)
} }
case DHCP_NACK: case DHCP_NACK:
if (state != REQUESTING) if (state != REQUESTING
&& state != REBOOTING
&& state != REBINDING
&& state != RENEWING)
continue; continue;
if (state == REBOOTING) {
// server reject our request on previous assigned address
// back to square one...
fAssignedAddress = 0;
}
// try again (maybe we should prefer other servers if this // try again (maybe we should prefer other servers if this
// happens more than once) // happens more than once)
status = _SendMessage(socket, discover, broadcast); status = _SendMessage(socket, discover, broadcast);
@@ -819,7 +847,8 @@ DHCPClient::_PrepareMessage(dhcp_message& message, dhcp_state state)
(uint32)server.sin_addr.s_addr); (uint32)server.sin_addr.s_addr);
} }
if (state == INIT || state == REQUESTING) { if (state == INIT || state == INIT_REBOOT
|| state == REQUESTING) {
next = message.PutOption(next, OPTION_REQUEST_IP_ADDRESS, next = message.PutOption(next, OPTION_REQUEST_IP_ADDRESS,
(uint32)fAssignedAddress); (uint32)fAssignedAddress);
} else } else
@@ -866,7 +895,7 @@ DHCPClient::_TimeoutShift(int socket, time_t& timeout, uint32& tries)
if (++tries > 2) if (++tries > 2)
return false; return false;
} }
syslog(LOG_DEBUG, "Timeout shift for %s: %lu secs (try %lu)\n", syslog(LOG_DEBUG, "%s: Timeout shift: %lu secs (try %lu)\n",
Device(), timeout, tries); Device(), timeout, tries);
struct timeval value; struct timeval value;
@@ -898,9 +927,16 @@ status_t
DHCPClient::_SendMessage(int socket, dhcp_message& message, DHCPClient::_SendMessage(int socket, dhcp_message& message,
const BNetworkAddress& address) const const BNetworkAddress& address) const
{ {
syslog(LOG_DEBUG, "Send %s to %s on %s\n", message_type type = message.Type();
dhcp_message::TypeToString(message.Type()), BString text;
address.ToString().String(), Device()); text << dhcp_message::TypeToString(type);
const uint8* requestAddress = message.FindOption(OPTION_REQUEST_IP_ADDRESS);
if (type == DHCP_REQUEST && requestAddress != NULL)
text << " for " << _AddressToString(requestAddress).String();
syslog(LOG_DEBUG, "%s: Send %s to %s\n", Device(), text.String(),
address.ToString().String());
ssize_t bytesSent = sendto(socket, &message, message.Size(), ssize_t bytesSent = sendto(socket, &message, message.Size(),
address.IsBroadcast() ? MSG_BCAST : 0, address, address.Length()); address.IsBroadcast() ? MSG_BCAST : 0, address, address.Length());
@@ -921,7 +957,7 @@ DHCPClient::_CurrentState() const
if (now >= fRebindingTime) if (now >= fRebindingTime)
return REBINDING; return REBINDING;
if (now >= fRenewalTime) if (now >= fRenewalTime)
return RENEWAL; return RENEWING;
return BOUND; return BOUND;
} }
@@ -938,7 +974,7 @@ DHCPClient::MessageReceived(BMessage* message)
bigtime_t next; bigtime_t next;
if (_Negotiate(state) == B_OK) { if (_Negotiate(state) == B_OK) {
switch (state) { switch (state) {
case RENEWAL: case RENEWING:
next = fRebindingTime; next = fRebindingTime;
break; break;
case REBINDING: case REBINDING:
@@ -948,7 +984,7 @@ DHCPClient::MessageReceived(BMessage* message)
} }
} else { } else {
switch (state) { switch (state) {
case RENEWAL: case RENEWING:
next = (fLeaseTime - fRebindingTime) / 4 + system_time(); next = (fLeaseTime - fRebindingTime) / 4 + system_time();
break; break;
case REBINDING: case REBINDING:
+6 -4
View File
@@ -22,11 +22,13 @@ class dhcp_message;
enum dhcp_state { enum dhcp_state {
INIT, INIT,
SELECTING,
INIT_REBOOT,
REBOOTING,
REQUESTING, REQUESTING,
BOUND, BOUND,
RENEWAL, RENEWING,
REBINDING, REBINDING,
ACKNOWLEDGED,
}; };
@@ -55,9 +57,9 @@ private:
bool _TimeoutShift(int socket, time_t& timeout, bool _TimeoutShift(int socket, time_t& timeout,
uint32& tries); uint32& tries);
void _RestartLease(bigtime_t lease); void _RestartLease(bigtime_t lease);
static BString _AddressToString(const uint8* data); static BString _AddressToString(const uint8* data);
static BString _AddressToString(in_addr_t address); static BString _AddressToString(in_addr_t address);
private: private:
BMessage fConfiguration; BMessage fConfiguration;
+5 -6
View File
@@ -533,12 +533,10 @@ NetServer::_ConfigureInterface(BMessage& message)
parse_address(family, string, broadcast); parse_address(family, string, broadcast);
} }
if (!autoConfigured || autoConfig) if (autoConfig) {
_QuitLooperForDevice(name); _QuitLooperForDevice(name);
startAutoConfig = true;
startAutoConfig = autoConfig; } else if (addressMessage.FindString("gateway", &string) == B_OK
if (addressMessage.FindString("gateway", &string) == B_OK
&& parse_address(family, string, gateway)) { && parse_address(family, string, gateway)) {
// add gateway route, if we're asked for it // add gateway route, if we're asked for it
interface.RemoveDefaultRoute(family); interface.RemoveDefaultRoute(family);
@@ -611,7 +609,8 @@ NetServer::_ConfigureInterface(BMessage& message)
looper->Run(); looper->Run();
fDeviceMap[name] = looper; fDeviceMap[name] = looper;
} } else if (!autoConfigured)
_QuitLooperForDevice(name);
return B_OK; return B_OK;
} }