Class: Stack

Inherits:
Object
  • Object
show all
Defined in:
lib/diameter/stack.rb

Instance Method Summary (collapse)

Constructor Details

- (Stack) initialize

Returns a new instance of Stack



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/diameter/stack.rb', line 66

def initialize
  @local_host = "rkd"
  @local_realm = "rkd-realm"
  @local_port = nil

  @auth_apps = [16777216]
  @acct_apps = []
  @vendor_auth_apps = []
  @vendor_acct_apps = []

  @pending_ete = []

  @ete = 1
  @hbh = 1
  
  @tcp_helper = TCPStackHelper.new(self)
  @peer_table = {}
  Diameter::logger.log(Logger::INFO, "Stack initialized")
end

Instance Method Details

- (Object) add_handler_for_app



152
153
# File 'lib/diameter/stack.rb', line 152

def add_handler_for_app
end

- (Object) answer_for(req)



175
176
177
# File 'lib/diameter/stack.rb', line 175

def answer_for(req)
  req.create_answer(@local_host)
end

- (Object) connect_to_peer(peer_uri, peer_host, realm)

Creates a Peer connection to a Diameter agent at the specific network location indicated by peer_uri.

Parameters:

  • peer_uri (URI)

    The aaa:// URI identifying the peer. Should contain a hostname/IP; may contain a port (default 3868) and a transport param indicating TCP or SCTP (default TCP).

  • peer_host (String)

    The DiameterIdentity of this peer, which will uniquely identify it in the peer table.

  • realm (String)

    The Diameter realm of this peer.



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/diameter/stack.rb', line 115

def connect_to_peer(peer_uri, peer_host, realm)
  uri = URI(peer_uri)
  cxn = @tcp_helper.setup_new_connection(uri.host, uri.port)
  avps = [AVP.create("Origin-Host", @local_host),
          AVP.create("Origin-Realm", @local_realm),
          AVP.create("Host-IP-Address", IPAddr.new("127.0.0.1")),
          AVP.create("Vendor-Id", 100),
          AVP.create("Product-Name", "ruby-diameter"),
         ]
  avps += @auth_apps.collect { | code| AVP.create("Auth-Application-Id", code)}
  cer_bytes = DiameterMessage.new(version: 1, command_code: 257, app_id: 0, hbh: 1, ete: 1, request: true, proxyable: false, retransmitted: false, error: false, avps: avps).to_wire
  @tcp_helper.send(cer_bytes, cxn)
  @peer_table[peer_host] = Peer.new(peer_host)
  @peer_table[peer_host].state = :WAITING
  @peer_table[peer_host].cxn = cxn
  @peer_table[peer_host]
  # Will move to :UP when the CEA is received
end

- (Object) disconnect_from_peer(peer_host)



134
135
# File 'lib/diameter/stack.rb', line 134

def disconnect_from_peer(peer_host)
end

- (Object) handle_message(msg_bytes, cxn)



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/diameter/stack.rb', line 179

def handle_message(msg_bytes, cxn)
  # Common processing - ensure that this message has come in on this
  # peer's expected connection, and update the last time we saw
  # activity on this peer
  msg = DiameterMessage.from_bytes(msg_bytes)
  peer = msg.avp_by_name("Origin-Host").octet_string
  if @peer_table[peer]
    @peer_table[peer].reset_timer
    unless @peer_table[peer].cxn == cxn
      Diameter::logger.log(Logger::WARN, "Ignoring message - claims to be from #{peer_name} but comes from #{cxn} not #{@peer_table[peer].cxn}")
    end
  end
  
  if msg.command_code == 257 and msg.answer
    handle_cea(msg)
  elsif msg.command_code == 257 and msg.request
    handle_cer(msg, cxn)
  elsif msg.command_code == 280 and msg.request      
    handle_dwr(msg, cxn)
  elsif msg.command_code == 280 and msg.answer
    # No-op - we've already updated our timestamp
  elsif msg.answer
    handle_other_answer(msg, cxn)
  else
    fail "Received unknown message of type #{msg.command_code}"
  end
end

- (Object) new_request(code, options = {})



86
87
88
# File 'lib/diameter/stack.rb', line 86

def new_request(code, options={})
  DiameterMessage.new({version: 1, command_code: code, hbh: next_hbh, ete: next_ete, request: true}.merge(options))
end

- (Fixnum) next_ete

been issued before by this stack.

Returns:

  • (Fixnum)

    An End-to-End identifier number that has never



92
93
94
# File 'lib/diameter/stack.rb', line 92

def next_ete
  @ete += 1
end

- (Fixnum) next_hbh

been issued before by this stack.

Returns:

  • (Fixnum)

    A Hop-by-Hop identifier number that has never



98
99
100
# File 'lib/diameter/stack.rb', line 98

def next_hbh
  @hbh += 1
end

- (Object) peer_state(id)



141
142
143
144
145
146
147
# File 'lib/diameter/stack.rb', line 141

def peer_state(id)
  if not @peer_table.has_key? id
    :CLOSED
  else
    @peer_table[id].state
  end
end

- (Object) send_message(req)



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/diameter/stack.rb', line 155

def send_message(req)
  if req.request
    q = Queue.new
    req.avps += [AVP.create("Origin-Host", @local_host),
                 AVP.create("Origin-Realm", @local_realm)]
    @pending_ete[req.ete] = q
    peer_name = req.avp_by_name("Destination-Host").octet_string
    peer = @peer_table[peer_name]
    if peer.state == :UP
      #puts "Sending over wire"
      @tcp_helper.send(req.to_wire, peer.cxn)
      return Concurrent::Promise.execute { q.pop }
    else
      Diameter::logger.log(Logger::WARN, "Peer #{peer_name} is in state #{peer.state} - cannot route")
    end
  else
      Diameter::logger.log(Logger::ERROR, "Routing answers is currently unimplemented")
  end
end

- (Object) shutdown_cleanly



149
150
# File 'lib/diameter/stack.rb', line 149

def shutdown_cleanly
end

- (Object) start



102
103
104
# File 'lib/diameter/stack.rb', line 102

def start
  @tcp_helper.start_main_loop
end

- (Object) timer_loop



137
138
139
# File 'lib/diameter/stack.rb', line 137

def timer_loop

end