diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2020-02-18 00:47:21 +0900 |
---|---|---|
committer | Lorenzo Colitti <lorenzo@google.com> | 2020-02-18 10:49:59 +0900 |
commit | b4af853264c8d0083491e35b2e157355bf8919bd (patch) | |
tree | 175f96b1e33b7fe92e52ab6246415fa45b8dbab8 /src/android/net/dhcp/DhcpLeaseRepository.java | |
parent | 886e641f32fd6487fe3cecdf1c8f9a056237e030 (diff) |
Revert "Revert "Add DhcpLeaseCallbacks""
This reverts commit e8fff42022f8c22e84d51bc093189d469bdd9af1.
Bug: 135411507
Test: atest NetworkStackTests
Change-Id: I0609301d7b37309a35c764a7551b0ca93b3faeee
Diffstat (limited to 'src/android/net/dhcp/DhcpLeaseRepository.java')
-rw-r--r-- | src/android/net/dhcp/DhcpLeaseRepository.java | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/src/android/net/dhcp/DhcpLeaseRepository.java b/src/android/net/dhcp/DhcpLeaseRepository.java index 4e74dc8..1dc2f7f 100644 --- a/src/android/net/dhcp/DhcpLeaseRepository.java +++ b/src/android/net/dhcp/DhcpLeaseRepository.java @@ -31,6 +31,8 @@ import android.net.IpPrefix; import android.net.MacAddress; import android.net.dhcp.DhcpServer.Clock; import android.net.util.SharedLog; +import android.os.RemoteCallbackList; +import android.os.RemoteException; import android.util.ArrayMap; import androidx.annotation.NonNull; @@ -45,6 +47,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Set; import java.util.function.Function; @@ -73,6 +76,7 @@ class DhcpLeaseRepository { @NonNull private Set<Inet4Address> mReservedAddrs; private int mSubnetAddr; + private int mPrefixLength; private int mSubnetMask; private int mNumAddresses; private long mLeaseTimeMs; @@ -84,6 +88,9 @@ class DhcpLeaseRepository { */ private long mNextExpirationCheck = EXPIRATION_NEVER; + @NonNull + private RemoteCallbackList<IDhcpLeaseCallbacks> mLeaseCallbacks = new RemoteCallbackList<>(); + static class DhcpLeaseException extends Exception { DhcpLeaseException(String message) { super(message); @@ -131,27 +138,34 @@ class DhcpLeaseRepository { long leaseTimeMs) { mPrefix = prefix; mReservedAddrs = Collections.unmodifiableSet(new HashSet<>(reservedAddrs)); - mSubnetMask = prefixLengthToV4NetmaskIntHTH(prefix.getPrefixLength()); + mPrefixLength = prefix.getPrefixLength(); + mSubnetMask = prefixLengthToV4NetmaskIntHTH(mPrefixLength); mSubnetAddr = inet4AddressToIntHTH((Inet4Address) prefix.getAddress()) & mSubnetMask; mNumAddresses = 1 << (IPV4_ADDR_BITS - prefix.getPrefixLength()); mLeaseTimeMs = leaseTimeMs; - cleanMap(mCommittedLeases); cleanMap(mDeclinedAddrs); + if (cleanMap(mCommittedLeases)) { + notifyLeasesChanged(); + } } /** * From a map keyed by {@link Inet4Address}, remove entries where the key is invalid (as * specified by {@link #isValidAddress(Inet4Address)}), or is a reserved address. + * @return true iff at least one entry was removed. */ - private <T> void cleanMap(Map<Inet4Address, T> map) { + private <T> boolean cleanMap(Map<Inet4Address, T> map) { final Iterator<Entry<Inet4Address, T>> it = map.entrySet().iterator(); + boolean removed = false; while (it.hasNext()) { final Inet4Address addr = it.next().getKey(); if (!isValidAddress(addr) || mReservedAddrs.contains(addr)) { it.remove(); + removed = true; } } + return removed; } /** @@ -181,7 +195,7 @@ class DhcpLeaseRepository { mLog.log("Offering extended lease " + newLease); // Do not update lease time in the map: the offer is not committed yet. } else if (reqAddr != null && isValidAddress(reqAddr) && isAvailable(reqAddr)) { - newLease = new DhcpLease(clientId, hwAddr, reqAddr, expTime, hostname); + newLease = new DhcpLease(clientId, hwAddr, reqAddr, mPrefixLength, expTime, hostname); mLog.log("Offering requested lease " + newLease); } else { newLease = makeNewOffer(clientId, hwAddr, expTime, hostname); @@ -267,7 +281,8 @@ class DhcpLeaseRepository { if (assignedLease != null) { if (sidSet && reqAddr != null) { // Client in SELECTING state; remove any current lease before creating a new one. - mCommittedLeases.remove(assignedLease.getNetAddr()); + // Do not notify of change as it will be done when the new lease is committed. + removeLease(assignedLease.getNetAddr(), false /* notifyChange */); } else if (!assignedLease.getNetAddr().equals(leaseAddr)) { // reqAddr null (RENEWING/REBINDING): client renewing its own lease for clientAddr. // reqAddr set with sid not set (INIT-REBOOT): client verifying configuration. @@ -314,7 +329,7 @@ class DhcpLeaseRepository { final DhcpLease lease; if (currentLease == null) { if (isValidAddress(addr) && !mReservedAddrs.contains(addr)) { - lease = new DhcpLease(clientId, hwAddr, addr, expTime, hostname); + lease = new DhcpLease(clientId, hwAddr, addr, mPrefixLength, expTime, hostname); } else { throw new InvalidAddressException("Lease not found and address unavailable"); } @@ -328,6 +343,13 @@ class DhcpLeaseRepository { private void commitLease(@NonNull DhcpLease lease) { mCommittedLeases.put(lease.getNetAddr(), lease); maybeUpdateEarliestExpiration(lease.getExpTime()); + notifyLeasesChanged(); + } + + private void removeLease(@NonNull Inet4Address address, boolean notifyChange) { + // Earliest expiration remains <= the first expiry time on remove, so no need to update it. + mCommittedLeases.remove(address); + if (notifyChange) notifyLeasesChanged(); } /** @@ -343,8 +365,8 @@ class DhcpLeaseRepository { return false; } if (currentLease.matchesClient(clientId, hwAddr)) { - mCommittedLeases.remove(addr); mLog.log("Released lease " + currentLease); + removeLease(addr, true /* notifyChange */); return true; } mLog.w(String.format("Not releasing lease %s: does not match client (cid %s, hwAddr %s)", @@ -352,6 +374,24 @@ class DhcpLeaseRepository { return false; } + private void notifyLeasesChanged() { + final List<DhcpLeaseParcelable> leaseParcelables = + new ArrayList<>(mCommittedLeases.size()); + for (DhcpLease committedLease : mCommittedLeases.values()) { + leaseParcelables.add(committedLease.toParcelable()); + } + + final int cbCount = mLeaseCallbacks.beginBroadcast(); + for (int i = 0; i < cbCount; i++) { + try { + mLeaseCallbacks.getBroadcastItem(i).onLeasesChanged(leaseParcelables); + } catch (RemoteException e) { + mLog.e("Could not send lease callback", e); + } + } + mLeaseCallbacks.finishBroadcast(); + } + public void markLeaseDeclined(@NonNull Inet4Address addr) { if (mDeclinedAddrs.containsKey(addr) || !isValidAddress(addr)) { mLog.logf("Not marking %s as declined: already declined or not assignable", @@ -383,6 +423,14 @@ class DhcpLeaseRepository { } /** + * Add callbacks that will be called on leases update. + */ + public void addLeaseCallbacks(@NonNull IDhcpLeaseCallbacks cb) { + Objects.requireNonNull(cb, "Callbacks must be non-null"); + mLeaseCallbacks.register(cb); + } + + /** * Given the expiration time of a new committed lease or declined address, update * {@link #mNextExpirationCheck} so it stays lower than or equal to the time for the first lease * to expire. @@ -541,7 +589,7 @@ class DhcpLeaseRepository { for (int i = 0; i < mNumAddresses; i++) { final Inet4Address addr = intToInet4AddressHTH(intAddr); if (isAvailable(addr) && !mDeclinedAddrs.containsKey(addr)) { - return new DhcpLease(clientId, hwAddr, addr, expTime, hostname); + return new DhcpLease(clientId, hwAddr, addr, mPrefixLength, expTime, hostname); } intAddr = getNextAddress(intAddr); } @@ -557,7 +605,7 @@ class DhcpLeaseRepository { // However declined addresses may have been requested (typically by the machine that was // already using the address) after being declined. if (isAvailable(addr)) { - return new DhcpLease(clientId, hwAddr, addr, expTime, hostname); + return new DhcpLease(clientId, hwAddr, addr, mPrefixLength, expTime, hostname); } } |