Skip to content

Latest commit

 

History

History
330 lines (261 loc) · 7.81 KB

File metadata and controls

330 lines (261 loc) · 7.81 KB

Module Development Examples

The OpenSIPS MCP Server includes tools and prompts that help develop new OpenSIPS C modules.

Getting Started with Module Development

Use the write_module Prompt

The write_module prompt provides a comprehensive guide for developing a new OpenSIPS module, including C code scaffolding, build system integration, and testing guidance.

{
  "prompt": "write_module",
  "arguments": {
    "module_name": "my_custom_module",
    "description": "A module that implements custom call routing logic based on time-of-day and caller reputation scores from an external API"
  }
}

The prompt generates:

  1. Module skeleton -- Complete C source file with the OpenSIPS module interface.
  2. Module exports -- Function exports, parameter definitions, MI commands.
  3. Build integration -- Makefile fragment for the OpenSIPS build system.
  4. Documentation template -- Module documentation in OpenSIPS format.

Module Scaffolding

The prompt produces a module structure like this:

modules/my_custom_module/
    my_custom_module.c       # Main module source
    my_custom_module.h       # Header with types and declarations
    Makefile                 # Build file
    doc/
        my_custom_module.xml # Module documentation

Main Module File Structure

A typical OpenSIPS module follows this pattern:

/*
 * my_custom_module - Custom call routing module
 *
 * Copyright (C) 2026 Your Organization
 */

#include "../../sr_module.h"
#include "../../dprint.h"
#include "../../mod_fix.h"
#include "../../parser/parse_uri.h"

/* Module parameters */
static int    reputation_threshold = 50;
static char  *api_endpoint = "http://localhost:8080/reputation";

/* Module functions */
static int mod_init(void);
static int child_init(int rank);
static void mod_destroy(void);
static int w_check_reputation(struct sip_msg *msg, str *caller);
static int w_route_by_time(struct sip_msg *msg, int *start_hour, int *end_hour);

/* MI commands */
static mi_response_t *mi_show_stats(const mi_params_t *params,
                                     struct mi_handler *async_hdl);

/* Exported functions */
static const cmd_export_t cmds[] = {
    {"check_reputation", (cmd_function)w_check_reputation, {
        {CMD_PARAM_STR, 0, 0},
        {0, 0, 0}
    }, ALL_ROUTES},
    {"route_by_time", (cmd_function)w_route_by_time, {
        {CMD_PARAM_INT, 0, 0},
        {CMD_PARAM_INT, 0, 0},
        {0, 0, 0}
    }, REQUEST_ROUTE|FAILURE_ROUTE},
    {0, 0, {{0, 0, 0}}, 0}
};

/* Exported parameters */
static const param_export_t params[] = {
    {"reputation_threshold", INT_PARAM, &reputation_threshold},
    {"api_endpoint",         STR_PARAM, &api_endpoint},
    {0, 0, 0}
};

/* MI commands */
static const mi_export_t mi_cmds[] = {
    {"my_custom_stats", 0, 0, 0, {
        {mi_show_stats, {0}},
        {EMPTY_MI_RECIPE}
    }},
    {EMPTY_MI_EXPORT}
};

/* Module interface */
struct module_exports exports = {
    "my_custom_module",  /* module name */
    MOD_TYPE_DEFAULT,    /* class of this module */
    MODULE_VERSION,
    DEFAULT_DLFLAGS,
    0,                   /* load function */
    NULL,                /* OpenSIPS module dependencies */
    cmds,                /* exported functions */
    0,                   /* exported async functions */
    params,              /* exported parameters */
    0,                   /* exported statistics */
    mi_cmds,             /* exported MI functions */
    0,                   /* exported pseudo-variables */
    0,                   /* exported transformations */
    0,                   /* extra processes */
    0,                   /* module pre-initialization function */
    mod_init,            /* module initialization function */
    0,                   /* response handling function */
    mod_destroy,         /* destroy function */
    child_init,          /* per-child init function */
    0                    /* reload confirm function */
};

Understanding the OpenSIPS Module API

Use the teach_concept Prompt

Learn about specific aspects of module development:

{
  "prompt": "teach_concept",
  "arguments": {
    "topic": "OpenSIPS module exports structure"
  }
}
{
  "prompt": "teach_concept",
  "arguments": {
    "topic": "OpenSIPS shared memory management"
  }
}
{
  "prompt": "teach_concept",
  "arguments": {
    "topic": "OpenSIPS MI command implementation"
  }
}

Module Development Workflow

1. Plan the Module

Use the design_architecture prompt to plan how your module fits into the OpenSIPS processing pipeline:

{
  "prompt": "design_architecture",
  "arguments": {
    "requirements": "I need a module that queries an external HTTP API during call setup to check caller reputation and make routing decisions"
  }
}

2. Generate the Scaffold

Use the write_module prompt to generate the initial code.

3. Review Existing Modules

Use resources to understand how similar modules work:

{"resource": "opensips://modules/pike"}
{"resource": "opensips://modules/dispatcher"}

4. Understand Route Script Integration

Use cfg_explain_route to understand how modules are called from the route script:

{
  "tool": "cfg_explain_route",
  "arguments": {
    "route_code": "route {\n  if (check_reputation($fU)) {\n    route_by_time(9, 17);\n  } else {\n    sl_send_reply(403, \"Forbidden\");\n  }\n}"
  }
}

5. Test with a Generated Config

Generate a config that uses your new module:

{
  "tool": "cfg_add_module",
  "arguments": {
    "config": "# base opensips.cfg...",
    "module": "my_custom_module",
    "params": {
      "reputation_threshold": 50,
      "api_endpoint": "http://localhost:8080/reputation"
    }
  }
}

6. Validate the Config

{
  "tool": "cfg_validate",
  "arguments": {
    "config": "# config with your module..."
  }
}

Building the Module

Makefile

include ../../Makefile.openssl
include ../../Makefile.defs
auto_gen=
NAME=my_custom_module.so
LIBS=

DEFS+=-I$(LOCALBASE)/include
LIBS+=-L$(LOCALBASE)/lib

include ../../Makefile.modules

Compile

cd opensips/modules/my_custom_module
make

Install

make install

Version Compatibility

When developing modules, check version-specific APIs:

{
  "prompt": "compare_modules",
  "arguments": {
    "module": "dialog",
    "version_a": "3.4",
    "version_b": "3.6"
  }
}

Check what changed between versions for the module API patterns you are using:

{
  "prompt": "migrate_version",
  "arguments": {
    "from_version": "3.4",
    "to_version": "3.6"
  }
}

Common Patterns

SIP Message Parsing

{
  "prompt": "debug_sip_message",
  "arguments": {
    "sip_message": "INVITE sip:bob@example.com SIP/2.0\r\nVia: SIP/2.0/UDP 10.0.0.1:5060;branch=z9hG4bK776\r\nFrom: <sip:alice@example.com>;tag=1928301774\r\nTo: <sip:bob@example.com>\r\nCall-ID: a84b4c76e66710@10.0.0.1\r\nCSeq: 314159 INVITE\r\nContent-Length: 0\r\n\r\n"
  }
}

SIP Ladder Diagrams

{
  "prompt": "explain_sip_ladder",
  "arguments": {
    "sip_trace": "Alice -> Proxy: INVITE\nProxy -> Bob: INVITE\nBob -> Proxy: 180 Ringing\nProxy -> Alice: 180 Ringing\nBob -> Proxy: 200 OK\nProxy -> Alice: 200 OK\nAlice -> Proxy: ACK\nProxy -> Bob: ACK"
  }
}

Understanding SIP message flows is essential for knowing where in the processing pipeline your module should operate.

Capacity Planning for Module Design

When your module adds processing overhead, use the capacity planning prompt to understand the impact:

{
  "prompt": "plan_capacity",
  "arguments": {
    "call_volume": "200 CPS with 5000 concurrent calls",
    "features": "Custom reputation check via external HTTP API on every INVITE"
  }
}

This helps you design your module with appropriate caching, async processing, or connection pooling strategies.