Merge "Correctly time out CMD_START_DHCP." into mnc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ef2ccf5f4b
@@ -110,6 +110,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
private static final int CMD_KICK = BASE + 1;
|
private static final int CMD_KICK = BASE + 1;
|
||||||
private static final int CMD_RECEIVED_PACKET = BASE + 2;
|
private static final int CMD_RECEIVED_PACKET = BASE + 2;
|
||||||
private static final int CMD_TIMEOUT = BASE + 3;
|
private static final int CMD_TIMEOUT = BASE + 3;
|
||||||
|
private static final int CMD_ONESHOT_TIMEOUT = BASE + 4;
|
||||||
|
|
||||||
// DHCP parameters that we request.
|
// DHCP parameters that we request.
|
||||||
private static final byte[] REQUESTED_PARAMS = new byte[] {
|
private static final byte[] REQUESTED_PARAMS = new byte[] {
|
||||||
@@ -147,6 +148,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
private final PendingIntent mKickIntent;
|
private final PendingIntent mKickIntent;
|
||||||
private final PendingIntent mTimeoutIntent;
|
private final PendingIntent mTimeoutIntent;
|
||||||
private final PendingIntent mRenewIntent;
|
private final PendingIntent mRenewIntent;
|
||||||
|
private final PendingIntent mOneshotTimeoutIntent;
|
||||||
private final String mIfaceName;
|
private final String mIfaceName;
|
||||||
|
|
||||||
private boolean mRegisteredForPreDhcpNotification;
|
private boolean mRegisteredForPreDhcpNotification;
|
||||||
@@ -203,9 +205,17 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
|
|
||||||
mRandom = new Random();
|
mRandom = new Random();
|
||||||
|
|
||||||
|
// Used to schedule packet retransmissions.
|
||||||
mKickIntent = createStateMachineCommandIntent("KICK", CMD_KICK);
|
mKickIntent = createStateMachineCommandIntent("KICK", CMD_KICK);
|
||||||
|
// Used to time out PacketRetransmittingStates.
|
||||||
mTimeoutIntent = createStateMachineCommandIntent("TIMEOUT", CMD_TIMEOUT);
|
mTimeoutIntent = createStateMachineCommandIntent("TIMEOUT", CMD_TIMEOUT);
|
||||||
|
// Used to schedule DHCP renews.
|
||||||
mRenewIntent = createStateMachineCommandIntent("RENEW", DhcpStateMachine.CMD_RENEW_DHCP);
|
mRenewIntent = createStateMachineCommandIntent("RENEW", DhcpStateMachine.CMD_RENEW_DHCP);
|
||||||
|
// Used to tell the caller when its request (CMD_START_DHCP or CMD_RENEW_DHCP) timed out.
|
||||||
|
// TODO: when the legacy DHCP client is gone, make the client fully asynchronous and
|
||||||
|
// remove this.
|
||||||
|
mOneshotTimeoutIntent = createStateMachineCommandIntent("ONESHOT_TIMEOUT",
|
||||||
|
CMD_ONESHOT_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -471,6 +481,8 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
return "CMD_RECEIVED_PACKET";
|
return "CMD_RECEIVED_PACKET";
|
||||||
case CMD_TIMEOUT:
|
case CMD_TIMEOUT:
|
||||||
return "CMD_TIMEOUT";
|
return "CMD_TIMEOUT";
|
||||||
|
case CMD_ONESHOT_TIMEOUT:
|
||||||
|
return "CMD_ONESHOT_TIMEOUT";
|
||||||
default:
|
default:
|
||||||
return Integer.toString(what);
|
return Integer.toString(what);
|
||||||
}
|
}
|
||||||
@@ -520,12 +532,34 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The one-shot timeout is used to implement the timeout for CMD_START_DHCP. We can't use a
|
||||||
|
// state timeout to do this because obtaining an IP address involves passing through more than
|
||||||
|
// one state (specifically, it passes at least once through DhcpInitState and once through
|
||||||
|
// DhcpRequestingState). The one-shot timeout is created when CMD_START_DHCP is received, and is
|
||||||
|
// cancelled when exiting DhcpState (either due to a CMD_STOP_DHCP, or because of an error), or
|
||||||
|
// when we get an IP address (when entering DhcpBoundState). If it fires, we send ourselves
|
||||||
|
// CMD_ONESHOT_TIMEOUT and notify the caller that DHCP failed, but we take no other action. For
|
||||||
|
// example, if we're in DhcpInitState and sending DISCOVERs, we continue to do so.
|
||||||
|
//
|
||||||
|
// The one-shot timeout is not used for CMD_RENEW_DHCP because that is implemented using only
|
||||||
|
// one state, so we can just use the state timeout.
|
||||||
|
private void scheduleOneshotTimeout() {
|
||||||
|
final long alarmTime = SystemClock.elapsedRealtime() + DHCP_TIMEOUT_MS;
|
||||||
|
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime,
|
||||||
|
mOneshotTimeoutIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelOneshotTimeout() {
|
||||||
|
mAlarmManager.cancel(mOneshotTimeoutIntent);
|
||||||
|
}
|
||||||
|
|
||||||
class StoppedState extends LoggingState {
|
class StoppedState extends LoggingState {
|
||||||
@Override
|
@Override
|
||||||
public boolean processMessage(Message message) {
|
public boolean processMessage(Message message) {
|
||||||
super.processMessage(message);
|
super.processMessage(message);
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
case DhcpStateMachine.CMD_START_DHCP:
|
case DhcpStateMachine.CMD_START_DHCP:
|
||||||
|
scheduleOneshotTimeout();
|
||||||
if (mRegisteredForPreDhcpNotification) {
|
if (mRegisteredForPreDhcpNotification) {
|
||||||
transitionTo(mWaitBeforeStartState);
|
transitionTo(mWaitBeforeStartState);
|
||||||
} else {
|
} else {
|
||||||
@@ -568,6 +602,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exit() {
|
public void exit() {
|
||||||
|
cancelOneshotTimeout();
|
||||||
mReceiveThread.halt(); // Also closes sockets.
|
mReceiveThread.halt(); // Also closes sockets.
|
||||||
clearDhcpState();
|
clearDhcpState();
|
||||||
}
|
}
|
||||||
@@ -579,6 +614,10 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
case DhcpStateMachine.CMD_STOP_DHCP:
|
case DhcpStateMachine.CMD_STOP_DHCP:
|
||||||
transitionTo(mStoppedState);
|
transitionTo(mStoppedState);
|
||||||
return HANDLED;
|
return HANDLED;
|
||||||
|
case CMD_ONESHOT_TIMEOUT:
|
||||||
|
maybeLog("Timed out");
|
||||||
|
notifyFailure();
|
||||||
|
return HANDLED;
|
||||||
default:
|
default:
|
||||||
return NOT_HANDLED;
|
return NOT_HANDLED;
|
||||||
}
|
}
|
||||||
@@ -616,8 +655,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
*
|
*
|
||||||
* Concrete subclasses must implement sendPacket, which is called when the alarm fires and a
|
* Concrete subclasses must implement sendPacket, which is called when the alarm fires and a
|
||||||
* packet needs to be transmitted, and receivePacket, which is triggered by CMD_RECEIVED_PACKET
|
* packet needs to be transmitted, and receivePacket, which is triggered by CMD_RECEIVED_PACKET
|
||||||
* sent by the receive thread. They may also set mTimeout and if desired override the default
|
* sent by the receive thread. They may also set mTimeout and implement timeout.
|
||||||
* timeout implementation.
|
|
||||||
*/
|
*/
|
||||||
abstract class PacketRetransmittingState extends LoggingState {
|
abstract class PacketRetransmittingState extends LoggingState {
|
||||||
|
|
||||||
@@ -658,19 +696,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
|
|
||||||
abstract protected boolean sendPacket();
|
abstract protected boolean sendPacket();
|
||||||
abstract protected void receivePacket(DhcpPacket packet);
|
abstract protected void receivePacket(DhcpPacket packet);
|
||||||
|
protected void timeout() {}
|
||||||
// Default implementation of timeout. This is only invoked if mTimeout > 0, so it will never
|
|
||||||
// be called if the subclass does not set a timeout.
|
|
||||||
protected void timeout() {
|
|
||||||
maybeLog("Timeout in " + getName());
|
|
||||||
notifyFailure();
|
|
||||||
if (this != mDhcpInitState) {
|
|
||||||
// Only transition to INIT if we're not already there. Otherwise, we'll exit the
|
|
||||||
// state and re-enter it, which will reset the packet transmission interval, re-set
|
|
||||||
// the timeout, etc.
|
|
||||||
transitionTo(mDhcpInitState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void initTimer() {
|
protected void initTimer() {
|
||||||
mTimer = FIRST_TIMEOUT_MS;
|
mTimer = FIRST_TIMEOUT_MS;
|
||||||
@@ -706,7 +732,6 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
class DhcpInitState extends PacketRetransmittingState {
|
class DhcpInitState extends PacketRetransmittingState {
|
||||||
public DhcpInitState() {
|
public DhcpInitState() {
|
||||||
super();
|
super();
|
||||||
mTimeout = DHCP_TIMEOUT_MS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -765,13 +790,22 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
transitionTo(mDhcpInitState);
|
transitionTo(mDhcpInitState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void timeout() {
|
||||||
|
// After sending REQUESTs unsuccessfully for a while, go back to init.
|
||||||
|
transitionTo(mDhcpInitState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DhcpHaveAddressState extends LoggingState {
|
class DhcpHaveAddressState extends LoggingState {
|
||||||
@Override
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
super.enter();
|
super.enter();
|
||||||
if (!setIpAddress(mDhcpLease.ipAddress)) {
|
if (setIpAddress(mDhcpLease.ipAddress)) {
|
||||||
|
maybeLog("Configured IP address " + mDhcpLease.ipAddress);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Failed to configure IP address " + mDhcpLease.ipAddress);
|
||||||
notifyFailure();
|
notifyFailure();
|
||||||
// There's likely no point in going into DhcpInitState here, we'll probably just
|
// There's likely no point in going into DhcpInitState here, we'll probably just
|
||||||
// repeat the transaction, get the same IP address as before, and fail.
|
// repeat the transaction, get the same IP address as before, and fail.
|
||||||
@@ -781,6 +815,7 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exit() {
|
public void exit() {
|
||||||
|
maybeLog("Clearing IP address");
|
||||||
setIpAddress(new LinkAddress("0.0.0.0/0"));
|
setIpAddress(new LinkAddress("0.0.0.0/0"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -789,9 +824,10 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
@Override
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
super.enter();
|
super.enter();
|
||||||
|
cancelOneshotTimeout();
|
||||||
notifySuccess();
|
notifySuccess();
|
||||||
// TODO: DhcpStateMachine only supports renewing at 50% of the lease time, and does not
|
// TODO: DhcpStateMachine only supports renewing at 50% of the lease time, and does not
|
||||||
// support rebinding. Fix this.
|
// support rebinding. Once the legacy DHCP client is gone, fix this.
|
||||||
scheduleRenew();
|
scheduleRenew();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -841,6 +877,12 @@ public class DhcpClient extends BaseDhcpStateMachine {
|
|||||||
transitionTo(mDhcpInitState);
|
transitionTo(mDhcpInitState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void timeout() {
|
||||||
|
transitionTo(mDhcpInitState);
|
||||||
|
sendMessage(CMD_ONESHOT_TIMEOUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not implemented. DhcpStateMachine does not implement it either.
|
// Not implemented. DhcpStateMachine does not implement it either.
|
||||||
|
|||||||
Reference in New Issue
Block a user