RouteInfo.java revision ab5baa1d5fbd433e4c391ea06d177aa6a6c1c736
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.net; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21 22import java.net.UnknownHostException; 23import java.net.InetAddress; 24import java.net.Inet4Address; 25import java.net.Inet6Address; 26 27import java.util.Collection; 28 29/** 30 * A simple container for route information. 31 * 32 * @hide 33 */ 34public class RouteInfo implements Parcelable { 35 /** 36 * The IP destination address for this route. 37 */ 38 private final LinkAddress mDestination; 39 40 /** 41 * The gateway address for this route. 42 */ 43 private final InetAddress mGateway; 44 45 private final boolean mIsDefault; 46 47 public RouteInfo(LinkAddress destination, InetAddress gateway) { 48 if (destination == null) { 49 if (gateway != null) { 50 if (gateway instanceof Inet4Address) { 51 destination = new LinkAddress(Inet4Address.ANY, 0); 52 } else { 53 destination = new LinkAddress(Inet6Address.ANY, 0); 54 } 55 } else { 56 // no destination, no gateway. invalid. 57 throw new RuntimeException("Invalid arguments passed in."); 58 } 59 } 60 if (gateway == null) { 61 if (destination.getAddress() instanceof Inet4Address) { 62 gateway = Inet4Address.ANY; 63 } else { 64 gateway = Inet6Address.ANY; 65 } 66 } 67 mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(), 68 destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength()); 69 mGateway = gateway; 70 mIsDefault = isDefault(); 71 } 72 73 public RouteInfo(InetAddress gateway) { 74 this(null, gateway); 75 } 76 77 public static RouteInfo makeHostRoute(InetAddress host) { 78 return makeHostRoute(host, null); 79 } 80 81 public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway) { 82 if (host == null) return null; 83 84 if (host instanceof Inet4Address) { 85 return new RouteInfo(new LinkAddress(host, 32), gateway); 86 } else { 87 return new RouteInfo(new LinkAddress(host, 128), gateway); 88 } 89 } 90 91 private boolean isDefault() { 92 boolean val = false; 93 if (mGateway != null) { 94 if (mGateway instanceof Inet4Address) { 95 val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0); 96 } else { 97 val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0); 98 } 99 } 100 return val; 101 } 102 103 public LinkAddress getDestination() { 104 return mDestination; 105 } 106 107 public InetAddress getGateway() { 108 return mGateway; 109 } 110 111 public boolean isDefaultRoute() { 112 return mIsDefault; 113 } 114 115 public String toString() { 116 String val = ""; 117 if (mDestination != null) val = mDestination.toString(); 118 if (mGateway != null) val += " -> " + mGateway.getHostAddress(); 119 return val; 120 } 121 122 public int describeContents() { 123 return 0; 124 } 125 126 public void writeToParcel(Parcel dest, int flags) { 127 if (mDestination == null) { 128 dest.writeByte((byte) 0); 129 } else { 130 dest.writeByte((byte) 1); 131 dest.writeByteArray(mDestination.getAddress().getAddress()); 132 dest.writeInt(mDestination.getNetworkPrefixLength()); 133 } 134 135 if (mGateway == null) { 136 dest.writeByte((byte) 0); 137 } else { 138 dest.writeByte((byte) 1); 139 dest.writeByteArray(mGateway.getAddress()); 140 } 141 } 142 143 @Override 144 public boolean equals(Object obj) { 145 if (this == obj) return true; 146 147 if (!(obj instanceof RouteInfo)) return false; 148 149 RouteInfo target = (RouteInfo) obj; 150 151 boolean sameDestination = ( mDestination == null) ? 152 target.getDestination() == null 153 : mDestination.equals(target.getDestination()); 154 155 boolean sameAddress = (mGateway == null) ? 156 target.getGateway() == null 157 : mGateway.equals(target.getGateway()); 158 159 return sameDestination && sameAddress 160 && mIsDefault == target.mIsDefault; 161 } 162 163 @Override 164 public int hashCode() { 165 return (mDestination == null ? 0 : mDestination.hashCode()) 166 + (mGateway == null ? 0 :mGateway.hashCode()) 167 + (mIsDefault ? 3 : 7); 168 } 169 170 public static final Creator<RouteInfo> CREATOR = 171 new Creator<RouteInfo>() { 172 public RouteInfo createFromParcel(Parcel in) { 173 InetAddress destAddr = null; 174 int prefix = 0; 175 InetAddress gateway = null; 176 177 if (in.readByte() == 1) { 178 byte[] addr = in.createByteArray(); 179 prefix = in.readInt(); 180 181 try { 182 destAddr = InetAddress.getByAddress(addr); 183 } catch (UnknownHostException e) {} 184 } 185 186 if (in.readByte() == 1) { 187 byte[] addr = in.createByteArray(); 188 189 try { 190 gateway = InetAddress.getByAddress(addr); 191 } catch (UnknownHostException e) {} 192 } 193 194 LinkAddress dest = null; 195 196 if (destAddr != null) { 197 dest = new LinkAddress(destAddr, prefix); 198 } 199 200 return new RouteInfo(dest, gateway); 201 } 202 203 public RouteInfo[] newArray(int size) { 204 return new RouteInfo[size]; 205 } 206 }; 207 208 private boolean matches(InetAddress destination) { 209 if (destination == null) return false; 210 211 // if the destination is present and the route is default. 212 // return true 213 if (isDefault()) return true; 214 215 // match the route destination and destination with prefix length 216 InetAddress dstNet = NetworkUtils.getNetworkPart(destination, 217 mDestination.getNetworkPrefixLength()); 218 219 return mDestination.getAddress().equals(dstNet); 220 } 221 222 /** 223 * Find the route from a Collection of routes that best matches a given address. 224 * May return null if no routes are applicable. 225 * @param routes a Collection of RouteInfos to chose from 226 * @param dest the InetAddress your trying to get to 227 * @return the RouteInfo from the Collection that best fits the given address 228 */ 229 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) { 230 if ((routes == null) || (dest == null)) return null; 231 232 RouteInfo bestRoute = null; 233 // pick a longest prefix match under same address type 234 for (RouteInfo route : routes) { 235 if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) { 236 if ((bestRoute != null) && 237 (bestRoute.mDestination.getNetworkPrefixLength() >= 238 route.mDestination.getNetworkPrefixLength())) { 239 continue; 240 } 241 if (route.matches(dest)) bestRoute = route; 242 } 243 } 244 return bestRoute; 245 } 246} 247