summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Clayton <alex.clayton@isode.com>2016-07-13 15:42:34 (GMT)
committerAlex Clayton <alex.clayton@isode.com>2016-07-15 15:19:04 (GMT)
commit4e70a84a8a792cfeae96bf7a0cb4c9b549e44d29 (patch)
treeaf606f030af75a86dcb0187c20d6466b1501b851
parent8708b7b01cf4f36524bff3dc9aa5a7a6534ce221 (diff)
downloadstroke-4e70a84a8a792cfeae96bf7a0cb4c9b549e44d29.zip
stroke-4e70a84a8a792cfeae96bf7a0cb4c9b549e44d29.tar.bz2
Stop HostAddress constructor running DNS lookup.
When running the latest stroke against harrier android a NetworkOnMainThread exception was encountered. This was traced to the new constructor HostAddress(String) that was been called by Connector.start() method. The issue was dues to difference between the java code in stroke and the c++ code in swiften. In swiften the equivalent conde calls boost::asio::ip::address::from_string, which parses a string that may be an ipv4 or ipv6 address into an IP address object. If the string is not one of these then the object is left invalid. In the java code InetAddress.getByName(String name) is used instead. If this is an ipv4 or ipv6 address then it parses it into an InetAddress object. However if is not one of these it does a DNS lookup on the address. This was what was causing the error. To match the C++ the java code should only create an InetAddress if the input is an IP address, if not it should be left null. This was done by copying the IPv4 and IPv6 regexes in the Regex class in isode lib. The input to HostAddress(String) is checked against these if it matches InetAddress.getByName is called, otherwise address is set to null. Test-information: Ran unit tests in stroke they all pass. Ran code against android harrier, no longer fails. Ran against MLC (with updates for other changes in stroke api) it still passes. Change-Id: I1945c7c3cdfece8feb45b9196483131c0d9c4e7c
-rw-r--r--src/com/isode/stroke/network/HostAddress.java70
1 files changed, 64 insertions, 6 deletions
diff --git a/src/com/isode/stroke/network/HostAddress.java b/src/com/isode/stroke/network/HostAddress.java
index a8eea1b..dae2558 100644
--- a/src/com/isode/stroke/network/HostAddress.java
+++ b/src/com/isode/stroke/network/HostAddress.java
@@ -4,13 +4,14 @@
4 * See Documentation/Licenses/GPLv3.txt for more information. 4 * See Documentation/Licenses/GPLv3.txt for more information.
5 */ 5 */
6/* 6/*
7 * Copyright (c) 2010, Isode Limited, London, England. 7 * Copyright (c) 2010-2016, Isode Limited, London, England.
8 * All rights reserved. 8 * All rights reserved.
9 */ 9 */
10package com.isode.stroke.network; 10package com.isode.stroke.network;
11 11
12import java.net.InetAddress; 12import java.net.InetAddress;
13import java.net.UnknownHostException; 13import java.net.UnknownHostException;
14import java.util.regex.Pattern;
14 15
15public class HostAddress { 16public class HostAddress {
16 17
@@ -19,11 +20,15 @@ public class HostAddress {
19 } 20 }
20 21
21 public HostAddress(String address) { 22 public HostAddress(String address) {
22 try { 23 // To match C++ code this should try and create a InetAddress
23 address_ = InetAddress.getByName(address); 24 // if and only if the input is a IPv4 or IPv6 address.
24 } 25 if (isIPv4OrIPv6Address(address)) {
25 catch (UnknownHostException e) { 26 try {
26 address_ = null; 27 address_ = InetAddress.getByName(address);
28 }
29 catch (UnknownHostException e) {
30 address_ = null;
31 }
27 } 32 }
28 } 33 }
29 34
@@ -86,4 +91,57 @@ public class HostAddress {
86 } 91 }
87 92
88 private InetAddress address_; 93 private InetAddress address_;
94
95 /**
96 * Indicates if the value is an IPv4 address in dot notation or
97 * an IPv6 address in hexadecimal notation
98 * @param value A string to test. If {@code null} result will
99 * be false.
100 * @return {@code true} if the string is an IPv4 address in dot
101 * notation, or a IPv6 address in hexadecimal notation.
102 */
103 private static boolean isIPv4OrIPv6Address(String value) {
104 if (value == null) {
105 return false;
106 }
107 if (ipv4Pattern.matcher(value).matches()) {
108 return true;
109 }
110 if (ipv6Pattern.matcher(value).matches()) {
111 return true;
112 }
113 return false;
114 }
115
116 /**
117 * Regular expression for IPv4 address.
118 *
119 * @see <a href="http://www.mkyong.com/regular-expressions/how-to-validate-ip-address-with-regular-expression/"> web link</a>
120 */
121 private static final String ipv4Regex =
122 "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
123 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
124 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
125 + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
126 /**
127 * A pattern that can be used to match an IPv4 address (e.g. "1.2.3.4").
128 *
129 */
130 private static final Pattern ipv4Pattern = Pattern.compile(ipv4Regex);
131
132 /**
133 * Regular expression for IPv6 address. Note that this needs to be
134 * compiled with the CASE_INSENSITIVE option.
135 */
136 private static final String ipv6Regex =
137 "^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}"
138 + "|([0-9A-F]{1,4}:){6})(\\2([0-9A-F]{1,4}(::?|$)){0,2}"
139 + "|((25[0-5]|(2[0-4]|1\\d|[1-9])?\\d)(\\.|$)){4}"
140 + "|[0-9A-F]{1,4}:[0-9A-F]{1,4})(?<![^:]:|\\.)\\z";
141
142 /**
143 * A pattern that can be used to match an IPv6 address (e.g. "3ffe:1900:4545:3:200:f8ff:fe21:67cf").
144 */
145 private static final Pattern ipv6Pattern = Pattern.compile(ipv6Regex, Pattern.CASE_INSENSITIVE);
146
89} 147}