PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/ext/socket/extconf.rb

https://code.google.com/p/arosruby/
Ruby | 317 lines | 265 code | 28 blank | 24 comment | 68 complexity | 64b1c7dd5843a6ba3f52e0cb1560caad MD5 | raw file
Possible License(s): AGPL-3.0, 0BSD, Unlicense, GPL-2.0, BSD-3-Clause, LGPL-2.1
  1. require 'mkmf'
  2. case RUBY_PLATFORM
  3. when /bccwin32/
  4. test_func = "WSACleanup"
  5. have_library("ws2_32", "WSACleanup")
  6. when /mswin32|mingw/
  7. test_func = "WSACleanup"
  8. if with_config("winsock2")
  9. have_library("ws2_32", "WSACleanup")
  10. else
  11. have_library("wsock32", "WSACleanup")
  12. end
  13. when /cygwin/
  14. test_func = "socket"
  15. when /beos/
  16. test_func = "socket"
  17. have_library("net", "socket")
  18. have_func("closesocket")
  19. when /i386-os2_emx/
  20. test_func = "socket"
  21. have_library("socket", "socket")
  22. else
  23. test_func = "socket"
  24. have_library("nsl", "t_open")
  25. have_library("socket", "socket")
  26. end
  27. unless $mswin or $bccwin or $mingw
  28. headers = %w<sys/types.h netdb.h string.h sys/socket.h netinet/in.h>
  29. end
  30. if /solaris/ =~ RUBY_PLATFORM and !try_compile("")
  31. # bug of gcc 3.0 on Solaris 8 ?
  32. headers << "sys/feature_tests.h"
  33. end
  34. if have_header("arpa/inet.h")
  35. headers << "arpa/inet.h"
  36. end
  37. ipv6 = false
  38. default_ipv6 = /cygwin/ !~ RUBY_PLATFORM
  39. if enable_config("ipv6", default_ipv6)
  40. if checking_for("ipv6") {try_link(<<EOF)}
  41. #include <sys/types.h>
  42. #include <sys/socket.h>
  43. int
  44. main()
  45. {
  46. socket(AF_INET6, SOCK_STREAM, 0);
  47. }
  48. EOF
  49. $defs << "-DENABLE_IPV6" << "-DINET6"
  50. ipv6 = true
  51. end
  52. end
  53. if ipv6
  54. ipv6lib = nil
  55. class << (fmt = "unknown")
  56. def %(s) s || self end
  57. end
  58. idirs, ldirs = dir_config("inet6", %w[/usr/inet6 /usr/local/v6].find {|d| File.directory?(d)})
  59. checking_for("ipv6 type", fmt) do
  60. if have_macro("IPV6_INRIA_VERSION", "netinet/in.h")
  61. "inria"
  62. elsif have_macro("__KAME__", "netinet/in.h")
  63. have_library(ipv6lib = "inet6")
  64. "kame"
  65. elsif have_macro("_TOSHIBA_INET6", "sys/param.h")
  66. have_library(ipv6lib = "inet6") and "toshiba"
  67. elsif have_macro("__V6D__", "sys/v6config.h")
  68. have_library(ipv6lib = "v6") and "v6d"
  69. elsif have_macro("_ZETA_MINAMI_INET6", "sys/param.h")
  70. have_library(ipv6lib = "inet6") and "zeta"
  71. elsif ipv6lib = with_config("ipv6-lib")
  72. warn <<EOS
  73. --with-ipv6-lib and --with-ipv6-libdir option will be obsolete, use
  74. --with-inet6lib and --with-inet6-{include,lib} options instead.
  75. EOS
  76. find_library(ipv6lib, nil, with_config("ipv6-libdir", ldirs)) and
  77. ipv6lib
  78. elsif have_library("inet6")
  79. "inet6"
  80. end
  81. end or not ipv6lib or abort <<EOS
  82. Fatal: no #{ipv6lib} library found. cannot continue.
  83. You need to fetch lib#{ipv6lib}.a from appropriate
  84. ipv6 kit and compile beforehand.
  85. EOS
  86. end
  87. if have_struct_member("struct sockaddr_in", "sin_len", headers)
  88. $defs[-1] = "-DHAVE_SIN_LEN"
  89. end
  90. # doug's fix, NOW add -Dss_family... only if required!
  91. [nil, " -Dss_family=__ss_family -Dss_len=__ss_len"].each do |flags|
  92. if flags
  93. cppflags = $CPPFLAGS
  94. $CPPFLAGS += flags
  95. end
  96. if have_struct_member("struct sockaddr_storage", "ss_family", headers)
  97. $defs[-1] = "-DHAVE_SOCKADDR_STORAGE"
  98. break
  99. elsif flags
  100. $CPPFLAGS = cppflags
  101. end
  102. end
  103. if have_struct_member("struct sockaddr", "sa_len", headers)
  104. $defs[-1] = "-DHAVE_SA_LEN "
  105. end
  106. have_header("netinet/tcp.h") if not /cygwin/ =~ RUBY_PLATFORM # for cygwin 1.1.5
  107. have_header("netinet/udp.h")
  108. if have_func("sendmsg") | have_func("recvmsg")
  109. have_struct_member('struct msghdr', 'msg_control', ['sys/types.h', 'sys/socket.h'])
  110. have_struct_member('struct msghdr', 'msg_accrights', ['sys/types.h', 'sys/socket.h'])
  111. end
  112. getaddr_info_ok = (enable_config("wide-getaddrinfo") && :wide) ||
  113. (checking_for("wide getaddrinfo") {try_run(<<EOF)} && :os)
  114. #{COMMON_HEADERS}
  115. #{cpp_include(headers)}
  116. #include <stdlib.h>
  117. #ifndef EXIT_SUCCESS
  118. #define EXIT_SUCCESS 0
  119. #endif
  120. #ifndef EXIT_FAILURE
  121. #define EXIT_FAILURE 1
  122. #endif
  123. #ifndef AF_LOCAL
  124. #define AF_LOCAL AF_UNIX
  125. #endif
  126. int
  127. main()
  128. {
  129. int passive, gaierr, inet4 = 0, inet6 = 0;
  130. struct addrinfo hints, *ai, *aitop;
  131. char straddr[INET6_ADDRSTRLEN], strport[16];
  132. #ifdef _WIN32
  133. WSADATA retdata;
  134. WSAStartup(MAKEWORD(2, 0), &retdata);
  135. #endif
  136. for (passive = 0; passive <= 1; passive++) {
  137. memset(&hints, 0, sizeof(hints));
  138. hints.ai_family = AF_UNSPEC;
  139. hints.ai_protocol = IPPROTO_TCP;
  140. hints.ai_flags = passive ? AI_PASSIVE : 0;
  141. hints.ai_socktype = SOCK_STREAM;
  142. if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
  143. (void)gai_strerror(gaierr);
  144. goto bad;
  145. }
  146. for (ai = aitop; ai; ai = ai->ai_next) {
  147. if (ai->ai_family == AF_LOCAL) continue;
  148. if (ai->ai_addr == NULL)
  149. goto bad;
  150. #if defined(_AIX)
  151. if (ai->ai_family == AF_INET6 && passive) {
  152. inet6++;
  153. continue;
  154. }
  155. ai->ai_addr->sa_len = ai->ai_addrlen;
  156. ai->ai_addr->sa_family = ai->ai_family;
  157. #endif
  158. if (ai->ai_addrlen == 0 ||
  159. getnameinfo(ai->ai_addr, ai->ai_addrlen,
  160. straddr, sizeof(straddr), strport, sizeof(strport),
  161. NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
  162. goto bad;
  163. }
  164. if (strcmp(strport, "54321") != 0) {
  165. goto bad;
  166. }
  167. switch (ai->ai_family) {
  168. case AF_INET:
  169. if (passive) {
  170. if (strcmp(straddr, "0.0.0.0") != 0) {
  171. goto bad;
  172. }
  173. } else {
  174. if (strcmp(straddr, "127.0.0.1") != 0) {
  175. goto bad;
  176. }
  177. }
  178. inet4++;
  179. break;
  180. case AF_INET6:
  181. if (passive) {
  182. if (strcmp(straddr, "::") != 0) {
  183. goto bad;
  184. }
  185. } else {
  186. if (strcmp(straddr, "::1") != 0) {
  187. goto bad;
  188. }
  189. }
  190. inet6++;
  191. break;
  192. case AF_UNSPEC:
  193. goto bad;
  194. break;
  195. default:
  196. /* another family support? */
  197. break;
  198. }
  199. }
  200. }
  201. if (!(inet4 == 0 || inet4 == 2))
  202. goto bad;
  203. if (!(inet6 == 0 || inet6 == 2))
  204. goto bad;
  205. if (aitop)
  206. freeaddrinfo(aitop);
  207. exit(EXIT_SUCCESS);
  208. bad:
  209. if (aitop)
  210. freeaddrinfo(aitop);
  211. exit(EXIT_FAILURE);
  212. }
  213. EOF
  214. if ipv6 and not getaddr_info_ok
  215. abort <<EOS
  216. Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
  217. But your getaddrinfo() and getnameinfo() are appeared to be broken. Sorry,
  218. you cannot compile IPv6 socket classes with broken these functions.
  219. You can try --enable-wide-getaddrinfo.
  220. EOS
  221. end
  222. case with_config("lookup-order-hack", "UNSPEC")
  223. when "INET"
  224. $defs << "-DLOOKUP_ORDER_HACK_INET"
  225. when "INET6"
  226. $defs << "-DLOOKUP_ORDER_HACK_INET6"
  227. when "UNSPEC"
  228. # nothing special
  229. else
  230. abort <<EOS
  231. Fatal: invalid value for --with-lookup-order-hack (expected INET, INET6 or UNSPEC)
  232. EOS
  233. end
  234. have_type("struct addrinfo", headers)
  235. have_func("freehostent")
  236. have_func("freeaddrinfo")
  237. if have_func("gai_strerror")
  238. if checking_for("gai_strerror() returns const pointer") {!try_compile(<<EOF)}
  239. #{COMMON_HEADERS}
  240. #{cpp_include(headers)}
  241. #include <stdlib.h>
  242. void
  243. conftest_gai_strerror_is_const()
  244. {
  245. *gai_strerror(0) = 0;
  246. }
  247. EOF
  248. $defs << "-DGAI_STRERROR_CONST"
  249. end
  250. end
  251. $objs = ["socket.#{$OBJEXT}"]
  252. if getaddr_info_ok == :wide or
  253. !have_func("getnameinfo", headers) or !have_func("getaddrinfo", headers)
  254. if have_struct_member("struct in6_addr", "s6_addr8", headers)
  255. $defs[-1] = "s6_addr=s6_addr8"
  256. end
  257. if ipv6 == "kame" && have_struct_member("struct in6_addr", "s6_addr32", headers)
  258. $defs[-1] = "-DFAITH"
  259. end
  260. $CPPFLAGS="-I. "+$CPPFLAGS
  261. $objs += ["getaddrinfo.#{$OBJEXT}"]
  262. $objs += ["getnameinfo.#{$OBJEXT}"]
  263. have_func("inet_ntop") or have_func("inet_ntoa")
  264. have_func("inet_pton") or have_func("inet_aton")
  265. have_func("getservbyport")
  266. have_header("arpa/nameser.h")
  267. have_header("resolv.h")
  268. end
  269. unless have_type("socklen_t", headers)
  270. $defs << "-Dsocklen_t=int"
  271. end
  272. have_header("sys/un.h")
  273. have_header("sys/uio.h")
  274. if have_func(test_func)
  275. have_func("hsterror")
  276. have_func("getipnodebyname") or have_func("gethostbyname2")
  277. have_func("socketpair")
  278. unless have_func("gethostname")
  279. have_func("uname")
  280. end
  281. if enable_config("socks", ENV["SOCKS_SERVER"])
  282. if have_library("socks5", "SOCKSinit")
  283. $defs << "-DSOCKS5" << "-DSOCKS"
  284. elsif have_library("socks", "Rconnect")
  285. $defs << "-DSOCKS"
  286. end
  287. end
  288. create_makefile("socket")
  289. end