coturn 简介

coturn 简介文章目录一 安装 1 1 下载 1 2 安装二 配置三 启动 amp 测试 3 1 Server3 2 Client 四 代码流程 4 1 大体框架涉及的函数 4 2 设置 relay 相关 4 3 处理请求或数据 4 4 分析请求并构造返回数据 4 5 真正的返回数据一 安装 1 1 下载 gitgitcloneh github com coturn co

一. 安装

1.1. 下载

  • git
git clone https://github.com/coturn/coturn.git 
  • 压缩包安装
wget https://github.com/coturn/coturn/archive/4.5.0.8.tar.gz 

1.2. 安装

cd coturn ./configure make sudo make install 

注: 如果编译出错,记得安装相关依赖。

二. 配置

我这里在 /etc 下单独建立了个 turnserver 的目录,将 coturn 配置文件 turnserver.conf 拷贝过来。

sudo mkdir /etc/turnserver sudo cp coturn/examples/etc/turnserver.conf /etc/turnserver/ sudo cp coturn/examples/etc/turn_server_*.pem /etc/turnserver/ 

配置 /etc/turnserver/turnserver.conf

# TURN 的监听端口,默认 3478 listening-port=3478 # 监听 relay server 的地址 listening-ip=192.168.110.146 # 可以和 listening IP 一样 relay-ip=192.168.110.146 # 同上 external-ip=192.168.110.146 # 输出详细过程 verbose # TURN 消息中可使用 FINGERPRINT fingerprint # 开启长期证书机制 lt-cred-mech # 设置静态账户 user=test:test # realm=mytest # 关闭 TLS 和 DTLS 监听 no-tls no-dtls # 连接的生命周期,默认 10min stale-nonce=600 # 证书和私钥文件 cert=/etc/turnserver/turn_server_cert.pem pkey=/etc/turnserver/turn_server_pkey.pem # 屏蔽 loopback, multicast IP 地址 no-loopback-peers no-multicast-peers # 支持移动 ICE mobility no-cli 

三. 启动 & 测试

3.1. Server

turnserver -v -L 192.168.110.146 -a -f -r mytest -c /etc/turnserver/turnserver.conf 
  • -L 指定 relay 的监听 IP
  • -a 使用 long-term credential
  • -f fingerprints
  • -r 指定 realm
  • -c 指定配置文件

3.2. Client

turnutils_uclient -u test -w test -v -y 192.168.110.146 
  • -u 指定用户名
  • -w 指定密码
  • -v 详细输出
  • -y 使用 client-to-client 连接

看到如下提示则为成功:

0: success: 0x4690 0: Total connect time is 0 1: start_mclient: msz=4, tot_send_msgs=0, tot_recv_msgs=0, tot_send_bytes ~ 0, tot_recv_bytes ~ 0 2: start_mclient: msz=4, tot_send_msgs=0, tot_recv_msgs=0, tot_send_bytes ~ 0, tot_recv_bytes ~ 0 3: start_mclient: msz=4, tot_send_msgs=1, tot_recv_msgs=1, tot_send_bytes ~ 100, tot_recv_bytes ~ 100 4: start_mclient: msz=4, tot_send_msgs=10, tot_recv_msgs=10, tot_send_bytes ~ 1000, tot_recv_bytes ~ 1000 5: start_mclient: msz=4, tot_send_msgs=15, tot_recv_msgs=15, tot_send_bytes ~ 1500, tot_recv_bytes ~ 1500 5: done, connection 0x1fcd600 closed. 5: done, connection 0x7f40c0d10010 closed. 5: done, connection 0x7f40c0b9a010 closed. 5: done, connection 0x7f40c0bbb010 closed. 5: start_mclient: tot_send_msgs=20, tot_recv_msgs=20 5: start_mclient: tot_send_bytes ~ 2000, tot_recv_bytes ~ 2000 5: Total transmit time is 5 5: Total lost packets 0 (0.000000%), total send dropped 0 (0.000000%) 5: Average round trip delay 0.000000 ms; min = 0 ms, max = 0 ms 5: Average jitter 0. ms; min = 0 ms, max = 2 ms 

四. 代码流程

注: 基于 coturn-4.5.0.8 版本

4.1. 大体框架涉及的函数

...各种初始化 read_config_file() // 读取配置文件 setup_server() // 设置 -> setup_listener() -> turnipports_create() // 设置 turn 端口范围 -> turn_event_base_new() // event -> allocate_relay_addrs_ports() // relay 地址 -> setup_listener() -> setup_general_relay_servers() // 设置 relay -> setup_auth_server() // 认证相关 

4.2. 设置 relay 相关

setup_general_relay_servers() -> setup_relay_server() -> relay_receive_message() -> handle_relay_message() // 读取 event 发往 relay 的消息 -> open_client_connection_session() -> client_input_handler() -> read_client_connection() -> handle_turn_command() // 处理 TURN 协议的各种请求或数据发送与接收 -> write_client_connection() // 返回数据给 Client 
  • 设置 event 的回调函数 relay_receive_message()
  • relay_receive_message() 循环从 event buffer 中读取数据交给 handle_relay_message()

4.3. 处理请求或数据

handle_turn_command(server, ss, in_buffer, nbh, &resp_constructed, can_resume); 
handle_turn_command() -> stun_is_request_str() // 判断 method 是否是请求 -> handle_turn_allocate() // 处理 Allocate Request -> handle_turn_create_permission() // 处理 CreatePermission Request -> handle_turn_refresh() // 处理 Refresh Request -> handle_turn_channel_bind() // 处理 ChannelBind Request -> stun_is_indication_str() // 判断 method 是否是数据 -> handle_turn_send() // 处理 Send Request 
  • nbh 是从 server 的 ioa_engine_handle 结构的 bufs 中创建并传入进来的
  • 处理结束后,将 resp_constructed 的值赋为 1。
struct _ioa_engine { 
    super_memory_t *sm; struct event_base *event_base; int deallocate_eb; int verbose; turnipports* tp; rtcp_map *map_rtcp; stun_buffer_list bufs; // ... } 
typedef struct _stun_buffer_list { 
    stun_buffer_list_elem *head; size_t tsz; } stun_buffer_list; 

4.4. 分析请求并构造返回数据

handle_turn_allocate() 举例来说:

handle_turn_allocate(server, ss, &tid, resp_constructed, &err_code, &reason, unknown_attrs, &ua_num, in_buffer, nbh); 
handle_turn_allocate() -> stun_attr_get_first_str() // 获取第一个属性 -> stun_attr_get_type() // 依次获取其他属性 -> stun_attr_get_len() // 获取属性长度 -> stun_attr_get_value() // 获取属性 value -> stun_set_allocate_response_str() // 创建返回数据 -> stun_attr_add_addr_str() // 添加各种属性 
  • 读取 in_buffer 中的 nbh 结构
  • 将 nbh 强转为 stun_buffer_list_elem 结构,其中 next 是链表的指针,buf 承载属性等信息,根据 len 和 offset 来获取属性信息
  • 填充 nbh 结构,用于返回数据
typedef struct _stun_buffer_list_elem { 
    struct _stun_buffer_list_elem *next; stun_buffer buf; } stun_buffer_list_elem; 
typedef struct _stun_buffer { 
    u08bits channel[STUN_CHANNEL_HEADER_LENGTH]; u08bits buf[STUN_BUFFER_SIZE]; size_t len; u16bits offset; u08bits coffset; } stun_buffer; 

4.5. 真正的返回数据

write_client_connection(server, ss, nbh, TTL_IGNORE, TOS_IGNORE); 
write_client_connection() -> send_data_from_ioa_socket_nbh() -> udp_send() -> sendto() 
  • 参数中的 nbh 就是前面构造出来的
  • udp_send() 使用的 fd 是参数 server 的 client_socket 字段中的 fd
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/205140.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午6:42
下一篇 2026年3月19日 下午6:43


相关推荐

  • android基于xposed框架,基于Xposed框架的模块:Android EagleEye

    android基于xposed框架,基于Xposed框架的模块:Android EagleEye基于Xposed框架的模块:AndroidEagleEye2015-06-2609:59:42阅读:0次一个基于Xposed框架的模块(可对Android系统APIs和应用的方法进行hook操作)。相关联的被hook的APIs或应用的方法信息将被作为输出被记录。使用AndroidEagleEye的一切风险由自己承担特性对Android系统APIs和应用的方法进行hook操作Hook需要的…

    2022年8月16日
    8
  • managementobjectsearch_beanpropertyrowmapper

    managementobjectsearch_beanpropertyrowmapperclassWin32_Service:Win32_BaseService{ booleanAcceptPause; booleanAcceptStop; stringCaption; uint32CheckPoint; stringCreationClassName; stringDescription; booleanDesktopInteract; st

    2022年10月2日
    5
  • AQS原理详解

    AQS原理详解1 AQS 原理概览 AQS 核心思想是 如果被请求的共享资源空闲 则将当前请求资源的线程设置为有效的工作线程 并且将共享资源设置为锁定状态 如果被请求的共享资源被占用 那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制 这个机制 AQS 是用 CLH 队列锁实现的 即将暂时获取不到锁的线程加入到队列中 CLH Craig Landin andHagersten 队列是一个虚拟的双向队列 虚拟的双向队列即不存在队列实例 仅存在结点之间的关联关系 AQS 是将每条请求共享资源的线程封装成一个 CLH 锁队列的一个结点

    2026年3月17日
    2
  • awk 数组学习

    awk 数组学习awk是Linux一个必不可少的文本处理工具,其编程简单,功能强大。其中awk处理文本的几块比较常用:1、行分隔;2、正则表达式匹配;3、字符串处理;4、awk数组。接下来主要介绍一下awk数组的相关内容。awk数组特点:(1)、是一种关联数组(AssociativeArrays),下表可以是数字也可以是字符串,(2)、数组名和元素无需提前声明,(3)、无需指定数…

    2022年7月19日
    20
  • 养龙虾,别被偷了家

    养龙虾,别被偷了家

    2026年3月12日
    2
  • 微信公众平台开发(PHP)(二) 微信公众平台示例代码分析

    微信公众平台开发(PHP)(二) 微信公众平台示例代码分析一 摘要微信公众平台提供了一个简单的 php 示例代码 在做进一步开发之前 我们有必要将其详细了解一下 二 获取代码微信官网 http mp weixin com mpres htmledition res wx sample zip 三 分析代码完整代码如下 php wechatphptes defi

    2026年3月19日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号