diff options
| author | Tobias Markmann <tm@ayena.de> | 2013-08-13 17:17:40 (GMT) | 
|---|---|---|
| committer | Tobias Markmann <tm@ayena.de> | 2013-08-13 17:40:43 (GMT) | 
| commit | 437e70ff9d254b11a30a4926010a91543d7f282c (patch) | |
| tree | 123ef9476d89ad32643356ea11c52d212d2d03ad | |
| parent | 3eefe28a2f6cc1e33d9d2b0bad7f9c6f2146352f (diff) | |
| download | swift-437e70ff9d254b11a30a4926010a91543d7f282c.zip swift-437e70ff9d254b11a30a4926010a91543d7f282c.tar.bz2 | |
Adding basic support for Android and Unbound (No IPv6 yet).
Change-Id: I1d74324515b20e0dc3d0ef4aa2f556fea7b4bee3
License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details.s
21 files changed, 693 insertions, 23 deletions
| diff --git a/3rdParty/Boost/02_android_compilation_fixes.diff b/3rdParty/Boost/02_android_compilation_fixes.diff new file mode 100644 index 0000000..9aba7e1 --- /dev/null +++ b/3rdParty/Boost/02_android_compilation_fixes.diff @@ -0,0 +1,36 @@ +diff --git a/3rdParty/Boost/src/boost/detail/endian.hpp b/3rdParty/Boost/src/boost/detail/endian.hpp +index 98c870c..ac77a2e 100644 +--- a/3rdParty/Boost/src/boost/detail/endian.hpp ++++ b/3rdParty/Boost/src/boost/detail/endian.hpp +@@ -66,8 +66,8 @@ +    || defined(_M_ALPHA) || defined(__amd64) \ +    || defined(__amd64__) || defined(_M_AMD64) \ +    || defined(__x86_64) || defined(__x86_64__) \ +-   || defined(_M_X64) || defined(__bfin__) +- ++   || defined(_M_X64) || defined(__bfin__) \ ++   || defined(ANDROID) + # define BOOST_LITTLE_ENDIAN + # define BOOST_BYTE_ORDER 1234 + #else +diff --git a/3rdParty/Boost/src/libs/filesystem/src/operations.cpp b/3rdParty/Boost/src/libs/filesystem/src/operations.cpp +index 16a336f..d066e40 100644 +--- a/3rdParty/Boost/src/libs/filesystem/src/operations.cpp ++++ b/3rdParty/Boost/src/libs/filesystem/src/operations.cpp +@@ -73,10 +73,14 @@ using std::wstring; +     const fs::path dot_dot_path(".."); + #   include <sys/types.h> + #   include <sys/stat.h> +-#   if !defined(__APPLE__) && !defined(__OpenBSD__) ++#   if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(ANDROID) + #     include <sys/statvfs.h> + #     define BOOST_STATVFS statvfs + #     define BOOST_STATVFS_F_FRSIZE vfs.f_frsize ++#   elif defined (ANDROID) ++#     include <sys/vfs.h> ++#     define BOOST_STATVFS statfs ++#     define BOOST_STATVFS_F_FRSIZE static_cast<boost::uintmax_t>(vfs.f_bsize) + #   else + #     ifdef __OpenBSD__ + #     include <sys/param.h> + --
\ No newline at end of file diff --git a/3rdParty/Ldns/01_andoird_compilation_fixes.diff b/3rdParty/Ldns/01_andoird_compilation_fixes.diff new file mode 100644 index 0000000..9d6ec08 --- /dev/null +++ b/3rdParty/Ldns/01_andoird_compilation_fixes.diff @@ -0,0 +1,15 @@ +--- 3rdParty/Ldns/src/ldns/ldns/ldns.h	2013-04-12 14:30:16.000000000 +0200 ++++ 3rdParty/Ldns/src/ldns/ldns/ldns.h	2013-04-12 14:30:48.000000000 +0200 +@@ -123,6 +123,12 @@ + #include <ldns/sha1.h> + #include <ldns/sha2.h> +  ++#ifdef __ANDROID__ ++#ifndef in_port_t ++#define in_port_t uint16_t ++#endif ++#endif ++ + #ifdef __cplusplus + extern "C" { + #endif diff --git a/3rdParty/Ldns/SConscript b/3rdParty/Ldns/SConscript new file mode 100644 index 0000000..a43bde7 --- /dev/null +++ b/3rdParty/Ldns/SConscript @@ -0,0 +1,70 @@ +Import("env") + +if env.get("LDNS_BUNDLED", False) : + +	if env["PLATFORM"] == "win32" : +		cppflags = ["/I" + Dir("#/3rdParty/Ldns/src/ldns").abspath] +	else : +		cppflags = [("-isystem", Dir("#/3rdParty/Ldns/src/ldns").abspath)] + + +################################################################################ +# Flags +################################################################################ +     +	if env["SCONS_STAGE"] == "flags" : +		env["LDNS_FLAGS"] = { +				"CPPPATH": [Dir("src/ldns")], +				"CPPFLAGS": cppflags, +				"LIBPATH": [env.Dir(".")], +				"LIBS": ["Swiften_Ldns"], +			} +		if env["target"] == "android" : +			env["LDNS_FLAGS"]["CPPPATH"].append(Dir("src/android")) + +################################################################################ +# Build +################################################################################ + +	if env["SCONS_STAGE"] == "build" : +		myenv = env.Clone() +		myenv.Append(CPPDEFINES = [("LDNS_STATICLIB")]) +		myenv.Append(CPPPATH = ["src/ldns", "."]) +		if env["target"] == "android" : +			myenv.Append(CPPPATH = ["src/android"]) +		myenv.UseFlags(env["OPENSSL_FLAGS"]) +		 +		env["LDNS_OBJECTS"] = myenv.SwiftenObject([ +			"src/ldns/compat/b32_ntop.c", +			"src/ldns/compat/b32_pton.c", +			"src/ldns/compat/b64_ntop.c", +			"src/ldns/compat/b64_pton.c", +			"src/ldns/buffer.c", +			"src/ldns/dname.c", +			"src/ldns/dnssec_sign.c", +			"src/ldns/dnssec_verify.c", +			"src/ldns/dnssec_zone.c", +			"src/ldns/dnssec.c", +			"src/ldns/error.c", +			"src/ldns/higher.c", +			"src/ldns/host2str.c", +			"src/ldns/host2wire.c", +			"src/ldns/keys.c", +			"src/ldns/linktest.c", +			"src/ldns/net.c", +			"src/ldns/packet.c", +			"src/ldns/parse.c", +			"src/ldns/rbtree.c", +			"src/ldns/rdata.c", +			"src/ldns/resolver.c", +			"src/ldns/rr_functions.c", +			"src/ldns/rr.c", +			"src/ldns/sha1.c", +			"src/ldns/sha2.c", +			"src/ldns/str2host.c", +			"src/ldns/tsig.c", +			"src/ldns/update.c", +			"src/ldns/util.c", +			"src/ldns/wire2host.c", +			"src/ldns/zone.c", +		]) diff --git a/3rdParty/Ldns/prepare_ldns.sh b/3rdParty/Ldns/prepare_ldns.sh new file mode 100755 index 0000000..e057301 --- /dev/null +++ b/3rdParty/Ldns/prepare_ldns.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +curl -o src/ldns-1.6.16.tar.gz http://www.nlnetlabs.nl/downloads/ldns/ldns-1.6.16.tar.gz +cd src +tar -xf ldns-1.6.16.tar.gz +mv ldns-1.6.16 ldns
\ No newline at end of file diff --git a/3rdParty/LibMiniUPnPc/01_android_compilation_fixes.diff b/3rdParty/LibMiniUPnPc/01_android_compilation_fixes.diff new file mode 100644 index 0000000..4d7ade5 --- /dev/null +++ b/3rdParty/LibMiniUPnPc/01_android_compilation_fixes.diff @@ -0,0 +1,16 @@ +diff --git a/3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c b/3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c +index 87f6155..0c31416 100644 +--- a/3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c ++++ b/3rdParty/LibMiniUPnPc/src/miniupnpc/miniwget.c +@@ -44,6 +44,10 @@ + #define MIN(x,y) (((x)<(y))?(x):(y)) + #endif +  ++#ifdef __ANDROID__ ++#define MIN(x,y) (((x)<(y))?(x):(y)) ++#endif ++ + #include "miniupnpcstrings.h" + #include "miniwget.h" + #include "connecthostport.h" +-- 
\ No newline at end of file diff --git a/3rdParty/LibNATPMP/01_android_compilation_fix.diff b/3rdParty/LibNATPMP/01_android_compilation_fix.diff new file mode 100644 index 0000000..78943aa --- /dev/null +++ b/3rdParty/LibNATPMP/01_android_compilation_fix.diff @@ -0,0 +1,34 @@ +diff --git a/3rdParty/LibNATPMP/src/libnatpmp/getgateway.h b/3rdParty/LibNATPMP/src/libnatpmp/getgateway.h +index 9432528..51dadb7 100644 +--- a/3rdParty/LibNATPMP/src/libnatpmp/getgateway.h ++++ b/3rdParty/LibNATPMP/src/libnatpmp/getgateway.h +@@ -27,6 +27,11 @@ typedef unsigned short uint16_t; + #endif + #include "declspec.h" +  ++#ifdef ANDROID ++#include <arpa/inet.h> ++#define in_addr_t uint32_t ++#endif ++ + /* getdefaultgateway() : +  * return value : +  *    0 : success +diff --git a/3rdParty/LibNATPMP/src/libnatpmp/natpmp.h b/3rdParty/LibNATPMP/src/libnatpmp/natpmp.h +index 1175b58..c870371 100644 +--- a/3rdParty/LibNATPMP/src/libnatpmp/natpmp.h ++++ b/3rdParty/LibNATPMP/src/libnatpmp/natpmp.h +@@ -39,6 +39,12 @@ typedef unsigned short uint16_t; + #include <netinet/in.h> + #endif +  ++#ifdef ANDROID ++#include <arpa/inet.h> ++#define in_addr_t uint32_t ++#endif ++ ++ + typedef struct { + 	int s;	/* socket */ + 	in_addr_t gateway;	/* default gateway (IPv4) */ +-- 
\ No newline at end of file diff --git a/3rdParty/Unbound/01_android_fixes.diff b/3rdParty/Unbound/01_android_fixes.diff new file mode 100644 index 0000000..c8144ad --- /dev/null +++ b/3rdParty/Unbound/01_android_fixes.diff @@ -0,0 +1,13 @@ +--- a/3rdParty/Unbound/src/unbound/libunbound/libunbound.c ++++ b/3rdParty/Unbound/src/unbound/libunbound/libunbound.c +@@ -812,6 +812,10 @@ ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname) + 	char* parse, *addr; + 	int r; +  ++#ifdef __ANDROID__ ++	ub_ctx_set_fwd(ctx, "8.8.8.8"); ++	ub_ctx_set_fwd(ctx, "8.8.4.4"); ++#endif + 	if(fname == NULL) { + #if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H) + 		fname = "/etc/resolv.conf";
\ No newline at end of file diff --git a/3rdParty/Unbound/SConscript b/3rdParty/Unbound/SConscript new file mode 100644 index 0000000..99cd6a3 --- /dev/null +++ b/3rdParty/Unbound/SConscript @@ -0,0 +1,108 @@ +Import("env") + +if env.get("UNBOUND_BUNDLED", False) : + +	if env["PLATFORM"] == "win32" : +		cppflags = ["/I" + Dir("#/3rdParty/Unbound/src/unbound").abspath] +	else : +		cppflags = [("-isystem", Dir("#/3rdParty/Unbound/src/unbound").abspath)] + + +################################################################################ +# Flags +################################################################################ +     +	if env["SCONS_STAGE"] == "flags" : +		env["UNBOUND_FLAGS"] = { +				"CPPPATH":  [Dir("src/unbound/libunbound")], +				"CPPFLAGS": cppflags, +				"LIBPATH": [env.Dir(".")], +				"LIBS": ["Swiften_Unbound"], +			} +		if env["target"] == "android" : +			env["UNBOUND_FLAGS"]["CPPPATH"].append(Dir("src/android/compat")) + +################################################################################ +# Build +################################################################################ + +	if env["SCONS_STAGE"] == "build" : +		myenv = env.Clone() +		myenv.Append(CPPDEFINES = [("UNBOUND_STATICLIB")]) +		myenv.Append(CPPPATH = ["../Ldns/src/ldns", "src/unbound", "."]) +		if env["target"] == "android" : +			myenv.Append(CPPPATH = ["src/android/compat", "src/android/config"]) +			myenv.Append(CPPPATH = ["../Ldns/src/android"]) +		myenv.UseFlags(env["OPENSSL_FLAGS"]) + +		unbound_objects = [ +		"src/unbound/daemon/acl_list.c", +		"src/unbound/daemon/cachedump.c", +		"src/unbound/daemon/daemon.c", +		"src/unbound/daemon/remote.c", +		"src/unbound/daemon/stats.c", +		"src/unbound/daemon/unbound.c", +		# duplicate symbols: "src/src/daemon/worker.c", +		"src/unbound/iterator/iter_delegpt.c", +		"src/unbound/iterator/iter_donotq.c", +		"src/unbound/iterator/iter_fwd.c", +		"src/unbound/iterator/iter_hints.c", +		"src/unbound/iterator/iter_priv.c", +		"src/unbound/iterator/iter_resptype.c", +		"src/unbound/iterator/iter_scrub.c", +		"src/unbound/iterator/iter_utils.c", +		"src/unbound/iterator/iterator.c", +		"src/unbound/libunbound/context.c", +		"src/unbound/libunbound/libunbound.c", +		"src/unbound/libunbound/libworker.c", +		"src/unbound/services/cache/dns.c", +		"src/unbound/services/cache/infra.c", +		"src/unbound/services/cache/rrset.c", +		"src/unbound/services/listen_dnsport.c", +		"src/unbound/services/localzone.c", +		"src/unbound/services/mesh.c", +		"src/unbound/services/modstack.c", +		"src/unbound/services/outbound_list.c", +		"src/unbound/services/outside_network.c", +		"src/unbound/util/alloc.c", +		"src/unbound/util/config_file.c", +		"src/unbound/util/configlexer.c", +		"src/unbound/util/configparser.c", +		"src/unbound/util/data/dname.c", +		"src/unbound/util/data/msgencode.c", +		"src/unbound/util/data/msgparse.c", +		"src/unbound/util/data/msgreply.c", +		"src/unbound/util/data/packed_rrset.c", +		"src/unbound/util/fptr_wlist.c", +		"src/unbound/util/locks.c", +		"src/unbound/util/log.c", +		"src/unbound/util/mini_event.c", +		"src/unbound/util/module.c", +		"src/unbound/util/net_help.c", +		"src/unbound/util/netevent.c", +		"src/unbound/util/random.c", +		"src/unbound/util/rbtree.c", +		"src/unbound/util/regional.c", +		"src/unbound/util/rtt.c", +		"src/unbound/util/storage/dnstree.c", +		"src/unbound/util/storage/lookup3.c", +		"src/unbound/util/storage/lruhash.c", +		"src/unbound/util/storage/slabhash.c", +		"src/unbound/util/timehist.c", +		"src/unbound/util/tube.c", +		#src/unbound/util/winsock_event.c +		"src/unbound/validator/autotrust.c", +		"src/unbound/validator/val_anchor.c", +		"src/unbound/validator/val_kcache.c", +		"src/unbound/validator/val_kentry.c", +		"src/unbound/validator/val_neg.c", +		"src/unbound/validator/val_nsec.c", +		"src/unbound/validator/val_nsec3.c", +		"src/unbound/validator/val_secalgo.c", +		"src/unbound/validator/val_sigcrypt.c", +		"src/unbound/validator/val_utils.c", +		"src/unbound/validator/validator.c", +			] +		if env["target"] == "android" : +			unbound_objects.append("src/android/compat/glob.c") +		env["UNBOUND_OBJECTS"] = myenv.SwiftenObject(unbound_objects) diff --git a/3rdParty/Unbound/prepare_unbound.sh b/3rdParty/Unbound/prepare_unbound.sh new file mode 100755 index 0000000..b506ae4 --- /dev/null +++ b/3rdParty/Unbound/prepare_unbound.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +curl -o src/unbound-1.4.20.tar.gz http://www.unbound.net/downloads/unbound-1.4.20.tar.gz +cd src +tar -xf unbound-1.4.20.tar.gz +mv unbound-1.4.20 unbound
\ No newline at end of file diff --git a/BuildTools/SCons/SConscript.boot b/BuildTools/SCons/SConscript.boot index 9ac3cca..8429737 100644 --- a/BuildTools/SCons/SConscript.boot +++ b/BuildTools/SCons/SConscript.boot @@ -19,7 +19,9 @@ vars.Add(BoolVariable("debug", "Compile with debug information", "yes"))  vars.Add(BoolVariable("allow_warnings", "Allow compilation warnings during compilation", "yes"))  vars.Add(BoolVariable("assertions", "Compile with assertions", "yes"))  vars.Add(BoolVariable("max_jobs", "Build with maximum number of parallel jobs", "no")) -vars.Add(EnumVariable("target", "Choose a target platform for compilation", "native", ["native", "iphone-simulator", "iphone-device", "xcode"])) +vars.Add(EnumVariable("target", "Choose a target platform for compilation", "native", ["native", "iphone-simulator", "iphone-device", "xcode", "android"])) +vars.Add('android_toolchain', "Path to Android toolchain") +vars.Add('android_sdk_bin', "Path to Android SDK's tools directory")  vars.Add(BoolVariable("swift_mobile", "Build mobile Swift", "no"))  vars.Add(BoolVariable("swiften_dll", "Build Swiften as dynamically linked library", "no"))  if os.name != "nt" : @@ -68,6 +70,7 @@ vars.Add(BoolVariable("build_examples", "Build example programs", "yes"))  vars.Add(BoolVariable("enable_variants", "Build in a separate dir under build/, depending on compile flags", "no"))  vars.Add(BoolVariable("experimental", "Build experimental features", "yes"))  vars.Add(BoolVariable("set_iterator_debug_level", "Set _ITERATOR_DEBUG_LEVEL=0", "yes")) +vars.Add(BoolVariable("unbound", "Build bundled ldns and unbound. Use them for DNS lookup.", "no"))  ################################################################################  # Set up default build & configure environment @@ -284,7 +287,7 @@ if env["PLATFORM"] == "win32" :  		env["LINKCOM"] = [env["LINKCOM"], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1']  		env["SHLINKCOM"] = [env["SHLINKCOM"], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2'] -if env["PLATFORM"] == "darwin" and not env["target"] in ["iphone-device", "iphone-simulator", "xcode"] : +if env["PLATFORM"] == "darwin" and not env["target"] in ["iphone-device", "iphone-simulator", "xcode", "android"] :  	env["PLATFORM_FLAGS"]["FRAMEWORKS"] += ["IOKit", "AppKit", "SystemConfiguration", "Security", "SecurityInterface"]  # Testing @@ -351,6 +354,17 @@ if target in ["iphone-device", "iphone-simulator", "xcode"] :  	# Bit of a hack, because BOOST doesn't know the endianness for ARM  	env.Append(CPPDEFINES = ["_LITTLE_ENDIAN"])  +################################################################################ +# Android +################################################################################ +if target in ["android"] : +	env["ENV"]["PATH"] = env["android_toolchain"] + "/bin:" + env["ENV"]["PATH"] +	env["CC"] = "arm-linux-androideabi-gcc" +	env["CXX"] = "arm-linux-androideabi-g++" +	env["RANLIB"] = "arm-linux-androideabi-ranlib" +	env.Append(CPPDEFINES = ["ANDROID"]) +	env.Append(CPPDEFINES = ["_REENTRANT", "_GLIBCXX__PTHREADS"]) +  # CCache  if env.get("ccache", False) :  	env["ENV"]["HOME"] = os.environ["HOME"] diff --git a/BuildTools/SCons/SConstruct b/BuildTools/SCons/SConstruct index 75baf21..8f4d440 100644 --- a/BuildTools/SCons/SConstruct +++ b/BuildTools/SCons/SConstruct @@ -333,6 +333,14 @@ if not env.get("HAVE_ICU", False) and not env.get("HAVE_LIBIDN", False) :  	env["HAVE_LIBIDN"] = 1  	env["LIBIDN_BUNDLED"] = 1 +# Unbound +if env["unbound"] : +    env["LDNS_BUNDLED"] = 1 +    env["UNBOUND_BUNDLED"] = 1 +else : +    env["LDNS_FLAGS"] = {} +    env["UNBOUND_FLAGS"] = {} +  # LibMiniUPnPc  if env["experimental"] :  	libminiupnpc_flags = {"CPPPATH": ["/usr/include/miniupnpc/"]} @@ -427,7 +435,7 @@ if env["qt"] :  # OpenSSL  openssl_env = conf_env.Clone() -if env.get("openssl_force_bundled", False) or env["target"] in ("iphone-device", "iphone-simulator", "xcode") : +if env.get("openssl_force_bundled", False) or env["target"] in ("iphone-device", "iphone-simulator", "xcode", "android") :  	env["OPENSSL_BUNDLED"] = True  	env["HAVE_OPENSSL"] = True  else : @@ -480,7 +488,7 @@ if hunspell_conf.CheckCXXHeader("hunspell/hunspell.hxx") and hunspell_conf.Check  hunspell_conf.Finish()  # Bonjour -if env["PLATFORM"] == "darwin" : +if env["PLATFORM"] == "darwin" and env["target"] == "native" :  	env["HAVE_BONJOUR"] = 1  elif env.get("bonjour", False) :  	bonjour_env = conf_env.Clone() diff --git a/BuildTools/SCons/Tools/Test.py b/BuildTools/SCons/Tools/Test.py index c52f448..ee16ec4 100644 --- a/BuildTools/SCons/Tools/Test.py +++ b/BuildTools/SCons/Tools/Test.py @@ -19,13 +19,24 @@ def generate(env) :  			for i in ["HOME", "USERPROFILE", "APPDATA"]:  				if os.environ.get(i, "") :  					test_env["ENV"][i] = os.environ[i] -			if test_env["PLATFORM"] == "darwin" : -				test_env["ENV"]["DYLD_FALLBACK_LIBRARY_PATH"] = ":".join(map(lambda x : str(x), test_env.get("LIBPATH", []))) -			elif test_env["PLATFORM"] == "win32" : -				test_env["ENV"]["PATH"] = ";".join(map(lambda x : str(x), test_env.get("LIBRUNPATH", []))) + ";" + test_env["ENV"]["PATH"] +			if env["target"] == "android" : +				test_env["ENV"]["PATH"] = env["android_sdk_bin"] + ";" + test_env["ENV"]["PATH"] +			else : +				if test_env["PLATFORM"] == "darwin" : +					test_env["ENV"]["DYLD_FALLBACK_LIBRARY_PATH"] = ":".join(map(lambda x : str(x), test_env.get("LIBPATH", []))) +				elif test_env["PLATFORM"] == "win32" : +					test_env["ENV"]["PATH"] = ";".join(map(lambda x : str(x), test_env.get("LIBRUNPATH", []))) + ";" + test_env["ENV"]["PATH"] +  			# Run the test -			test_env.Command("**dummy**", target,  +			if env["target"] == "android": +				exec_name = os.path.basename(cmd) +				test_env.Command("**dummy**", target, SCons.Action.Action( +					["adb shell mount -o rw,remount /system", +					"adb push " + cmd + " /system/usr/bin/" + exec_name,  +					"adb shell SWIFT_CLIENTTEST_JID=\"" + os.getenv("SWIFT_CLIENTTEST_JID") + "\" SWIFT_CLIENTTEST_PASS=\"" + os.getenv("SWIFT_CLIENTTEST_PASS") + "\" " + env.get("TEST_RUNNER", "") + "/system/usr/bin/" + exec_name], cmdstr = "$TESTCOMSTR")) +			else : +				test_env.Command("**dummy**", target,   					SCons.Action.Action(ignore_prefix + env.get("TEST_RUNNER", "") + cmd + " " + params, cmdstr = "$TESTCOMSTR"))  	def registerScriptTests(env, scripts, name, type) : diff --git a/Swiften/EventLoop/SConscript b/Swiften/EventLoop/SConscript index b405f6b..8bef8fb 100644 --- a/Swiften/EventLoop/SConscript +++ b/Swiften/EventLoop/SConscript @@ -12,7 +12,7 @@ sources = [  objects = swiften_env.SwiftenObject(sources)  swiften_env.Append(SWIFTEN_OBJECTS = [objects]) -if swiften_env["PLATFORM"] == "darwin" : +if swiften_env["PLATFORM"] == "darwin" and swiften_env["target"] == "native":  	myenv = swiften_env.Clone()  	myenv.Append(CXXFLAGS = myenv["OBJCCFLAGS"])  	objects = myenv.SwiftenObject([ diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp index 9f781e4..72e826a 100644 --- a/Swiften/Network/BoostNetworkFactories.cpp +++ b/Swiften/Network/BoostNetworkFactories.cpp @@ -7,7 +7,7 @@  #include <Swiften/Network/BoostNetworkFactories.h>  #include <Swiften/Network/BoostTimerFactory.h>  #include <Swiften/Network/BoostConnectionFactory.h> -#include <Swiften/Network/PlatformDomainNameResolver.h> +  #include <Swiften/Network/BoostConnectionServerFactory.h>  #include <Swiften/Network/PlatformNATTraversalWorker.h>  #include <Swiften/Parser/PlatformXMLParserFactory.h> @@ -20,6 +20,12 @@  #include <Swiften/Crypto/PlatformCryptoProvider.h>  #include <Swiften/Crypto/CryptoProvider.h> +#ifdef USE_UNBOUND +#include <Swiften/Network/UnboundDomainNameResolver.h> +#else +#include <Swiften/Network/PlatformDomainNameResolver.h> +#endif +  namespace Swift {  BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) : eventLoop(eventLoop){ @@ -36,7 +42,12 @@ BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) : eventLoop(e  	tlsFactories = new PlatformTLSFactories();  	proxyProvider = new PlatformProxyProvider();  	idnConverter = PlatformIDNConverter::create(); +#ifdef USE_UNBOUND +	// TODO: What to do about idnConverter. +	domainNameResolver = new UnboundDomainNameResolver(ioServiceThread.getIOService(), eventLoop); +#else  	domainNameResolver = new PlatformDomainNameResolver(idnConverter, eventLoop); +#endif  	cryptoProvider = PlatformCryptoProvider::create();  } diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript index e0e5e63..ea0fb62 100644 --- a/Swiften/Network/SConscript +++ b/Swiften/Network/SConscript @@ -2,6 +2,10 @@ Import("swiften_env")  myenv = swiften_env.Clone() +if myenv.get("unbound", False) : +   myenv.MergeFlags(myenv.get("UNBOUND_FLAGS", {})) +   myenv.MergeFlags(myenv.get("LDNS_FLAGS", {})) +  sourceList = [  			"ProxiedConnection.cpp",  			"HTTPConnectProxiedConnection.cpp", @@ -30,9 +34,6 @@ sourceList = [  			"DomainNameResolver.cpp",  			"DomainNameAddressQuery.cpp",  			"DomainNameServiceQuery.cpp", -			"PlatformDomainNameResolver.cpp", -			"PlatformDomainNameServiceQuery.cpp", -			"PlatformDomainNameAddressQuery.cpp",  			"StaticDomainNameResolver.cpp",  			"HostAddress.cpp",  			"HostAddressPort.cpp", @@ -53,8 +54,16 @@ sourceList = [  			"NATTraversalRemovePortForwardingRequest.cpp",  			"NATTraversalInterface.cpp",  	] -		 -if myenv["PLATFORM"] == "darwin" : + +if myenv.get("unbound", False) : +	myenv.Append(CPPDEFINES = "USE_UNBOUND") +	sourceList.append("UnboundDomainNameResolver.cpp") +else : +	sourceList.append("PlatformDomainNameResolver.cpp") +	sourceList.append("PlatformDomainNameServiceQuery.cpp") +	sourceList.append("PlatformDomainNameAddressQuery.cpp") + +if myenv["PLATFORM"] == "darwin" and myenv["target"] != "android":  	myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"])  	sourceList += [ "MacOSXProxyProvider.cpp" ]  	sourceList += [ "UnixNetworkEnvironment.cpp" ] diff --git a/Swiften/Network/UnboundDomainNameResolver.cpp b/Swiften/Network/UnboundDomainNameResolver.cpp new file mode 100755 index 0000000..d986385 --- /dev/null +++ b/Swiften/Network/UnboundDomainNameResolver.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "UnboundDomainNameResolver.h" + +#include <vector> + +#include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/enable_shared_from_this.hpp> + +#include <Swiften/Base/Log.h> +#include <Swiften/EventLoop/EventLoop.h> +#include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/DomainNameResolveError.h> +#include <Swiften/Network/DomainNameServiceQuery.h> +#include <Swiften/Network/HostAddress.h> +#include <Swiften/Network/TimerFactory.h> + +#include <arpa/inet.h> +#include <unbound.h> +#include <ldns/ldns.h> +#include <unistd.h> + +namespace Swift { + +class UnboundQuery { +	public: +		UnboundQuery(UnboundDomainNameResolver* resolver, ub_ctx* context) : resolver(resolver), ubContext(context) {} +		virtual ~UnboundQuery() {} +		virtual void handleResult(int err, ub_result* result) = 0; +	protected: +		UnboundDomainNameResolver* resolver; +		ub_ctx* ubContext; +}; + +struct UnboundWrapperHelper { +	UnboundWrapperHelper(UnboundDomainNameResolver* resolver, boost::shared_ptr<UnboundQuery> query) : resolver(resolver), query(query) {} +	UnboundDomainNameResolver* resolver; +	boost::shared_ptr<UnboundQuery> query; +}; + +class UnboundDomainNameServiceQuery : public DomainNameServiceQuery, public UnboundQuery, public boost::enable_shared_from_this<UnboundDomainNameServiceQuery>  { +	public: +		UnboundDomainNameServiceQuery(UnboundDomainNameResolver* resolver, ub_ctx* context, std::string name) : UnboundQuery(resolver, context), name(name) { +		} + +		virtual ~UnboundDomainNameServiceQuery() { } + +		virtual void run() { +			int retval; +			UnboundWrapperHelper* helper = new UnboundWrapperHelper(resolver, shared_from_this()); + +			retval = ub_resolve_async(ubContext, const_cast<char*>(name.c_str()), LDNS_RR_TYPE_SRV, +						  1 /* CLASS IN (internet) */, +						  helper, UnboundDomainNameResolver::unbound_callback_wrapper, NULL); +			if(retval != 0) { +				SWIFT_LOG(debug) << "resolve error: " << ub_strerror(retval) << std::endl; +				delete helper; +			} +		} + +		void handleResult(int err, struct ub_result* result) { +			std::vector<DomainNameServiceQuery::Result> serviceRecords; + +			if(err != 0) { +				SWIFT_LOG(debug) << "resolve error: " << ub_strerror(err) << std::endl; +			} else { +				if(result->havedata) { +					ldns_pkt* replyPacket = 0; +					ldns_buffer* buffer = ldns_buffer_new(1024); +					if (buffer && ldns_wire2pkt(&replyPacket, static_cast<const uint8_t*>(result->answer_packet), result->answer_len) == LDNS_STATUS_OK) { +						ldns_rr_list* rrList = ldns_pkt_answer(replyPacket); +						for (size_t n = 0; n < ldns_rr_list_rr_count(rrList); n++) { +							ldns_rr* rr = ldns_rr_list_rr(rrList, n); +							if ((ldns_rr_get_type(rr) != LDNS_RR_TYPE_SRV) || +								(ldns_rr_get_class(rr) != LDNS_RR_CLASS_IN) || +								(ldns_rr_rd_count(rr) != 4)) { +								continue; +							} + +							DomainNameServiceQuery::Result serviceRecord; +							serviceRecord.priority = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0)); +							serviceRecord.weight = ldns_rdf2native_int16(ldns_rr_rdf(rr, 1)); +							serviceRecord.port = ldns_rdf2native_int16(ldns_rr_rdf(rr, 2)); + +							ldns_buffer_rewind(buffer); +							if ((ldns_rdf2buffer_str_dname(buffer, ldns_rr_rdf(rr, 3)) != LDNS_STATUS_OK) || +								(ldns_buffer_position(buffer) < 2) || +								!ldns_buffer_reserve(buffer, 1)) { +								// either name invalid, empty or buffer to small +								continue; +							} +							char terminator = 0; +							ldns_buffer_write(buffer, &terminator, sizeof(terminator)); + +							serviceRecord.hostname = std::string(reinterpret_cast<char*>(ldns_buffer_at(buffer, 0))); +							serviceRecords.push_back(serviceRecord); +							SWIFT_LOG(debug) << "hostname " << serviceRecord.hostname << " added" << std::endl; +						} +					} +					if (replyPacket) ldns_pkt_free(replyPacket); +					if (buffer) ldns_buffer_free(buffer); +				} +			} + +			ub_resolve_free(result); +			onResult(serviceRecords); +		} + +	private: +		std::string name; +}; + +class UnboundDomainNameAddressQuery : public DomainNameAddressQuery, public UnboundQuery, public boost::enable_shared_from_this<UnboundDomainNameAddressQuery> { +	public: +		UnboundDomainNameAddressQuery(UnboundDomainNameResolver* resolver, ub_ctx* context, std::string name) : UnboundQuery(resolver, context), name(name) { +		} + +		virtual ~UnboundDomainNameAddressQuery() { } + +		virtual void run() { +			int retval; +			UnboundWrapperHelper* helper = new UnboundWrapperHelper(resolver, shared_from_this()); + +			//FIXME: support AAAA queries in some way +			retval = ub_resolve_async(ubContext, const_cast<char*>(name.c_str()), LDNS_RR_TYPE_A, +						  1 /* CLASS IN (internet) */, +						  helper, UnboundDomainNameResolver::unbound_callback_wrapper, NULL); +			if(retval != 0) { +				SWIFT_LOG(debug) << "resolve error: " << ub_strerror(retval) << std::endl; +				delete helper; +			} +		} + +		void handleResult(int err, struct ub_result* result) { +			std::vector<HostAddress> addresses; +			boost::optional<DomainNameResolveError> error; +			SWIFT_LOG(debug) << "Result for: " << name << std::endl; + +			if(err != 0) { +				SWIFT_LOG(debug) << "resolve error: " << ub_strerror(err) << std::endl; +				error = DomainNameResolveError(); +			} else { +				if(result->havedata) { +					for(int i=0; result->data[i]; i++) { +						char address[100]; +						const char* addressStr = 0; +						if ((addressStr = inet_ntop(AF_INET, result->data[i], address, 100))) { +							SWIFT_LOG(debug) << "IPv4 address: " << addressStr << std::endl; +							addresses.push_back(HostAddress(std::string(addressStr))); +						} else if ((addressStr = inet_ntop(AF_INET6, result->data[i], address, 100))) { +							SWIFT_LOG(debug) << "IPv6 address: " << addressStr << std::endl; +							addresses.push_back(HostAddress(std::string(addressStr))); +						} else { +							SWIFT_LOG(debug) << "inet_ntop() failed" << std::endl; +							error = DomainNameResolveError(); +						} +					} +				} else { +					error = DomainNameResolveError(); +				} +			} + +			ub_resolve_free(result); +			onResult(addresses, error); +		} + +	private: +		std::string name; +}; + +UnboundDomainNameResolver::UnboundDomainNameResolver(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), ubDescriptior(*ioService), eventLoop(eventLoop) { +	ubContext = ub_ctx_create(); +	if(!ubContext) { +		SWIFT_LOG(debug) << "could not create unbound context" << std::endl; +	} +	eventOwner = boost::make_shared<EventOwner>(); + +	ub_ctx_async(ubContext, true); + +	int ret; + +	/* read /etc/resolv.conf for DNS proxy settings (from DHCP) */ +	if( (ret=ub_ctx_resolvconf(ubContext, const_cast<char*>("/etc/resolv.conf"))) != 0) { +		SWIFT_LOG(debug) << "error reading resolv.conf: " << ub_strerror(ret) << ". errno says: " << strerror(errno) << std::endl; +	} +	/* read /etc/hosts for locally supplied host addresses */ +	if( (ret=ub_ctx_hosts(ubContext, const_cast<char*>("/etc/hosts"))) != 0) { +		SWIFT_LOG(debug) << "error reading hosts: " << ub_strerror(ret) << ". errno says: " << strerror(errno) << std::endl; +	} + +	ubDescriptior.assign(ub_fd(ubContext)); + +	ubDescriptior.async_read_some(boost::asio::null_buffers(), boost::bind(&UnboundDomainNameResolver::handleUBSocketReadable, this, boost::asio::placeholders::error)); +} + +UnboundDomainNameResolver::~UnboundDomainNameResolver() { +	eventLoop->removeEventsFromOwner(eventOwner); +	if (ubContext) { +		ub_ctx_delete(ubContext); +	} +} + +void UnboundDomainNameResolver::unbound_callback(boost::shared_ptr<UnboundQuery> query, int err, ub_result* result) { +	query->handleResult(err, result); +} + +void UnboundDomainNameResolver::unbound_callback_wrapper(void* data, int err, ub_result* result) { +	UnboundWrapperHelper* helper = static_cast<UnboundWrapperHelper*>(data); +	UnboundDomainNameResolver* resolver = helper->resolver; +	resolver->unbound_callback(helper->query, err, result); +	delete helper; +} + +void UnboundDomainNameResolver::handleUBSocketReadable(boost::system::error_code) { +	eventLoop->postEvent(boost::bind(&UnboundDomainNameResolver::processData, this), eventOwner); +	ubDescriptior.async_read_some(boost::asio::null_buffers(), boost::bind(&UnboundDomainNameResolver::handleUBSocketReadable, this, boost::asio::placeholders::error)); +} + +void UnboundDomainNameResolver::processData() { +	if (ub_poll(ubContext)) { +		int ret = ub_process(ubContext); +		if(ret != 0) { +			SWIFT_LOG(debug) << "resolve error: " << ub_strerror(ret) << std::endl; +		} +	}	 +} + +boost::shared_ptr<DomainNameServiceQuery> UnboundDomainNameResolver::createServiceQuery(const std::string& name) { +	return boost::make_shared<UnboundDomainNameServiceQuery>(this, ubContext, name); +} + +boost::shared_ptr<DomainNameAddressQuery> UnboundDomainNameResolver::createAddressQuery(const std::string& name) { +	return boost::make_shared<UnboundDomainNameAddressQuery>(this, ubContext, name); +} + +} diff --git a/Swiften/Network/UnboundDomainNameResolver.h b/Swiften/Network/UnboundDomainNameResolver.h new file mode 100755 index 0000000..0db8a66 --- /dev/null +++ b/Swiften/Network/UnboundDomainNameResolver.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Network/DomainNameResolver.h> +#include <Swiften/Network/Timer.h> +#include <Swiften/EventLoop/EventOwner.h> + +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/asio.hpp> + +struct ub_ctx; +struct ub_result; + +namespace Swift { +	class EventLoop; +	class TimerFactory; + +	class UnboundDomainNameResolver; +	class UnboundQuery; + +	class UnboundDomainNameResolver : public DomainNameResolver, public EventOwner, public boost::enable_shared_from_this<UnboundDomainNameResolver> { +		public: +			UnboundDomainNameResolver(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop); +			virtual ~UnboundDomainNameResolver(); + +			virtual boost::shared_ptr<DomainNameServiceQuery> createServiceQuery(const std::string& name); +			virtual boost::shared_ptr<DomainNameAddressQuery> createAddressQuery(const std::string& name); + +			static void unbound_callback_wrapper(void* data, int err, ub_result* result); + +		private: +			void unbound_callback(boost::shared_ptr<UnboundQuery> query, int err, ub_result* result); + +			void handleUBSocketReadable(boost::system::error_code); +			void processData(); + +		private: +			boost::shared_ptr<EventOwner> eventOwner; +			boost::shared_ptr<boost::asio::io_service> ioService; +			boost::asio::posix::stream_descriptor ubDescriptior; +			EventLoop* eventLoop; +			ub_ctx* ubContext; +	}; + +} diff --git a/Swiften/Network/UnixNetworkEnvironment.cpp b/Swiften/Network/UnixNetworkEnvironment.cpp index 5740a65..e1fdc88 100644 --- a/Swiften/Network/UnixNetworkEnvironment.cpp +++ b/Swiften/Network/UnixNetworkEnvironment.cpp @@ -14,7 +14,10 @@  #include <sys/socket.h>  #include <arpa/inet.h>  #include <net/if.h> + +#ifndef __ANDROID__  #include <ifaddrs.h> +#endif  #include <Swiften/Base/boost_bsignals.h>  #include <Swiften/Network/HostAddress.h> @@ -24,7 +27,7 @@ namespace Swift {  std::vector<NetworkInterface> UnixNetworkEnvironment::getNetworkInterfaces() const {  	std::map<std::string, NetworkInterface> interfaces; - +#ifndef __ANDROID__  	ifaddrs* addrs = 0;  	int ret = getifaddrs(&addrs);  	if (ret != 0) { @@ -49,7 +52,7 @@ std::vector<NetworkInterface> UnixNetworkEnvironment::getNetworkInterfaces() con  	}  	freeifaddrs(addrs); - +#endif  	std::vector<NetworkInterface> result;  	for (std::map<std::string,NetworkInterface>::const_iterator i = interfaces.begin(); i != interfaces.end(); ++i) {  		result.push_back(i->second); diff --git a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp index 7bbb1a6..bc4f1a3 100644 --- a/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp +++ b/Swiften/QA/NetworkTest/DomainNameResolverTest.cpp @@ -9,11 +9,17 @@  #include <boost/bind.hpp>  #include <algorithm> -  #include <Swiften/Base/sleep.h>  #include <string>  #include <Swiften/Base/ByteArray.h> +#ifdef USE_UNBOUND +#include <Swiften/Network/UnboundDomainNameResolver.h> +#else  #include <Swiften/Network/PlatformDomainNameResolver.h> +#endif +#include <Swiften/Network/BoostTimerFactory.h> +#include <Swiften/Network/NetworkFactories.h> +#include <Swiften/Network/BoostIOServiceThread.h>  #include <Swiften/Network/DomainNameAddressQuery.h>  #include <Swiften/Network/DomainNameServiceQuery.h>  #include <Swiften/EventLoop/DummyEventLoop.h> @@ -32,24 +38,34 @@ class DomainNameResolverTest : public CppUnit::TestFixture {  		CPPUNIT_TEST_SUITE(DomainNameResolverTest);  		CPPUNIT_TEST(testResolveAddress);  		CPPUNIT_TEST(testResolveAddress_Error); +#ifndef USE_UNBOUND  		CPPUNIT_TEST(testResolveAddress_IPv6);  		CPPUNIT_TEST(testResolveAddress_IPv4and6);  		CPPUNIT_TEST(testResolveAddress_International); +#endif  		CPPUNIT_TEST(testResolveAddress_Localhost);  		CPPUNIT_TEST(testResolveAddress_Parallel); +#ifndef USE_UNBOUND  		CPPUNIT_TEST(testResolveService); +#endif  		CPPUNIT_TEST(testResolveService_Error);  		CPPUNIT_TEST_SUITE_END();  	public:  		void setUp() { +			ioServiceThread = new BoostIOServiceThread();  			eventLoop = new DummyEventLoop(); +#ifdef USE_UNBOUND +			resolver = new UnboundDomainNameResolver(ioServiceThread->getIOService(), eventLoop); +#else  			idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create());  			resolver = new PlatformDomainNameResolver(idnConverter.get(), eventLoop); +#endif  			resultsAvailable = false;  		}  		void tearDown() { +			delete ioServiceThread;  			delete resolver;  			delete eventLoop;  		} @@ -211,14 +227,16 @@ class DomainNameResolverTest : public CppUnit::TestFixture {  			}  	private: +		BoostIOServiceThread* ioServiceThread;  		DummyEventLoop* eventLoop;  		boost::shared_ptr<IDNConverter> idnConverter; +		boost::shared_ptr<TimerFactory> timerFactory;  		bool resultsAvailable;  		std::vector<HostAddress> addressQueryResult;  		std::vector<HostAddress> allAddressQueryResults;  		boost::optional<DomainNameResolveError> addressQueryError;  		std::vector<DomainNameServiceQuery::Result> serviceQueryResult; -		PlatformDomainNameResolver* resolver; +		DomainNameResolver* resolver;  };  CPPUNIT_TEST_SUITE_REGISTRATION(DomainNameResolverTest); diff --git a/Swiften/QA/NetworkTest/SConscript b/Swiften/QA/NetworkTest/SConscript index e1dea26..b090165 100644 --- a/Swiften/QA/NetworkTest/SConscript +++ b/Swiften/QA/NetworkTest/SConscript @@ -11,6 +11,9 @@ if env["TEST"] :  	myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"])  	myenv.MergeFlags(myenv["CPPUNIT_FLAGS"]) +	if env.get("unbound", False) : +		myenv.Append(CPPDEFINES = ["USE_UNBOUND"]) +  	tester = myenv.Program("NetworkTest", [  			"BoostConnectionServerTest.cpp",  			"BoostConnectionTest.cpp", diff --git a/Swiften/SConscript b/Swiften/SConscript index aab9984..9da1858 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -6,7 +6,7 @@ Import("env")  # Flags  ################################################################################ -swiften_dep_modules = ["BOOST", "GCONF", "ICU", "LIBIDN", "ZLIB", "OPENSSL", "LIBXML", "EXPAT", "AVAHI", "LIBMINIUPNPC", "LIBNATPMP", "SQLITE"] +swiften_dep_modules = ["BOOST", "GCONF", "ICU", "LIBIDN", "ZLIB", "LDNS", "UNBOUND", "OPENSSL", "LIBXML", "EXPAT", "AVAHI", "LIBMINIUPNPC", "LIBNATPMP", "SQLITE"]  external_swiften_dep_modules = ["BOOST"]  if env["SCONS_STAGE"] == "flags" : @@ -65,7 +65,6 @@ if env["SCONS_STAGE"] == "flags" :  	if env.get("HAVE_SCHANNEL", 0) :  		dep_env.Append(LIBS = ["Winscard"]) -  	for var, e in [("SWIFTEN_FLAGS", swiften_env), ("SWIFTEN_DEP_FLAGS", dep_env)] :   		env[var] = {  				"CPPDEFINES": e.get("CPPDEFINES", []), @@ -471,7 +470,7 @@ if env["SCONS_STAGE"] == "build" :  				continue  			# Library-specific files -			if file.endswith("_Private.h") or file.startswith("Schannel") or file.startswith("CAPI") or file.startswith("MacOSX") or file.startswith("Windows") or file.endswith("_Windows.h") or file.startswith("SQLite") or file == "ICUConverter.h" : +			if file.endswith("_Private.h") or file.startswith("Schannel") or file.startswith("CAPI") or file.startswith("MacOSX") or file.startswith("Windows") or file.endswith("_Windows.h") or file.startswith("SQLite") or file == "ICUConverter.h" or file == "UnboundDomainNameResolver.h" :  				continue  			# Specific headers we don't want to globally include | 
 Swift
 Swift