C.3. RTC:engine protocol details

C.3.1. Terminology
C.3.1.1. Connector
C.3.1.2. Router
C.3.1.3. User
C.3.1.4. App
C.3.1.5. Network
C.3.1.6. Session
C.3.1.7. Account
C.3.1.8. Browser SDK
C.3.2. Messages
C.3.2.1. Fields
C.3.2.2. method
C.3.2.3. from
C.3.2.4. to
C.3.2.5. session
C.3.2.6. body
C.3.3. Account
C.3.3.1. Flow
C.3.3.2. Messages
C.3.3.3. account.connect
C.3.3.4. account.state
C.3.3.5. State reasons
C.3.3.6. States
C.3.4. Call
C.3.4.1. Flow
C.3.4.2. call.start
C.3.4.3. Body properties
C.3.4.4. id
C.3.4.5. gcid
C.3.4.6. account
C.3.4.7. replace
C.3.4.8. trickle
C.3.4.9. target
C.3.4.10. sdp
C.3.4.11. call.alive
C.3.4.12. call.ringing
C.3.4.13. call.accept
C.3.4.14. call.ack.accept
C.3.4.15. call.candidate
C.3.4.16. call.fullsdp
C.3.4.17. call.change….
C.3.4.18. call.change.lock.reset
C.3.4.19. call.change.lock
C.3.4.20. call.change.lock.ok
C.3.4.21. call.change.offer
C.3.4.22. call.change.answer
C.3.4.23. call.dtmf
C.3.4.24. call.end
C.3.4.25. call.ack.end
C.3.5. Session
C.3.5.1. Flow
C.3.5.2. Messages
C.3.5.3. session.open
C.3.5.4. session.validated
C.3.5.5. Reason types

C.3.1. Terminology

C.3.1.1. Connector

There are two kinds of connectors. The front and the back connectors. The only front connector is the BrowserConnector. It has access to all WebSocket connections and is responsible for delivering RCT:engine protocol messages to the WebSocket clients, and for forwarding messages from the WebSocket clients to the router.

Currently there are four back connectors (SipConnector, XmppConnector, WebrtcConnector, ConferenceConnector). Every back connector implements a certain communication use case.

C.3.1.2. Router

The router is very simple stateless message broker, that is responsible for delivering the messages to the right connector. To decide where to send the message, the router takes a look at the recipient address (to) and forwards the message to the specified connector.

C.3.1.3. User
C.3.1.4. App

An app is a scope for a certain RTC:engine integration. Every user can have multiple apps. And an app contains sessions.

C.3.1.5. Network

A network is a user wide configuration, that maps a custom network name (tag) to a certain back connector. Additionally it can also store network specific configurations. And any account that is related to a certain network, will merge its custom configs with the network configs, and send its messages to the specified connector.

C.3.1.6. Session
C.3.1.7. Account

An account represents the credentials for a specific network. Usually it consists of an identifier like a SIP uri (sip:user@domain.tld) and an access token or rather a password.

C.3.1.8. Browser SDK

The Browser SDK is an abstraction layer on top of the RTC:engine protocol. It is served as bundled javascript library, and provides convenient components and methods for all use cases.

C.3.2. Messages

A typical message created by the browser sdk contains the following fields:

{
  "method": "module.action",
  "from": "connector:id",
  "to": "connector:id",
  "session": "session",
  "body": {
    ...
  }
}
C.3.2.1. Fields
C.3.2.2. method

It is separated in two parts. The first part is the module. It is a delegation key to separate concerns in the code. The second part is the action, which represents a specific method in a module.

C.3.2.3. from

It represents the current sender of a message. For example the user creates a new call via the browser sdk, the message would look like this:

{
  "method": "call.start",
  "from": "",
  "to": "webrtc:b2bua1",
  "session": "session1",
  "body": {
    ...
  }
}

The content of the field is completely irrelevant, because the BrowserConnector will overwrite this field. The reason is to avoid user manipulation.

{
  "method": "call.start",
  "from": "browser:ws1",
  "to": "webrtc:b2bua1",
  "session": "session1",
  "body": {
    ...
  }
}
C.3.2.4. to

In general this field represents the recipient of a message. The recipients address consists of two parts. First part is the prefix that targets the connector. Second part is the identifier of the recipient.

C.3.2.5. session

If you provisioned with the RTCEngine, you get a session and its token property. The browser SDK adds this token to every message.

C.3.2.6. body

The body contains the payload of the message. Every message type has its own body schema.

C.3.3. Account

Mainly an account consists of credentials (identifier, accessToken), that are needed to authenticate against the related network. Its lifecycle is bound to the lifecycle of the related session.

After RTC:engine received session.open, it responds a session.validated message. This message contains all provisioned accounts in its property "body.accounts".

C.3.3.1. Flow

Account flow

C.3.3.2. Messages
C.3.3.3. account.connect

RTC:engine needs one message per account. The message should contain the id of the account. The id is the object key in the accounts object from the [session.validated](../session/index.md) message.

{
  "from": "",
  "to": "...:...",
  "method": "account.connect",
  "session": "...",
  "body": {
    "id": "..."
  }
}
C.3.3.4. account.state

This message gives state information about the authentication and registration process of the related network and the corresponding connector. For example, if the related connector is the SipConnector, it creates a new SIP B2BUA in background, and notify the browser if any state change happens.

{
  "from": "...:...",
  "to": "browser:...",
  "method": "account.state",
  "session": "...",
  "body": {
    "id": "...",
    "reason": "...",
    "state": "..."
  }
}
C.3.3.5. State reasons
  • OK
  • CONNECTING
  • DISCONNECTING
  • SERVICE_UNAVAILABLE
  • SERVICE_ERROR
  • BAD_CONFIGURATION
  • WRONG_CREDENTIALS
  • CONNECTOR_UNAVAILABLE
  • CONNECTOR_BUSY
  • CONNECTOR_ERROR
  • ACCOUNT_NOT_FOUND
C.3.3.6. States
  • CONNECTED
  • DISCONNECTED

C.3.4. Call

C.3.4.1. Flow

Call flow

C.3.4.2. call.start

The caller sends this message to the RTC:engine to initiate a new call dialog.

{
  "from": "local",
  "to": ["...:..."],
  "method": "call.start",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "...",
    "account": "..."
    "replace": true|false,
    "trickle": true|false,
    "target": "...",
    "sdp": "..."
  }
}
C.3.4.3. Body properties
C.3.4.4. id

The id is a UUID version 4 that identifies the call dialog in the system. But caller and callee never have the same.

C.3.4.5. gcid

Whereas the gcid is a system wide and end-to-end consistent call identifier. It is necessary to track the entire call dialog.

C.3.4.6. account

It contains the callers account id. [(See accounts)](../account/index.md)

C.3.4.7. replace

This property is not used yet. It should support a call handover scenario.

C.3.4.8. trickle

If is set to true, the callee expects ice candidates, before the full sdp delivered by the caller, to accelerate the negotiation process.

C.3.4.9. target

It’s the URI (sip:user@domain.tld) of the callee.

C.3.4.10. sdp

The sdp property contains a very early state of the browsers media machine. It contains no ice candidates so far.

C.3.4.11. call.alive

After the callee received the "call.start" message, it responds with a "call.alive" to the RTC:engine, immediately.

{
  "from": "...",
  "to": "...",
  "method": "call.alive",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "..."
  }
}
C.3.4.12. call.ringing

After the callee received the "call.start" message, it responds with a "call.ringing" to the RTC:engine, immediately.

{
  "from": "...",
  "to": "...",
  "method": "call.ringing",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "...",
    "account": null
  }
}
C.3.4.13. call.accept

The callee sends this message after accepting the call explicitly.

{
  "from": "...",
  "to": "...",
  "method": "call.accept",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "...",
    "account": null,
    "trickle": true|false,
    "sdp": "..."
  }
}
C.3.4.14. call.ack.accept

Caller sends this message after it received the "call.accept" message from the callee.

{
  "from": "...",
  "to": "...",
  "method": "call.ack.accept",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "..."
  }
}
C.3.4.15. call.candidate

Both, caller and callee send ice candidates immediately after initiating respectively accepting the call.

{
  "from": "...",
  "to": "...",
  "method": "call.candidate",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "...",
    "candidate": {
      "payload": "...",
      "type": "WEBRTC_LEGACY"
    }
  }
}
C.3.4.16. call.fullsdp

Both, caller and callee send this message after the ice gathering finished and all candidates are available.

{
  "from": "...",
  "to": "...",
  "method": "call.fullsdp",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "...",
    "sdp": "..."
  }
}
C.3.4.17. call.change….

All messages, that begin with "call.change", are important for renegotiation and glare handling.

C.3.4.18. call.change.lock.reset
C.3.4.19. call.change.lock
C.3.4.20. call.change.lock.ok
C.3.4.21. call.change.offer
C.3.4.22. call.change.answer
C.3.4.23. call.dtmf

Only works if the connector of the related account supports DTMF messages.

{
  "from": "...",
  "to": "...",
  "method": "call.dtmf",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "...",
    "dtmf": "...",
    "account": null
  }
}
C.3.4.24. call.end

Both, caller and callee can send this message. It forces the counter part to end and destroy the call.

{
    "from": "...",
    "to": "...",
    "method": "call.end",
    "session": "...",
    "body": {
        "id": "...",
        "gcid": "...",
        "reason": "..."
    }
}
C.3.4.25. call.ack.end

The counter part, that receives the "call.end" message, sends the "call.ack.end" message.

{
  "from": "...",
  "to": "...",
  "method": "call.ack.end",
  "session": "...",
  "body": {
    "id": "...",
    "gcid": "...",
    "account": null
  }
}

C.3.5. Session

C.3.5.1. Flow

Session flow

C.3.5.2. Messages
C.3.5.3. session.open
{
  "method": "session.open",
  "from": "",
  "to": "",
  "session": "session1",
  "body": {
    "credentials": {
      "userSession": "session1"
    }
  }
}
C.3.5.4. session.validated

This message is the response to session.open. If the session property is a valid session, you get a response where the result property is true. In addition you get the account information to connect to the networks.

{
  "method": "session.validated",
  "from": "core",
  "to": "browser:ws1",
  "session": "session1"
  "body": {
    "result": true,
    "accounts": {
      "account1": {
        "identifier": "sip:account1@foo.bar"
        "target": "sip-connector:b2bua-account1",
        "network": {
          "tag": "sip-network"
        }
      }
    }
  },
}

If something went wrong, result is set to false and an error reason appears.

{
  "method": "session.validated",
  "from": "core",
  "to": "browser:ws1",
  "session": "session1"
    "body": {
      "result": false,
      "reason": {
        "type": "invalidToken",
        "message": "Your token is not a valid user session token!"
      }
    }
  },
}
C.3.5.5. Reason types
  • invalidToken
  • tokenExpired
  • missingCredentials