coturn 简介
·
文章目录
一. 安装
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.650000 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
更多推荐
已为社区贡献3条内容
所有评论(0)