UDPSocket#bind should interpret the empty string as INADDR_ANY, not loopback
----------------------------------------------------------------------------

                 Key: JRUBY-3564
                 URL: http://jira.codehaus.org/browse/JRUBY-3564
             Project: JRuby
          Issue Type: Bug
          Components: Core Classes/Modules
    Affects Versions: JRuby 1.2
         Environment: Solaris 10 x86 and Mac OS X 10.5 Intel
            Reporter: Clayton Wheeler
         Attachments: udp_inaddr_any.patch

Calling UDPSocket#bind with the empty string for the address specification is 
meant to signify INADDR_ANY (0.0.0.0), but in JRuby it binds to the loopback 
address (127.0.0.1) instead. The RubyUDPSocket class passes the empty string to 
the InetSocketAddress constructor, which interprets it as 127.0.0.1. (See 
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4970439 for confirmation 
that this is intentional JDK behavior.)

I noticed this because it breaks the Resolv::DNS library in JRuby. It binds a 
UDP socket with the empty string; on MRI this gives it an INADDR_ANY socket 
that works for queries, but on JRuby it gets a socket bound to the loopback 
interface and tries to query name servers with that, which does not work. This 
is a non-obvious failure mode, too; it took me half an hour with truss, pfiles, 
and jstack to work out what was going on.

There is an RSpec test case for this in 
spec/ruby/library/socket/udpsocket/bind_spec.rb; "binds to INADDR_ANY if the 
hostname is empty". However, it currently fails for an unrelated reason; 
JRuby's getsockname returns something that isn't a struct sockaddr. I have 
filed JRUBY-3563 which contains a fix for that.

In the mean time, the test script included should suffice.

See the attached udp_inaddr_any.patch for a fix.


==== START test script ====

#!/usr/bin/env ruby

require 'socket'

s = UDPSocket.new()
s.bind('', 21264)
addr = s.addr[3]
if addr == '0.0.0.0'
  puts "OK, got INADDR_ANY: #{s.addr.inspect}"
  exit 0
else
  puts "WRONG, got loopback: #{s.addr.inspect}"
end

==== END test script ====

$ ruby bind-test-case
OK, got INADDR_ANY: ["AF_INET", 21264, "0.0.0.0", "0.0.0.0"]
$ ./bin/jruby bind-test-case
WRONG, got loopback: ["AF_INET", 21264, "localhost", "127.0.0.1"]


==== With patch for JRUBY-3563, before fix ====

$ ./spec/mspec/bin/mspec run -t j 
spec/ruby/library/socket/udpsocket/bind_spec.rb
jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-04-11 rev 9531) [i386-java]
..F

1)
UDPSocket.bind binds to INADDR_ANY if the hostname is empty FAILED
Expected "127.0.0.1"
 to equal "0.0.0.0"

/Users/csw/src/jruby-1_2/spec/ruby/library/socket/udpsocket/bind_spec.rb:32
/Users/csw/src/jruby-1_2/spec/ruby/library/socket/udpsocket/bind_spec.rb:4
/Users/csw/src/jruby-1_2/spec/ruby/library/socket/udpsocket/bind_spec.rb:55:in 
`load'

Finished in 0.205000 seconds

1 file, 3 examples, 4 expectations, 1 failure, 0 errors

==== With fix ====

$ ./spec/mspec/bin/mspec run -t j 
spec/ruby/library/socket/udpsocket/bind_spec.rb
jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-04-11 rev 9531) [i386-java]
...

Finished in 0.219000 seconds

1 file, 3 examples, 4 expectations, 0 failures, 0 errors

$ ./bin/jruby bind-test-case
OK, got INADDR_ANY: ["AF_INET", 21264, "0.0.0.0", "0.0.0.0"]



-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to