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



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/endpoint.rb', line 87

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
  @hashes = []
  @contact_header = "<sip:quaff@#{Utils::local_ip}:#{@local_port};transport=#{transport};ob>"
  initialize_queues
  start
end

Instance Attribute Details

#contact_headerObject

Returns the value of attribute contact_header.



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

def contact_header
  @contact_header
end

#instance_idObject

Returns the value of attribute instance_id.



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

def instance_id
  @instance_id
end

#local_portObject (readonly)

Returns the value of attribute local_port.



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

def local_port
  @local_port
end

#msg_logObject (readonly)

Returns the value of attribute msg_log.



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

def msg_log
  @msg_log
end

#msg_traceObject

Returns the value of attribute msg_trace.



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

def msg_trace
  @msg_trace
end

#sdp_portObject

Returns the value of attribute sdp_port.



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

def sdp_port
  @sdp_port
end

#sdp_socketObject

Returns the value of attribute sdp_socket.



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

def sdp_socket
  @sdp_socket
end

#uriObject

Returns the value of attribute uri.



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

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



36
37
# File 'lib/endpoint.rb', line 36

def add_sock sock
end

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

Not yet ready for use



73
74
# File 'lib/endpoint.rb', line 73

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



65
66
# File 'lib/endpoint.rb', line 65

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



69
70
# File 'lib/endpoint.rb', line 69

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.



153
154
155
# File 'lib/endpoint.rb', line 153

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



46
47
48
49
50
51
52
53
54
55
# File 'lib/endpoint.rb', line 46

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.



161
162
163
164
165
166
# File 'lib/endpoint.rb', line 161

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



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

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.



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/endpoint.rb', line 124

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:



104
105
106
107
108
# File 'lib/endpoint.rb', line 104

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



111
112
113
114
# File 'lib/endpoint.rb', line 111

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



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

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

#terminateObject



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

def terminate
  @terminated = true
  terminate_specific
end

#terminate_specificObject

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



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

def terminate_specific
end

#unregisterObject



145
146
147
# File 'lib/endpoint.rb', line 145

def unregister
  register 0
end