Skip to content

Commit

Permalink
more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
davehorton committed Nov 23, 2017
1 parent d7cfe71 commit 3c2ef57
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 33 deletions.
Binary file removed .DS_Store
Binary file not shown.
55 changes: 35 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,19 +164,22 @@ srf.request('sip:daveh@drachtio.org', {

## Creating SIP Dialogs

The examples above show how to send and receive individual SIP messages, but drachtio-srf also provides APIs to work with the higher-level [concept of SIP dialogs](https://tools.ietf.org/html/rfc3261#section-12). A SIP dialog is established through INVITE (or SUBSCRIBE) messages and represents a long-lived signaling and media connection between two endpoints. SIP dialogs can be created, modified, and destroyed using drachtio-srf. The API allows developers to create user agent servers (i.e., a SIP dialog initiated by responding to an incoming SIP INVITE), user agent clients (dialogs created by initiating a new SIP INVITE request), and back-to-back user agents.
The examples above show how to send and receive individual SIP messages, but drachtio-srf also provides APIs to work with the [higher-level concept of SIP dialogs](https://tools.ietf.org/html/rfc3261#section-12). A SIP dialog is established through INVITE (or SUBSCRIBE) messages and represents a long-lived signaling and media connection between two endpoints. SIP dialogs can be created, modified, and destroyed using drachtio-srf.

The API allows developers to create user agent servers (i.e., a SIP dialog initiated by responding to an incoming SIP INVITE), user agent clients (dialogs created by initiating a new SIP INVITE request), and back-to-back user agents.

All of the API methods below supporting returning a created dialog object either via a callback or returning a Promise.

### Srf#createUAS

Use this to respond to an incoming INVITE and establish a sip dialog as a user agent server.
Use this method to respond to an incoming INVITE and establish a sip dialog as a user agent server.

returning a Promise:
```js
srf.invite((req, res) => {
srf.createUAS(req, res, {
localSdp: someSdp // a string, or a Promise-returning function that resolves to a string
localSdp: someSdp // a string, or
// a function returning a Promise that resolves to a string
})
.then((dialog) => {
console.log('successfully created UAS dialog');
Expand Down Expand Up @@ -300,7 +303,7 @@ srf.createB2BUA(req, res, uri, {
cbFinalizedUac: (uac) => {...} // if you need the created UAC dialog as soon it is created
// i.e, as soon as 200 OK received by B,
// before 200 OK/ACK exchanged with A
}, (err, dialog) => {....});
}, (err, {uas, uac}) => {....});
```
It is also possible to provide a list of headers that should be propogated from the incoming INVITE to the outgoing one (or vice versa on responses traveling back upstream):
```js
Expand All @@ -321,7 +324,7 @@ srf.createB2BUA(req, res, uri, {
});
```
## More on SIP Dialogs
All of the APIs above create a SIP dialog object, which is an event emitter. For full details, [please see the API documentation here](http://davehorton.github.io/drachtio-srf/api/Dialog.html). Developers will interact with dialogs to listen for events, call methods, and read properties. An overview of the most common interfaces is described below:
All of the APIs above create a SIP dialog object, which is an event emitter. For full details, [please see the API documentation](http://davehorton.github.io/drachtio-srf/api/Dialog.html). Developers will interact with dialogs to listen for events, call methods, and read properties. An overview of the most common interfaces is described below:

### Dialog events
The most important event is the `destroy` event, which is triggered when a BYE is received for a SIP dialog (or a NOTIFY with Subscription-State: terminated for a SUBSCRIBE dialog). Applications should always listen for the 'destroy' event and take appropriate action (e.g., write a cdr, destroy related dialogs, etc).
Expand All @@ -333,38 +336,52 @@ In the case of an INVITE on hold (or off hold), the dialog will emit the `hold`
Similarly, if a session timer refreshing re-INVITE is received, a `refresh` event is emitted and no action is required by the application.

## Dialog properties
Some of the commonly-accessed properties are as follows:
* the `sip` object, which includes the `callId`, `remoteTag`, and `localTag` string properties; these uniquely define a SIP dialog per [RFC 3261](https://tools.ietf.org/html/rfc3261#section-12)
* the `local` object, which provides information related to the local side of the dialog: `uri`, `sdp`, and `contact`
Some of the more commonly-accessed properties are as follows:
* the `sip` object, which includes the `callId`, `remoteTag`, and `localTag` string properties; these [uniquely define a SIP dialog](https://tools.ietf.org/html/rfc3261#section-12)
* the `local` object, which provides information related to the local side of the dialog: the `uri`, `sdp`, and `contact` properties
* the `remote` object, which contains the `uri` and `sdp` properties for the remote side of the dialog
* `connected`, which is true if the dialog is active, false otherwise
* `onHold`, which is true if the dialog is currently in an on-hold state, false otherwise.

## Dialog methods
The most common method is `destroy`, which tears down a SIP dialog by sending a BYE (and a SUBSCRIBE dialog by sending a NOTIFY with Subscription-State: terminated). The `destroy` method optionally takes one parameter, a callback which provides the SIP message sent over the wire (BYE or NOTIFY).

```js
// if I need to wait till I get a response to the BYE..
dlg.destroy((bye) => {
bye.on('response', (msg) => {
console.log(`response to bye on ${bye.get('Call-Id)} was ${msg.status}'));
});
})
```
The dialog also exposes a `modify` method, which can be used to modify the session description protocol. It can be used in any of the following ways:
```js
dlg.modify(newSdp, (err) => {...}); // provide a modified sdp for the local side of the dialog..
// on success, dlg.remote.sdp will have the new remote sdp

dlg.modify('hold', (err) => {...}); // put the dialog on hold (sdp is automatically generated)

dlg.modify('unhold', (err) => {....}) // take the dialog off hold (sdp is automatically generated)
// provide a modified sdp for the local side of the dialog..
dlg.modify(newSdp, (err) => {
// on success, dlg.remote.sdp will have the new remote sdp
});
// put the dialog on hold (sdp is automatically generated)
dlg.modify('hold', (err) => {...});
// take the dialog off hold (sdp is automatically generated)
dlg.modify('unhold', (err) => {....})
```

## Creating a SIP Proxy Server
Creating a SIP proxy server is quite simple:
```js
srf.invite((req, res) => {
// simple outbound proxy - INVITE is proxied to the sip uri in the inbound request header
// simple outbound proxy -
// INVITE is proxied to the sip uri in the inbound request header
srf.proxyRequest(req, res);
// proxy to a specified destination
srf.proxyRequest( req, res, 'sip:next.hop.com');
// lots of options available, plus a callback to indicate success if needed
// lots of options available,
// plus a callback to indicate success if needed
srf.proxyRequest( req, res, ['sip:try.this.com', 'sip:try.that.com'], {
recordRoute: true,
forking: 'sequential',
Expand All @@ -382,7 +399,7 @@ srf.invite((req, res) => {
For full details, [see here](http://davehorton.github.io/drachtio-srf/api/Srf.html#proxyRequest#)

## Call Detail Records (CDRs)
Applications can connect to the drachtio server and receive call detail record information about all calls handled by the server. It is possible to create an application that both performs call control and receives call detail record information; as well, it is possible to separate these into separate applications.
Applications can connect to the drachtio server and receive call detail record information about all calls passing through the server. It is possible to create an application that both performs call control and receives call detail record information; as well, it is possible to separate these into separate applications.

Call detail records are emitted as events on the drachtio server framework instance that is created by `new Srf();`.

Expand Down Expand Up @@ -453,6 +470,4 @@ srf.use(function (err, req, res, next) {
// an error occurred!
});
srf.invite((req, res) => {...});
```
## License
[MIT](https://github.com/davehorton/drachtio-srf/blob/master/LICENSE)
```
49 changes: 37 additions & 12 deletions lib/srf.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ class Srf extends Emitter {

/**
* Creates a signaling resource framework instance.
* @constructor
* @param {Object} app - drachtio app, or connects args (optional)
* It is preferred to not pass any arguments to the constructor, e.g.
* const srf = new Srf();
* although
* @param {Object} [app] - drachtio app, or connects args.
*/
constructor(app) {
super() ;
Expand Down Expand Up @@ -102,7 +104,8 @@ class Srf extends Emitter {
* @param {Response} res drachtio response object
* @param {Srf~uasOptions} [opts] configuration options
* @param {Srf~uasCallback} [callback] optional callback
* @return {Promise} Promise if no callback is specified, a Promise is returned that resolves with the dialog
* @return {Promise} if no callback is supplied, a Promise is returned that resolves with the dialog created;
* otherwise the function returns undefined
*/
createUAS(req, res, opts = {}, callback) {
const self = this ;
Expand Down Expand Up @@ -156,10 +159,10 @@ class Srf extends Emitter {
*
* @param {string} uri - request uri to send to
* @param {Srf~uacOptions} opts configuration options
* @param {Srf~requestCreationCallback} [cbRequest] callback that provides the request that was sent over the wire
* @param {Srf~provisionalResponseCallback} [cbProvisional] callback that passes on provisional responses
* @param {Srf~uacProgressCallbacks} [progressCallbacks] contains callbacks with call progress info
* @param {Srf~uacCallback} [callback] optional callback
* @return {Promise} Promise if no callback is specified, a Promise is returned that resolves with the dialog
* @return {Promise} if no callback is supplied, a Promise is returned that resolves with the dialog created;
* otherwise the function returns undefined
*/
createUAC(uri, opts, cbRequest, cbProvisional, callback) {
var self = this ;
Expand Down Expand Up @@ -298,9 +301,10 @@ class Srf extends Emitter {
* @param {Response} res - drachtio Response passed with incoming request
* @param {String} uri - an IP address[:port] to send the B leg to
* @param {Srf~b2bOptions} [opts] - configuration options
* @param {Srf~requestCreationCallback} [cbRequest] callback that provides the UAC request that was sent over the wire
* @param {Srf~provisionalResponseCallback} [cbProvisional] callback that passes on provisional responses on UAC leg
* @returns {Promise} promise fulfilled with {uac, uas} pair of dialogs, or rejected with cause of failure
* @param {Srf~b2bProgressCallbacks} [progresssCallbacks] contains callbacks with call progress info
* @param {Srf~b2bCallback} [callback] optional callback
* @return {Promise} if no callback is supplied, a Promise is returned that resolves with the two dialogs created -
* {uas, uac}; otherwise the function returns undefined
*/
createB2BUA(req, res, uri, opts, cbRequest, cbProvisional, callback) {
const self = this ;
Expand Down Expand Up @@ -492,7 +496,7 @@ class Srf extends Emitter {
}
/**
* respond to an incoming INVITE message by creating a user-agent server (UAS) dialog
* @deprecated please use createUAS instead
* @deprecated please use [createUAS]{@link Srf#createUAS} instead
* @param {Request} req incoming drachtio Request object, received in app.invite(...) method
* @param {Response} res drachtio Response passed with incoming request
* @param {Srf~uasOptions} opts configuration options
Expand Down Expand Up @@ -538,7 +542,7 @@ class Srf extends Emitter {

/**
* create a user-agent client (UAC) dialog by generating an INVITE request
* @deprecated please use createUAC instead
* @deprecated please use [createUAC]{@link Srf#createUAC} instead
* @param {RequestUri} uri - request uri to send to
* @param {Srf~uacOptions} opts configuration options
* @param {Srf~dialogCreationCallback} cb callback that provides the created Dialog
Expand Down Expand Up @@ -650,7 +654,7 @@ class Srf extends Emitter {

/**
* create back-to-back dialogs; i.e. act as a back-to-back user agent
* @deprecated please use createB2BUA instead
* @deprecated please use [createB2BUA]{@link Srf#createB2BUA} instead
* @param {Request} req - incoming drachtio Request object, received in app.invite(...) method
* @param {Response} res - drachtio Response passed with incoming request
* @param {String|Array} uri] - an IP address[:port], or list of same, to send the B leg to
Expand Down Expand Up @@ -1044,6 +1048,14 @@ methods.forEach((method) => {
* @property {RequestUri=} [uri] request uri to send to
*/

/**
* Callbacks providing call progress information for a UAC INVITE
* @typedef {Object} Srf~uacProgressCallbacks
* @property {Function} cbRequest - callback that provides request sent over the wire: cbRequest: (req) => {..}
* @property {Function} cbProvisional - callback that provides a provisional response:
* received cbProvisional: (req) => {..}
*/

/**
* Arguments provided when creating a B2BUA
* @typedef {Object} Srf~b2bOptions
Expand All @@ -1061,6 +1073,19 @@ methods.forEach((method) => {
* @property {string} provisionalTimeout - timeout after which to attempt next uri in the destination array (e.g '1s')
*/

/**
* Callbacks providing call progress information for a B2BUA
* @typedef {Object} Srf~b2bProgressCallbacks
* @property {Function} cbRequest - callback that provides request sent over the wire: cbRequest: (req) => {..}
* @property {Function} cbProvisional - callback that provides a provisional response:
* received cbProvisional: (req) => {..}
* @property {Function} cbFinalizedUac - callback that provides the finalized UAC dialog as soon as a 200 OK
* is received from the B leg, and before the 200 OK is sent on the A leg: cbFinalizedUac: (uac) => {..}
* An application should only supply this callback if there is a need to have access to the uac object before
* both legs are established (i.e. typically, an application will simply wait to get both the uac and uas objects
* when the returned Promise from the method fulfills.
*/

/**
* Arguments provided when proxying an incoming request
* @typedef {Object} Srf~proxyOptions
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "drachtio-srf",
"version": "4.2.1",
"version": "4.2.2",
"description": "drachtio signaling resource framework",
"main": "lib/srf.js",
"scripts": {
Expand Down

0 comments on commit 3c2ef57

Please sign in to comment.