Sofia-SIP 使用教程

news2024/11/30 7:39:28

Sofia-SIP 是一个开源的 SIP 协议栈,广泛用于 VoIP 和即时通讯应用。以下是一些基本的使用教程,帮助你快速上手 Sofia-SIP。

1. 安装 Sofia-SIP

首先,你需要安装 Sofia-SIP 库。你可以从其官方 GitHub 仓库克隆源代码并编译安装:

git clone https://github.com/doubango/sofia-sip.git
cd sofia-sip
./bootstrap.sh
./configure
make
sudo make install
2. 初始化 Sofia-SIP

在使用 Sofia-SIP 之前,需要初始化库并创建一个 NUA(Network Unified Access)对象。NUA 是 Sofia-SIP 的核心对象,用于管理 SIP 会话。

#include <sofia-sip/su.h>
#include <sofia-sip/nua.h>

int main() {
    su_root_t *root;
    nua_t *nua;

    // 初始化 SU 根
    root = su_root_create(NULL);
    if (!root) {
        fprintf(stderr, "Failed to create SU root\n");
        return -1;
    }

    // 创建 NUA 对象
    nua = nua_create(root, NULL, NULL, 0, NULL, NULL);
    if (!nua) {
        fprintf(stderr, "Failed to create NUA object\n");
        su_root_destroy(root);
        return -1;
    }

    // 运行事件循环
    su_root_run(root);

    // 清理资源
    nua_destroy(nua);
    su_root_destroy(root);

    return 0;
}
3. 注册 SIP 用户

注册 SIP 用户涉及发送 REGISTER 请求。以下是一个简单的示例:

#include <sofia-sip/su.h>
#include <sofia-sip/nua.h>
#include <sofia-sip/sip.h>

void register_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, sip_t const *sip, tagi_t tags[]) {
    if (status == 200) {
        printf("Registration successful\n");
    } else {
        printf("Registration failed: %d %s\n", status, phrase);
    }
}

int main() {
    su_root_t *root;
    nua_t *nua;
    nua_handle_t *nh;

    // 初始化 SU 根
    root = su_root_create(NULL);
    if (!root) {
        fprintf(stderr, "Failed to create SU root\n");
        return -1;
    }

    // 创建 NUA 对象
    nua = nua_create(root, NULL, NULL, 0, NULL, NULL);
    if (!nua) {
        fprintf(stderr, "Failed to create NUA object\n");
        su_root_destroy(root);
        return -1;
    }

    // 创建 NUA 句柄
    nh = nua_handle(nua, NULL, NUTAG_URL("sip:example.com"), TAG_END());
    if (!nh) {
        fprintf(stderr, "Failed to create NUA handle\n");
        nua_destroy(nua);
        su_root_destroy(root);
        return -1;
    }

    // 发送 REGISTER 请求
    nua_register(nh, NUTAG_URL("sip:alice@example.com"), SIPTAG_TO_STR("sip:alice@example.com"), SIPTAG_FROM_STR("sip:alice@example.com"), SIPTAG_CONTACT_STR("sip:alice@192.168.1.100"), SIPTAG_EXPIRES_STR("3600"), NUTAG_REGISTRAR("sip:example.com"), TAG_END());

    // 运行事件循环
    su_root_run(root);

    // 清理资源
    nua_handle_destroy(nh);
    nua_destroy(nua);
    su_root_destroy(root);

    return 0;
}
4. 处理 SIP 消息

Sofia-SIP 提供了丰富的回调机制来处理 SIP 消息。你可以在回调函数中处理各种 SIP 事件,例如来电、挂断等

void incoming_call_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, sip_t const *sip, tagi_t tags[]) {
    if (event == NUA_I_INVITE) {
        printf("Incoming call from %s\n", sip->sip_from->a_url->url_user);
        // 接受来电
        nua_respond(nh, SIP_200_OK, SIPTAG_TO(sip->sip_to), TAG_END());
    }
}

int main() {
    su_root_t *root;
    nua_t *nua;
    nua_handle_t *nh;

    // 初始化 SU 根
    root = su_root_create(NULL);
    if (!root) {
        fprintf(stderr, "Failed to create SU root\n");
        return -1;
    }

    // 创建 NUA 对象
    nua = nua_create(root, incoming_call_callback, NULL, 0, NULL, NULL);
    if (!nua) {
        fprintf(stderr, "Failed to create NUA object\n");
        su_root_destroy(root);
        return -1;
    }

    // 创建 NUA 句柄
    nh = nua_handle(nua, NULL, NUTAG_URL("sip:example.com"), TAG_END());
    if (!nh) {
        fprintf(stderr, "Failed to create NUA handle\n");
        nua_destroy(nua);
        su_root_destroy(root);
        return -1;
    }

    // 运行事件循环
    su_root_run(root);

    // 清理资源
    nua_handle_destroy(nh);
    nua_destroy(nua);
    su_root_destroy(root);

    return 0;
}
5. 发送 SIP 消息

发送 SIP 消息(例如 INVITE 请求)可以通过 nua_invite 函数实现

void invite_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, sip_t const *sip, tagi_t tags[]) {
    if (event == NUA_R_INVITE) {
        if (status == 200) {
            printf("Call established\n");
        } else {
            printf("Call failed: %d %s\n", status, phrase);
        }
    }
}

int main() {
    su_root_t *root;
    nua_t *nua;
    nua_handle_t *nh;

    // 初始化 SU 根
    root = su_root_create(NULL);
    if (!root) {
        fprintf(stderr, "Failed to create SU root\n");
        return -1;
    }

    // 创建 NUA 对象
    nua = nua_create(root, invite_callback, NULL, 0, NULL, NULL);
    if (!nua) {
        fprintf(stderr, "Failed to create NUA object\n");
        su_root_destroy(root);
        return -1;
    }

    // 创建 NUA 句柄
    nh = nua_handle(nua, NULL, NUTAG_URL("sip:example.com"), TAG_END());
    if (!nh) {
        fprintf(stderr, "Failed to create NUA handle\n");
        nua_destroy(nua);
        su_root_destroy(root);
        return -1;
    }

    // 发送 INVITE 请求
    nua_invite(nh, NUTAG_URL("sip:bob@example.com"), SIPTAG_TO_STR("sip:bob@example.com"), SIPTAG_FROM_STR("sip:alice@example.com"), SIPTAG_CONTACT_STR("sip:alice@192.168.1.100"), TAG_END());

    // 运行事件循环
    su_root_run(root);

    // 清理资源
    nua_handle_destroy(nh);
    nua_destroy(nua);
    su_root_destroy(root);

    return 0;
}
6. 错误处理

在实际应用中,错误处理是非常重要的。Sofia-SIP 提供了详细的错误代码和描述,你可以在回调函数中进行处理。

void error_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, sip_t const *sip, tagi_t tags[]) {
    if (status != 200) {
        printf("Error: %d %s\n", status, phrase);
    }
}

int main() {
    su_root_t *root;
    nua_t *nua;
    nua_handle_t *nh;

    // 初始化 SU 根
    root = su_root_create(NULL);
    if (!root) {
        fprintf(stderr, "Failed to create SU root\n");
        return -1;
    }

    // 创建 NUA 对象
    nua = nua_create(root, error_callback, NULL, 0, NULL, NULL);
    if (!nua) {
        fprintf(stderr, "Failed to create NUA object\n");
        su_root_destroy(root);
        return -1;
    }

    // 创建 NUA 句柄
    nh = nua_handle(nua, NULL, NUTAG_URL("sip:example.com"), TAG_END());
    if (!nh) {
        fprintf(stderr, "Failed to create NUA handle\n");
        nua_destroy(nua);
        su_root_destroy(root);
        return -1;
    }

    // 发送 INVITE 请求
    nua_invite(nh, NUTAG_URL("sip:bob@example.com"), SIPTAG_TO_STR("sip:bob@example.com"), SIPTAG_FROM_STR("sip:alice@example.com"), SIPTAG_CONTACT_STR("sip:alice@192.168.1.100"), TAG_END());

    // 运行事件循环
    su_root_run(root);

    // 清理资源
    nua_handle_destroy(nh);
    nua_destroy(nua);
    su_root_destroy(root);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2250292.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hot100 - 搜索二维矩阵II

Hot100 - 搜索二维矩阵II 最佳思路&#xff1a; 利用矩阵的特性&#xff0c;针对搜索操作可以从右上角或者左下角开始。通过判断当前位置的元素与目标值的关系&#xff0c;逐步缩小搜索范围&#xff0c;从而达到较高的效率。 从右上角开始&#xff1a;假设矩阵是升序排列的&a…

Hello SpringBoot!

Spring Initializr&#xff1a;一个快速构建springboot项目的网站 进入网站后&#xff0c;选择&#xff1a; Project: MavenLanguage: JavaSpring Boot: 最新稳定版Dependencies: Spring Web 生成的文件结构类似于&#xff1a; my-spring-boot-app ├── src │ ├── m…

模型压缩——量化方法解读

1.引言 前面我们已经介绍了剪枝、蒸馏等通过减少模型参数量来进行压缩的方法。除这些方法以外&#xff0c;量化 (quantization) 是另一种能够压缩模型参数的方法。与前面方法不同的是&#xff0c;量化并不减少模型参数量&#xff0c;而是通过修改网络中每个参数占用的比特数&a…

Core 授权 认证 案例

利用 cookie 模式 》》 框架默认的 利用 cookie 模式 》》 策略授权

计算机网络常见面试题总结(上)

计算机网络基础 网络分层模型 OSI 七层模型是什么&#xff1f;每一层的作用是什么&#xff1f; OSI 七层模型 是国际标准化组织提出的一个网络分层模型&#xff0c;其大体结构以及每一层提供的功能如下图所示&#xff1a; 每一层都专注做一件事情&#xff0c;并且每一层都需…

Macos远程连接Linux桌面教程;Ubuntu配置远程桌面;Mac端远程登陆Linux桌面;可能出现的问题

文章目录 1. Ubuntu配置远程桌面2. Mac端远程登陆Linux桌面3. 可能出现的问题1.您用来登录计算机的密码与登录密钥环里的密码不再匹配2. 找不到org->gnome->desktop->remote-access 1. Ubuntu配置远程桌面 打开设置->共享->屏幕共享。勾选允许连接控制屏幕&…

【C语言】结构体、联合体、枚举类型的字节大小详解

在C语言中&#xff0c;结构体&#xff08;struct&#xff09;和联合体&#xff08;union&#xff09; 是常用的复合数据类型&#xff0c;它们的内存布局和字节大小直接影响程序的性能和内存使用。下面为大家详细解释它们的字节大小计算方法&#xff0c;包括对齐规则、内存分配方…

免交互运用

免交互的概念 文本免交互 免交互的格式 变量配置 expect expect的格式 在脚本外传参 嵌套 练习 免交互ssh远程连接

物联网客户端在线服务中心(客服功能/私聊/群聊/下发指令等功能)

一、界面 私聊功能&#xff08;下发通知类&#xff0c;一对多&#xff09;群聊&#xff08;点对点&#xff09;发送指令&#xff08;配合使用客户端&#xff0c;基于cefsharp做的物联网浏览器客户端&#xff09;修改远程参数配置&#xff08;直接保存到本地&#xff09;&#…

使用C#开发VTK笔记(一)-开发环境搭建

一.使用C#开发VTK的背景 因为C#开发的友好性,一直都比较习惯于从C#开发程序。而长期以来,都希望有一个稳定可靠的三位工程数模的开发演示平台,经过多次对比之后,感觉VTK和OpenCasCade这两个开源项目是比较好的,但它们都是用C++编写的,我用C#形式开发,只能找到发布的C#组…

力扣96:不同的二叉搜索树

给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;5示例 2&#xff1a; 输入&#xff1a;n 1 输出&#xff1a;1 卡…

k8s Init:ImagePullBackOff 的解决方法

kubectl describe po (pod名字) -n kube-system 可查看pod所在的节点信息 例如&#xff1a; kubectl describe po calico-node-2lcxx -n kube-system 执行拉取前先把用到的节点的源换了 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"re…

人工智能如何改变你的生活?

在我们所处的这个快节奏的世界里&#xff0c;科技融入日常生活已然成为司空见惯的事&#xff0c;并且切实成为了我们生活的一部分。在这场科技变革中&#xff0c;最具变革性的角色之一便是人工智能&#xff08;AI&#xff09;。从我们清晨醒来直至夜晚入睡&#xff0c;人工智能…

道路机器人识别交通灯,马路,左右转,黄线,人行道,机器人等路面导航标志识别-使用YOLO标记

数据集分割 train组66% 268图片 validation集22% 91图片 test集12&#xff05; 48图片 预处理 没有采用任何预处理步骤。 增强 未应用任何增强。 数据集图片&#xff1a; 交通灯 马路 右转 向右掉头 机器人识别 人行横道 黄线 直行或右转 数据集下载&#xff1a; 道路…

【四轴】利用PWM捕获解析接收机信号

在学习这部分之间&#xff0c;建议大家先看之前这篇博客&#xff0c;里面包含对PWM一些重要概念的基本介绍。 【四轴】利用PWM输出驱动无刷电机-CSDN博客 1. 基本原理 1.1 PWM是什么 这一部分可以看我之前的博客&#xff0c;已经对PWM有了基本的介绍。 1.2 什么叫捕获PWM波&…

洛谷 P1162 填涂颜色 C语言 bfs

题目&#xff1a; https://www.luogu.com.cn/problem/P1162 由数字 0 组成的方阵中&#xff0c;有一任意形状的由数字 1 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 22。例如&#xff1a;66的方阵&#xff08;n6&#xff09;&#xff0c;涂色前和涂色后的方阵如下&am…

38 基于单片机的宠物喂食(ESP8266、红外、电机)

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机&#xff0c;采用L298N驱动连接P2.3和P2.4口进行电机驱动&#xff0c; 然后串口连接P3.0和P3.1模拟ESP8266&#xff0c; 红外传感器连接ADC0832数模转换器连接单片机的P1.0~P1.…

霍夫变换:原理剖析与 OpenCV 应用实例

简介&#xff1a;本文围绕霍夫变换相关内容展开&#xff0c;先是讲解霍夫变换基本原理&#xff0c;包含从 xy 坐标系到 kb 坐标系及极坐标系的映射等。接着介绍了 cv2.HoughLines、cv2.HoughLinesP 概率霍夫变换、cv2.HoughCircles 霍夫圆变换的函数用法、参数含义、与常规霍夫…

【Debug】hexo-github令牌认证 Support for password authentication was removed

title: 【Debug】hexo-github令牌认证 date: 2024-07-19 14:40:54 categories: bug解决日记 description: “Support for password authentication was removed on August 13, 2021.” cover: https://pic.imgdb.cn/item/669b38ebd9c307b7e9f3e5e0.jpg 第一章 第一篇博客记录一…

JVM 性能调优 -- JVM常用调优工具【jps、jstack、jmap、jstats 命令】

前言&#xff1a; 前面我们分析怎么去预估系统资源&#xff0c;怎么去设置 JVM 参数以及怎么去看 GC 日志&#xff0c;本篇我们分享一些常用的 JVM 调优工具&#xff0c;我们在进行 JVM 调优的时候&#xff0c;通常需要借助一些工具来对系统的进行相关分析&#xff0c;从而确定…