diff --git a/conf/settings.ini.dist b/conf/settings.ini.dist index 98c1dbc..2658785 100644 --- a/conf/settings.ini.dist +++ b/conf/settings.ini.dist @@ -15,11 +15,24 @@ ; The turn server sent to cliet, you should set it to your own server. Takes a comma separated list of full ; turn uri as defined by rfc7065 ;turn_server = 'turns:my-turn-server.net:5349?transport=tcp' -; You can use fixed username/login to access turn. If you omit this, VROOM will generate credentials on the fly -; for rfc5766-turn-server in its database -;turn_user = '' -;turn_password = '' -; the realm used for turn accounts. Must match the realm of your turn server +; +; How turn creds are managed can be +; * static: credentials are static (set with turn_user and turn_password), same for every rooms +; +; * rest: Use a TURN REST API compatible method and generate credentials on the fly. You need to set "secret_key" +; to the secret key you set in your turn server. See http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00 +; This has been tested with rfc-5766-turn-server but should work with any compatible turn server +; +; * rfc-5766-turn-server: In this mode, a MySQL view is used to manage one turn username per room +; It works only with rfc-5766-turn-server but it's recommanded to use rest now +; even when using rfc-5766-turn-server +credentials = 'rest' +; Credentials to use with the "static" method +;turn_user = 'foo' +;turn_password = 'bar' +; Secret key shared with the turn server when using the "rest" method +;secret_key = 'secret' +; the realm used for turn accounts. Only needed when using the rfc-5766-turn-server method ;realm = 'vroom' [video] diff --git a/vroom.pl b/vroom.pl index 34669ad..2a76c9a 100755 --- a/vroom.pl +++ b/vroom.pl @@ -11,6 +11,7 @@ use Mojolicious::Plugin::Mail; use Mojolicious::Plugin::Database; use Vroom::Constants; use Crypt::SaltedHash; +use Digest::HMAC_SHA1 qw(hmac_sha1); use MIME::Base64; use File::stat; use File::Basename; @@ -35,8 +36,10 @@ $config->{'database.password'} ||= 'vroom'; $config->{'signaling.uri'} ||= 'https://vroom.example.com/'; $config->{'turn.stun_server'} ||= 'stun.l.google.com:19302'; $config->{'turn.turn_server'} ||= undef; -$config->{'turn.turn_user'} ||= undef; -$config->{'turn.turn_password'} ||= undef; +$config->{'turn.credentials'} ||= 'static'; +$config->{'turn.secret_key'} ||= ''; +$config->{'turn.turn_user'} ||= ''; +$config->{'turn.turn_password'} ||= ''; $config->{'turn.realm'} ||= 'vroom'; $config->{'video.frame_rate'} ||= 15; $config->{'email.from '} ||= 'vroom@example.com'; @@ -951,6 +954,33 @@ helper get_member_limit => sub { return 0; }; + +# Get credentials for the turn servers. Return an array (username,password) +helper get_turn_creds => sub { + my $self = shift; + my $room = $self->get_room_by_name(shift); + if (!$room){ + return (undef,undef); + } + elsif ($config->{'turn.credentials'} eq 'static'){ + return ($config->{'turn.turn_user'},$config->{'turn.turn_password'}); + } + elsif ($config->{'turn.credentials'} eq 'rfc-5766-turn-server'){ + return ($room->{name},$room->{token}); + } + elsif ($config->{'turn.credentials'} eq 'rest'){ + my $expire = time + 300; + my $user = $expire . ':' . $room->{name}; + my $pass = encode_base64(hmac_sha1($user, $config->{'turn.secret_key'})); +# my $pass = encode_base64(Digest::HMAC_SHA1->new($config->{'turn.secret_key'})->add($user)->digest); + chomp $pass; + return ($user,$pass); + } + else { + return (undef,undef); + } +}; + # Socket.IO handshake get '/socket.io/:ver' => sub { my $self = shift; @@ -1748,14 +1778,7 @@ any '/api' => sub { } foreach my $t (@{$config->{'turn.turn_server'}}){ my $turn = { url => $t }; - if ($config->{'turn.turn_user'} && $config->{'turn.turn_password'}){ - $turn->{username} = $config->{'turn.turn_user'}; - $turn->{credential} = $config->{'turn.turn_password'}; - } - else{ - $turn->{username} = $room->{name}; - $turn->{credential} = $room->{token}; - } + ($turn->{username},$turn->{credential}) = $self->get_turn_creds($room->{name}); push @{$resp->{peerConnectionConfig}->{iceServers}}, $turn; } }