自建 AppRTC

字数3158 阅读1718 评论2 喜欢2

AppRTC 是 webrtc 的一个 demo。
自建 AppRTC 可以苦其心志劳其筋骨饿其体肤,更重要的是能学会 webrtc 服务器的搭建流程……

AppRTC 的组成部分是这样的:
1、AppRTC - 房间服务器。Github 
2、Collider - 信令服务器。上面 Github 工程里自带,在 src/collider 下
3、coTurn - 打洞(内网穿透)服务器。Google Code 
4、还需要自己实现一个 coTurn 连接信息(主要是用户名、密码的配置)获取接口,通常叫做 TURN REST API。

零. 准备工作
0、为避免其他操作系统的各种尿性问题,这里操作系统推荐使用 Ubuntu 14.04。
1、AppRTC 依赖 grunt 和 Google AppEngine SDK for Python 离线版本
  GAE SDK 安装很简单:下载、解压、添加到PATH环境变量即可完成。
  grunt,是 Node.js 下的一套任务执行系统,经过 Gruntfile.js 的配置,可以做很多事情。首先安装 Node.js。使用 nvm 可以很方便的为自己的 Linux 账户安装并设置好 Node.js。(而后,你可以选择安装 cnpm,这样就可以使用国内的缓存节点,npm install 命令会快许多,如果你只用这一次 grunt,那么不装这个也是可以的。)接下来只需要执行一个 npm install -g grunt-cli 即可安装好 grunt。
2、Collider 依赖 golang。尿性的问题来了:墙……安装 golang 和日后使用 golang 所需的包,几乎都要翻墙。所以这里解决掉墙这个问题后,再使用 gvm 安装 golang(当前版本 go1.4.2) 即可完成我们的准备工作。

一. coTurn,打洞服务器,安装需 sudo
0、这货是一个基本依赖,而且不需要改代码,只要安装,然后改配置文件,再启动服务、开好端口就行了。
1、下载,去 这里 ,下载最新版,turnserver-*-debian-wheezy-ubuntu-mint-x86-64bits.tar.gz
2、创建个目录,然后,tar xzf <下载的文件名> -c <目录名>。
3、进入目录,cat INSTALL,查看安装须知,并根据指引安装所需软件,而后安装该目录下的deb包。
4、安装完成后,修改配置文件 /etc/turnserver.conf 成如下内容:

# 不多讲
listening-device=eth0
listening-port=3478
relay-device=eth0
# 记得开防火墙
min-port=59000
max-port=65000
# 更繁杂的输出日志
Verbose
# WebRTC 的消息里会用到
fingerprint
# WebRTC 认证需要
lt-cred-mech
# REST API 认证需要
use-auth-secret
# REST API 加密所需的 KEY
# 这里我们使用“静态”的 KEY,Google 自己也用的这个
static-auth-secret=4080218913
# 用户登录域
realm=<填写你自己的域名>
# 可为 TURN 服务提供更安全的访问
stale-nonce
# SSL 需要用到的, 生成命令:
# sudo openssl req -x509 -newkey rsa:2048 -keyout /etc/turn_server_pkey.pem -out /etc/turn_server_cert.pem -days 99999 -nodes
cert=/etc/turn_server_cert.pem
pkey=/etc/turn_server_pkey.pem
# 屏蔽 loopback, multicast IP地址的 relay
no-loopback-peers
no-multicast-peers
# 启用 Mobility ICE 支持(具体干啥的我也不晓得)
mobility
# 禁用本地 telnet cli 管理接口
no-cli

配置文件保存成功后,使用命令 service coturn start ,启动 coTurn 服务。
如果服务器在内网,还需要做好端口映射:3478,3479:tcp&udp,外加配置文件里的 59000~65000:tcp&udp。

二. coTurn 连接信息接口(TURN REST API)
0、由于 coTurn 没有自带该接口,所以需要我们码农自行实现。关于该接口的实现方式,详细的内容请参考 coTurn原始文档。我这里只做简要说明:

* TURN 服务器自身没有必要实现该接口,所以需要服务提供方自行实现及部署。
* 此 TURN REST API 有标准的参考文档,包括了请求参数以及返回内容,都有明确规定。码农们需要按照该文档内描述的内容来实现该接口。
* 文档里提到的内容有:
* ① 请求信息,方式 GET:
*     需要包含:service(“turn”)、username、key
*     例如:/turn?username=392938130&key=4080218913
* ② 响应信息,内容格式 JSON Dictionary:
*     需要包涵:username、password、ttl(可选, 单位秒. 推荐86400)、uris(数组)
*     例如:

{"username": "1433065916:392938130", "password": "***base64 encoded string***", "ttl":86400, "uris": ["turn:104.155.31.139:3478?transport=udp", "turn:104.155.31.139:3478?transport=tcp", "turn:104.155.31.139:3479?transport=udp", "turn:104.155.31.139:3479?transport=tcp"]}

基本形式就是这样。需要提及的有:
1、响应的 username 字段,需要以【timestamp + ":" + username】的形式输出。注意:这里 timestamp 为密码失效的 UNIX 时间戳,即【当前 timestamp + ttl 时长】;而 username 则是请求时提交的 username,原封不动;中间使用半角冒号做字符串连接(默认设置下是这样,你也可以自己改,不过多蛋疼……)。为便于后文叙述,此处响应内容里的 username 字段,我们称之为 turn-username。
2、响应的 password 字段,需要以 HMAC-SHA1 算法计算得出,公式为:【base64_encode( hmac( key, turn-username ) )】。此处的 key,为 coTurn 服务器配置中的 “static-auth-secret”值。以 key 作为 hmac 算法的密钥,turn-username 为被计算的内容,得出的 hmac 摘要后,经 base64 编码得到最终密码。
3、就是这些。uris 一般根据 coTurn 服务器的假设规模来从后台配置好,而后再直接输出到前台。我用 Node.js 简单写了个接口代码,有需要可以参考:

var express = require('express');
var crypto = require('crypto');
var app = express();

var hmac = function(key, content){
    var method = crypto.createHmac('sha1', key);
    method.setEncoding('base64');
    method.write(content);
    method.end();
    return method.read();
};

app.get('/turn', function(req, resp) {

var query = req.query;
var key = '4080218913'; // 这里的 key 是事先设置好的, 我们把他当成一个常亮来看, 所以就不从HTTP请求参数里读取了

if (!query['username']) {
    return resp.send({'error':'AppError', 'message':'Must provide username.'});
} else {
    var time_to_live = 600;
    var timestamp = Math.floor(Date.now() / 1000) + time_to_live;
    var turn_username = timestamp + ':' + query['username'];
    var password = hmac(key, turn_username);

return resp.send({
        username:turn_username,
        password:password,
        ttl:time_to_live,
        "uris": [
            "turn:turn.server.ip.address:3478?transport=udp",
            "turn:turn.server.ip.address:3478?transport=tcp",
            "turn:turn.server.ip.address:3479?transport=udp",
            "turn:turn.server.ip.address:3479?transport=tcp"
            ]
    });
}

});

app.listen('3033', function(){
    console.log('server started');
});

代码里没处理跨域的问题,所以虽说上面代码监听了 3033 端口,但我用 nginx 做了一个反代,以便能够使用同一个域名。这样也就不会出现跨域的问题了。

三. Collider 信令服务器
0、现在可以摆好翻墙的pose了,如果不知道怎么翻说明你还没有准备好……
1、首先,可能是因为WALL的原因亦或是我翻墙的姿势不对,我在 get Collider 的依赖库的时候遇到了点麻烦,不过改了源代码就好了:

# $PWD = apprtc/src/collider/collider/
进入上面的这个目录
# $FILES = [ 'collider.go', 'collider_test.go' ]
把上面俩文件里的这行:
"code.google.com/p/go.net/websocket"
替换成:
"golang.org/x/net/websocket"
记得保存

2、然后就可以参照着 src/collider/README.md 里面的步骤执行了:

......

# $PWD = apprtc/src/collider/
3. 将 以下3个目录, 软链接到 $GOPATH/src/
注意,应当先检查自己的 golang 是否安装好,并检查 $GOPATH 是否不为空且路径 $GOPATH/src/ 已存在.
假设:当前现在就在 apprtc/src/collider/ 下
命令:ln -s $PWD/{collider,collidermain,collidertest} $GOPATH/src/
结果:会把 3 个目录软链接到 $GOPATH/src/ 下

4. 软链接创建好后,执行:
命令:go get collidermain && go install collidermain

3、以上命令成功执行后,路径 $GOPATH/bin/collidermain 将会是一个可执行文件。
可以追加 --help 参数查看所有可用的命令行参数。这里我们使用这样的配置:

# $GOPATH/bin/collidermain -port=8089 -room-server=‘http://apprtc.domain.com:8083' -tls=false

# 到这里我们还没有接触过 AppRTC 的搭建,所以暂时我们并不知道 room-server 参数的值是什么。
# 这条命令应该是等下搞好了 AppRTC 后,再回来执行的。

-port = 表示 collider 监听的端口。我们这里用 8089。如果有防火墙,记得打开,如果在内网,记得在路由器上做映射。
-room-server = 表示 AppRTC 可访问的 URL。如果使用了非标准端口(80、443),则务必写好端口号。
-tls = false 表示关闭 TLS 加密。因为这个需要配置证书("/cert/cert.pem", "/cert/key.pem"),所以以自己研究为目的的,关了是最方便的……

4、这里的 8089 是服务端口,如果你在内网里并需要对外提供服务,需要将 8089:tcp 映射出外网。

四. AppRTC 房间服务器
0、这是最后一步,只需要改几处配置就可以打开运行了。这里假设你所在的路径是 apprtc 项目的根目录。
1、由于前面我们的 Collider 使用了 tls = false 参数,且为了访问方便,这里需要做以下修改:

# $FILE = apprtc/src/app_engine/apprtc.py

搜索 "wss:" 和 "https:" (注意冒号)
可以在方法 get_wss_parameters 里搜索到,这里需要把 wss: 替换成 ws:、把 https: 替换成 http:,保存退出,就可以了。

2、编辑配置文件,文件位于 apprtc/src/app_engine/constants.py。

① 搜索 TURN_BASE_URL
  将等号后面的字符串替换为 apprtc 可以访问到的地址,如:'http://apprtc.domain.com:8083'

② 搜索 WSS_INSTANCES
  可以看到,这里被配置为了一个数组,不过我们只有单台服务器。所以先删掉数组的其他元素,只保留一个。
  在保留下来的元素中,我们只修改 WSS_INSTANCE_HOST_KEY 对应的值即可。
  将其改为上面 Collider 服务器的可访问地址。比如:apprtc.domain.com:8089。不需要协议,没有 URI。

改完以上两处,可以保存退出了

3、如果你使用了非标准端口,或者使用路由器上的端口映射为广域网提供测试和服务,还需要修改WEB前端的一些代码。否则会遇到浏览器的跨域访问问题(主要是 pushState 会产生一个错误),这么改:

# $FILE = apprtc/src/web_app/js/appcontroller.js

这个文件里有这样的两个函数:
AppController.prototype.pushCallNavigation_
AppController.prototype.displaySharingInfo_

分别在这两行函数内部的开头,加上如下代码:
roomLink = roomLink.replace(/apprtc\.domain\.com\//, 'apprtc.domain.com:8083/');

保存退出

4、现在再次确认当前目录是 apprtc 项目的根目录,而后执行:

$ grunt build; dev_appserver.py --host=0.0.0.0 ./out/app_engine

# 因为是为公网、或者局域网其他人提供服务,所以这里 host=0.0.0.0,以避免只监听 127.0.0.1 的状况。

5、需要注意的是,dev_appserver 默认监听了 8080 端口。但配置里到处都是 8083,因为还差了最后一步……

五. nginx,用来统一 HTTP 对外服务端口,以及最主要的反代 3033 TURN REST API 服务。
0、先装好nginx:apt-get install nginx -y
1、默认配置文件在 /etc/nginx/sites-enabled/default 。打开后,新增:

server {
  listen 8083;
  server_name apprtc.domain.com;
  location / {
    proxy_pass http://ip.address.of.apprtc:8080;
    proxy_set_header Host $host;
  }
  location /turn {
    proxy_pass http://ip.address.of.turn-rest-api:3033;
    proxy_set_header Host $host;
  }
}

# 保存后退出

2、使用 service nginx reload 重载配置文件。
3、如果有需要,可以在路由器上做端口映射:8083:tcp。
4、此时,外部可以访问到的 AppRTC 服务的 URL 已经确定了,你可以检查并执行【三(3)】中的命令。注意如果前面运行过此命令,就不需要再次运行了。

六. 打开浏览器访问 http://apprtc.domain.com:8083/ 。输入房间号,并把房间URL发给你的好基友,就可以面基了……

--------------------------------------------------------------

由于我搭建整套环境是在内网虚拟机上操作的,所以文章里到处都会出现”在路由器上设置好端口映射“这样的句子。
在这里,统一做一下整理吧:

8083:tcp - AppRTC 的端口,提供 HTTP 服务。默认使用的是 8080:tcp,我把它改了。
8089:tcp - Collider 服务的端口,提供 WebSocket 服务。
3478、3479:tcp&udp - coTurn 的监听端口。
59000~65000:tcp&udp - coTurn 的服务端口。

TURN REST API 的端口(3033)由于被 nginx 反向代理了,所以并不需要再单独给它做端口映射。

就这样吧,EOF

自建 AppRTC的更多相关文章

  1. WebRTC技术调研

    相关网址: 协议:https://www.w3.org/TR/webrtc/ https://apprtc.webrtc.org/ https://apprtc.appspot.com/ https: ...

  2. SQL 数据优化索引建suo避免全表扫描

    首先什么是全表扫描和索引扫描?全表扫描所有数据过一遍才能显示数据结果,索引扫描就是索引,只需要扫描一部分数据就可以得到结果.如果数据没建立索引. 无索引的情况下搜索数据的速度和占用内存就会比用索引的检 ...

  3. Vertica 安装,建库,新建测试用户并授予权限,建表,入库

    测试环境:RHEL 6.4 + Vertica 6.1.3-7 需求:搭建Vertica数据库3节点的测试环境,建立测试用户,建表,测试数据入库. 1.各节点关闭防火墙和SELinux,配置主机名,I ...

  4. Troubleshooting:重新安装Vertica建库后无法启动

    环境:RHEL6.5 + Vertica7.1.0-3 1.故障现象 2.重装集群 3.再次定位 4.解决问题 5.总结 1.故障现象 故障现象:Vertica集群安装成功,但是创建数据库后一直无法u ...

  5. 读书笔记--SQL必知必会17--创建和操纵表

    17.1 创建表 使用CREATE TABLE语句创建表. 不同的DBMS中CREATE TABLE语句的语法可能不同. 17.1.1 表创建基础 利用CREATE TABLE创建表,必须具备如下信息 ...

  6. “为什么DirectX里表示三维坐标要建一个4*4的矩阵?”

    0x00 前言 首先要说明的是,本文的标题事实上来自于知乎上的一个同名问题:为什么directX里表示三维坐标要建一个4*4的矩阵? - 编程 .因此,正如Milo Yip大神所说的这个标题事实上是存 ...

  7. 【手记】为windows2008建个睡眠快捷方式

    ----------------201607041343更新---------------- 在另一台电脑上SetSystemPowerState又不好使了,执行了根本没反应.又回头来试SetSusp ...

  8. 自建Ceph存储与 AWS、阿里云、腾讯云的成本对比

    本文单从存储成本角度对比了自建Ceph存储和业界公有云存储的硬件成本,不包括IDC带宽成本. 统计Ceph集群的用到的主要设备为: OSD.MON.RGW服务器 .TOR交换机. 机架. 下表解释: ...

  9. pgsql 建数据库注意事项

    在用navacat建好表之后,需要主键自增的时候,把字段建好之后,可以使用下面的sql来建立主键自增. ALTER TABLE "public"."chart_sql&q ...

随机推荐

  1. SpringBoot中@EnableAutoConfiguration注解用法收集

    参考: http://blog.csdn.net/xiaoyu411502/article/details/52770723 https://docs.spring.io/spring-boot/do ...

  2. 字符串(NSString)及常见字符串处理函数

    从本系列文章的开始,我们就使用过字符串对象,但是我们却还没有比较详细的介绍过它.使用@符,再一对双引号将一组字符串引用起来,例如: @”In fact, Objective-C is very sim ...

  3. Android 源码编译记录

    问题1:Can't locate Switch.pm in @INC (you may need to install the Switch module) (@INC contains: /etc/ ...

  4. C#制作、打包、签名、发布Activex全过程【转】

    http://www.cnblogs.com/still-windows7/p/3148623.html 一.前言 最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信.调用,单单依靠H ...

  5. Proftpd快速搭建FTP服务器

    前言 在Linux系统中,FTP服务器软件有很多,都已经成熟,像vsftpd, wu-ftp, Pure-FTPd等.但这些软件安装配置起来都比较麻烦,搭建个人的FTP服务器,还是Proftpd比较简 ...

  6. sql分级汇总

    --測试数据 create table tb([DB-ID] varchar(10),ENTITY varchar(10),DATE varchar(10),[CUST-NO] int,AMOUNT ...

  7. SpringMVC:走通一个SpringMVC

    我们现在使用SpringMVC来做一个小的用户管理系统,由于重点在学习SpringMVC,这里我们就不用数据库了. 该小系统实现的功能是:1.登录,不做用户名密码的正确性判断,任何用户名+密码都可以成 ...

  8. 2.nginx整合PHP

    /usr/local/src/下都有什么:.tar.gz文件和解压之后的源码 /usr/local/下都有什么:源码编译之后的东西 安装mysql客户端 安装mysql服务端 启动mysql服务端 s ...

  9. mysql服务停止

    mysql链接方式分为 tcp链接和 sock链接,   你刚才看到服务停止了还能链接 那种会员是 sock的会话模式   所以需要把所有链接mysql的进程结束掉,才能启动起来的   windows ...

  10. ffmpeg 视频教程 添加水印附源码

    本文主要讲述如何利用Ffmpeg向视频文件 添加水印这一功能,文中最后会给出源代码下载地址以及视频 下载地址,视频除了讲述添加水印的基本原理以及代码实现,还提到了要注意的一些地方,因为直接运行 dem ...