{"id":13086,"library":"drachtio-srf","title":"drachtio Signaling Resource Framework","description":"The `drachtio-srf` package, currently at version 5.0.22, is a Node.js framework for building Signaling Resource Function (SRF) applications, primarily for SIP (Session Initiation Protocol) servers. It provides a high-level API for handling SIP signaling, allowing developers to create complex SIP applications such as proxies, Back-to-Back User Agents (B2BUAs), and custom routing logic. The framework abstracts much of the complexity of the SIP protocol, leveraging a network connection to a separate `drachtio-server` process which handles the underlying SIP transaction processing. It requires Node.js version 18.x or higher and ships with TypeScript types, facilitating modern JavaScript and TypeScript development for real-time communication services.","status":"active","version":"5.0.22","language":"javascript","source_language":"en","source_url":"https://github.com/drachtio/drachtio-srf","tags":["javascript","typescript"],"install":[{"cmd":"npm install drachtio-srf","lang":"bash","label":"npm"},{"cmd":"yarn add drachtio-srf","lang":"bash","label":"yarn"},{"cmd":"pnpm add drachtio-srf","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"drachtio-srf requires a running drachtio-server process to which it connects and delegates SIP transaction processing.","package":"drachtio-server","optional":false}],"imports":[{"note":"While CommonJS `require` is shown in older examples, `drachtio-srf` ships with TypeScript types and targets Node.js 18+, making ESM `import` the recommended and modern approach. Ensure your project is configured for ESM (e.g., `\"type\": \"module\"` in package.json) for native ESM usage.","wrong":"const Srf = require('drachtio-srf');","symbol":"Srf","correct":"import { Srf } from 'drachtio-srf';"},{"note":"For type-safe development, explicitly import types for core classes like Dialog, Request, Response, and SipMessage, which represent key SIP entities and interactions.","symbol":"Srf, Dialog, Request, Response, SipMessage","correct":"import type { Srf, Dialog, Request, Response, SipMessage } from 'drachtio-srf';"},{"note":"The Srf constructor optionally accepts a string or array of strings as a `tag` parameter for routing, not an object.","wrong":"const srf = new Srf({ tag: 'my-app-tag' });","symbol":"Srf constructor with tags","correct":"import { Srf } from 'drachtio-srf';\nconst srf = new Srf('my-app-tag');"}],"quickstart":{"code":"import { Srf } from 'drachtio-srf';\n\nconst srf = new Srf();\n\nsrf.connect({\n  host: process.env.DRACHTIO_HOST ?? '127.0.0.1',\n  port: parseInt(process.env.DRACHTIO_PORT ?? '9022', 10),\n  secret: process.env.DRACHTIO_SECRET ?? 'cymru'\n});\n\nsrf.on('connect', () => console.log('Connected to drachtio server.'));\nsrf.on('error', (err) => console.error('drachtio-srf error:', err));\n\nsrf.invite(async (req, res) => {\n  console.log(`Incoming INVITE from ${req.callingNumber} to ${req.calledNumber}`);\n  try {\n    // Create a Back-to-Back User Agent (B2BUA)\n    // Replace 'sip:1234@10.10.100.1' with an actual SIP URI for the B party\n    const { uas, uac } = await srf.createB2BUA('sip:1234@10.10.100.1', req, res, {\n      localSdpB: req.body, // Offer SDP from incoming INVITE to B-party\n      // Additional options like provisionalTimeout, proxyRequestHeaders can be added\n    });\n    console.log('Call connected successfully as B2BUA');\n\n    // When one side terminates, hang up the other\n    uas.on('destroy', () => { \n      console.log('UAS leg destroyed, destroying UAC leg.');\n      uac.destroy(); \n    });\n    uac.on('destroy', () => { \n      console.log('UAC leg destroyed, destroying UAS leg.');\n      uas.destroy(); \n    });\n  } catch (err: any) {\n    console.error(`B2BUA call failed to connect: ${err.status || err.message}`);\n    if (!res.headersSent) {\n      res.send(err.status || 500, err.reason || 'B2BUA setup failed');\n    }\n  }\n});","lang":"typescript","description":"This quickstart demonstrates setting up a basic Back-to-Back User Agent (B2BUA) with `drachtio-srf`. It connects to a `drachtio-server`, listens for incoming SIP INVITEs, and attempts to establish a call to a specified URI, relaying media and signaling between the two call legs. It includes error handling and proper cleanup on call termination."},"warnings":[{"fix":"Ensure your `drachtio-server` process is running version 0.9.0 or later. Check the drachtio-server GitHub releases for the latest compatible version.","message":"When upgrading `drachtio-srf` to version 5.0.0 or higher, you MUST also upgrade your `drachtio-server` to version 0.9.0 or higher. Older server versions are incompatible due to significant changes in the wire protocol.","severity":"breaking","affected_versions":">=5.0.0"},{"fix":"Modify headers like `From` and `To` to use placeholders:\n```typescript\n  headers: {\n    'From': '<sip:user@placeholder>',\n    'To': '<sip:target@placeholder>'\n  }\n```","message":"When initiating outbound SIP requests (e.g., `srf.request` or `srf.createUAC`), use the string `'placeholder'` for the host part in `From` and `To` header URIs to allow the `drachtio-server` to automatically insert its local listening IP address. Do not manually set the IP or the `tag` attribute in these headers.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always check the status code in the `response` event handler for INVITEs and call the `ack` function for 200 OK responses:\n```typescript\nsrf.request('sip:target@domain.com', { method: 'INVITE', /* ... */ }, (err, req) => {\n  req.on('response', (res, ack) => {\n    if (res.status === 200) {\n      ack(); // Send the ACK for 200 OK\n    }\n  });\n});\n```","message":"For successful (200 OK) responses to an incoming INVITE request that creates a dialog (e.g., via `srf.request` for an INVITE client), the application is responsible for sending the final ACK. The `response` event handler will provide an `ack` function as a second argument which must be called.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the `drachtio-server` process is running and configured to listen on the host and port specified in `srf.connect()`. Verify network connectivity and firewall rules.","cause":"The `drachtio-srf` application failed to connect to the `drachtio-server` process, usually because the server is not running, is running on a different host/port, or a firewall is blocking the connection.","error":"Error: connect ECONNREFUSED"},{"fix":"If your project uses ESM, ensure you use `import` statements. If your project is CommonJS and you need to load an ESM-only dependency, you may need to convert your project to ESM by adding `\"type\": \"module\"` to your `package.json` and adjusting imports/exports, or use dynamic `import()` for the specific module.","cause":"This error occurs in Node.js when attempting to use CommonJS `require()` to load an ECMAScript Module (ESM) within a CommonJS context.","error":"Error [ERR_REQUIRE_ESM]: require() of ES Module ... not supported. Instead change the require of ... to a dynamic import()"},{"fix":"Examine the `status` code and `reason` phrase returned in the error object. This indicates a SIP protocol error (e.g., 404 Not Found, 486 Busy Here). Debug the SIP URI, headers, and routing logic. Use SIP trace tools to analyze the full SIP message flow.","cause":"A SIP transaction (e.g., INVITE, SUBSCRIBE) initiated by `drachtio-srf` resulted in a non-success (non-2xx) final SIP response from the remote endpoint.","error":"Call failed with final status XXX"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":""}