0x00 环境说明
appr.tc 是 WebRTC 官方推荐的 Demo,非常适合通过亲手搭建来理解 RTC 的通信机制,本文简要叙述了 AppRTC 的实践过程。
需要提前搭建的环境:
- Ubuntu 18.04
- Node.js 开发环境
- Golang 开发环境
- Python3 开发环境
- Java 开发环境
- 科学上网环境
- 域名和对应的证书
上述环境的搭建过程这里不进行讲解,通常都有标准化的操作流程,下文中假设上述环境已经具备。
因隐私需要,本文中提到的域名都使用
<your-realm>
来代替,其他敏感信息也是使用<xxx>
格式来代替,请自行替换。
0x01 服务配置
AppRTC 依赖 3 个 服务
- Collider | WebSocket 服务,提供信令交互能力
- Coturn | Stun/Turn 服务,提供 P2P 转发能力
- AppRTC | Web 服务,提供 MVC 能力
本文对官方推荐的配置方式做了一些修改,通过 Nginx 反向代理的方式对外暴露服务,这样更贴近于真实环境,结构如下图所示:
所以我们一共需要配置 4 个服务 Collider
/ Coturn
/ AppRTC
/ Nginx
,下面简述配置过程。
1. Collider
git clone https://github.com/webrtc/apprtc.git
mkdir -p gopath_collider
export GOPATH=`pwd`/gopath_collider
mkdir -p $GOPATH/src
ln -s `pwd`/apprtc/src/collider/collider $GOPATH/src
ln -s `pwd`/apprtc/src/collider/collidermain $GOPATH/src
ln -s `pwd`/apprtc/src/collider/collidertest $GOPATH/src
go get -v collidermain
go install collidermain
$GOPATH/bin/collidermain -port=8089 -tls=false -room-server="https://<your-realm>:8443"
2. Coturn
sudo apt-get install libevent-dev
https://github.com/coturn/coturn.git
cd coturn
./configure
make
sudo ./bin/turnserver -L 0.0.0.0 -a -u test:test -v -n -f -r <your-realm>
参数 | 说明 |
---|---|
-L | 绑定 IP |
-a | 使用长期凭证机制,turn中继转发模式,WebRTC 中必须使用长期凭证机制 |
-u | 用户名密码 -u user:password |
-v | 日志输出级别 |
-n | 不使用配置文件 |
-f | 指定 turn 消息使用 fingerprint |
-r | 指定域名 |
-c | 指定配置文件,否则使用默认配置文件/etc/turnserver.conf |
备注: 因为 coturn 默认需要在系统文件夹创建文件
/var/run/turnserver.pid
和/usr/local/var/db/turndb
所以需要 sudo 运行。
3. AppRTC
修改 apprtc/src/app_engine/constants.py
配置文件如下:
# Copyright 2015 Google Inc. All Rights Reserved.
"""AppRTC Constants.
This module contains the constants used in AppRTC Python modules.
"""
import os
# Deprecated domains which we should to redirect to REDIRECT_URL.
REDIRECT_DOMAINS = [
'apprtc.appspot.com', 'apprtc.webrtc.org', 'www.appr.tc'
]
# URL which we should redirect to if matching in REDIRECT_DOMAINS.
REDIRECT_URL = 'https://appr.tc'
ROOM_MEMCACHE_EXPIRATION_SEC = 60 * 60 * 24
MEMCACHE_RETRY_LIMIT = 100
LOOPBACK_CLIENT_ID = 'LOOPBACK_CLIENT_ID'
# Turn/Stun server override. This allows AppRTC to connect to turn servers
# directly rather than retrieving them from an ICE server provider.
# ICE_SERVER_OVERRIDE = None
# Enable by uncomment below and comment out above, then specify turn and stun
ICE_SERVER_OVERRIDE = [
{
"urls": [
"turn:<your-realm>:3478?transport=udp",
"turn:<your-realm>:3478?transport=tcp"
],
"username": "test",
"credential": "test"
},
{
"urls": [
"stun:<your-realm>:3478"
]
}
]
ICE_SERVER_BASE_URL = 'https://appr.tc'
ICE_SERVER_URL_TEMPLATE = '%s/v1alpha/iceconfig?key=%s'
ICE_SERVER_API_KEY = os.environ.get('ICE_SERVER_API_KEY')
HEADER_MESSAGE = os.environ.get('HEADER_MESSAGE')
ICE_SERVER_URLS = [url for url in os.environ.get('ICE_SERVER_URLS', '').split(',') if url]
# Dictionary keys in the collider instance info constant.
WSS_INSTANCE_HOST_KEY = '<your-realm>:8443'
WSS_INSTANCE_NAME_KEY = 'vm_name'
WSS_INSTANCE_ZONE_KEY = 'zone'
WSS_INSTANCES = [{
WSS_INSTANCE_HOST_KEY: '<your-realm>:8443',
WSS_INSTANCE_NAME_KEY: 'wsserver-std',
WSS_INSTANCE_ZONE_KEY: 'us-central1-a'
}]
WSS_HOST_PORT_PAIRS = [ins[WSS_INSTANCE_HOST_KEY] for ins in WSS_INSTANCES]
# memcache key for the active collider host.
WSS_HOST_ACTIVE_HOST_KEY = 'wss_host_active_host'
# Dictionary keys in the collider probing result.
WSS_HOST_IS_UP_KEY = 'is_up'
WSS_HOST_STATUS_CODE_KEY = 'status_code'
WSS_HOST_ERROR_MESSAGE_KEY = 'error_message'
RESPONSE_ERROR = 'ERROR'
RESPONSE_ROOM_FULL = 'FULL'
RESPONSE_UNKNOWN_ROOM = 'UNKNOWN_ROOM'
RESPONSE_UNKNOWN_CLIENT = 'UNKNOWN_CLIENT'
RESPONSE_DUPLICATE_CLIENT = 'DUPLICATE_CLIENT'
RESPONSE_SUCCESS = 'SUCCESS'
RESPONSE_INVALID_REQUEST = 'INVALID_REQUEST'
IS_DEV_SERVER = os.environ.get('APPLICATION_ID', '').startswith('dev')
BIGQUERY_URL = 'https://www.googleapis.com/auth/bigquery'
# Dataset used in production.
BIGQUERY_DATASET_PROD = 'prod'
# Dataset used when running locally.
BIGQUERY_DATASET_LOCAL = 'dev'
# BigQuery table within the dataset.
BIGQUERY_TABLE = 'analytics'
为解决反向代理的跨域问题 Failed to start signaling: Failed to execute 'pushState' on 'History'
,需要修改 apprtc/src/web_app/js/appcontroller.js
文件,将 AppController.prototype.pushCallNavigation_
函数内容注释掉:
AppController.prototype.pushCallNavigation_ = function(roomId, roomLink) {
// window.history.pushState({'roomId': roomId, 'roomLink': roomLink}, roomId,
// roomLink);
};
安装 Google Cloud SDK https://cloud.google.com/sdk/docs/install
sudo apt-get install \
google-cloud-sdk-app-engine-python \
google-cloud-sdk-app-engine-python-extras \
google-cloud-sdk-datastore-emulator
cd apprtc
npm install
pip install -r requirements.txt
grunt build
dev_appserver.py --host=0.0.0.0 --port=8080 ./out/app_engine --skip_sdk_update_check
4. Nginx
sudo apt-get install nginx
创建配置文件 /etc/nginx/conf.d/8443-apprtc-web.conf
,内容如下:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 8443;
server_name <your-realm>;
ssl on;
ssl_certificate <your-cert-path>;
ssl_certificate_key <your-key-path>;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://127.0.0.1:8080;
}
location /ws {
proxy_pass http://127.0.0.1:8089;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}
sudo systemctl restart nginx
最后通过浏览器访问 https://<your-realm>:8443
即可。