4 Customizing Messages for New SIP or JSON Data

This chapter contains examples of how to use Oracle Communications WebRTC Session Controller Signaling Engine (Signaling Engine) to process customized SIP data in messages, and add new JSON data to support protocol changes.

Processing Messages With Custom SIP Data

This section provides some examples for how to translate SIP messages which contain custom SIP data.

Example SIP Request Variable

The examples in this chapter assume that you have created a custom sipReq variable as shown in this example:

// Create REGISTER request
def from = getFromAddress(context)
def to = getToAddress(context)
def sipReq = context.sipFactory.createSipRequest("REGISTER", from, to)
 
// Set request URI
sipReq.requestURI = context.sipFactory.createSipAddress(Constants.PROXY_SIP_URI).URI
 
// Set contact user
if (from.URI?.user) {
  sipReq.setContactUser(from.URI.user)
}
 
// Set sip.instance to allow container to use SIP Outbound
// for routing purposes as defined in RFC 5626
def sipInstance = "\"<urn:uuid:" + java.util.UUID.randomUUID() + ">\""
sipReq.setSipContactParameter("+sip.instance", sipInstance)
sipReq.setSipContactParameter("reg-id", "1")
context.subSessionStore.put("sip.instance", sipInstance)

sipReq.send()

Extending SIP Messages with New Headers

This Groovy code snippet from the default register package, in the FROM_APP/connect/request/default criteria (commented out) adds support for a Globally Routable User agent URI (GRUU).

sipReq.setHeader("Supported", "gruu")
// P-Charging-Vector example
def icidValue = context.uniqueId
def myIp = java.net.InetAddress.localHost.hostAddress
sipReq.setHeader("P-Charging-Vector", "icid-value=" + icidValue +
";icid-generated-at=" + myIp)

Protecting System Performance by Removing SIP Messages

You can save network bandwidth by removing unimportant messages during processing. For example, you would use this code snippet to remove provisional SIP responses (the 1xx SIP messages). You would put this in the Groovy script for the FROM_NET/INVITE/response criteria:

if (sipResponse.status < 200) {
  // Ignore provisional responses
} else if (sipResponse.status < 300) 
  // Proceed with processing
}
{...
}

Removing a SIP Header in a Message

Use this Groovy code snippet to remove a header. Headers cannot be renamed.

sipReq.removeHeader("headername")

Replacing a SIP Header in a Message

You use the setHeader method to replace a header in a SIP message. Setting a header overwrites its value.

Conditionally Passing SIP Headers in Messages

This example Groovy code snippet probes for a JSON parameter called myWebParmeter and if present it copies the value to a SIP header.

def myWebParameter = context.webMessage?.header.?myParameter
if (myWebParameter) {
  sipRequest.setHeader("MyHeader", myWebParameter)
}

You pass SIP headers as extension headers (extHeader) in the JSON API. See WebRTC Session Controller Application Developer's Guide for examples of using extension headers.

Changing JSON Data to Support Protocol Changes

If the JSON protocol specification changes, you can add processing for additional data in your Groovy scripts. WebRTC Session Controller ignores new JSON data if you do not use it in processing.

Retrieving Session Addressing Information from Groovy

In certain instances, you may need to retrieve connection information from a particular WebRTC Session Controller session, in order, for instance, to provide media service route lookups to a WebRTC Session Controller Media Engine. To facilitate such communication, the authenticationContext passed to the buildSecurityContext Groovy library function initializes the properties listed in Table 4-1.

Table 4-1 authenticationContext Properties

Property Description

authContext.properties.connection.remote_ip

Returns the Internet Protocol (IP) address of the client or the last proxy that sent the request.

authContext.properties.connection.remote_port

Returns the IP source port number of the client or the last proxy that sent the request.

authContext.properties.connection.local_ip

Returns the IP address of the interface on which the request was received.

authContext.properties.connection.local_port

Returns the IP port number of the interface on which the request was received.

authContext.properties.connection.server_name

Returns the host name of the server to which the request was sent.

authContext.properties.connection.headers

Returns the Websocket headers such as origin, host and others. For a complete listing, see https://tools.ietf.org/html/rfc6455#page-25.


The authenticationContext properties are initiated during the session handshake upon client connection and are available to all WebRTC Session Controller Groovy packages.

Example 4-1 shows how to retrieve the authenticationContext properties from Groovy.

Example 4-1 Retrieving authenticationContext Properties

// Retrieve the properties from the authenticationContext...
def properties = authContext.properties
// Retrieve the connection associated with the properties...
def connection = properties.connection

// Print the properties to the WebLogic console...
println "Remote IP address: "+connection.remote_ip
println "Remote port: "+connection.remote_port
println "Local IP address: "+connection.local_ip
println "Local port "+connection.local_port
println "Server name: "+connection.server_name
println "Websocket headers "+connection.headers

Initiating REST Calls from Groovy

This section describes how you can initiate arbitrary Representational State Transformation (REST) calls to external network endpoints.

The WebRTC Session Controller REST call functionality supports the following features:

  • Asynchronous and synchronous callback responses

  • Support for HTTP and HTTPS

  • Support for all standard REST methods:

    • GET

    • POST

    • PUT

    • DELETE

    • HEAD

    • OPTIONS

  • Support for REST calls during message processing or WebSocket connection establishment

For complete details on the Groovy REST API, see Oracle Communications WebRTC Session Controller Configuration API Reference.

Adding a REST URI Endpoint Constant

As a matter of convenience and to simplify maintenance, you should define a Groovy constant for your REST endpoint URI. In the global constants block of the WebRTC Session Controller Groovy script library, add a line similar to Example 4-2, replacing server, port and rest_endpoint with the correct values for your configuration.

Example 4-2 Defining a REST URL Endpoint Constant

public static final MY_REST_URL = "http://server:port/rest_endpoint"

With the constant defined, you can reference from the script library or WebRTC Session Controller packages similar to Example 4-3.

Example 4-3 Referencing the URL Constant

def restRequest = context.restClient.createRequest(Constants.MY_REST_URL...);

Creating a REST Request in Groovy

To create a REST request in Groovy, you use the WebRTC Session Controller restClient object's createRequest method:

def restRequest = context.restClient.createRequest(rest_url[, http_method][, synchronous]);

The rest_url parameter is required and represents a valid REST endpoint. The http_method parameter is a valid REST HTTP method, while the synchronous parameter is a boolean value indicating, if true, that the REST invocation is synchronous. Both the http_method and synchronous parameters are optional, and, if omitted, a REST request is created using the provided rest_url and the HTTP GET method by default.

Note:

REST requests created in WebRTC Session Controller packages must always be asynchronous. If you initiate REST calls from the buildSecurityContext Groovy library script, they must be synchronous.

In Example 4-4, an asynchronous REST request is created using the REST endpoint constant from Example 4-2 and the HTTP PUT method.

Example 4-4 Creating a REST Request

def myRestRequest = context.restClient.createRequest(Constants.MY_REST_URL, "PUT");

Configuring the REST Request

Once the REST request is created, you can customize it using the following methods:

  • addHeader(string name, string value): add an arbitrary header to the REST request

  • setAccept(RestMediaType mediatypes): define the data types the REST endpoint accepts, defined as a RestMediaType enum:

    • APPLICATION_JSON: an application/json content type

    • APPLICATION_XML: an application/xml content type

    • TEXT_PLAIN: a text/plain content type

  • setAcceptLanguage(string locales): a string defining the acceptable locales

  • setEntity(object entity, RestMediaType mediatype): set the request entity for REST POST and PUT methods

    Note:

    Depending upon the RestMediaType, the following requirements apply to the setEntity method:
    • APPLICATION_JSON: the entity object should be an object expected by the call method of groovy.json.JsonBuilder, or a groovy.json.JsonBuilder object which is a groovy.lang.Writable.

    • APPLICATION_XML: the entity object should be a groovy.lang.Closure object as expected by the bind method of groovyl.xml.StreamingMarkupBuilder or a groovy.lang.Writable object obtained from groovy.xml.StreamingMarkupBuilder.

    • TEXT_PLAIN: the entity object should be a java.lang.string.

    For more details on Groovy objects and data types, see the Groovy documentation at http://groovy-lang.org/documentation.html.

  • setStackConfiguration(string name, object value): adds a property supported by the underlying REST stack implementation

Example 4-5 configures some basic parameters for the REST request object created in Example 4-4.

Example 4-5 Configuring a REST Request Object

myRestRequest.setAccept(APPLICATION_XML);
myRestRequest.setAcceptLanguage("en-us", "de-de", "fr-fr");
myRestRequest.addHeader("My Key", "My Value");

Sending the REST Request

In Example 4-6, using the REST request created Example 4-4, you use the request object's send method to send the REST request. Example 4-6 provides as arguments to the send method an optional entity, in this case an XML snippet, and also provides the RestMediaType of the entity. The send method may also be called with no arguments, and returns the future of the REST invocation, here stored in the variable myRestFuture.

Example 4-6 Sending the REST Request

def xml = {  mkp.xmlDeclaration()  fish {    name("salmon")    price("10")    }};

def myRestFuture = myRestRequest.send(xml, APPLICATION_XML);

Note:

Specifying the entity and RestMediaType arguments for the send method is equivalent to using the setEntity method described in "Configuring the REST Request."

Handling REST Responses

In order to handle REST responses from asynchronous REST requests, using the context object's taskBuilder method, you bind the restClient context to a Groovy callback function that will handle the REST response.

In Example 4-7, myRestFuture from Example 4-6 is bound to the Groovy function processResponse for getTaskBuilder's onSuccess and onError methods.

Example 4-7 Binding the REST Response to a Groovy Callback

context.getTaskBuilder("processResponse").withArg("myRestFuture", restFuture)
            .onSuccess(restFuture).build();
context.getTaskBuilder("processResponse").withArg("myRestFuture", restFuture)
            .onError(restFuture).build();

Note:

While the onError and onSuccess methods in Example 4-7, are bound to the same processResponse function, you can choose different functions for each depending upon your requirements.

The processResponse Groovy function referenced in Example 4-7 can be defined in the WebRTC Session Controller script library to process the REST response. Example 4-8 shows a basic example using the XML document defined in Example 4-6.

Example 4-8 REST Response Handler

void processResponse(TemplateContext context) {
  def result = context.taskArgs.restFuture.get()
  if (result.status == 200) {            
    def fish = result.value()
    if (fish.name.text() == "salmon") {
      // Continue processing...
    }
  } else {
    // Handle any errors...
  }
}

The RestResult variable, resp, itself provides the following utility methods that you can use when processing the REST response:

  • getAllow

  • getCookies

  • getEntityTag

  • getHeaders

  • getLanguage

  • getLastModified

  • getLength

  • getLocation

  • getResponseData

  • getStatus

  • hasEntity

  • value

For details on those methods, see Oracle Communications WebRTC Session Controller Configuration API Reference.

REST Authentication

The WebRTC Session Controller REST API supports basic and digest authentication schemes. You use the methods setCredentials and setDigestCredentials to specify username and password for basic and digest authentication respectively:

  • setCredentials(string username, byte[] password)

  • setDigestCredentials(string username, byte[] password)

Note:

The API accepts encrypted passwords that you can retrieve using the weblogic.security.Encrypt utility.

In Example 4-9, a synchronous REST request is created, myRestAuthRequest, and the setCredentials method is used to initialize a username and password.

Example 4-9 Creating a Basic Authentication REST Request

def myRestAuthRequest = context.restClient.createRequest(Constants.MY_REST_URL, "PUT", true);
def username = "myuserid";
def password = [231, 245, 675, 232, 123] as byte[];
myRestAuthRequest.setCredentials(username, password);

Useful XML Groovy Utilities for REST Calls

If you are using XML markup in your REST requests and responses, there are Groovy utilities that can streamline much of your work:

  • StreamingMarkupBuilder: a utility that simplifies building XML documents

  • XmlSlurper: a utility that simplifies reading and formatting XML documents

For more details on those and other Groovy utilities, see http://groovy-lang.org/documentation.html#apidocumentation.

Extending WebRTC Session Controller Functionality

If your implementation requires client application logic that WebRTC Session Controller or Javascript does not support by default, you need to create new software packages to implement it. The procedure below offers guidelines for creating a new package. The exact steps and sequence depend on your requirements.

See "JSONRTC Protocol Reference" for details on the JSONRTC protocol that WebRTC uses to communicate with client applications. Also see "Prerequisites for Extending WebRTC Session Controller Functionality" for information on other protocols you may need to understand.

To create a new package:

  1. Design your new package.

    Include the new JSON to SIP message mapping and any new JSON and SIP data, formats, and headers.

  2. Use the WebRTC Session Controller console to create the criteria and Groovy script processing necessary to implement your new package.

    See "Creating Criteria" for details on creating criteria.

  3. Create or extend the tools necessary to use the package with a client application.

    • If you use the JavaScript Development Environment client operating system, see the WebRTC Session Controller Application Developer's Guide for more information.

    • If you use a different client operating system, see that operating system documentation for details. You may also find the WebRTC Session Controller Application Developer's Guide helpful.

  4. Write the client application.

    • To develop JavaScript client applications see the WebRTC Session Controller Application Developer's Guide for more information.

    • To develop client applications in another operating system, see that operating system documentation for information on how to communicate with WebRTC Session Controller.