はじめに
「WebRTCを利用した1対1のビデオ通話サンプル」をMojolicious::Liteに移植しました。
環境
TLSサポートにはIO::Socket::SSLが要求されます。
IO::Socket::SSLはNet::SSLeayに依存しています。
Net::SSLeayのインストールには
- DebianとUbuntuでは、libssl-devとzlib1g-dev
- Red Hat Enterprise LinuxとFedoraでは、openssl-develとzlib-devel
が必要になります。
インストール
webrtc_server.pl
public
+ index.html
+ webrtc.js
Ubuntu
sudo apt install libssl-dev
sudo apt install zlib1g-dev
CentOS(CentOS6.4上でMojolicious+WebSocket+SSL環境構築)
sudo yum install openssl-devel
sudo yum install zlib-devel
IO::Socket::SSLとMojoliciousをインストールします。
cpanm IO::Socket::SSL
cpanm Mojolicious
開発サーバーを起動します。
morbo -l https://*:8443 webrtc_server.pl
サーバー
webrtc_server.jsの移植はリアルタイムチャット (Mojolicious::Lite)を参考にしました。
サーバーから3分ごと、クライアントから30秒ごと接続確認をしていましたが、3時間に延命してますのでお兄さん許して。
webrtc_server.pl
use strict;
use warnings;
use Mojo::JSON 'encode_json';
use Mojolicious::Lite;
# 接続リスト
my @connections = ();
# WebSocket処理
websocket '/' => sub {
my $self = shift;
$self->inactivity_timeout(10800);
my $log = $self->log;
# Receive message
$self->on('json' => sub {
my ($self, $json) = @_;
if ($json->{open}) {
$log->info('open: '
. $self->{tx}->remote_address
. ': local='
. $json->{open}{local}
. ', remote='
. $json->{open}{remote});
# 同一IDが存在するときは古い方を削除
@connections = grep {
!( $_->{local} eq $json->{open}{local}
&& $_->{remote} eq $json->{open}{remote})
} @connections;
# 接続情報を保存
push(
@connections,
{
local => $json->{open}{local},
remote => $json->{open}{remote},
ws => $self
}
);
foreach my $data (@connections) {
if ($data->{local} eq $json->{open}{remote}) {
# 両方が接続済の場合にstartを通知
$data->{ws}->send(encode_json({start => 'answer'}));
$self->send(encode_json({start => 'offer'}));
last;
}
}
return;
}
# 対向の接続を検索
foreach my $data (@connections) {
if ($data->{local} eq $json->{remote}) {
# シグナリングメッセージの転送
$data->{ws}->send(encode_json($json));
last;
}
}
});
# Finish
$self->on('finish' => sub {
@connections = grep {
if ($_->{ws} != $self) { 1; }
else {
foreach my $remoteData (@connections) {
if ($remoteData->{local} eq $_->{remote}) {
# 対向に切断を通知
$remoteData->{ws}->send(encode_json({close => 1}));
last;
}
}
}
} @connections;
$log->info('close: ' . $self->{tx}->remote_address);
});
};
# 静的ファイル処理
get '/' => sub {
my $self = shift;
$self->reply->static('index.html');
};
app->start;
クライアント
index.htmlとwebrtc.jsは省略します。
(startVideoは一度しか呼ばれず、その前にwindow.streamは設定されないので、「既存のストリームを破棄」する必要はないのでは?と思います)