PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/ext/socket/extconf.rb

https://github.com/thewoolleyman/ruby
Ruby | 350 lines | 291 code | 34 blank | 25 comment | 62 complexity | a534b3de5e875e3f123758dfe1080593 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, AGPL-3.0
  1. require 'mkmf'
  2. case RUBY_PLATFORM
  3. when /(ms|bcc)win32|mingw/
  4. test_func = "WSACleanup"
  5. have_library("ws2_32", "WSACleanup")
  6. when /cygwin/
  7. test_func = "socket"
  8. when /beos/
  9. test_func = "socket"
  10. have_library("net", "socket")
  11. when /haiku/
  12. test_func = "socket"
  13. have_library("network", "socket")
  14. when /i386-os2_emx/
  15. test_func = "socket"
  16. have_library("socket", "socket")
  17. else
  18. test_func = "socket"
  19. have_library("nsl", "t_open")
  20. have_library("socket", "socket")
  21. end
  22. unless $mswin or $bccwin or $mingw
  23. headers = %w<sys/types.h netdb.h string.h sys/socket.h netinet/in.h>
  24. end
  25. if /solaris/ =~ RUBY_PLATFORM and !try_compile("")
  26. # bug of gcc 3.0 on Solaris 8 ?
  27. headers << "sys/feature_tests.h"
  28. end
  29. if have_header("arpa/inet.h")
  30. headers << "arpa/inet.h"
  31. end
  32. ipv6 = false
  33. default_ipv6 = /mswin|cygwin|beos|haiku/ !~ RUBY_PLATFORM
  34. if enable_config("ipv6", default_ipv6)
  35. if checking_for("ipv6") {try_link(<<EOF)}
  36. #include <sys/types.h>
  37. #ifndef _WIN32
  38. #include <sys/socket.h>
  39. #endif
  40. int
  41. main()
  42. {
  43. socket(AF_INET6, SOCK_STREAM, 0);
  44. }
  45. EOF
  46. $defs << "-DENABLE_IPV6" << "-DINET6"
  47. ipv6 = true
  48. end
  49. end
  50. if ipv6
  51. if $mingw
  52. $CPPFLAGS << " -D_WIN32_WINNT=0x501"
  53. end
  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. doug = proc {have_struct_member("struct sockaddr_storage", "ss_family", headers)}
  92. if (doug[] or
  93. with_cppflags($CPPFLAGS + " -Dss_family=__ss_family -Dss_len=__ss_len", &doug))
  94. $defs[-1] = "-DHAVE_SOCKADDR_STORAGE"
  95. end
  96. if have_struct_member("struct sockaddr", "sa_len", headers)
  97. $defs[-1] = "-DHAVE_SA_LEN "
  98. end
  99. have_header("netinet/tcp.h") if not /cygwin/ =~ RUBY_PLATFORM # for cygwin 1.1.5
  100. have_header("netinet/udp.h")
  101. if have_func("sendmsg") | have_func("recvmsg")
  102. have_struct_member('struct msghdr', 'msg_control', ['sys/types.h', 'sys/socket.h'])
  103. have_struct_member('struct msghdr', 'msg_accrights', ['sys/types.h', 'sys/socket.h'])
  104. end
  105. getaddr_info_ok = enable_config("wide-getaddrinfo") do
  106. checking_for("wide getaddrinfo") {try_run(<<EOF)}
  107. #{cpp_include(headers)}
  108. #include <stdlib.h>
  109. #ifndef EXIT_SUCCESS
  110. #define EXIT_SUCCESS 0
  111. #endif
  112. #ifndef EXIT_FAILURE
  113. #define EXIT_FAILURE 1
  114. #endif
  115. #ifndef AF_LOCAL
  116. #define AF_LOCAL AF_UNIX
  117. #endif
  118. int
  119. main()
  120. {
  121. int passive, gaierr, inet4 = 0, inet6 = 0;
  122. struct addrinfo hints, *ai, *aitop;
  123. char straddr[INET6_ADDRSTRLEN], strport[16];
  124. #ifdef _WIN32
  125. WSADATA retdata;
  126. WSAStartup(MAKEWORD(2, 0), &retdata);
  127. #endif
  128. for (passive = 0; passive <= 1; passive++) {
  129. memset(&hints, 0, sizeof(hints));
  130. hints.ai_family = AF_UNSPEC;
  131. hints.ai_protocol = IPPROTO_TCP;
  132. hints.ai_flags = passive ? AI_PASSIVE : 0;
  133. hints.ai_socktype = SOCK_STREAM;
  134. if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
  135. (void)gai_strerror(gaierr);
  136. goto bad;
  137. }
  138. for (ai = aitop; ai; ai = ai->ai_next) {
  139. if (ai->ai_family == AF_LOCAL) continue;
  140. if (ai->ai_addr == NULL)
  141. goto bad;
  142. #if defined(_AIX)
  143. if (ai->ai_family == AF_INET6 && passive) {
  144. inet6++;
  145. continue;
  146. }
  147. ai->ai_addr->sa_len = ai->ai_addrlen;
  148. ai->ai_addr->sa_family = ai->ai_family;
  149. #endif
  150. if (ai->ai_addrlen == 0 ||
  151. getnameinfo(ai->ai_addr, ai->ai_addrlen,
  152. straddr, sizeof(straddr), strport, sizeof(strport),
  153. NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
  154. goto bad;
  155. }
  156. if (strcmp(strport, "54321") != 0) {
  157. goto bad;
  158. }
  159. switch (ai->ai_family) {
  160. case AF_INET:
  161. if (passive) {
  162. if (strcmp(straddr, "0.0.0.0") != 0) {
  163. goto bad;
  164. }
  165. } else {
  166. if (strcmp(straddr, "127.0.0.1") != 0) {
  167. goto bad;
  168. }
  169. }
  170. inet4++;
  171. break;
  172. case AF_INET6:
  173. if (passive) {
  174. if (strcmp(straddr, "::") != 0) {
  175. goto bad;
  176. }
  177. } else {
  178. if (strcmp(straddr, "::1") != 0) {
  179. goto bad;
  180. }
  181. }
  182. inet6++;
  183. break;
  184. case AF_UNSPEC:
  185. goto bad;
  186. break;
  187. default:
  188. /* another family support? */
  189. break;
  190. }
  191. }
  192. }
  193. if (!(inet4 == 0 || inet4 == 2))
  194. goto bad;
  195. if (!(inet6 == 0 || inet6 == 2))
  196. goto bad;
  197. if (aitop)
  198. freeaddrinfo(aitop);
  199. exit(EXIT_SUCCESS);
  200. bad:
  201. if (aitop)
  202. freeaddrinfo(aitop);
  203. exit(EXIT_FAILURE);
  204. }
  205. EOF
  206. end
  207. if ipv6 and not getaddr_info_ok
  208. abort <<EOS
  209. Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
  210. But your getaddrinfo() and getnameinfo() are appeared to be broken. Sorry,
  211. you cannot compile IPv6 socket classes with broken these functions.
  212. You can try --enable-wide-getaddrinfo.
  213. EOS
  214. end
  215. case with_config("lookup-order-hack", "UNSPEC")
  216. when "INET"
  217. $defs << "-DLOOKUP_ORDER_HACK_INET"
  218. when "INET6"
  219. $defs << "-DLOOKUP_ORDER_HACK_INET6"
  220. when "UNSPEC"
  221. # nothing special
  222. else
  223. abort <<EOS
  224. Fatal: invalid value for --with-lookup-order-hack (expected INET, INET6 or UNSPEC)
  225. EOS
  226. end
  227. $objs = [
  228. "init.#{$OBJEXT}",
  229. "constants.#{$OBJEXT}",
  230. "basicsocket.#{$OBJEXT}",
  231. "socket.#{$OBJEXT}",
  232. "ipsocket.#{$OBJEXT}",
  233. "tcpsocket.#{$OBJEXT}",
  234. "tcpserver.#{$OBJEXT}",
  235. "sockssocket.#{$OBJEXT}",
  236. "udpsocket.#{$OBJEXT}",
  237. "unixsocket.#{$OBJEXT}",
  238. "unixserver.#{$OBJEXT}",
  239. "option.#{$OBJEXT}",
  240. "ancdata.#{$OBJEXT}",
  241. "raddrinfo.#{$OBJEXT}"
  242. ]
  243. unless getaddr_info_ok and have_func("getnameinfo", headers) and have_func("getaddrinfo", headers)
  244. if have_struct_member("struct in6_addr", "s6_addr8", headers)
  245. $defs[-1] = "-DHAVE_ADDR8"
  246. end
  247. $CPPFLAGS="-I. "+$CPPFLAGS
  248. $objs += ["getaddrinfo.#{$OBJEXT}"]
  249. $objs += ["getnameinfo.#{$OBJEXT}"]
  250. $defs << "-DGETADDRINFO_EMU"
  251. have_func("inet_ntop") or have_func("inet_ntoa")
  252. have_func("inet_pton") or have_func("inet_aton")
  253. have_func("getservbyport")
  254. if have_func("gai_strerror")
  255. unless checking_for("gai_strerror() returns const pointer") {!try_compile(<<EOF)}
  256. #{cpp_include(headers)}
  257. #include <stdlib.h>
  258. void
  259. conftest_gai_strerror_is_const()
  260. {
  261. *gai_strerror(0) = 0;
  262. }
  263. EOF
  264. $defs << "-DGAI_STRERROR_CONST"
  265. end
  266. end
  267. have_header("arpa/nameser.h")
  268. have_header("resolv.h")
  269. end
  270. have_header("ifaddrs.h")
  271. have_func("getifaddrs")
  272. have_header("sys/ioctl.h")
  273. have_header("sys/sockio.h")
  274. have_header("net/if.h", headers)
  275. have_header("sys/param.h", headers)
  276. have_header("sys/ucred.h", headers)
  277. unless have_type("socklen_t", headers)
  278. $defs << "-Dsocklen_t=int"
  279. end
  280. have_header("sys/un.h")
  281. have_header("sys/uio.h")
  282. have_type("struct in_pktinfo", headers) {|src|
  283. src.sub(%r'^/\*top\*/', '\1'"\n#if defined(IPPROTO_IP) && defined(IP_PKTINFO)") <<
  284. "#else\n" << "#error\n" << ">>>>>> no in_pktinfo <<<<<<\n" << "#endif\n"
  285. }
  286. have_type("struct in6_pktinfo", headers) {|src|
  287. src.sub(%r'^/\*top\*/', '\1'"\n#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO)") <<
  288. "#else\n" << "#error\n" << ">>>>>> no in6_pktinfo <<<<<<\n" << "#endif\n"
  289. }
  290. if have_struct_member("struct in_pktinfo", "ipi_spec_dst", headers)
  291. $defs[-1] = "-DHAVE_IPI_SPEC_DST"
  292. end
  293. have_type("struct sockcred", headers)
  294. have_type("struct cmsgcred", headers)
  295. have_func("getpeereid")
  296. have_header("ucred.h", headers)
  297. have_func("getpeerucred")
  298. # workaround for recent Windows SDK
  299. $defs << "-DIPPROTO_IPV6=IPPROTO_IPV6" if have_const("IPPROTO_IPV6") && !have_macro("IPPROTO_IPV6")
  300. $distcleanfiles << "constants.h" << "constdefs.*"
  301. if have_func(test_func)
  302. have_func("hsterror")
  303. have_func("getipnodebyname") or have_func("gethostbyname2")
  304. have_func("socketpair")
  305. unless have_func("gethostname")
  306. have_func("uname")
  307. end
  308. if enable_config("socks", ENV["SOCKS_SERVER"])
  309. if have_library("socks5", "SOCKSinit")
  310. $defs << "-DSOCKS5" << "-DSOCKS"
  311. elsif have_library("socks", "Rconnect")
  312. $defs << "-DSOCKS"
  313. end
  314. end
  315. create_makefile("socket")
  316. end