diameter 0.2.0pre2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5f3f9bf79194a1bf46cdeb9f5554f4d6b1e12969
4
- data.tar.gz: a652abd1f5e36bb61de18851e17fc097fab8c806
3
+ metadata.gz: 78fdef7d94263e4950aec0b5c1dbf6e18925c817
4
+ data.tar.gz: 6d2d7d32b7701e73474c048cc39cb5e9c0263311
5
5
  SHA512:
6
- metadata.gz: 9ba23cea6ecdb922d02f9d2bd0589054e4e098fe3b522442835f36deb59649f83baa56ab84592c5fb2ae053bd0408838eebc732de2d6f1c73501ef12436780f5
7
- data.tar.gz: 1cd7b01d9b41dff2608da114711b83cad13b9fd196eff9bbc8b6eddff325bff9d3515674ed7be0157e29a591faa7c9b56b700ad320e3d1444305b9f89b8d2c20
6
+ metadata.gz: f1cf4fe297f2f6dfa12ccb5645282b4c59bc7f8df21f8a16ec00cfd59580ad02981000d0feac28a0e8afb46a771740917fd4a05c7753557e31f003d66400dde3
7
+ data.tar.gz: 75d82606e30f397720fd18bbc950cd3e7ce2f00891e79f2983d93a9a94cb93788d3e59f164012317a3d84e620a73fb310fc4e6707c548e20b660c28a7e0b3812
@@ -10,7 +10,7 @@ module Diameter
10
10
  'NAS-Port' => [5, Unsigned32],
11
11
  'Service-Type' => [6, Enumerated],
12
12
  'Framed-Protocol' => [7, Enumerated],
13
- 'Framed-IP-Address' => [8, IPAddress],
13
+ 'Framed-IP-Address' => [8, OctetString],
14
14
  'Framed-IP-Netmask' => [9, IPAddress],
15
15
  'Framed-Routing' => [10, Enumerated],
16
16
  'Filter-Id' => [11, UTF8String],
@@ -233,7 +233,9 @@ module Diameter
233
233
  def create_answer(result_code, opts={})
234
234
  fail "Cannot answer an answer" if answer
235
235
 
236
- avps = opts.fetch(:avps, [])
236
+ avps = []
237
+ avps << avp_by_name("Session-Id") unless avp_by_name("Session-Id").nil?
238
+ avps += opts.fetch(:avps, [])
237
239
  avps << if opts[:experimental_result_vendor]
238
240
  AVP.create("Experimental-Result",
239
241
  [AVP.create("Experimental-Result-Code", result_code),
data/lib/diameter/peer.rb CHANGED
@@ -25,8 +25,9 @@ module Diameter
25
25
  attr_accessor :identity, :static, :cxn, :realm, :expiry_time, :last_message_seen
26
26
  attr_reader :state
27
27
 
28
- def initialize(identity)
28
+ def initialize(identity, realm)
29
29
  @identity = identity
30
+ @realm = realm
30
31
  @state = :CLOSED
31
32
  @state_change_q = Queue.new
32
33
  end
@@ -8,21 +8,6 @@ require 'concurrent'
8
8
  require 'dnsruby'
9
9
 
10
10
  module Diameter
11
- class Realm
12
- def initialize(peer_name)
13
- @peers = []
14
- add_peer(peer_name)
15
- end
16
-
17
- def add_peer(name)
18
- @peers << name
19
- end
20
-
21
- def best_peer
22
- @peers[0]
23
- end
24
- end
25
-
26
11
  class Stack
27
12
  include Internals
28
13
 
@@ -51,7 +36,6 @@ module Diameter
51
36
 
52
37
  @tcp_helper = TCPStackHelper.new(self)
53
38
  @peer_table = {}
54
- @realm_table = {}
55
39
  @handlers = {}
56
40
 
57
41
  @answer_timeout = opts.fetch(:timeout, 60)
@@ -60,7 +44,7 @@ module Diameter
60
44
  min_threads: 5,
61
45
  max_threads: 5,
62
46
  max_queue: 1,
63
- overflow_policy: :caller_runs
47
+ fallback_policy: :caller_runs
64
48
  )
65
49
 
66
50
  @res = Dnsruby::Resolver.new
@@ -187,9 +171,7 @@ module Diameter
187
171
  cer_bytes = Message.new(version: 1, command_code: 257, app_id: 0, request: true, proxyable: false, retransmitted: false, error: false, avps: avps).to_wire
188
172
  @tcp_helper.send(cer_bytes, cxn)
189
173
 
190
- @realm_table[realm] = Realm.new(peer_host)
191
-
192
- @peer_table[peer_host] = Peer.new(peer_host)
174
+ @peer_table[peer_host] = Peer.new(peer_host, realm)
193
175
  @peer_table[peer_host].state = :WAITING
194
176
  # Will move to :UP when the CEA is received
195
177
  @peer_table[peer_host].cxn = cxn
@@ -205,31 +187,40 @@ module Diameter
205
187
  # those AVPs don't already exist.
206
188
  #
207
189
  # @param req [Message] The request to send.
208
- def send_request(req)
190
+ # @param peer [Peer] (Optional) A peer to use as the first hop for the message
191
+ def send_request(req, options={})
209
192
  fail "Must pass a request" unless req.request
210
193
  req.add_origin_host_and_realm(@local_host, @local_realm)
211
- peer_name = if req['Destination-Host']
212
- req['Destination-Host'].octet_string
213
- elsif req['Destination-Realm']
214
- realm = req['Destination-Realm'].octet_string
215
- if @realm_table.has_key? realm
216
- @realm_table[realm].best_peer
217
- else
218
- fail "No connection to realm #{realm}"
219
- end
220
- else
221
- fail "Request must have Destination-Host or Destination-Realm"
222
- end
223
- state = peer_state(peer_name)
224
- if state == :UP
225
- peer = @peer_table[peer_name]
226
- @tcp_helper.send(req.to_wire, peer.cxn)
194
+
195
+ peer = options[:peer]
196
+
197
+ if peer.nil?
198
+ peer = if req['Destination-Host']
199
+ peer_identity = req['Destination-Host'].octet_string
200
+ Diameter.logger.debug("Selecting peer by Destination-Host (#{peer_identity})")
201
+ @peer_table[peer_identity]
202
+ elsif req['Destination-Realm']
203
+ realm = req['Destination-Realm'].octet_string
204
+ Diameter.logger.debug("Selecting peer by Destination-Realm (#{realm})")
205
+ @peer_table.values.select { |p| p.realm == realm }.sample
206
+ else
207
+ fail "Request must have Destination-Host or Destination-Realm"
208
+ end
209
+ else
210
+ Diameter.logger.debug("Peer selection forced to #{peer.identity}")
211
+ end
212
+
213
+ if peer.nil?
214
+ Diameter.logger.warn("No peer is available to send message - cannot route")
215
+ fail "No acceptable peer"
216
+ elsif peer.state == :UP
227
217
  q = Queue.new
228
218
  @pending_ete[req.ete] = q
219
+ @tcp_helper.send(req.to_wire, peer.cxn)
229
220
 
221
+ =begin
230
222
  # Time this request out if no answer is received
231
223
  Diameter.logger.debug("Scheduling timeout for #{@answer_timeout}s time")
232
- =begin
233
224
  Concurrent::timer(@answer_timeout) do
234
225
  Diameter.logger.debug("Timing out message with EtE #{req.ete}")
235
226
  q = @pending_ete.delete(req.ete)
@@ -247,7 +238,7 @@ module Diameter
247
238
  }
248
239
  return p
249
240
  else
250
- Diameter.logger.log(Logger::WARN, "Peer #{peer_name} is in state #{state} - cannot route")
241
+ Diameter.logger.warn("Peer #{peer.identity} is in state #{peer.state} - cannot route")
251
242
  end
252
243
  end
253
244
 
@@ -302,7 +293,7 @@ module Diameter
302
293
  end
303
294
 
304
295
  if msg.command_code == 257 && msg.answer
305
- handle_cea(msg)
296
+ handle_cea(msg, cxn)
306
297
  elsif msg.command_code == 257 && msg.request
307
298
  handle_cer(msg, cxn)
308
299
  elsif msg.command_code == 280 && msg.request
@@ -381,8 +372,9 @@ module Diameter
381
372
 
382
373
  if rc == 2001
383
374
  peer = cer.avp_by_name('Origin-Host').octet_string
384
- Diameter.logger.debug("Creating peer table entry for peer #{peer}")
385
- @peer_table[peer] = Peer.new(peer)
375
+ realm = cer.avp_by_name('Origin-Realm').octet_string
376
+ Diameter.logger.debug("Creating peer table entry for peer #{peer} in realm #{realm}")
377
+ @peer_table[peer] = Peer.new(peer, realm)
386
378
  @peer_table[peer].state = :UP
387
379
  @peer_table[peer].reset_timer
388
380
  @peer_table[peer].cxn = cxn
@@ -391,14 +383,26 @@ module Diameter
391
383
  end
392
384
  end
393
385
 
394
- def handle_cea(cea)
395
- peer = cea.avp_by_name('Origin-Host').octet_string
396
- if @peer_table.has_key? peer
397
- @peer_table[peer].state = :UP
398
- @peer_table[peer].reset_timer
386
+ def handle_cea(cea, cxn)
387
+ host = cea.avp_by_name('Origin-Host').octet_string
388
+ if @peer_table.has_key? host
389
+ @peer_table[host].state = :UP
390
+ @peer_table[host].reset_timer
399
391
  else
400
- Diameter.logger.warn("Ignoring CEA from unknown peer #{peer}")
401
- Diameter.logger.debug("Known peers are #{@peer_table.keys}")
392
+ entry = @peer_table.find { |h, p| p.cxn == cxn }
393
+ if entry.nil?
394
+ Diameter.logger.warn("Ignoring CEA from unknown peer #{host}")
395
+ Diameter.logger.debug("Known peers are #{@peer_table.keys}")
396
+ else
397
+ old_host, peer = entry
398
+ Diameter.logger.warn("Peer identity changed #{old_host} => #{host}")
399
+
400
+ @peer_table.delete(old_host)
401
+ peer.identity = host
402
+ @peer_table[host] = peer
403
+ @peer_table[host].state = :UP
404
+ @peer_table[host].reset_timer
405
+ end
402
406
  end
403
407
  end
404
408
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diameter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0pre2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Day
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-01 00:00:00.000000000 Z
11
+ date: 2016-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.7'
19
+ version: '0.9'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.7'
26
+ version: '0.9'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: dnsruby
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rubocop
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +122,20 @@ dependencies:
108
122
  - - '='
109
123
  - !ruby/object:Gem::Version
110
124
  version: 0.0.3
125
+ - !ruby/object:Gem::Dependency
126
+ name: minitest
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 5.8.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 5.8.0
111
139
  description:
112
140
  email: ruby-diameter@rkd.me.uk
113
141
  executables: []
@@ -120,7 +148,6 @@ files:
120
148
  - lib/diameter/avp_parser.rb
121
149
  - lib/diameter/constants.rb
122
150
  - lib/diameter/diameter_logger.rb
123
- - lib/diameter/fsm.rb
124
151
  - lib/diameter/message.rb
125
152
  - lib/diameter/peer.rb
126
153
  - lib/diameter/stack.rb
@@ -141,12 +168,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
168
  version: '0'
142
169
  required_rubygems_version: !ruby/object:Gem::Requirement
143
170
  requirements:
144
- - - ">"
171
+ - - ">="
145
172
  - !ruby/object:Gem::Version
146
- version: 1.3.1
173
+ version: '0'
147
174
  requirements: []
148
175
  rubyforge_project:
149
- rubygems_version: 2.4.3
176
+ rubygems_version: 2.4.8
150
177
  signing_key:
151
178
  specification_version: 4
152
179
  summary: Pure-Ruby Diameter stack
data/lib/diameter/fsm.rb DELETED
@@ -1,27 +0,0 @@
1
- require 'micromachine'
2
-
3
- machine = MicroMachine.new(:closed) # Initial state.
4
-
5
- # Define the possible transitions for each event.
6
- machine.when(:closed, :start => :wait_conn_ack)
7
- machine.when(:closed, :r_conn_cer => :r_open)
8
-
9
- machine.when(:wait_conn_ack, :i_rcv_conn_ack => :wait_i_cea)
10
- machine.when(:wait_conn_ack, :i_rcv_conn_nack => :closed)
11
- machine.when(:wait_conn_ack, :r_conn_cer => :wait_conn_ack_elect)
12
- machine.when(:wait_conn_ack, :timeout => :closed)
13
-
14
-
15
- machine.when(:reset, :confirmed => :new, :ignored => :new)
16
-
17
- machine.trigger(:confirm) #=> true
18
- machine.state #=> :confirmed
19
-
20
- machine.trigger(:ignore) #=> false
21
- machine.state #=> :confirmed
22
-
23
- machine.trigger(:reset) #=> true
24
- machine.state #=> :new
25
-
26
- machine.trigger(:ignore) #=> true
27
- machine.state #=> :ignored