Setup & Context

Introduction

These methods in from TestSipLuaAgent Lua API are methods called prior to performing the SIP Test actions, for the purpose of setting up the endpoints and the context in preperation for an INVITE or non-INVITE transaction, including registration for inbound transactions.

Setup & Context API

.default_endpoints [Synchronous]

An “endpoints” object is a representation of the IP address and port numbers which will be used for the a SIP message flow test, either outcall (we send SIP INVITE) or incall (we receive SIP INVITE). This structure is also required for non-INVITE test scripts.

The default_endpoints method is the standard way to initialize the endpoints object. It will simply set the required SIP and RTP IP address and UDP/TCP port numbers into a single table by taking them from the LogicApp global defaults, with optional overrides.

The method takes a single, optional custom argument which allows for the explicit override of the individual default values. The most common parameter to override is the RTP port number, which is dynamically assigned by the TestRtpApp and which is unique to the call for the lifetime of that RTP stream.

Argument Type Description
custom Object Container for override values.
(Default = use default global values for all endpoints).
.local_sip_ip IPv4 Address Override the local SIP IP address (the address of our near SIP endpoint).
(Default = the value of the LOCAL_SIP_IP Lua global).
.local_sip_port Integer Override the local SIP UDP port (the port of our near SIP endpoint).
(Default = the value of the LOCAL_SIP_PORT Lua global).
.remote_sip_ip IPv4 Address Override the remote SIP IP address (the address of the far SIP endpoint).
(Default = the value of the REMOTE_SIP_IP Lua global).
.remote_sip_ip Integer Override the remote SIP UDP port (the port of the far SIP endpoint).
(Default = the value of the REMOTE_SIP_PORT Lua global).
.local_rtp_ip IPv4 Address Override the local RTP IP address (the address of the local RTP endpoint).
(Default = the value of the LOCAL_RTP_IP Lua global).
.local_rtp_port Integer Specify the local RTP UDP port (the UDP port of the local RTP stream endpoint).
(Default = no RTP port is assigned, and we cannot construct an SDP Offer or SDP Answer).

The method returns an endpoints object.

Argument Type Description
endpoints Object The local SIP IP address (the address of our near SIP endpoint) from default or custom.
.local_sip_ip Object The local SIP IP address (the address of our near SIP endpoint) from default or custom.
.local_sip_port Object The local SIP UDP port (the port of our near SIP endpoint) from default or custom.
.remote_sip_ip Object The remote SIP IP address (the address of the far SIP endpoint) from default or custom.
.remote_sip_ip Object The remote SIP UDP port (the port of the far SIP endpoint) from default or custom.
.local_rtp_port Object The local RTP IP address (the address of the local RTP endpoint) from default or custom.
.local_rtp_ip Object The local RTP UDP port (the port of the local RTP endpoint) as specified (no default value applies).

This table will subsequently become part of the overall “context” of the test call, and will be passed through as part of that table, the script will no longer need to refer to it explicitly.

Example getting endpoints with override:

-- Ask the TestRtpApp to assign us an RTP port.
local result = truo.register ()
local rtp_listener_port = result.local_port
...

-- Initialise endpoints from global variables, but with our private RTP port.
local endpoints = tsuo.default_endpoints ({ local_rtp_port = rtp_listener_port })
...

-- Create a new outcall SIP INVITE Context for our endpoints and calling/called parties.
local context = tsuo.invite_context (endpoints, "7000", "048989777")
...

.non_invite_context [Synchronous]

The “context” object for a non-INVITE transaction is a simple container of a Call-ID plus associated To/From/Contact URI values, counters, and other state variables.

The non_invite_context method on the TestSipAgent API is the method used to construct a context which is ready to send out a non-INVITE SIP Request. The test script will act as a User Agent Client.

The non_invite_context method takes the following arguments:

Argument Type Description
endpoints Object [Required] The endpoints object defining the IP address and ports which will be used for sending and receiving messages for this UAC transaction.
This object is typically constructed using the default_endpoints method.
calling_party Hex Digits [Required] The user part of the local URI which will be placed in the From header for the initial SIP Request.
called_party Hex Digits [Required] The user part of the remote URI which will be placed in the To header for the initial SIP Request.
options Object Additional override/customisation behavior for this test transaction.
(Default = see defaults for individual options).
.compact_headers Boolean Should we use the "Compact" header names for messages we send within this non-INVITE transaction.
(Default = use full-length header names).
.from_domain String Override the default domain for the local URI in the "From" header local URI sent by us.
(Default = the from domain is the local SIP address from the endpoints).
.contact_sip_instance String Add this value as a ;+sip_instance= parameter on the "Contact" header for the SIP Request.
(Default = do not include a ";+sip_instance= parameter on our "Contact" header).
.contact_expires Integer Add this value as a ;expires= parameter on the "Contact" header for the SIP Request.
(Default = do not include a ;expires= parameter on our "Contact" header).

The method returns a single argument which is the “context” object. This object should be passed in to subsequent SIP Test API methods related to this non-INVITE transaction.

The “context” object is nominally opaque, but it is documented here for completeness.

Argument Type Description
context Object Container for the context which aggregates the information for this non-INVITE transaction.
.compact_headers Boolean Should we use the "Compact" header names for messages we send within this transaction.
(Default = use full-length header names).
.call_id String The allocated Call-ID we will use for this transaction.
.local_tag String The local ;tag= value which will be added to our local URI in the "From" header.
.request_uri String The URI which will be placed into all SIP Requests sent by us for this transaction.
.local_uri String The local URI used as the "From" header, complete including the local "tag" parameter.
.local_uri_notag String The local URI but without the ;tag= parameter.
.remote_uri String The remote URI used as the "To" header.
There is no ;tag= parameter, and will not be one for a non-INVITE context.
.contact String The "Contact" header URI which we will send for the non-INVITE SIP Request.
This is relevant for the REGISTER request, but is not sent for OPTIONS or other methods.
.local_seq Integer The CSeq value which will be used for the first (and only) SIP Request in this non-INVITE transaction.
.endpoints Object A stored reference to the endpoints object supplied in the method.

The standard sequence for testing a non-INVITE outbound request is:

Example of constructing and using a context for an outbound non-INVITE SIP Request test sequence:

-- Get a SIP outbound non-INVITE request context from our helper library.
local context = tsuo.non_invite_context (endpoints, calling_party, called_party, { contact_expires = '3600' })

-- Switch the authentication mode to DIGEST.
n2svcd.management_configuration_scalar ('LHO', 'sip_auth_schema', 'digest')

-- Attempt to register again this time expecting an unauthorized response.
tsuo.register_send_request (context)

-- Expect REGISTER response (401 Unauthorized).
local response = tsuo.register_expect_response (context, 401, "Unauthorized")

-- Generate the authorization header for our request.
local www_auth_header = tsuo.header_fetch (response.headers, "WWW-Authenticate")
local authorization_header = tsuo.auth_header_value (context, 'REGISTER', www_auth_header, username, password)

-- Attempt to register again this time expecting a successful auth response.
tsuo.register_send_request (context, { { name = "Authorization", value = authorization_header } })

-- Expect REGISTER response 200 OK.
tsuo.register_expect_response (context, 200, "OK")

-- Switch the authentication mode back to OPEN.
n2svcd.management_configuration_scalar ('LHO', 'sip_auth_schema', 'open')

.invite_context [Synchronous]

The “context” object for an INVITE transaction/dialog is very similar to the non-INVITE context, but contains some additional fields related to the ongoing dialog and the secondary transactions.

The invite_context method on the TestSipAgent API is the method used to construct a context which is ready to send out a non-INVITE SIP Request. The test script will act as a User Agent Client.

Note: For inbound calls, the INVITE context object is returned from the invite_expect_request method as documented for the Inbound INVITE methods.

The invite_context method takes the following arguments:

Argument Type Description
endpoints Object [Required] The endpoints object defining the IP address and ports which will be used for sending and receiving messages for this UAC transaction.
This object is typically constructed using the default_endpoints method.
calling_party Hex Digits [Required] The user part of the local URI which will be placed in the From header for the initial SIP Request.
called_party Hex Digits [Required] The user part of the remote URI which will be placed in the To header for the initial SIP Request.
options Object Additional override/customisation behavior for this test transaction.
Note the difference in supported options from the non-INVITE case.
(Default = see defaults for individual options).
.prack_supported Boolean Do we include 100rel in a Supported header for INVITE Requests we send within this dialog.
(Default = do not advertise support for 100rel).
.compact_headers Boolean Should we use the "Compact" header names for messages we send within this transaction.
(Default = use full-length header names).
.from_otg String Value to include as the ;otg= parameter in the "From" header local URI value.
(Default = do not include ;otg= parameter in the "From" header local URI value).
.from_isup_oli String Value to include as the ;isup-oli= parameter in the "From" header local URI value.
(Default = do not include ;isup-oli= parameter in the "From" header local URI value).
.from_domain String Override the default domain for the local URI in the "From" header sent by us.
(Default = the from domain is the local SIP address from the endpoints).
.from_display_name String Include the indicated display name when constructing the "From" header local URI value.
(Default = do not include any display name part in the "From" header local URI value).
.contact_sip_instance String Add this value as a ;+sip_instance= parameter on the "Contact" header for the SIP Request.
(Default = do not include a ";+sip_instance= parameter on our "Contact" header).
.contact_expires Integer Add this value as a ;expires= parameter on the "Contact" header for the SIP Request.
(Default = do not include a ;expires= parameter on our "Contact" header).

The method returns a single argument which is the “context” object. This object should be passed in to subsequent SIP Test API methods related to this INVITE transaction/dialog.

The “context” object is nominally opaque, but it is documented here for completeness. Note the additional attributes related to the ongoing dialog which are not present for the non-INVITE context equivalent.

Argument Type Description
context Object Container for the context which aggregates the information for this INVITE transaction.
.prack_supported Boolean Do we include 100rel in a Supported header for INVITE Requests we send within this dialog.
(Default = do not advertise support for 100rel).
.compact_headers Boolean Should we use the "Compact" header names for messages we send within this INVITE transaction.
(Default = use full-length header names).
.call_id String The allocated Call-ID we will use for this transaction/dialog.
.local_tag String The local ;tag= value which will be added to our local URI in the "From" header.
.request_uri String The URI which will be placed into all SIP Requests sent by us for this transaction.
.local_uri String The local URI used as the "From" header (or "To" header for incall scenarios).
This is complete including the local "tag" parameter.
.local_uri_notag String The local URI used as the "From" header (or "To" header for incall scenarios).
This version does not have the ;tag= parameter.
.remote_uri String The remote URI used as the "To" header in the initial INVITE (or "From" header for incall scenarios).
At the time of construction this will not have the ;tag= as it is not yet known.
However, the ;tag= will be added to this attribute as soon as the tag is received from the far end.
.remote_uri_notag String The remote URI used as the "To" header (or "From" header for incall scenarios).
This version will never have the ;tag= parameter.
.contact String The "Contact" header URI which we will send for any outbound SIP INVITE or re-INVITE Request within this dialog.
.local_seq Integer The CSeq value which will be used for the first SIP Request transaction in this INVITE dialog.
Any subsequent outbound transactions within the dialog will increment this value by one.
.invite_pcv String This value is not initialized when the context is created.
It will subsequently be given the value of the P-Charging-Vector (if present) from the sent or received SIP INVITE Request.
.endpoints Object A stored reference to the endpoints object supplied in the method.

The standard sequence for testing an INVITE outbound request is:

Example fragment showing creating a new INVITE context from existing endpoints object:

-- Get a SIP outcall context from our helper library.
local context = tsuo.invite_context (endpoints, calling_party, called_party, {
    contact_sip_instance = '"<urn:uuid:27b843f9-d300-49fb-b108-fff03a6369e3>"',
    contact_expires = '3600'
})

-- Construct the SDP
local sdp_offer = tsuo.sdp_offer (context, tsuo.SDP_LINPHONE)

-- Construct and Send INVITE Request.
tsuo.invite_send_request (context, sdp_offer, { { name = 'Prefer-EM', value = '1' }, { name = 'Scenario', value = '533' } })

-- Expect Trying (no Ringing) from the IVR.
tsuo.invite_expect_response (context, 100, "Trying")

.register_incall [Asynchronous]

The register_incall method informs the TestSipApp that we are expecting to receive an new SIP Dialog from an uncorrelated inbound SIP INVITE Request on one of the ports/connections on which it is listening.

We do not know what the Call-ID will be, so we instead specify another match attribute which can be used to identify that this test is indeed the owner of that call when it arrives.

Argument Type Description
match Object Container for the possible match fields used to claim ownership of the new Call/Dialog.
.calling_party Hex&String Calling Party address digits to match.
If present, this address must be a full-length, case-insensitive match on the "user" part of the From header URI of the new-dialog SIP INVITE Request.
.called_party Hex&String Called Party address digits to match.
If present, this address must be a full-length, case-insensitive match on the "user" part of the To header URI of the new-dialog SIP INVITE Request.

The register_incall is asynchronous, it waits until the TestSipApp confirms the registration.

The registration lifetime is determined by the TestSipApp, currently an inbound registration is valid for 5 seconds, and this value is not configurable or controllable.

The register_incall method returns nil.

The standard sequence for testing an INVITE incall is:

Example incall registration and REST request:

-- Register to claim the next call for this called party.
tsuo.register_incall ({ called_party = called_party })

-- Start timer for elapsed checking.
local tv = match.elapsed ()

-- Open a rest client request to start the call.
local result = rest_agent.send_request (nil, {
    path = '/outcall_pa_internal',
    query = 'calling_party=' .. calling_party ..  
        '&called_party=' .. called_party ..
        '&scenario=' .. scenario
  })

local rest_response = rest_agent.expect_response ()
tv = match.elapsed ("Received REST Response (immediate)", tv, 0.0)

local context = tsuo.invite_expect_request (endpoints, { ['User-Agent'] = "N-Squared LHO", Scenario = scenario })
local call_pcv = context.invite_pcv
tv = match.elapsed ("Received SIP INVITE (immediate)", tv, 0)