自建 AppRTC


自建 AppRTC

字數3158 閱讀1718 評論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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM