Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating a new TCPServer on the unspecified address (0.0.0.0) creates a ipv6 address, not ipv4 #5883

Open
nateberkopec opened this issue Sep 19, 2019 · 3 comments

Comments

@nateberkopec
Copy link

commented Sep 19, 2019

Environment

  • jruby 9.2.7.0 (2.5.3) 2019-04-09 8a269e3 Java HotSpot(TM) 64-Bit Server VM 25.65-b01 on 1.8.0_65-b17 +jit [darwin-x86_64]
  • Darwin odachi 18.7.0 Darwin Kernel Version 18.7.0: Thu Jun 20 18:42:21 PDT 2019; root:xnu-4903.270.47~4/RELEASE_X86_64 x86_64

Behavior

require 'socket'
s = TCPServer.new("0.0.0.0", 9292)
# MRI: #<TCPServer:fd 11, AF_INET, 0.0.0.0, 9292>
# JRuby: #<TCPServer:fd 5>
s.local_address
# MRI: #<Addrinfo: 0.0.0.0:9292 TCP>
# JRuby: #<Addrinfo: [::]:9292>

Maybe related maybe not:

Socket.ip_address_list.select do |addrinfo|
  addrinfo.ipv6_loopback? || addrinfo.ipv4_loopback?
end.map { |addrinfo| addrinfo.ip_address }.uniq
# MRI: ["127.0.0.1", "::1"]
# JRuby: ["::1", "127.0.0.1"]
@headius

This comment has been minimized.

Copy link
Member

commented Sep 21, 2019

This logic pretty much just leans on the JDK to make a connection. See the FAQ here: https://github.com/jruby/jruby/wiki/FAQs#networking

[] ~/projects/ruby $ jruby -rsocket -e 'p TCPServer.new("0.0.0.0", 9292).local_address'
#<Addrinfo: [::]:9292>

[] ~/projects/ruby $ jruby -J-Djava.net.preferIPv4Stack=true -rsocket -e 'p TCPServer.new("0.0.0.0", 9292).local_address'
#<Addrinfo: 0.0.0.0:9292>

Just to make it clear this is a JDK behavior, here's a script that uses the JDK classes directly from Ruby:

[] ~/projects/jruby $ cat blah.rb
addr = java.net.InetAddress.getByName('0.0.0.0')
ssc = java.nio.channels.ServerSocketChannel.open()
socket_address = java.net.InetSocketAddress.new(addr, 9292)
ssc.socket().bind(socket_address)
puts ssc

[] ~/projects/jruby $ jruby blah.rb
sun.nio.ch.ServerSocketChannelImpl[/0:0:0:0:0:0:0:0:9292]

[] ~/projects/jruby $ jruby -J-Djava.net.preferIPv4Stack=true blah.rb
sun.nio.ch.ServerSocketChannelImpl[/0.0.0.0:9292]
@headius

This comment has been minimized.

Copy link
Member

commented Sep 21, 2019

A bit more info from the docs of OpenJDK itself: https://docs.oracle.com/javase/8/docs/technotes/guides/net/ipv6_guide/index.html

On dual stack machines, system properties are provided for setting the preferred protocol stack—IPv4 or IPv6—as well as the preferred address family types—inet4 or inet6.

IPv6 stack is preferred by default, since on a dual-stack machine IPv6 socket can talk to both IPv4 and IPv6 peers.

This setting can be changed through the java.net.preferIPv4Stack=<true|false> system property.

At one point we did attempt to force IPv4, but that resulted in JRuby sockets being unable, by default, to connect to IPv6 hosts.

@headius

This comment has been minimized.

Copy link
Member

commented Sep 21, 2019

I think this is the issue where we removed the IPv4 property, because it was interfering with IPv6 operation: #1286.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.