<commit_before>class SocketError < StandardError
end

class BasicSocket < IO
  def self.do_not_reverse_lookup=(setting)
    @no_reverse_lookup = setting
  end

  def self.do_not_reverse_lookup
    @no_reverse_lookup ? true : false
  end

  def getsockopt(level, optname)
    Socket::Foreign.getsockopt descriptor, level, optname
  end

  def setsockopt(level, optname, optval)
    optval = 1 if optval == true
    optval = 0 if optval == false

    error = 0

    case optval
    when Fixnum then
      MemoryPointer.new :socklen_t do |val|
        val.write_int optval
        error = Socket::Foreign.setsockopt(descriptor, level, optname, val,
                                           val.size)
      end
    when String then
      MemoryPointer.new optval.size do |val|
        val.write_string optval
        error = Socket::Foreign.setsockopt(descriptor, level, optname, val,
                                           optval.size)
      end
    else
      raise "socket option should be a String, a Fixnum, true, or false"
    end

    Errno.handle "Unable to set socket option" unless error == 0
    
    return 0
  end
end

class Socket < BasicSocket

  module Constants
    FFI.config_hash("socket").each do |name, value|
      const_set name, value
    end

    families = FFI.config_hash('socket').select { |name,| name =~ /^AF_/ }
    families = families.map { |name, value| [value, name] }

    AF_TO_FAMILY = Hash[*families.flatten]
  end

  module Foreign
    class AddrInfo < FFI::Struct
      config("rbx.platform.addrinfo", :ai_flags, :ai_family, :ai_socktype,
             :ai_protocol, :ai_addrlen, :ai_addr, :ai_canonname, :ai_next)
    end

    attach_function "accept", :accept, [:int, :pointer, :pointer], :int
    attach_function "bind", :_bind, [:int, :pointer, :socklen_t], :int
    attach_function "close", :close, [:int], :int
    attach_function "connect", :_connect, [:int, :pointer, :socklen_t], :int
    attach_function "listen", :listen, [:int, :int], :int
    attach_function "socket", :socket, [:int, :int, :int], :int

    attach_function "getsockopt", :_getsockopt,
                    [:int, :int, :int, :pointer, :pointer], :int
    attach_function "setsockopt", :setsockopt,
                    [:int, :int, :int, :pointer, :socklen_t], :int

    attach_function "gai_strerror", :gai_strerror, [:int], :string

    attach_function "getaddrinfo", :_getaddrinfo,
                    [:string, :string, :pointer, :pointer], :int
    attach_function "freeaddrinfo", :freeaddrinfo, [:pointer], :void
    attach_function "getpeername", :_getpeername,
                    [:int, :pointer, :pointer], :int
    attach_function "getsockname", :_getsockname,
                    [:int, :pointer, :pointer], :int

    attach_function "socketpair", :socketpair,
                    [:int, :int, :int, :pointer], :int

    attach_function "gethostname", :gethostname, [:pointer, :size_t], :int
    attach_function "getservbyname", :getservbyname,
                    [:pointer, :pointer], :pointer

    attach_function "htons", :htons, [:u_int16_t], :u_int16_t
    attach_function "ntohs", :ntohs, [:u_int16_t], :u_int16_t

    attach_function "ffi_getnameinfo", :_getnameinfo,
                    [:state, :pointer, :socklen_t, :int], :object

    #attach_function "ffi_pack_sockaddr_un", :pack_sa_unix,
    #                [:state, :string], :object

    def self.bind(descriptor, sockaddr)
      MemoryPointer.new :char, sockaddr.length do |sockaddr_p|
        sockaddr_p.write_string sockaddr, sockaddr.length

        _bind descriptor, sockaddr_p, sockaddr.length
      end
    end

    def self.connect(descriptor, sockaddr)
      err = 0
      MemoryPointer.new :char, sockaddr.length do |sockaddr_p|
        sockaddr_p.write_string sockaddr, sockaddr.length

        err = _connect descriptor, sockaddr_p, sockaddr.length
      end
      
      getsockopt(descriptor, Socket::SOL_SOCKET, Socket::SO_ERROR) if err < 0
      err
    end

    def self.getsockopt(descriptor, level, optname)
      MemoryPointer.new 256 do |val| # HACK magic number
        MemoryPointer.new :socklen_t do |length|
          length.write_int 256 # HACK magic number

          err = Socket::Foreign._getsockopt descriptor, level, optname, val, length

          Errno.handle "Unable to get socket option" unless err == 0

          return val.read_string(length.read_int)
        end
      end
    end

    def self.getaddrinfo(host, service, family, socktype, protocol, flags)
      hints = Socket::Foreign::AddrInfo.new
      hints[:ai_family] = family
      hints[:ai_socktype] = socktype
      hints[:ai_protocol] = protocol
      hints[:ai_flags] = flags
      host = "" if host.nil?

      if host.empty? 
        if (flags & Socket::AI_PASSIVE == 1) # Passive socket
          family == Socket::AF_INET6 ? (host = "::") : (host = "0.0.0.0") # IPv6 or IPv4
        else
          family == Socket::AF_INET6 ? (host = "::1") : (host = "127.0.0.1")
        end
      end

      res_p = MemoryPointer.new :pointer

      err = _getaddrinfo host, service, hints.pointer, res_p

      raise SocketError, Socket::Foreign.gai_strerror(err) unless err == 0

      ptr = res_p.read_pointer
      
      return [] unless ptr

      res = Socket::Foreign::AddrInfo.new ptr

      addrinfos = []

      loop do
        addrinfo = []
        addrinfo << res[:ai_flags]
        addrinfo << res[:ai_family]
        addrinfo << res[:ai_socktype]
        addrinfo << res[:ai_protocol]
        addrinfo << res[:ai_addr].read_string(res[:ai_addrlen])
        addrinfo << res[:ai_canonname]

        addrinfos << addrinfo

        break unless res[:ai_next]

        res = Socket::Foreign::AddrInfo.new res[:ai_next]
      end

      return addrinfos
    ensure
      hints.free if hints

      if res_p then
        ptr = res_p.read_pointer

        # Be sure to feed a legit pointer to freeaddrinfo
        if ptr and !ptr.null?
          Socket::Foreign.freeaddrinfo ptr
        end
        res_p.free
      end
    end

    def self.getaddress(host)
      addrinfos = Socket::Foreign.getaddrinfo(host, nil, 0, 0, 0, Socket::NI_NUMERICHOST)
      addrinfos.first[3]
    end
    <commit_msg>Fixing behavior for IPSocket#getaddress<commit_after>class SocketError < StandardError
end

class BasicSocket < IO
  def self.do_not_reverse_lookup=(setting)
    @no_reverse_lookup = setting
  end

  def self.do_not_reverse_lookup
    @no_reverse_lookup ? true : false
  end

  def getsockopt(level, optname)
    Socket::Foreign.getsockopt descriptor, level, optname
  end

  def setsockopt(level, optname, optval)
    optval = 1 if optval == true
    optval = 0 if optval == false

    error = 0

    case optval
    when Fixnum then
      MemoryPointer.new :socklen_t do |val|
        val.write_int optval
        error = Socket::Foreign.setsockopt(descriptor, level, optname, val,
                                           val.size)
      end
    when String then
      MemoryPointer.new optval.size do |val|
        val.write_string optval
        error = Socket::Foreign.setsockopt(descriptor, level, optname, val,
                                           optval.size)
      end
    else
      raise "socket option should be a String, a Fixnum, true, or false"
    end

    Errno.handle "Unable to set socket option" unless error == 0
    
    return 0
  end
end

class Socket < BasicSocket

  module Constants
    FFI.config_hash("socket").each do |name, value|
      const_set name, value
    end

    families = FFI.config_hash('socket').select { |name,| name =~ /^AF_/ }
    families = families.map { |name, value| [value, name] }

    AF_TO_FAMILY = Hash[*families.flatten]
  end

  module Foreign
    class AddrInfo < FFI::Struct
      config("rbx.platform.addrinfo", :ai_flags, :ai_family, :ai_socktype,
             :ai_protocol, :ai_addrlen, :ai_addr, :ai_canonname, :ai_next)
    end

    attach_function "accept", :accept, [:int, :pointer, :pointer], :int
    attach_function "bind", :_bind, [:int, :pointer, :socklen_t], :int
    attach_function "close", :close, [:int], :int
    attach_function "connect", :_connect, [:int, :pointer, :socklen_t], :int
    attach_function "listen", :listen, [:int, :int], :int
    attach_function "socket", :socket, [:int, :int, :int], :int

    attach_function "getsockopt", :_getsockopt,
                    [:int, :int, :int, :pointer, :pointer], :int
    attach_function "setsockopt", :setsockopt,
                    [:int, :int, :int, :pointer, :socklen_t], :int

    attach_function "gai_strerror", :gai_strerror, [:int], :string

    attach_function "getaddrinfo", :_getaddrinfo,
                    [:string, :string, :pointer, :pointer], :int
    attach_function "freeaddrinfo", :freeaddrinfo, [:pointer], :void
    attach_function "getpeername", :_getpeername,
                    [:int, :pointer, :pointer], :int
    attach_function "getsockname", :_getsockname,
                    [:int, :pointer, :pointer], :int

    attach_function "socketpair", :socketpair,
                    [:int, :int, :int, :pointer], :int

    attach_function "gethostname", :gethostname, [:pointer, :size_t], :int
    attach_function "getservbyname", :getservbyname,
                    [:pointer, :pointer], :pointer

    attach_function "htons", :htons, [:u_int16_t], :u_int16_t
    attach_function "ntohs", :ntohs, [:u_int16_t], :u_int16_t

    attach_function "ffi_getnameinfo", :_getnameinfo,
                    [:state, :pointer, :socklen_t, :int], :object

    #attach_function "ffi_pack_sockaddr_un", :pack_sa_unix,
    #                [:state, :string], :object

    def self.bind(descriptor, sockaddr)
      MemoryPointer.new :char, sockaddr.length do |sockaddr_p|
        sockaddr_p.write_string sockaddr, sockaddr.length

        _bind descriptor, sockaddr_p, sockaddr.length
      end
    end

    def self.connect(descriptor, sockaddr)
      err = 0
      MemoryPointer.new :char, sockaddr.length do |sockaddr_p|
        sockaddr_p.write_string sockaddr, sockaddr.length

        err = _connect descriptor, sockaddr_p, sockaddr.length
      end
      
      getsockopt(descriptor, Socket::SOL_SOCKET, Socket::SO_ERROR) if err < 0
      err
    end

    def self.getsockopt(descriptor, level, optname)
      MemoryPointer.new 256 do |val| # HACK magic number
        MemoryPointer.new :socklen_t do |length|
          length.write_int 256 # HACK magic number

          err = Socket::Foreign._getsockopt descriptor, level, optname, val, length

          Errno.handle "Unable to get socket option" unless err == 0

          return val.read_string(length.read_int)
        end
      end
    end

    def self.getaddrinfo(host, service, family, socktype, protocol, flags)
      hints = Socket::Foreign::AddrInfo.new
      hints[:ai_family] = family
      hints[:ai_socktype] = socktype
      hints[:ai_protocol] = protocol
      hints[:ai_flags] = flags
      host = "" if host.nil?

      if host.empty? 
        if (flags & Socket::AI_PASSIVE == 1) # Passive socket
          family == Socket::AF_INET6 ? (host = "::") : (host = "0.0.0.0") # IPv6 or IPv4
        else
          family == Socket::AF_INET6 ? (host = "::1") : (host = "127.0.0.1")
        end
      end

      res_p = MemoryPointer.new :pointer

      err = _getaddrinfo host, service, hints.pointer, res_p

      raise SocketError, Socket::Foreign.gai_strerror(err) unless err == 0

      ptr = res_p.read_pointer
      
      return [] unless ptr

      res = Socket::Foreign::AddrInfo.new ptr

      addrinfos = []

      loop do
        addrinfo = []
        addrinfo << res[:ai_flags]
        addrinfo << res[:ai_family]
        addrinfo << res[:ai_socktype]
        addrinfo << res[:ai_protocol]
        addrinfo << res[:ai_addr].read_string(res[:ai_addrlen])
        addrinfo << res[:ai_canonname]

        addrinfos << addrinfo

        break unless res[:ai_next]

        res = Socket::Foreign::AddrInfo.new res[:ai_next]
      end

      return addrinfos
    ensure
      hints.free if hints

      if res_p then
        ptr = res_p.read_pointer

        # Be sure to feed a legit pointer to freeaddrinfo
        if ptr and !ptr.null?
          Socket::Foreign.freeaddrinfo ptr
        end
        res_p.free
      end
    end

    def self.getaddress(host)
      addrinfos = Socket.getaddrinfo(host)
      addrinfos.first[3]
    end
    
{'fraction_non_alphanumeric': 0.1104195295449034, 'fraction_numerical': 0.0067092393500929595, 'mean_word_length': 2.5561943087093995, 'pattern_counts': {'":': 4, '<': 41, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '599441', 'n_tokens_mistral': 4073, 'n_tokens_neox': 3887, 'n_words': 992}