content: /*
   * Copyright (C) 2012 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package android.net;
  
  import android.annotation.UnsupportedAppUsage;
  import android.net.shared.InetAddressUtils;
  import android.os.Parcel;
  import android.os.Parcelable;
  import android.text.TextUtils;
  import android.util.Log;
  
  import java.net.Inet4Address;
  import java.net.InetAddress;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Objects;
  
  /**
   * A simple object for retrieving the results of a DHCP request.
   * Optimized (attempted) for that jni interface
   * TODO: remove this class and replace with other existing constructs
   * @hide
   */
  public final class DhcpResults implements Parcelable {
      private static final String TAG = "DhcpResults";
  
      @UnsupportedAppUsage
      public LinkAddress ipAddress;
  
      @UnsupportedAppUsage
      public InetAddress gateway;
  
      @UnsupportedAppUsage
      public final ArrayList<InetAddress> dnsServers = new ArrayList<>();
  
      @UnsupportedAppUsage
      public String domains;
  
      @UnsupportedAppUsage
      public Inet4Address serverAddress;
  
      /** Vendor specific information (from RFC 2132). */
      @UnsupportedAppUsage
      public String vendorInfo;
  
      @UnsupportedAppUsage
      public int leaseDuration;
  
      /** Link MTU option. 0 means unset. */
      @UnsupportedAppUsage
      public int mtu;
  
      public String serverHostName;
  
      public DhcpResults() {
          super();
      }
  
      /**
       * Create a {@link StaticIpConfiguration} based on the DhcpResults.
       */
      public StaticIpConfiguration toStaticIpConfiguration() {
          return new StaticIpConfiguration.Builder()
                  .setIpAddress(ipAddress)
                  .setGateway(gateway)
                  .setDnsServers(dnsServers)
                  .setDomains(domains)
                  .build();
      }
  
      public DhcpResults(StaticIpConfiguration source) {
          if (source != null) {
              ipAddress = source.getIpAddress();
              gateway = source.getGateway();
              dnsServers.addAll(source.getDnsServers());
              domains = source.getDomains();
          }
      }
  
      /** copy constructor */
      public DhcpResults(DhcpResults source) {
          this(source == null ? null : source.toStaticIpConfiguration());
          if (source != null) {
              serverAddress = source.serverAddress;
              vendorInfo = source.vendorInfo;
              leaseDuration = source.leaseDuration;
              mtu = source.mtu;
              serverHostName = source.serverHostName;
          }
      }
  
      /**
       * @see StaticIpConfiguration#getRoutes(String)
       * @hide
       */
      public List<RouteInfo> getRoutes(String iface) {
          return toStaticIpConfiguration().getRoutes(iface);
      }
  
      /**
       * Test if this DHCP lease includes vendor hint that network link is
       * metered, and sensitive to heavy data transfers.
       */
      public boolean hasMeteredHint() {
          if (vendorInfo != null) {
              return vendorInfo.contains("ANDROID_METERED");
          } else {
              return false;
          }
      }
  
      public void clear() {
          ipAddress = null;
          gateway = null;
          dnsServers.clear();
          domains = null;
          serverAddress = null;
          vendorInfo = null;
          leaseDuration = 0;
          mtu = 0;
          serverHostName = null;
      }
  
      @Override
      public String toString() {
          StringBuffer str = new StringBuffer(super.toString());
  
          str.append(" DHCP server ").append(serverAddress);
          str.append(" Vendor info ").append(vendorInfo);
          str.append(" lease ").append(leaseDuration).append(" seconds");
          if (mtu != 0) str.append(" MTU ").append(mtu);
          str.append(" Servername ").append(serverHostName);
  
          return str.toString();
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj) return true;
  
          if (!(obj instanceof DhcpResults)) return false;
  
          DhcpResults target = (DhcpResults)obj;
  
          return toStaticIpConfiguration().equals(target.toStaticIpConfiguration())
                  && Objects.equals(serverAddress, target.serverAddress)
                  && Objects.equals(vendorInfo, target.vendorInfo)
                  && Objects.equals(serverHostName, target.serverHostName)
                  && leaseDuration == target.leaseDuration
                  && mtu == target.mtu;
      }
  
      /**
       * Implement the Parcelable interface
       */
      public static final @android.annotation.NonNull Creator<DhcpResults> CREATOR =
          new Creator<DhcpResults>() {
              public DhcpResults createFromParcel(Parcel in) {
                  return readFromParcel(in);
              }
  
              public DhcpResults[] newArray(int size) {
                  return new DhcpResults[size];
              }
          };
  
      /** Implement the Parcelable interface */
      public void writeToParcel(Parcel dest, int flags) {
          toStaticIpConfiguration().writeToParcel(dest, flags);
          dest.writeInt(leaseDuration);
          dest.writeInt(mtu);
          InetAddressUtils.parcelInetAddress(dest, serverAddress, flags);
          dest.writeString(vendorInfo);
          dest.writeString(serverHostName);
      }
  
      @Override
      public int describeContents() {
          return 0;
      }
  
      private static DhcpResults readFromParcel(Parcel in) {
          final StaticIpConfiguration s = StaticIpConfiguration.CREATOR.createFromParcel(in);
          final DhcpResults dhcpResults = new DhcpResults(s);
          dhcpResults.leaseDuration = in.readInt();
          dhcpResults.mtu = in.readInt();
          dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in);
          dhcpResults.vendorInfo = in.readString();
          dhcpResults.serverHostName = in.readString();
          return dhcpResults;
      }
  
      // Utils for jni population - false on success
      // Not part of the superclass because they're only used by the JNI iterface to the DHCP daemon.
      public boolean setIpAddress(String addrString, int prefixLength) {
          try {
              Inet4Address addr = (Inet4Address) InetAddresses.parseNumericAddress(addrString);
              ipAddress = new LinkAddress(addr, prefixLength);
          } catch (IllegalArgumentException|ClassCastException e) {
              Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength);
              return true;
          }
          return false;
      }
  
      public boolean setGateway(String addrString) {
          try {
              gateway = InetAddresses.parseNumericAddress(addrString);
          } catch (IllegalArgumentException e) {
              Log.e(TAG, "setGateway failed with addrString " + addrString);
              return true;
          }
          return false;
      }
  
      public boolean addDns(String addrString) {
          if (TextUtils.isEmpty(addrString) == false) {
              try {
                  dnsServers.add(InetAddresses.parseNumericAddress(addrString));
              } catch (IllegalArgumentException e) {
                  Log.e(TAG, "addDns failed with addrString " + addrString);
                  return true;
              }
          }
          return false;
      }
  
      public LinkAddress getIpAddress() {
          return ipAddress;
      }
  
      public void setIpAddress(LinkAddress ipAddress) {
          this.ipAddress = ipAddress;
      }
  
      public InetAddress getGateway() {
          return gateway;
      }
  
      public void setGateway(InetAddress gateway) {
          this.gateway = gateway;
      }
  
      public List<InetAddress> getDnsServers() {
          return dnsServers;
      }
  
      /**
       * Add a DNS server to this configuration.
       */
      public void addDnsServer(InetAddress server) {
          dnsServers.add(server);
      }
  
      public String getDomains() {
          return domains;
      }
  
      public void setDomains(String domains) {
          this.domains = domains;
      }
  
      public Inet4Address getServerAddress() {
          return serverAddress;
      }
  
      public void setServerAddress(Inet4Address addr) {
          serverAddress = addr;
      }
  
      public int getLeaseDuration() {
          return leaseDuration;
      }
  
      public void setLeaseDuration(int duration) {
          leaseDuration = duration;
      }
  
      public String getVendorInfo() {
          return vendorInfo;
      }
  
      public void setVendorInfo(String info) {
          vendorInfo = info;
      }
  
      public int getMtu() {
          return mtu;
      }
  
      public void setMtu(int mtu) {
          this.mtu = mtu;
      }
  }
  