Class: Quaff::BaseEndpoint

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

Direct Known Subclasses

TCPSIPEndpoint, UDPSIPEndpoint

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, username, password, local_port, outbound_proxy = nil, outbound_port = 5060) ⇒ BaseEndpoint

Constructs a new endpoint Params:

uri

The SIP URI of this endpoint

username

The authentication username of this endpoint

password

The authentication password of this endpoint

local_port

The port this endpoint should bind to. Use

‘:anyport’ to bind to an ephemeral port.

outbound_proxy

The outbound proxy where all requests should

be directed. Optional, but it only makes sense to omit it when Quaff is emulating a server rather than a client.

outbound_port

The port of the outbound proxy



76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/endpoint.rb', line 76

def initialize(uri, username, password, local_port, outbound_proxy=nil, outbound_port=5060)
  @msg_log = Array.new
  @uri = uri
  @resolver = Resolv::DNS.new
  @username = username
  @password = password
  @local_port = local_port
  initialize_connection
  if outbound_proxy
    @outbound_connection = new_connection(outbound_proxy, outbound_port)
  end
  initialize_queues
  start
end

Instance Attribute Details

#instance_idObject

Returns the value of attribute instance_id.



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

def instance_id
  @instance_id
end

#local_portObject (readonly)

Returns the value of attribute local_port.



14
15
16
# File 'lib/endpoint.rb', line 14

def local_port
  @local_port
end

#msg_logObject (readonly)

Returns the value of attribute msg_log.



14
15
16
# File 'lib/endpoint.rb', line 14

def msg_log
  @msg_log
end

#msg_traceObject

Returns the value of attribute msg_trace.



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

def msg_trace
  @msg_trace
end

#sdp_portObject

Returns the value of attribute sdp_port.



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

def sdp_port
  @sdp_port
end

#sdp_socketObject

Returns the value of attribute sdp_socket.



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

def sdp_socket
  @sdp_socket
end

#uriObject

Returns the value of attribute uri.



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

def uri
  @uri
end

Instance Method Details

#add_sock(sock) ⇒ Object

Adds a socket connection to another UA - designed to be overriden by per-transport subclasses



30
31
# File 'lib/endpoint.rb', line 30

def add_sock sock
end

#create_aka_client(uri, username, key, op, outbound_proxy, outbound_port = 5060) ⇒ Object

Not yet ready for use



62
63
# File 'lib/endpoint.rb', line 62

def create_aka_client(uri, username, key, op, outbound_proxy, outbound_port=5060) # :nodoc:
end

#create_client(uri, username, password, outbound_proxy, outbound_port = 5060) ⇒ Object

Not yet ready for use



54
55
# File 'lib/endpoint.rb', line 54

def create_client(uri, username, password, outbound_proxy, outbound_port=5060) # :nodoc:
end

#create_server(uri, local_port = 5060, outbound_proxy = nil, outbound_port = 5060) ⇒ Object

Not yet ready for use



58
59
# File 'lib/endpoint.rb', line 58

def create_server(uri, local_port=5060, outbound_proxy=nil, outbound_port=5060) # :nodoc:
end

#get_new_message(cid, time_limit = 30) ⇒ Object

Only designed for use by the Call class. Retrieves a new message on a particular call. If no new message has been received, blocks for up to time_limit seconds waiting for one. If nothing arrives, raises a TimeoutError.



140
141
142
# File 'lib/endpoint.rb', line 140

def get_new_message(cid, time_limit=30) # :nodoc:
  Timeout::timeout(time_limit) { @messages[cid].deq }
end

#incoming_callObject

Retrieves the next unhandled call for this endpoint and returns a Call object representing it



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

def incoming_call
  begin
    call_id = get_new_call_id
  rescue Timeout::Error
    raise "#{ @uri } timed out waiting for new incoming call"
  end
  
  puts "Call-Id for endpoint on #{@local_port} is #{call_id}" if @msg_trace
  Call.new(self, call_id, @instance_id, @uri)
end

#mark_call_dead(cid) ⇒ Object

Flags that a particular call has ended, and any more messages using it shold be ignored.



148
149
150
151
152
153
# File 'lib/endpoint.rb', line 148

def mark_call_dead(cid)
    @messages.delete cid
    now = Time.now
    @dead_calls[cid] = now + 30
    @dead_calls = @dead_calls.keep_if {|k, v| v > now}
end

#outgoing_call(to_uri) ⇒ Object

Creates a Call object representing a new outbound call



47
48
49
50
51
# File 'lib/endpoint.rb', line 47

def outgoing_call to_uri
  call_id = generate_call_id
  puts "Call-Id for endpoint on #{@local_port} is #{call_id}" if @msg_trace
  Call.new(self, call_id, @instance_id, @uri, @outbound_connection, to_uri)
end

#register(expires = "3600", aka = false) ⇒ Object

Utility method - handles a REGISTER/200 or REGISTER/401/REGISTER/200 flow to authenticate the subscriber. Currently only supports SIP Digest authentication. Re-REGISTERs are not handled; if you need long-running endpoints you should create a thread to re-REGISTER them yourself.

Returns the Message representing the 200 OK, or throws an exception on failure to authenticate successfully.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/endpoint.rb', line 111

def register expires="3600", aka=false
  @reg_call ||= outgoing_call(@uri)
  auth_hdr = Quaff::Auth.gen_empty_auth_header @username
  @reg_call.update_branch
  @reg_call.send_request("REGISTER", "", {"Authorization" =>  auth_hdr, "Expires" => expires.to_s})
  response_data = @reg_call.recv_response("401|200")
  if response_data.status_code == "401"
    if aka
      rand = Quaff::Auth.extract_rand response_data.header("WWW-Authenticate")
      password = @kernel.f3 rand
    else
      password = @password
    end
    auth_hdr = Quaff::Auth.gen_auth_header response_data.header("WWW-Authenticate"), @username, @password, "REGISTER", @uri
    @reg_call.update_branch
    @reg_call.send_request("REGISTER", "", {"Authorization" =>  auth_hdr, "Expires" => expires.to_s})
    response_data = @reg_call.recv_response("200")
  end
  return response_data # always the 200 OK
end

#send_msg(data, source) ⇒ Object

:nodoc:



91
92
93
94
95
# File 'lib/endpoint.rb', line 91

def send_msg(data, source) # :nodoc:
  @msg_log.push "Endpoint on #{@local_port} sending:\n\n#{data.strip}\n\nto #{source.inspect}"
  puts "Endpoint on #{@local_port} sending #{data} to #{source.inspect}" if @msg_trace
    source.send_msg(@cxn, data)
end

#set_aka_credentials(key, op) ⇒ Object

Not yet ready for use



98
99
100
101
# File 'lib/endpoint.rb', line 98

def set_aka_credentials key, op # :nodoc:
  @kernel = Milenage.Kernel key
  @kernel.op = op
end

#setup_sdpObject

Creates an SDP socket bound to an ephemeral port



17
18
19
20
21
# File 'lib/endpoint.rb', line 17

def setup_sdp
  @sdp_socket = UDPSocket.new
  @sdp_socket.bind('0.0.0.0', 0)
  @sdp_port = @sdp_socket.addr[1]
end

#terminateObject

Cleans up the endpoint - designed to be overriden by per-transport subclasses



25
26
# File 'lib/endpoint.rb', line 25

def terminate
end

#unregisterObject



132
133
134
# File 'lib/endpoint.rb', line 132

def unregister
  register 0
end