Giter Club home page Giter Club logo

drachtio-fsmrf's Introduction

drachtio-fsmrf Build Status

drachtio logo

Welcome to the Drachtio Media Resource framework, a partner module to drachtio-srf for building high-performance SIP server applications in pure javascript.

drachtio-fsmrf implements common media server functions on top of Freeswitch and enables rich media applications involving IVR, conferencing and other features to be built in pure javascript without requiring in-depth knowledge of freeswitch configuration.

Note, drachtio-fsmrf applications require a freeswitch media server, configured as per this ansible role.

API documentation for drachtio-fsmrf can be found here.

Data Model

This module exports a single class, Mrf (aka Media Resource Framework).

Invoking the constructor creates an instance of the Mrf class that can then be used to connect to Mediaservers; once connected to a Mediaserver you can create and manipulate instances of Endpoints and Conferences.

That's it -- those are all the classes you need to work with. You can connect calls to a Mediaserver, producing an Endpoint. You can then perform operations like play, say, bridge, park etc on the Endpoint (which equates to a Freeswitch channel). You can create Conferences, join Endpoints into Conferences, and perform operations on the Conference. And you can call any of the myriad freeswitch applications or api methods via the Endpoint and Conference classes.

Let's dive in.

Getting Started

First, create an instance of both the drachtio signaling resource framework and the media resource framework, as per below.

const Srf = require('drachtio-srf');
const Mrf = require('drachtio-fsmrf');

const srf = new Srf() ;
srf.connect(host: '127.0.0.1');

srf.on('connect', (err, hostport) => {
  console.log(`successfully connected to drachtio listening on ${hostport}`);
});

const mrf = new Mrf(srf) ;

At that point, the mrf instance can be used to connect to and produce instances of MediaServers

mrf.connect({address: '127.0.0.1', port: 8021, secret: 'ClueCon'})
  .then((mediaserver) => {
    console.log('successfully connected to mediaserver');
  })
  .catch ((err) => {
    console.error(`error connecting to mediaserver: ${err}`);
  });

In the example above, we see the mrf#connect method returns a Promise that resolves with an instance of the media server. As with all public methods, a callback variant is available as well:

// we're connecting to the Freeswitch event socket
mrf.connect({address: '127.0.0.1', port: 8021, secret: 'ClueCon'}, (err, mediaserver) => {
    if (err) {
      return console.log(`error connecting to mediaserver: ${err}`);
    }
    console.log(`connected to mediaserver listening on ${JSON.stringify(ms.sip)}`);
    /*
      {
        "ipv4": {
          "udp": {
            "address":"172.28.0.11:5060"
          },
          "dtls": {
            "address":"172.28.0.11:5081"
          }
        },
        "ipv6":{
          "udp":{},
          "dtls":{}
        }
      }
    */
  }
});

Having a media server instance, we can now create instances of Endpoints and Conferences and invoke operations on those objects.

Performing Media Operations

We can create an Endpoint when we have an incoming call, by connecting it to a Mediaserver.

srf.invite((req, res) => {
  mediaserver.connectCaller(req, res)
    .then(({endpoint, dialog}) => {
      console.log('successfully connected call to media server');

In the example above, we use MediaServer#connectCaller() to connect a call to a Mediaserver, producing both an Endpoint (represening the channel on Freeswitch) and a Dialog (representing the UAS dialog).

Again, note that a callback version is also available:

srf.invite((req, res) => {   
  mediaserver.connectCaller(req, res, (err, {endpoint, dialog} => {
    if (err) return console.log(`Error connecting ${err}`);
    console.log('successfully connected call to media server');
  });

We can also create an Endpoint outside of any inbound call by calling MediaServer#createEndpoint(). This will give us an initially inactive Endpoint that we can later modify to stream to a remote destination:

mediaserver.createEndpoint()
  .then((endpoint) => {

    // some time later...
    endpoint.modify(remoteSdp);

  });

Once we have an Endpoint, we can do things like play a prompt and collect dtmf:

endpoint.playCollect({file: myFile, min: 1, max: 4})
  .then((obj) => {
    console.log(`collected digits: ${obj.digits}`);
  });

Conferences work similarly - we create them and then can join Endpoints to them.

mediaserver.createConference('my_conf', {maxMembers: 50})
  .then((conference) => {
    return endpoint.join(conference)
  })
  .then(() => {
    console.log('endpoint joined to conference')
  });

When an Endpoint is joined to a Conference, we have an additional set of operations we can invoke on the Endpoint -- things like mute/unmute, turn on or off automatic gain control, playing a file directly to the participant on that Endpoint, etc. These actions are performed by methods that all begin with conf:

endpoint.join(conference, (err) => {
  if (err) return console.log(`Error ${err}`);

  endpoint.confMute();
  endpoint.confPlay(myFile);
}

Execute any Freeswitch application or api

As shown above, some methods have been added to the Endpoint and Conference class to provide syntactic sugar over freeswitch aplications and apis. However, any Freeswitch application or api can also be called directly.

Endpoint#execute executes a Freeswitch application and returns in either the callback or the Prompise the contents of the associated CHANNEL_EXECUTE_COMPLETE event that Freeswitch returns. The event structure is defined here:

// generate dtmf from an Endpoint
endpoint.execute('send_dtmf', `${digits}@125`, (err, evt) => {
  if (err) return console.error(err);

  console.log(`last dtmf duration was ${evt.getHeader('variable_last_dtmf_duration')}`);
})

Endpoint#api executes a Freeswitch api call and returns in either the callback or the Promise the response that Freeswitch returns to the command.

endpoint.api('uuid_dump', endpoint.uuid)
  .then((response) => {
    console.log(`${JSON.stringify(response)}`);
    //
    //    {
    //  "headers": [{
    //    "name": "Content-Type",
    //    "value": "api/response"
    //  }, {
    //    "name": "Content-Length",
    //    "value": 8475
    //  }],
    //  "hPtr": null,
    //  "body": "Event-Name: CHANNEL_DATA\n..

  });

Note that Content-Type api/response returned by api requests return a body consisting of plain text separated by newlines. To parse this body into a plain javascript object with named properties, use the Mrf#utils#parseBodyText method, as per below:

endpoint.api('uuid_dump', endpoint.uuid)
  .then((evt) => {
    const vars = Mrf.utils.parseBodyText(evt.getBody());
    console.log(`${JSON.stringify(vars)}`);
    //   {
    //    "Event-Name": "CHANNEL_DATA",
    //    "Core-UUID": "de006bc8-f892-11e7-a989-3b397b4b8083",
    //     ...
    //   }
  });

Tests

To run tests you will need Docker and docker-compose installed on your host, as the test suite runs in a docker network created by docker-compose-testbed.yaml. The first time you run the tests, it will take a while since docker images will be downloaded to your host.

$ npm test

  starting docker network..

    docker network started, giving extra time for freeswitch to initialize...

  Mrf#connect using Promise

     mrf.localAddresses is an array
     socket connected
     mediaserver.srf is an Srf

    ...etc...

License

MIT

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.