Class: IParty::Address

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Address.

Raises:

  • (IPAddr::AddressFamilyError)


15
16
17
18
19
20
21
# File 'lib/iparty/address.rb', line 15

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.



13
14
15
# File 'lib/iparty/address.rb', line 13

def ipv6_significant
  @ipv6_significant
end

Class Method Details

.from_insignificant(long, **kw) ⇒ Object



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

def self.from_insignificant long, **kw
  new((long << 64) & ((1 >> 64) - 1), Socket::AF_INET6, **kw)
end

Instance Method Details

#annotationsObject



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

def annotations
  return @_annotations if defined?(@_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

  @_annotations = result.empty? ? nil : result
end

#as_jsonObject



152
153
154
155
156
157
158
159
160
161
# File 'lib/iparty/address.rb', line 152

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



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

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)


23
24
25
# File 'lib/iparty/address.rb', line 23

def force_significant?
  @family == Socket::AF_INET6 && (@addr == 1 || ipv4_mapped? || ipv4_compat?)
end

#geoObject



129
130
131
# File 'lib/iparty/address.rb', line 129

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

#geo_cityObject



125
126
127
# File 'lib/iparty/address.rb', line 125

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

#geo_countryObject



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

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

#original_to_sObject



100
# File 'lib/iparty/address.rb', line 100

alias_method :original_to_s, :to_s

#prefix(significant: ipv6_significant) ⇒ Object



87
88
89
90
91
# File 'lib/iparty/address.rb', line 87

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

  64
end

#range?(**kw) ⇒ Boolean

Returns:

  • (Boolean)


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

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

#size(significant: ipv6_significant) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
# File 'lib/iparty/address.rb', line 35

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

#tag?(tag) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
149
150
# File 'lib/iparty/address.rb', line 146

def tag? tag
  return false unless tags = annotations&.fetch(:tags, nil)

  tags.include?(tag)
end

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



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/iparty/address.rb', line 69

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



93
94
95
96
97
98
# File 'lib/iparty/address.rb', line 93

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

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

#to_insignificantObject



65
66
67
# File 'lib/iparty/address.rb', line 65

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

#to_long_range(**kw) ⇒ Object



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

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



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

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



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

def to_s significant: ipv6_significant
  return original_to_s unless @family == Socket::AF_INET6

  if significant || force_significant? || prefix(significant: true) <= 64
    to_significant.original_to_s
  else
    mask(64).original_to_s
  end
end

#to_significantObject



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

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

#to_string(significant: ipv6_significant) ⇒ Object



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

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

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

#typeObject



27
28
29
30
31
32
33
# File 'lib/iparty/address.rb', line 27

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