RouteInfo.java revision 59b1a4ede7032c1b4d897e13dd4ede09b5e14743
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 public static final Creator<RouteInfo> CREATOR = 144 new Creator<RouteInfo>() { 145 public RouteInfo createFromParcel(Parcel in) { 146 InetAddress destAddr = null; 147 int prefix = 0; 148 InetAddress gateway = null; 149 150 if (in.readByte() == 1) { 151 byte[] addr = in.createByteArray(); 152 prefix = in.readInt(); 153 154 try { 155 destAddr = InetAddress.getByAddress(addr); 156 } catch (UnknownHostException e) {} 157 } 158 159 if (in.readByte() == 1) { 160 byte[] addr = in.createByteArray(); 161 162 try { 163 gateway = InetAddress.getByAddress(addr); 164 } catch (UnknownHostException e) {} 165 } 166 167 LinkAddress dest = null; 168 169 if (destAddr != null) { 170 dest = new LinkAddress(destAddr, prefix); 171 } 172 173 return new RouteInfo(dest, gateway); 174 } 175 176 public RouteInfo[] newArray(int size) { 177 return new RouteInfo[size]; 178 } 179 }; 180 181 private boolean matches(InetAddress destination) { 182 if (destination == null) return false; 183 184 // if the destination is present and the route is default. 185 // return true 186 if (isDefault()) return true; 187 188 // match the route destination and destination with prefix length 189 InetAddress dstNet = NetworkUtils.getNetworkPart(destination, 190 mDestination.getNetworkPrefixLength()); 191 192 return mDestination.getAddress().equals(dstNet); 193 } 194 195 /** 196 * Find the route from a Collection of routes that best matches a given address. 197 * May return null if no routes are applicable. 198 * @param routes a Collection of RouteInfos to chose from 199 * @param dest the InetAddress your trying to get to 200 * @return the RouteInfo from the Collection that best fits the given address 201 */ 202 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) { 203 if ((routes == null) || (dest == null)) return null; 204 205 RouteInfo bestRoute = null; 206 // pick a longest prefix match under same address type 207 for (RouteInfo route : routes) { 208 if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) { 209 if ((bestRoute != null) && 210 (bestRoute.mDestination.getNetworkPrefixLength() >= 211 route.mDestination.getNetworkPrefixLength())) { 212 continue; 213 } 214 if (route.matches(dest)) bestRoute = route; 215 } 216 } 217 return bestRoute; 218 } 219} 220