SiddiqSoft.sip2json 2.4.0

dotnet add package SiddiqSoft.sip2json --version 2.4.0
                    
NuGet\Install-Package SiddiqSoft.sip2json -Version 2.4.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SiddiqSoft.sip2json" Version="2.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SiddiqSoft.sip2json" Version="2.4.0" />
                    
Directory.Packages.props
<PackageReference Include="SiddiqSoft.sip2json" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SiddiqSoft.sip2json --version 2.4.0
                    
#r "nuget: SiddiqSoft.sip2json, 2.4.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SiddiqSoft.sip2json@2.4.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SiddiqSoft.sip2json&version=2.4.0
                    
Install as a Cake Addin
#tool nuget:?package=SiddiqSoft.sip2json&version=2.4.0
                    
Install as a Cake Tool

sip2json

<b>SIP Parser for Modern C++</b><br/> <small>Copyright ©2020-2024 Abdelkareem Siddiq. All rights reserved.</small>

Build Status alternate text is missing from this package README image alternate text is missing from this package README image alternate text is missing from this package README image

Design Goals

A modern C++20 SIP parser that converts between SIP protocol messages and JSON for seamless integration with distributed systems and NoSQL databases.

Compiler Requirements: C++20 compliant compiler

  • Clang 17+
  • GCC 14+
  • Visual Studio 2022+

Design Tradeoffs:

  • Native C++20 API without wrappers
  • Minimal, focused codebase
  • Widely-used, respected dependencies
  • Easy JSON transformations for NoSQL integration

Features

  • Header-only library - Easy integration, no compilation required
  • Efficient JSON representation - Compact storage with minimal intermediate processing
  • Bidirectional conversion - Serialize to/from SIP messages
  • Streaming support - Parse multiple messages from a buffer asynchronously
  • SDP support - Full encoding/decoding of Session Description Protocol bodies
  • Modern C++20 - Leverages latest language features for type safety and performance

Dependencies

Out of scope

This library is intendended to be used as a basis for you application and does not provide:

  • IO facility
  • Buffer management
  • Encryption
  • Managing CSeq
  • Thread safety is your responsibility
  • No statemachine is provided and the sipmessage class as well as the sip2json class are stateless.

Usage

Nuget

Use siddiqsoft.sip2json nuget package.

CMakeList

    CPMAddPackage(NAME sip2json   GIT_REPOSITORY https://github.com/siddiqsoftware/sip2json.git
                                  GIT_TAG "v1.17.0" )
    ..
    ..
    target_link_libraries(your-project PRIVATE sip2json::sip2json)

Using the CPM will automatically pull in the latest nlohmann_json package and any other dependencies. As user you'll be linking only with this package!

Code

#include "siddiqsoftware/sip2json.hpp"

// Assume a method invoked by the IO system on each "frame" read
// from the tcp stream.
void onReadCompleted(std::string& readBuffer)
{
  auto bufferStart= readBuffer.begin();
  
  // Invokes the callback per each decoded sipmessage from the buffer
  // Keep track of the bufferStart as it is advanced to reach the readBuffer.end()
  // as objects are parsed.
  sip2json::parseAsync(bufferStart,
          readBuffer.end(),
          [](sipmessage&& msg) {
              // Got a valid sipmessage object.. the object has been moved into this argument.
              // The parameter msg has been std::move()'d and therefore the lifetime ends when
              // the callback is completed. It is up to the client to ensure that they
              // make copies as necessary.
              if(!msg.empty()) {
                 // Do something..
              }
          },
          [](sip2jsonErrors& errCode, const std::string& msg){
              // Invoked for an error during the processing of the buffer.
      });

  // Client is responsible for managing the state of the readBuffer
  // the library uses an iterator to parse the stream and advances
  // as each SIP frame is processed.
  readBuffer.erase(readBuffer.begin(), bufferStart); // what remains can be processed as more data arrives
}

Documentation

Comprehensive documentation is available in the docs/ folder:

Document Purpose
docs/INDEX.md 📚 Documentation index and quick navigation
docs/API.md 📖 Complete API reference with 20+ examples
docs/ARCHITECTURE.md 🏗️ Design patterns and architecture guide
docs/MIGRATION.md 🔄 Migration guide and troubleshooting

Quick Start

For a quick introduction to the API, see docs/API.md - Quick Start.

Complete API Reference

See docs/API.md for:

  • Complete method documentation
  • Constructor details
  • Getter/setter methods
  • Exception handling
  • Best practices

Architecture & Design

See docs/ARCHITECTURE.md for:

  • Design patterns (Factory, Builder, Strategy, etc.)
  • Class hierarchy
  • Data flow diagrams
  • Performance optimization
  • Memory management

Troubleshooting & Migration

See docs/MIGRATION.md for:

  • Migration from v1.x to v2.0+
  • Common issues and solutions
  • FAQ
  • Performance tips

Quick Example

#include "siddiqsoft/sip2json.hpp"

using namespace siddiqsoft;

int main()
{
    // Create an INVITE request
    sipmessage msg("INVITE", "sip:user@example.com", "call-123", 1);
    
    // Set headers with method chaining
    msg.setHeader("From", "sip:caller@example.com")
       .setHeader("To", "sip:user@example.com")
       .setHeader("User-Agent", "MyApp/1.0");
    
    // Add Via header (can have multiple)
    msg.headers()["Via"].push_back("SIP/2.0/TCP example.com");
    
    // Serialize to SIP message
    try {
        auto sip_message = sip2json::serialize(msg);
        std::cout << sip_message << std::endl;
    } catch (const sip2json_exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    
    return 0;
}

For more examples, see docs/API.md - Examples.

Code Quality & Best Practices

The codebase has been thoroughly reviewed and improved to follow modern C++ best practices:

For detailed information on design patterns and architecture, see docs/ARCHITECTURE.md.

Tests

  • There is a single C++ Native Unit Test using the Microsoft C++ Framework under vstest.
  • Code Coverage is enabled (only if you're using Visual Studio Enterprise).
  • Azure pipelines CI reports on the test results and the coverage results.
  • There are to date 142+ tests covering parsing, serialization, and Rule of Five compliance.
  • Clang-Tidy is used as a linter to highlight issues with best-practices and static code analysis.
  • Consistent formatting using Clang Format.

Test Categories

  • Parsing Tests - Verify correct SIP message parsing
  • Serialization Tests - Verify correct SIP message serialization
  • Edge Cases - Handle malformed and boundary condition messages
  • Stress Tests - Performance and scalability testing
  • Rule of Five Tests - Verify copy/move semantics compliance (24 tests)
  • Synthetic Tests - Generated test cases for comprehensive coverage

References

Json Schema

Container

The document contains single character entries: s, h, b and the diagnostic element meta which is used to track such items as version, time of arrival, time to decode, etc.

{
    "meta": {"version": "sip2json/1.10.2/1.0.1", "time": "2020-08-13T12:27:30.555Z", "ttx": 0},
    "s": {},
    "h": {},
    "b": null
}

This approach acknowledges the fact that SIP messages are generated at a very high rate and processing size of data matters. Keeping the data compact and mapping the raw SIP and SDP means less intermediate processing is involved and keeps our container usage to a single model (map).

Field Type Description
s object Represents the SIP start line.
meta object Diagnostic object that contains version, time of arrival and ttx milliseconds taken to parse.
h object Contains the SIP headers.
b object Contains the SIP body. Optional.<br/>Currently, only the application/sdp body encode/decode is supported.<br/>If the Content-Length is 0, despite the value of the Content-Type this element is skipped.
SIP Start Line
Field Type Description
type string One of request or response.
method string Present for request type. Represents the SIP method.
uri string Present when the type is request, this represents the SIP URI element of the SIP request line.
status string Present when the type is response and represents the status code of the SIP response line.
reason string Present when the type is response and represents the response phrase of the SIP response line.
version string Always SIP/2.0.
SIP Headers

The object contains key-value elements found in the SIP header section.

  • SIP headers with boolean value types are stored as JSON boolean.
  • Default storage type is string
  • The header field Content-Length is encoded as JSON number.
  • When more than one item with the same header name is found, it is stored in an array.
      "h": { "Authorization": "",
             "Via": [ "via-1",
                      "via-2",
                      "via-3"
             ],
             "Content-Length": 0 }
    
  • For header elements that are "empty", the JSON value "" is stored against that header key instead of null.
SIP Body

The object contains key-value elements found in the body section.

Field Type Description
v integer Contant; Set to 0. Do not modify! This tag is used to delimit a session descriptor block.
o string
s string This can be set to null if the item is empty in the SIP message.
i string Optional.
u string Optional.
e string Optional.
p string Optional.
c string Optional.
b string Optional.
t Array Timing for this block. Array of integer values representing the start and end time of the leg.
z string Optional.
k string Optional. Encryption key.
m string Media descriptors
a array Media-level a-line items. Session-level a-line items are not supported.
  • Elements with boolean value types are stored as JSON boolean.
  • Default storage type is string
  • When more than one item with the same name is found, it is stored in an array. "a":{"rtpmap":""} or "a":{"rtpmap":["",""]}.
      "a": { "remote": "",
             "rtpmap": [ "",
                         ""],
             "new_change": true }
    
  • Attribute keys that are a=new_change are stored as "a":{"new_change":true}
Request Document
{
    "meta": {"version": "sip2json/1.10.2/1.0.0", "time": "2020-08-13T12:27:30.555Z", "ttx": 0},
    "s": {
        "type": "request",
        "method": "INVITE",
        "uri": "sip:hello@world.com",
        "version": "SIP/.20"
    },
    "h": {},
    "b": {
        "sdp": [{
            "v": 0,
            "s": "",
            "c": {
                "type": "",
                "subtype": "",
                "dn": ""
            },
            "i": { "dn": "",
                   "name": "",
                   "type": ""
            },
            "o": {
                "user": "",
                "t1": "",
                "t2": "",
                "type": "",
                "subtype": "",
                "host": ""
            },
            "m": "",
            "t": [0, 0],
            "a": {}
        }]
    }
}
Response Document
{
    "meta": {"version": "sip2json/1.10.2/1.0.0", "time": "2020-08-13T12:27:30.555Z", "ttx": 0},
    "s": {
        "type": "response",
        "status": 100,
        "reason": "Trying",
        "version": "SIP/.20"
    },
    "h": {}
}
Request Sample

The source for the following is this sample SIP.

{
    "b": {
        "sdp": [
            {
                "a": {
                    "access_code": "0000000",
                    "acs_guid": "001010000004",
                    "audio_payload": "PCMU",
                    "cdr_start_time": "1594555399.0",
                    "cli-screening": "00",
                    "clir": "false",
                    "dial_once": "aaaa1-aaa13.aaaa2.com",
                    "dialout": "click_in",
                    "far_end": "10.254.254.33:12196",
                    "flags": "1049122",
                    "fmtp": "101 0-15",
                    "ivr": "dialout",
                    "legCallid": "1000000009@10.100.100.100",
                    "leg_no": "3",
                    "mediastatus": "nomedia",
                    "new_change": true,
                    "privs": "participant",
                    "remote": "10.254.254.38:12224",
                    "rtpmap": [
                        "0 pcmu/8000/1",
                        "101 telephone-event/8000"
                    ],
                    "server": "ukdc1-edm18.mediaco.com",
                    "sipphone": "usecallid_80000000000000aa-aa-aaaaaa-00@10.254.254.33;port=5060",
                    "status": "(205) answered hold ",
                    "trunk": "8:chan:0",
                    "useforfrom": "hello@world.com",
                    "user-agent": "mediaco mediaserver ACS 9.1.0b8050"
                },
                "c": {
                    "dn": "10.254.254.33",
                    "subtype": "IP4",
                    "type": "IN"
                },
                "i": {
                    "dn": "usecallid-leg-3",
                    "name": "usecallid-leg-3",
                    "type": "CallByPhone"
                },
                "m": "audio 8766 RTP/AVP 0 101",
                "o": {
                    "host": "localhost",
                    "subtype": "IP4",
                    "t1": "1011084562",
                    "t2": "804064065",
                    "type": "IN",
                    "user": "hello@world.com"
                },
                "s": "",
                "t": [
                    3803029099,
                    0
                ],
                "v": 0
            }
        ]
    },
    "h": {
        "CSeq": "9 NOTIFY",
        "Call-ID": "80000000000000aa-aa-aaaaaa-00",
        "Contact": "<sip:localhost:8443;transport=ssl>",
        "Content-Length": 880,
        "Content-Type": "application/sdp",
        "From": "sip:hello@world.com;pool=uk-ed-mediaserver2;box=s1.example.com;tag=12345678",
        "To": "\"mmyers\" <sip:hello@world.com>",
        "Via": [
            "SIP/2.0/tcp localhost:8443",
            "SIP/2.0/tcp localhost:8443;branch=hello@world.com__mediaserver_sep__hello@world.com"
        ],
        "X-Billing-code-required": false,
        "X-Call-Instance-ID": "ODQ0NDMaNaU5MaaaOTa1aa1lZC10aGFtZXMtMDE6MTU5NDA0MDI3Naa2NjQ5Nja=",
        "X-Call-Start-Time": "1594040277.665005",
        "X-Call-URL": true,
        "X-Conf_no": "236398",
        "X-From": "hello@world.com",
        "X-Route-ID": "1",
        "X-Sticky": "1",
        "X-Video-SingleView": "0",
        "X-Video-UsingMCU": false,
        "X-client-address": "10.44.200.95",
        "X-control-master": "hello@world.com",
        "X-dialout": "allowed",
        "X-domain": "DEFAULT",
        "X-last-change": "1594040299",
        "X-leader-required": true,
        "X-legs-on-server": "244",
        "X-no-audio": false,
        "X-no-unmute": false,
        "X-no-video": false,
        "X-notify-im": false,
        "X-recording-enabled": true,
        "X-restrict-notify": false,
        "X-restrict-participants": false,
        "X-rollcall": "disabled",
        "X-rss-id": "",
        "X-slave-site": "localhost",
        "X-start-muted": false,
        "X-subject": "Robert Bonds' Meeting Room",
        "X-suppress-system-im": false
    },
    "meta": {
        "version": "sip2json/1.10.2/1.0.0",
        "time": "2020-08-13T12:27:30.555Z",
        "ttx": 0
    },
    "s": {
        "method": "NOTIFY",
        "type": "request",
        "uri": "sip:hello@world.com",
        "version": "SIP/2.0"
    }
}

Build and Testing

Build

The project uses CMake with presets for easy configuration across multiple platforms and compilers.

# Configure with a preset
cmake --preset <preset-name>

# Build
cmake --build --preset <preset-name>

# Run tests
ctest --preset <preset-name>

Available Presets:

  • macOS: Apple-Debug, Apple-Release, Apple-Benchmark
  • Linux (GCC): Linux-GCC-Debug, Linux-GCC-Release
  • Linux (Clang): Linux-Clang-Debug, Linux-Clang-Release
  • Windows: Windows-Debug, Windows-Release
Manual Build
# Configure
cmake . -DCMAKE_BUILD_TYPE=Release -Dsip2json_BUILD_TESTS=ON

# Build
cmake --build .

# Run tests
ctest .
Cleaning Build Artifacts

To clean the repository of CMake-generated files and cached data:

git clean -d -x -f

File Termination (CRLF)

The SIP message samples are CRLF terminated. The repository includes a .gitattributes file that specifies proper handling of *.sip files. If tests fail, verify the EOL markers in sample files are correct.

Code Quality

  • Linting: Clang-Tidy enforces best practices and static code analysis
  • Formatting: Clang Format ensures consistent code style
  • Testing: 64+ tests covering parsing and serialization
  • Coverage: Code coverage reports available in CI (Visual Studio Enterprise)

External resources

Product Compatible and additional computed target framework versions.
native native is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on SiddiqSoft.sip2json:

Repository Stars
ubisoft/Sharpmake
Sharpmake is an open-source C#-based solution for generating project definition files, such as Visual Studio projects and solutions, GNU makefiles, Xcode projects, etc.
Version Downloads Last Updated
2.4.0 106 5/5/2026
2.3.3 113 5/4/2026
2.3.2 104 5/4/2026
2.3.1 111 5/4/2026
2.3.0 129 5/4/2026
2.2.2 132 4/29/2026
1.17.3 3,107 12/9/2024
1.17.2 504 12/9/2024
1.17.1 489 12/7/2024
1.17.0 501 11/30/2024
1.16.4 551 10/24/2024
1.16.3 507 10/24/2024
1.16.2 495 10/24/2024
1.16.0 482 10/21/2024
1.15.4 508 10/18/2024
1.15.3 486 10/15/2024
1.15.2 489 10/4/2024
1.15.1 492 10/4/2024
1.15.0 493 10/4/2024
1.14.12 485 10/4/2024
Loading failed

## v2.4 Release - Performance and Documentation Enhancements

### New Features
- **Constexpr Optimization**: Compile-time string constants for improved performance
- **Comprehensive Benchmarks**: 30+ benchmark tests including stress tests for large packets
- **HTML Benchmark Reports**: Professional performance analysis reports
- **Enhanced Documentation**: Complete API reference, architecture guide, and migration guide

### Improvements
- Optimized parsing with constexpr patterns
- High-frequency decode benchmarks for large packets
- Stress tests (100, 1000+ packet scenarios)
- Professional HTML and JSON benchmark reporting
- Streamlined documentation for better navigation

### Documentation
- **API Reference**: docs/API.md - Complete method documentation with examples
- **Architecture Guide**: docs/ARCHITECTURE.md - Design patterns and optimization
- **Documentation Index**: docs/INDEX.md - Quick navigation hub

For detailed release notes, visit: https://github.com/siddiqsoftware/sip2json/releases