drachtio-srf

repository·main·Indexed 42 days ago

https://github.com/drachtio/drachtio-srf

A Node.js framework for building SIP Server applications, providing high-level abstractions for proxying, B2BUA creation, and SIP request handling. It connects to a drachtio server to facilitate signaling operations and includes utilities for managing SIP Dialogs, handling authentication challenges via DigestClient, and implementing middleware for SIP requests and responses. Version 5.0.29.

Tokens
11.9K
Snippets
36
Records
47
Agent score
53%

What's inside drachtio-srf

  1. Overview of drachtio-srf

    main
    drachtio-srf is a Node.js framework designed for building SIP Server applications. It provides high-level abstractions for common SIP tasks such as proxying requests, creating Back-to-Back User Agents (B2BUAs), and sending manual SIP requests. It connects to a drachtio server to facilitate signaling operations.
  2. Connect to a drachtio server

    main

    To use drachtio-srf, you must first instantiate the Srf class and call the connect() method with your server configuration. The configuration object requires host, port, and secret.

    const Srf = require('drachtio-srf');
    const srf = new Srf();
    
    srf.connect({
      host: '192.168.32.5',
      port: 9022,
      secret: 'cymru'
    });
  3. Manage SIP session state with the Dialog class

    main

    The Dialog class represents a SIP dialog and manages its state, media attributes, and lifecycle events. You do not instantiate this class directly; instead, it is returned by Srf#createUAC, Srf#createUAS, or Srf#createB2BUA.

    Key properties available on a Dialog instance:

    • id: The unique identifier for the dialog.
    • type: The type of dialog (e.g., 'uac' or 'uas').
    • sip: An object containing callId, localTag, and remoteTag.
    • local: The local side of the session, containing uri, sdp, and contact.
    • remote: The remote side of the session, containing uri and sdp.
    • onHold: A boolean indicating if the session is currently on hold.
    • connected: A boolean indicating if the dialog is still active.
  4. Dialog States and Directions

    main

    The Srf framework uses DialogState and DialogDirection constants to represent the lifecycle and role of a SIP dialog.

    DialogState:

    • trying: Initial state.
    • proceeding: Provisional responses received.
    • early: Early media state.
    • confirmed: Dialog established (e.g., 200 OK sent/received).
    • terminated: Dialog ended normally.
    • rejected: Dialog failed due to a rejection.
    • cancelled: Dialog was cancelled (e.g., via CANCEL request).

    DialogDirection:

    • initiator: The side that started the dialog (UAC).
    • recipient: The side that received the request (UAS).
  5. Handle SIP Messages and Requests

    main

    SIP interactions involve SipMessage, SrfRequest, and SrfResponse objects:

    • SipMessage: The base interface containing raw data, headers, and methods to get, set, or has headers.
    • SrfRequest: Extends SipMessage with SIP-specific properties like method, callId, branch, sdp, and uri. It includes a cancel() method.
    • SrfResponse: Extends SipMessage with status (e.g., 200) and reason (e.g., 'OK'). It includes a send() method to transmit the response to the client.
  6. Handle SIP dialog events

    main

    The Dialog class is an EventEmitter that emits several events based on incoming SIP messages. When you attach a handler to these events, you are responsible for generating a SIP response using the provided res.send() method. If no handler is attached, the library automatically sends a 200 OK for most methods.

    Common Events:

    • destroy: Triggered when the dialog is torn down from the far end (e.g., receiving a BYE).
    • modify: Triggered when the far end sends a re-INVITE. You must call res.send() to respond.
    • refresh: Triggered when the far end sends a session refresh (notification only; no response required).
    • hold / unhold: Triggered when the far end modifies the session to hold or unhold.
    • info: Triggered when an INFO message is received.
    • notify: Triggered when a NOTIFY message is received.
    • options: Triggered when an OPTIONS message is received.
    • update: Triggered when an UPDATE message is received.
    • refer: Triggered when a REFER message is received.
    • message: Triggered when a MESSAGE message is received.
    • subscribe: Triggered when a SUBSCRIBE request is received.
    • ack: Triggered when an ACK is received.
  7. Manage a SIP Dialog

    main

    A Dialog object represents a SIP session (e.g., a call). It provides methods to interact with the session:

    • modify(sdp, opts): Sends a re-INVITE or UPDATE to change session parameters like SDP.
    • request(opts): Sends a new SIP request within the context of the dialog.
    • destroy(opts): Terminates the dialog.
    • on(event, callback): Listens for session events like ack, info, message, notify, refer, etc.
    // Example: Modifying SDP in a dialog
    await dialog.modify('v=0\r\no=...');
    
    // Example: Listening for a REFER event
    dialog.on('refer', (req, res) => {
      console.log('Received REFER');
    });
  8. Initialize and connect a DrachtioAgent

    main

    To use drachtio-srf, you must instantiate a DrachtioAgent and connect it to a drachtio server. The agent acts as the primary interface for sending SIP requests and receiving SIP messages.

    When connecting, you must provide a secret for authentication and optionally tags to identify the agent to the server. The agent uses a callback mechanism (passed to the constructor) to route incoming requests and responses to your application middleware.

    Common events to listen for include connect, close, and error.

    const DrachtioAgent = require('drachtio-srf').DrachtioAgent;
    
    // The callback passed to the constructor is the middleware handler
    const agent = new DrachtioAgent((req, res) => {
      // Handle incoming SIP requests here
      console.log('Received request:', req.method, req.uri);
    });
    
    agent.connect({
      host: '127.0.0.1',
      port: 9022,
      secret: 'your-secret',
      tags: ['my-agent']
    }, (err) => {
      if (err) {
        console.error('Connection error:', err);
        return;
      }
      console.log('Connected to drachtio server');
    });
  9. Create a Back-to-Back User Agent (B2BUA) with srf.createB2BUA()

    main

    The createB2BUA() method allows you to bridge two SIP legs (a User Agent Client and a User Agent Server). It is typically called within an invite handler.

    Parameters:

    • uri: The target SIP URI (e.g., 'sip:1234@10.10.100.1').
    • req: The incoming SIP request.
    • res: The incoming SIP response.
    • options: An object containing configuration, such as localSdpB to provide local SDP.

    Returns: Returns a Promise that resolves to an object containing {uas, uac}. You should listen for the 'destroy' event on both legs to ensure that when one side terminates, the other side is also hung up.

    srf.invite((req, res) => {
      srf.createB2BUA('sip:1234@10.10.100.1', req, res, {localSdpB: req.body})
        .then(({uas, uac}) => {
          console.log('call connected');
    
          // when one side terminates, hang up the other
          uas.on('destroy', () => { uac.destroy(); });
          uac.on('destroy', () => { uas.destroy(); });
        })
        .catch((err) => {
          console.log(`call failed to connect: ${err}`);
        });
    });
  10. Send manual SIP requests with srf.request()

    main

    You can send arbitrary SIP requests using srf.request(). This is useful for tasks like sending OPTIONS pings.

    Parameters:

    • uri: The target SIP URI.
    • options: An object containing the method (e.g., 'OPTIONS') and headers.
    • callback: A callback function that receives (err, req).

    Usage: Listen for the 'response' event on the returned request object to handle the SIP response.

    srf.request('sip:tighthead.drachtio.org', {
      method: 'OPTIONS',
      headers: {
        'Subject': 'OPTIONS Ping'
      }
    }, (err, req) => {
      if (err) return console.log(`Error sending OPTIONS: ${err}`);
      req.on('response', (res) => {
        console.log(`Response to OPTIONS ping: ${res.status}`);
      });
    });
  11. Proxy SIP requests with srf.proxyRequest()

    main

    You can act as a SIP proxy by using srf.proxyRequest(). This method takes an incoming request, a list of target destinations, and an optional configuration object. It returns a Promise that resolves with the results of the proxy operation.

    Options:

    • recordRoute: Boolean indicating if Record-Route should be used.
    • followRedirects: Boolean indicating if redirects should be followed.
    • provisionalTimeout: A string representing the timeout for provisional responses (e.g., '2s').

    Result Object: Resolves to an object containing:

    • finalStatus: The final SIP status code.
    • finalResponse: The final SIP response object.
    • responses: An array of intermediate responses.
    srf.invite((req, res) => {
      srf.proxyRequest(req, ['sip.example1.com', 'sip.example2.com'], {
        recordRoute: true,
        followRedirects: true,
        provisionalTimeout: '2s'
      }).then((results) => {
        console.log(JSON.stringify(results)); 
        // {finalStatus: 200, finalResponse:{..}, responses: [..]}
      });
    });
  12. Configure the Srf instance

    main

    When connecting to a drachtio server, use the SrfConfig object to specify connection details. You can provide the host, port, secret for authentication, and an optional logger function for debugging.

    const config: Srf.SrfConfig = {
      host: '127.0.0.1',
      port: 9000,
      secret: 'your-secret',
      logger: (msg) => console.log(msg)
    };