diameter 0.2.0pre2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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