RouteInfo.java revision be2b058ec1e11e1d33b6d03230c21e5d2d7ac40c
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 try { 50 if (gateway != null) { 51 if (gateway instanceof Inet4Address) { 52 destination = new LinkAddress(Inet4Address.ANY, 0); 53 } else { 54 destination = new LinkAddress(Inet6Address.ANY, 0); 55 } 56 } else { 57 // no destination, no gateway. invalid. 58 throw new RuntimeException("Invalid arguments passed in."); 59 } 60 } catch (Exception e) {} 61 } 62 if (gateway == null) { 63 if (destination.getAddress() instanceof Inet4Address) { 64 gateway = Inet4Address.ANY; 65 } else { 66 gateway = Inet6Address.ANY; 67 } 68 } 69 mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(), 70 destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength()); 71 mGateway = gateway; 72 mIsDefault = isDefault(); 73 } 74 75 public RouteInfo(InetAddress gateway) { 76 this(null, gateway); 77 } 78 79 private boolean isDefault() { 80 boolean val = false; 81 if (mGateway != null) { 82 if (mGateway instanceof Inet4Address) { 83 val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0); 84 } else { 85 val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0); 86 } 87 } 88 return val; 89 } 90 91 public LinkAddress getDestination() { 92 return mDestination; 93 } 94 95 public InetAddress getGateway() { 96 return mGateway; 97 } 98 99 public boolean isDefaultRoute() { 100 return mIsDefault; 101 } 102 103 public String toString() { 104 String val = ""; 105 if (mDestination != null) val = mDestination.toString(); 106 if (mGateway != null) val += " -> " + mGateway.getHostAddress(); 107 return val; 108 } 109 110 public int describeContents() { 111 return 0; 112 } 113 114 public void writeToParcel(Parcel dest, int flags) { 115 if (mDestination == null) { 116 dest.writeByte((byte) 0); 117 } else { 118 dest.writeByte((byte) 1); 119 dest.writeByteArray(mDestination.getAddress().getAddress()); 120 dest.writeInt(mDestination.getNetworkPrefixLength()); 121 } 122 123 if (mGateway == null) { 124 dest.writeByte((byte) 0); 125 } else { 126 dest.writeByte((byte) 1); 127 dest.writeByteArray(mGateway.getAddress()); 128 } 129 } 130 131 @Override 132 public boolean equals(Object obj) { 133 if (this == obj) return true; 134 135 if (!(obj instanceof RouteInfo)) return false; 136 137 RouteInfo target = (RouteInfo) obj; 138 139 boolean sameDestination = ( mDestination == null) ? 140 target.getDestination() == null 141 : mDestination.equals(target.getDestination()); 142 143 boolean sameAddress = (mGateway == null) ? 144 target.getGateway() == null 145 : mGateway.equals(target.getGateway()); 146 147 return sameDestination && sameAddress 148 && mIsDefault == target.mIsDefault; 149 } 150 151 @Override 152 public int hashCode() { 153 return (mDestination == null ? 0 : mDestination.hashCode()) 154 + (mGateway == null ? 0 :mGateway.hashCode()) 155 + (mIsDefault ? 3 : 7); 156 } 157 158 public static final Creator<RouteInfo> CREATOR = 159 new Creator<RouteInfo>() { 160 public RouteInfo createFromParcel(Parcel in) { 161 InetAddress destAddr = null; 162 int prefix = 0; 163 InetAddress gateway = null; 164 165 if (in.readByte() == 1) { 166 byte[] addr = in.createByteArray(); 167 prefix = in.readInt(); 168 169 try { 170 destAddr = InetAddress.getByAddress(addr); 171 } catch (UnknownHostException e) {} 172 } 173 174 if (in.readByte() == 1) { 175 byte[] addr = in.createByteArray(); 176 177 try { 178 gateway = InetAddress.getByAddress(addr); 179 } catch (UnknownHostException e) {} 180 } 181 182 LinkAddress dest = null; 183 184 if (destAddr != null) { 185 dest = new LinkAddress(destAddr, prefix); 186 } 187 188 return new RouteInfo(dest, gateway); 189 } 190 191 public RouteInfo[] newArray(int size) { 192 return new RouteInfo[size]; 193 } 194 }; 195 196 private boolean matches(InetAddress destination) { 197 if (destination == null) return false; 198 199 // if the destination is present and the route is default. 200 // return true 201 if (isDefault()) return true; 202 203 // match the route destination and destination with prefix length 204 InetAddress dstNet = NetworkUtils.getNetworkPart(destination, 205 mDestination.getNetworkPrefixLength()); 206 207 return mDestination.getAddress().equals(dstNet); 208 } 209 210 /** 211 * Find the route from a Collection of routes that best matches a given address. 212 * May return null if no routes are applicable. 213 * @param routes a Collection of RouteInfos to chose from 214 * @param dest the InetAddress your trying to get to 215 * @return the RouteInfo from the Collection that best fits the given address 216 */ 217 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) { 218 if ((routes == null) || (dest == null)) return null; 219 220 RouteInfo bestRoute = null; 221 // pick a longest prefix match under same address type 222 for (RouteInfo route : routes) { 223 if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) { 224 if ((bestRoute != null) && 225 (bestRoute.mDestination.getNetworkPrefixLength() >= 226 route.mDestination.getNetworkPrefixLength())) { 227 continue; 228 } 229 if (route.matches(dest)) bestRoute = route; 230 } 231 } 232 return bestRoute; 233 } 234} 235