Class: IParty::Address

Inherits:
IPAddr
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/iparty/address.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, **kw) ⇒ Address

Returns a new instance of Address.

Raises:

  • (IPAddr::AddressFamilyError)


11
12
13
14
15
16
17
# File 'lib/iparty/address.rb', line 11

def initialize *args, **kw
  self.ipv6_significant = kw.fetch(:significant, true)
  super(*args)
  self.ipv6_significant = true if force_significant?

  raise IPAddr::AddressFamilyError, "unsupported address family" unless ipv4? || ipv6?
end

Instance Attribute Details

#ipv6_significantObject

Returns the value of attribute ipv6_significant.



9
10
11
# File 'lib/iparty/address.rb', line 9

def ipv6_significant
  @ipv6_significant
end

Instance Method Details

#annotationsObject



124
125
126
127
128
129
130
131
132
133
# File 'lib/iparty/address.rb', line 124

def annotations
  result = {}
  IParty.config.annotations&.each do |ipp, adata|
    next unless ipp.include?(self)

    result.merge!(adata.merge(tags: result.fetch(:tags, []) | adata.fetch(:tags, [])))
  end

  result unless result.empty?
end

#as_jsonObject



135
136
137
138
139
140
141
142
143
144
# File 'lib/iparty/address.rb', line 135

def as_json
  {
    type: type,
    prefix: prefix,
    address: to_s,
    cidr: to_cidr,
    network: nil,
    annotations: annotations,
  }.merge(asn.merge(network: nil), geo).compact
end

#asnObject



108
109
110
# File 'lib/iparty/address.rb', line 108

def asn
  defined?(@_asn) ? @_asn : (@_asn = MaxMind.lookup(:ASN, self, result_class: MaxMind::Result::Asn) || MaxMind::Result::Asn.new)
end

#force_significant?Boolean

Returns:

  • (Boolean)


19
20
21
# File 'lib/iparty/address.rb', line 19

def force_significant?
  @family == Socket::AF_INET6 && @addr == 1
end

#geoObject



120
121
122
# File 'lib/iparty/address.rb', line 120

def geo
  defined?(@_geo) ? @_geo : (@_geo = geo_city.presence || geo_country.presence || MaxMind::Result::Geo.new)
end

#geo_cityObject



116
117
118
# File 'lib/iparty/address.rb', line 116

def geo_city
  defined?(@_city) ? @_city : (@_city = MaxMind.lookup(:City, self, result_class: MaxMind::Result::GeoCity) || MaxMind::Result::GeoCity.new)
end

#geo_countryObject



112
113
114
# File 'lib/iparty/address.rb', line 112

def geo_country
  defined?(@_country) ? @_country : (@_country = MaxMind.lookup(:Country, self, result_class: MaxMind::Result::GeoCountry) || MaxMind::Result::GeoCountry.new)
end

#prefix(significant: ipv6_significant) ⇒ Object



83
84
85
86
87
# File 'lib/iparty/address.rb', line 83

def prefix significant: ipv6_significant
  return super() if force_significant? || significant || !ipv6? || ipv4_mapped? || ipv4_compat? || super() <= 64

  64
end

#range?(**kw) ⇒ Boolean

Returns:

  • (Boolean)


43
44
45
# File 'lib/iparty/address.rb', line 43

def range? **kw
  size(**kw) > 1
end

#size(significant: ipv6_significant) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/iparty/address.rb', line 31

def size significant: ipv6_significant
  if ipv4?
    2**(32 - prefix)
  elsif ipv6?
    if force_significant? || significant || ipv4_mapped? || ipv4_compat?
      2**(128 - prefix)
    else
      2**[0, 128 - prefix - 64].max
    end
  end
end

#to_cidr(expand_v6: false, default_masks: false, netmask: false, significant: ipv6_significant) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/iparty/address.rb', line 65

def to_cidr expand_v6: false, default_masks: false, netmask: false, significant: ipv6_significant
  significant = true if force_significant?
  cidr = expand_v6 ? to_string(significant:) : to_s(significant:)
  return cidr if !default_masks && !range?(significant: true) && !(ipv6? && !significant)

  mp = prefix
  if @family == Socket::AF_INET
    masklen = 32 - mp
    mask_addr = ((IN4MASK >> masklen) << masklen)
  else
    mp = 64 if !significant && mp > 64
    masklen = 128 - mp
    mask_addr = ((IN6MASK >> masklen) << masklen)
  end

  "#{cidr}/#{netmask ? _to_string(mask_addr) : mp}"
end

#to_i(significant: ipv6_significant) ⇒ Object



89
90
91
92
93
94
# File 'lib/iparty/address.rb', line 89

def to_i significant: ipv6_significant
  return super() if force_significant? || significant || !ipv6? || ipv4_mapped? || ipv4_compat? || prefix(significant: true) <= 64

  # drop upper 64 bits / host-identifier of ipv6
  (super() >> 64) & ((1 << 64) - 1)
end

#to_insignificantObject



61
62
63
# File 'lib/iparty/address.rb', line 61

def to_insignificant
  self.class.new(@addr, @family, significant: false)
end

#to_long_range(**kw) ⇒ Object



52
53
54
55
# File 'lib/iparty/address.rb', line 52

def to_long_range **kw
  range = to_range
  [range.first.to_i(**kw), range.last.to_i(**kw)]
end

#to_rangeObject

super but keeping significant option



48
49
50
# File 'lib/iparty/address.rb', line 48

def to_range
  self.class.new(begin_addr, @family, significant: ipv6_significant)..self.class.new(end_addr, @family, significant: ipv6_significant)
end

#to_s(significant: ipv6_significant) ⇒ Object



96
97
98
99
100
# File 'lib/iparty/address.rb', line 96

def to_s significant: ipv6_significant
  return super() if force_significant? || significant || !ipv6? || ipv4_mapped? || ipv4_compat? || prefix(significant: true) <= 64

  mask(64).to_s(significant: true)
end

#to_significantObject



57
58
59
# File 'lib/iparty/address.rb', line 57

def to_significant
  self.class.new(@addr, @family, significant: true)
end

#to_string(significant: ipv6_significant) ⇒ Object



102
103
104
105
106
# File 'lib/iparty/address.rb', line 102

def to_string significant: ipv6_significant
  return super() if force_significant? || significant || !ipv6? || ipv4_mapped? || ipv4_compat? || prefix(significant: true) <= 64

  mask(64).to_string(significant: true)
end

#typeObject



23
24
25
26
27
28
29
# File 'lib/iparty/address.rb', line 23

def type
  if @family == Socket::AF_INET
    :ipv4
  elsif @family == Socket::AF_INET6
    :ipv6
  end
end