LinkProperties.java revision b07d81ac5fe9b21f08f29fcc49d0392cd22277da
1/* 2 * Copyright (C) 2010 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.net.ProxyInfo; 20import android.os.Parcelable; 21import android.os.Parcel; 22import android.text.TextUtils; 23 24import java.net.InetAddress; 25import java.net.Inet4Address; 26import java.net.Inet6Address; 27 28import java.net.UnknownHostException; 29import java.util.ArrayList; 30import java.util.Collection; 31import java.util.Collections; 32import java.util.Hashtable; 33 34/** 35 * Describes the properties of a network link. 36 * 37 * A link represents a connection to a network. 38 * It may have multiple addresses and multiple gateways, 39 * multiple dns servers but only one http proxy. 40 * 41 * Because it's a single network, the dns's 42 * are interchangeable and don't need associating with 43 * particular addresses. The gateways similarly don't 44 * need associating with particular addresses. 45 * 46 * A dual stack interface works fine in this model: 47 * each address has it's own prefix length to describe 48 * the local network. The dns servers all return 49 * both v4 addresses and v6 addresses regardless of the 50 * address family of the server itself (rfc4213) and we 51 * don't care which is used. The gateways will be 52 * selected based on the destination address and the 53 * source address has no relavence. 54 * 55 * Links can also be stacked on top of each other. 56 * This can be used, for example, to represent a tunnel 57 * interface that runs on top of a physical interface. 58 * 59 * @hide 60 */ 61public class LinkProperties implements Parcelable { 62 // The interface described by the network link. 63 private String mIfaceName; 64 private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>(); 65 private ArrayList<InetAddress> mDnses = new ArrayList<InetAddress>(); 66 private String mDomains; 67 private ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>(); 68 private ProxyInfo mHttpProxy; 69 private int mMtu; 70 71 // Stores the properties of links that are "stacked" above this link. 72 // Indexed by interface name to allow modification and to prevent duplicates being added. 73 private Hashtable<String, LinkProperties> mStackedLinks = 74 new Hashtable<String, LinkProperties>(); 75 76 public static class CompareResult<T> { 77 public Collection<T> removed = new ArrayList<T>(); 78 public Collection<T> added = new ArrayList<T>(); 79 80 @Override 81 public String toString() { 82 String retVal = "removed=["; 83 for (T addr : removed) retVal += addr.toString() + ","; 84 retVal += "] added=["; 85 for (T addr : added) retVal += addr.toString() + ","; 86 retVal += "]"; 87 return retVal; 88 } 89 } 90 91 public LinkProperties() { 92 } 93 94 // copy constructor instead of clone 95 public LinkProperties(LinkProperties source) { 96 if (source != null) { 97 mIfaceName = source.getInterfaceName(); 98 for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l); 99 for (InetAddress i : source.getDnses()) mDnses.add(i); 100 mDomains = source.getDomains(); 101 for (RouteInfo r : source.getRoutes()) mRoutes.add(r); 102 mHttpProxy = (source.getHttpProxy() == null) ? 103 null : new ProxyInfo(source.getHttpProxy()); 104 for (LinkProperties l: source.mStackedLinks.values()) { 105 addStackedLink(l); 106 } 107 setMtu(source.getMtu()); 108 } 109 } 110 111 public void setInterfaceName(String iface) { 112 mIfaceName = iface; 113 ArrayList<RouteInfo> newRoutes = new ArrayList<RouteInfo>(mRoutes.size()); 114 for (RouteInfo route : mRoutes) { 115 newRoutes.add(routeWithInterface(route)); 116 } 117 mRoutes = newRoutes; 118 } 119 120 public String getInterfaceName() { 121 return mIfaceName; 122 } 123 124 public Collection<String> getAllInterfaceNames() { 125 Collection interfaceNames = new ArrayList<String>(mStackedLinks.size() + 1); 126 if (mIfaceName != null) interfaceNames.add(new String(mIfaceName)); 127 for (LinkProperties stacked: mStackedLinks.values()) { 128 interfaceNames.addAll(stacked.getAllInterfaceNames()); 129 } 130 return interfaceNames; 131 } 132 133 /** 134 * Returns all the addresses on this link. 135 */ 136 public Collection<InetAddress> getAddresses() { 137 Collection<InetAddress> addresses = new ArrayList<InetAddress>(); 138 for (LinkAddress linkAddress : mLinkAddresses) { 139 addresses.add(linkAddress.getAddress()); 140 } 141 return Collections.unmodifiableCollection(addresses); 142 } 143 144 /** 145 * Returns all the addresses on this link and all the links stacked above it. 146 */ 147 public Collection<InetAddress> getAllAddresses() { 148 Collection<InetAddress> addresses = new ArrayList<InetAddress>(); 149 for (LinkAddress linkAddress : mLinkAddresses) { 150 addresses.add(linkAddress.getAddress()); 151 } 152 for (LinkProperties stacked: mStackedLinks.values()) { 153 addresses.addAll(stacked.getAllAddresses()); 154 } 155 return addresses; 156 } 157 158 private int findLinkAddressIndex(LinkAddress address) { 159 for (int i = 0; i < mLinkAddresses.size(); i++) { 160 if (mLinkAddresses.get(i).isSameAddressAs(address)) { 161 return i; 162 } 163 } 164 return -1; 165 } 166 167 /** 168 * Adds a link address if it does not exist, or updates it if it does. 169 * @param address The {@code LinkAddress} to add. 170 * @return true if {@code address} was added or updated, false otherwise. 171 */ 172 public boolean addLinkAddress(LinkAddress address) { 173 if (address == null) { 174 return false; 175 } 176 int i = findLinkAddressIndex(address); 177 if (i < 0) { 178 // Address was not present. Add it. 179 mLinkAddresses.add(address); 180 return true; 181 } else if (mLinkAddresses.get(i).equals(address)) { 182 // Address was present and has same properties. Do nothing. 183 return false; 184 } else { 185 // Address was present and has different properties. Update it. 186 mLinkAddresses.set(i, address); 187 return true; 188 } 189 } 190 191 /** 192 * Removes a link address. Specifically, removes the link address, if any, for which 193 * {@code isSameAddressAs(toRemove)} returns true. 194 * @param address A {@code LinkAddress} specifying the address to remove. 195 * @return true if the address was removed, false if it did not exist. 196 */ 197 public boolean removeLinkAddress(LinkAddress toRemove) { 198 int i = findLinkAddressIndex(toRemove); 199 if (i >= 0) { 200 mLinkAddresses.remove(i); 201 return true; 202 } 203 return false; 204 } 205 206 /** 207 * Returns all the addresses on this link. 208 */ 209 public Collection<LinkAddress> getLinkAddresses() { 210 return Collections.unmodifiableCollection(mLinkAddresses); 211 } 212 213 /** 214 * Returns all the addresses on this link and all the links stacked above it. 215 */ 216 public Collection<LinkAddress> getAllLinkAddresses() { 217 Collection<LinkAddress> addresses = new ArrayList<LinkAddress>(); 218 addresses.addAll(mLinkAddresses); 219 for (LinkProperties stacked: mStackedLinks.values()) { 220 addresses.addAll(stacked.getAllLinkAddresses()); 221 } 222 return addresses; 223 } 224 225 /** 226 * Replaces the LinkAddresses on this link with the given collection of addresses. 227 */ 228 public void setLinkAddresses(Collection<LinkAddress> addresses) { 229 mLinkAddresses.clear(); 230 for (LinkAddress address: addresses) { 231 addLinkAddress(address); 232 } 233 } 234 235 public void addDns(InetAddress dns) { 236 if (dns != null) mDnses.add(dns); 237 } 238 239 public Collection<InetAddress> getDnses() { 240 return Collections.unmodifiableCollection(mDnses); 241 } 242 243 public String getDomains() { 244 return mDomains; 245 } 246 247 public void setDomains(String domains) { 248 mDomains = domains; 249 } 250 251 public void setMtu(int mtu) { 252 mMtu = mtu; 253 } 254 255 public int getMtu() { 256 return mMtu; 257 } 258 259 private RouteInfo routeWithInterface(RouteInfo route) { 260 return new RouteInfo( 261 route.getDestination(), 262 route.getGateway(), 263 mIfaceName); 264 } 265 266 public void addRoute(RouteInfo route) { 267 if (route != null) { 268 String routeIface = route.getInterface(); 269 if (routeIface != null && !routeIface.equals(mIfaceName)) { 270 throw new IllegalArgumentException( 271 "Route added with non-matching interface: " + routeIface + 272 " vs. " + mIfaceName); 273 } 274 mRoutes.add(routeWithInterface(route)); 275 } 276 } 277 278 /** 279 * Returns all the routes on this link. 280 */ 281 public Collection<RouteInfo> getRoutes() { 282 return Collections.unmodifiableCollection(mRoutes); 283 } 284 285 /** 286 * Returns all the routes on this link and all the links stacked above it. 287 */ 288 public Collection<RouteInfo> getAllRoutes() { 289 Collection<RouteInfo> routes = new ArrayList(); 290 routes.addAll(mRoutes); 291 for (LinkProperties stacked: mStackedLinks.values()) { 292 routes.addAll(stacked.getAllRoutes()); 293 } 294 return routes; 295 } 296 297 public void setHttpProxy(ProxyInfo proxy) { 298 mHttpProxy = proxy; 299 } 300 public ProxyInfo getHttpProxy() { 301 return mHttpProxy; 302 } 303 304 /** 305 * Adds a stacked link. 306 * 307 * If there is already a stacked link with the same interfacename as link, 308 * that link is replaced with link. Otherwise, link is added to the list 309 * of stacked links. If link is null, nothing changes. 310 * 311 * @param link The link to add. 312 * @return true if the link was stacked, false otherwise. 313 */ 314 public boolean addStackedLink(LinkProperties link) { 315 if (link != null && link.getInterfaceName() != null) { 316 mStackedLinks.put(link.getInterfaceName(), link); 317 return true; 318 } 319 return false; 320 } 321 322 /** 323 * Removes a stacked link. 324 * 325 * If there a stacked link with the same interfacename as link, it is 326 * removed. Otherwise, nothing changes. 327 * 328 * @param link The link to remove. 329 * @return true if the link was removed, false otherwise. 330 */ 331 public boolean removeStackedLink(LinkProperties link) { 332 if (link != null && link.getInterfaceName() != null) { 333 LinkProperties removed = mStackedLinks.remove(link.getInterfaceName()); 334 return removed != null; 335 } 336 return false; 337 } 338 339 /** 340 * Returns all the links stacked on top of this link. 341 */ 342 public Collection<LinkProperties> getStackedLinks() { 343 Collection<LinkProperties> stacked = new ArrayList<LinkProperties>(); 344 for (LinkProperties link : mStackedLinks.values()) { 345 stacked.add(new LinkProperties(link)); 346 } 347 return Collections.unmodifiableCollection(stacked); 348 } 349 350 public void clear() { 351 mIfaceName = null; 352 mLinkAddresses.clear(); 353 mDnses.clear(); 354 mDomains = null; 355 mRoutes.clear(); 356 mHttpProxy = null; 357 mStackedLinks.clear(); 358 mMtu = 0; 359 } 360 361 /** 362 * Implement the Parcelable interface 363 * @hide 364 */ 365 public int describeContents() { 366 return 0; 367 } 368 369 @Override 370 public String toString() { 371 String ifaceName = (mIfaceName == null ? "" : "InterfaceName: " + mIfaceName + " "); 372 373 String linkAddresses = "LinkAddresses: ["; 374 for (LinkAddress addr : mLinkAddresses) linkAddresses += addr.toString() + ","; 375 linkAddresses += "] "; 376 377 String dns = "DnsAddresses: ["; 378 for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ","; 379 dns += "] "; 380 381 String domainName = "Domains: " + mDomains; 382 383 String mtu = "MTU: " + mMtu; 384 385 String routes = " Routes: ["; 386 for (RouteInfo route : mRoutes) routes += route.toString() + ","; 387 routes += "] "; 388 String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " "); 389 390 String stacked = ""; 391 if (mStackedLinks.values().size() > 0) { 392 stacked += " Stacked: ["; 393 for (LinkProperties link: mStackedLinks.values()) { 394 stacked += " [" + link.toString() + " ],"; 395 } 396 stacked += "] "; 397 } 398 return "{" + ifaceName + linkAddresses + routes + dns + domainName + mtu 399 + proxy + stacked + "}"; 400 } 401 402 /** 403 * Returns true if this link has an IPv4 address. 404 * 405 * @return {@code true} if there is an IPv4 address, {@code false} otherwise. 406 */ 407 public boolean hasIPv4Address() { 408 for (LinkAddress address : mLinkAddresses) { 409 if (address.getAddress() instanceof Inet4Address) { 410 return true; 411 } 412 } 413 return false; 414 } 415 416 /** 417 * Returns true if this link has an IPv6 address. 418 * 419 * @return {@code true} if there is an IPv6 address, {@code false} otherwise. 420 */ 421 public boolean hasIPv6Address() { 422 for (LinkAddress address : mLinkAddresses) { 423 if (address.getAddress() instanceof Inet6Address) { 424 return true; 425 } 426 } 427 return false; 428 } 429 430 /** 431 * Compares this {@code LinkProperties} interface name against the target 432 * 433 * @param target LinkProperties to compare. 434 * @return {@code true} if both are identical, {@code false} otherwise. 435 */ 436 public boolean isIdenticalInterfaceName(LinkProperties target) { 437 return TextUtils.equals(getInterfaceName(), target.getInterfaceName()); 438 } 439 440 /** 441 * Compares this {@code LinkProperties} interface addresses against the target 442 * 443 * @param target LinkProperties to compare. 444 * @return {@code true} if both are identical, {@code false} otherwise. 445 */ 446 public boolean isIdenticalAddresses(LinkProperties target) { 447 Collection<InetAddress> targetAddresses = target.getAddresses(); 448 Collection<InetAddress> sourceAddresses = getAddresses(); 449 return (sourceAddresses.size() == targetAddresses.size()) ? 450 sourceAddresses.containsAll(targetAddresses) : false; 451 } 452 453 /** 454 * Compares this {@code LinkProperties} DNS addresses against the target 455 * 456 * @param target LinkProperties to compare. 457 * @return {@code true} if both are identical, {@code false} otherwise. 458 */ 459 public boolean isIdenticalDnses(LinkProperties target) { 460 Collection<InetAddress> targetDnses = target.getDnses(); 461 String targetDomains = target.getDomains(); 462 if (mDomains == null) { 463 if (targetDomains != null) return false; 464 } else { 465 if (mDomains.equals(targetDomains) == false) return false; 466 } 467 return (mDnses.size() == targetDnses.size()) ? 468 mDnses.containsAll(targetDnses) : false; 469 } 470 471 /** 472 * Compares this {@code LinkProperties} Routes against the target 473 * 474 * @param target LinkProperties to compare. 475 * @return {@code true} if both are identical, {@code false} otherwise. 476 */ 477 public boolean isIdenticalRoutes(LinkProperties target) { 478 Collection<RouteInfo> targetRoutes = target.getRoutes(); 479 return (mRoutes.size() == targetRoutes.size()) ? 480 mRoutes.containsAll(targetRoutes) : false; 481 } 482 483 /** 484 * Compares this {@code LinkProperties} HttpProxy against the target 485 * 486 * @param target LinkProperties to compare. 487 * @return {@code true} if both are identical, {@code false} otherwise. 488 */ 489 public boolean isIdenticalHttpProxy(LinkProperties target) { 490 return getHttpProxy() == null ? target.getHttpProxy() == null : 491 getHttpProxy().equals(target.getHttpProxy()); 492 } 493 494 /** 495 * Compares this {@code LinkProperties} stacked links against the target 496 * 497 * @param target LinkProperties to compare. 498 * @return {@code true} if both are identical, {@code false} otherwise. 499 */ 500 public boolean isIdenticalStackedLinks(LinkProperties target) { 501 if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) { 502 return false; 503 } 504 for (LinkProperties stacked : mStackedLinks.values()) { 505 // Hashtable values can never be null. 506 String iface = stacked.getInterfaceName(); 507 if (!stacked.equals(target.mStackedLinks.get(iface))) { 508 return false; 509 } 510 } 511 return true; 512 } 513 514 /** 515 * Compares this {@code LinkProperties} MTU against the target 516 * 517 * @param target LinkProperties to compare. 518 * @return {@code true} if both are identical, {@code false} otherwise. 519 */ 520 public boolean isIdenticalMtu(LinkProperties target) { 521 return getMtu() == target.getMtu(); 522 } 523 524 @Override 525 /** 526 * Compares this {@code LinkProperties} instance against the target 527 * LinkProperties in {@code obj}. Two LinkPropertieses are equal if 528 * all their fields are equal in values. 529 * 530 * For collection fields, such as mDnses, containsAll() is used to check 531 * if two collections contains the same elements, independent of order. 532 * There are two thoughts regarding containsAll() 533 * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal. 534 * 2. Worst case performance is O(n^2). 535 * 536 * This method does not check that stacked interfaces are equal, because 537 * stacked interfaces are not so much a property of the link as a 538 * description of connections between links. 539 * 540 * @param obj the object to be tested for equality. 541 * @return {@code true} if both objects are equal, {@code false} otherwise. 542 */ 543 public boolean equals(Object obj) { 544 if (this == obj) return true; 545 546 if (!(obj instanceof LinkProperties)) return false; 547 548 LinkProperties target = (LinkProperties) obj; 549 550 return isIdenticalInterfaceName(target) && 551 isIdenticalAddresses(target) && 552 isIdenticalDnses(target) && 553 isIdenticalRoutes(target) && 554 isIdenticalHttpProxy(target) && 555 isIdenticalStackedLinks(target) && 556 isIdenticalMtu(target); 557 } 558 559 /** 560 * Compares the addresses in this LinkProperties with another 561 * LinkProperties, examining only addresses on the base link. 562 * 563 * @param target a LinkProperties with the new list of addresses 564 * @return the differences between the addresses. 565 */ 566 public CompareResult<LinkAddress> compareAddresses(LinkProperties target) { 567 /* 568 * Duplicate the LinkAddresses into removed, we will be removing 569 * address which are common between mLinkAddresses and target 570 * leaving the addresses that are different. And address which 571 * are in target but not in mLinkAddresses are placed in the 572 * addedAddresses. 573 */ 574 CompareResult<LinkAddress> result = new CompareResult<LinkAddress>(); 575 result.removed = new ArrayList<LinkAddress>(mLinkAddresses); 576 result.added.clear(); 577 if (target != null) { 578 for (LinkAddress newAddress : target.getLinkAddresses()) { 579 if (! result.removed.remove(newAddress)) { 580 result.added.add(newAddress); 581 } 582 } 583 } 584 return result; 585 } 586 587 /** 588 * Compares the DNS addresses in this LinkProperties with another 589 * LinkProperties, examining only DNS addresses on the base link. 590 * 591 * @param target a LinkProperties with the new list of dns addresses 592 * @return the differences between the DNS addresses. 593 */ 594 public CompareResult<InetAddress> compareDnses(LinkProperties target) { 595 /* 596 * Duplicate the InetAddresses into removed, we will be removing 597 * dns address which are common between mDnses and target 598 * leaving the addresses that are different. And dns address which 599 * are in target but not in mDnses are placed in the 600 * addedAddresses. 601 */ 602 CompareResult<InetAddress> result = new CompareResult<InetAddress>(); 603 604 result.removed = new ArrayList<InetAddress>(mDnses); 605 result.added.clear(); 606 if (target != null) { 607 for (InetAddress newAddress : target.getDnses()) { 608 if (! result.removed.remove(newAddress)) { 609 result.added.add(newAddress); 610 } 611 } 612 } 613 return result; 614 } 615 616 /** 617 * Compares all routes in this LinkProperties with another LinkProperties, 618 * examining both the the base link and all stacked links. 619 * 620 * @param target a LinkProperties with the new list of routes 621 * @return the differences between the routes. 622 */ 623 public CompareResult<RouteInfo> compareAllRoutes(LinkProperties target) { 624 /* 625 * Duplicate the RouteInfos into removed, we will be removing 626 * routes which are common between mRoutes and target 627 * leaving the routes that are different. And route address which 628 * are in target but not in mRoutes are placed in added. 629 */ 630 CompareResult<RouteInfo> result = new CompareResult<RouteInfo>(); 631 632 result.removed = getAllRoutes(); 633 result.added.clear(); 634 if (target != null) { 635 for (RouteInfo r : target.getAllRoutes()) { 636 if (! result.removed.remove(r)) { 637 result.added.add(r); 638 } 639 } 640 } 641 return result; 642 } 643 644 /** 645 * Compares all interface names in this LinkProperties with another 646 * LinkProperties, examining both the the base link and all stacked links. 647 * 648 * @param target a LinkProperties with the new list of interface names 649 * @return the differences between the interface names. 650 * @hide 651 */ 652 public CompareResult<String> compareAllInterfaceNames(LinkProperties target) { 653 /* 654 * Duplicate the interface names into removed, we will be removing 655 * interface names which are common between this and target 656 * leaving the interface names that are different. And interface names which 657 * are in target but not in this are placed in added. 658 */ 659 CompareResult<String> result = new CompareResult<String>(); 660 661 result.removed = getAllInterfaceNames(); 662 result.added.clear(); 663 if (target != null) { 664 for (String r : target.getAllInterfaceNames()) { 665 if (! result.removed.remove(r)) { 666 result.added.add(r); 667 } 668 } 669 } 670 return result; 671 } 672 673 674 @Override 675 /** 676 * generate hashcode based on significant fields 677 * Equal objects must produce the same hash code, while unequal objects 678 * may have the same hash codes. 679 */ 680 public int hashCode() { 681 return ((null == mIfaceName) ? 0 : mIfaceName.hashCode() 682 + mLinkAddresses.size() * 31 683 + mDnses.size() * 37 684 + ((null == mDomains) ? 0 : mDomains.hashCode()) 685 + mRoutes.size() * 41 686 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()) 687 + mStackedLinks.hashCode() * 47) 688 + mMtu * 51; 689 } 690 691 /** 692 * Implement the Parcelable interface. 693 */ 694 public void writeToParcel(Parcel dest, int flags) { 695 dest.writeString(getInterfaceName()); 696 dest.writeInt(mLinkAddresses.size()); 697 for(LinkAddress linkAddress : mLinkAddresses) { 698 dest.writeParcelable(linkAddress, flags); 699 } 700 701 dest.writeInt(mDnses.size()); 702 for(InetAddress d : mDnses) { 703 dest.writeByteArray(d.getAddress()); 704 } 705 dest.writeString(mDomains); 706 dest.writeInt(mMtu); 707 dest.writeInt(mRoutes.size()); 708 for(RouteInfo route : mRoutes) { 709 dest.writeParcelable(route, flags); 710 } 711 712 if (mHttpProxy != null) { 713 dest.writeByte((byte)1); 714 dest.writeParcelable(mHttpProxy, flags); 715 } else { 716 dest.writeByte((byte)0); 717 } 718 ArrayList<LinkProperties> stackedLinks = new ArrayList(mStackedLinks.values()); 719 dest.writeList(stackedLinks); 720 } 721 722 /** 723 * Implement the Parcelable interface. 724 */ 725 public static final Creator<LinkProperties> CREATOR = 726 new Creator<LinkProperties>() { 727 public LinkProperties createFromParcel(Parcel in) { 728 LinkProperties netProp = new LinkProperties(); 729 730 String iface = in.readString(); 731 if (iface != null) { 732 netProp.setInterfaceName(iface); 733 } 734 int addressCount = in.readInt(); 735 for (int i=0; i<addressCount; i++) { 736 netProp.addLinkAddress((LinkAddress)in.readParcelable(null)); 737 } 738 addressCount = in.readInt(); 739 for (int i=0; i<addressCount; i++) { 740 try { 741 netProp.addDns(InetAddress.getByAddress(in.createByteArray())); 742 } catch (UnknownHostException e) { } 743 } 744 netProp.setDomains(in.readString()); 745 netProp.setMtu(in.readInt()); 746 addressCount = in.readInt(); 747 for (int i=0; i<addressCount; i++) { 748 netProp.addRoute((RouteInfo)in.readParcelable(null)); 749 } 750 if (in.readByte() == 1) { 751 netProp.setHttpProxy((ProxyInfo)in.readParcelable(null)); 752 } 753 ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>(); 754 in.readList(stackedLinks, LinkProperties.class.getClassLoader()); 755 for (LinkProperties stackedLink: stackedLinks) { 756 netProp.addStackedLink(stackedLink); 757 } 758 return netProp; 759 } 760 761 public LinkProperties[] newArray(int size) { 762 return new LinkProperties[size]; 763 } 764 }; 765} 766