IPAddr -> IP

A month or two ago, I’d noticed some RSpec tests were taking a long time to run. When my ADSL connection dropped out during the day, I found the tests took an increasingly long time to run. Strange – how can lack of Internet connectivity cause some straightforward specs to… aah, it’s because they’re doing DNS lookups all the time.

Brian Candler, a colleague of mine, then published the API-compatible (UPDATE: Brian reminds me it is mostly API-compatible – see his comment) ruby-ip. To quote verbatim:

Why not IPAddr?

Ruby bundles an IPAddr class (ipaddr.rb). However there are a number of serious problems with this library.

  1. Given an IP address with a netmask or prefix (e.g. 192.0.2.0/24) it’s very hard to get access to the netmask part. It involves digging around instance variables.
  2. It’s impossible to deal with an off-base address with prefix, because IPAddr forcibly masks it to the base. e.g. 192.0.2.53/24 is stored as 192.0.2.0/24
  3. IPAddr uses calls to the socket library to validate IP addresses, and this can trigger spurious DNS lookups when given an invalid IP address. ruby-ip does not depend on the socket library at all, unless you require ‘ip/socket’ to have access to the Socket::AF_INET and Socket::AF_INET6 constants.

Today’s checkin waves goodbye to IPAddr, and gives a warm handshake to IP. Thanks, Brian!

2 Responses to “IPAddr -> IP”

  1. Thanks Peter. I must point out that ruby-ip is *not* API-compatible with IPAddr, but it’s mostly similar.

    IPAddr.new(“1.2.3.4″) –> IP.new(“1.2.3.4″)

    IPAddr.new(16909060, Socket::AF_INET) –> IP::V4.new(16909060)

    There are important semantic differences when dealing with prefixes though.

    IPAddr.new(“1.2.3.4/24″).to_s #=> “1.2.3.0″

    IP.new(“1.2.3.4/24″).to_s #=> “1.2.3.4/24″

  2. Sam Crooks says:

    Google has a really good python ipaddr manipulation library for routes and networks, IPv4, IPv6, masks, etc… could you leverage that? or port it to Ruby? maybe a wrapper for it in Ruby?

Leave a Reply