|
|
@ -193,6 +193,11 @@ helper logout => sub { |
|
|
|
if ($ec && $self->session($room) && $self->session($room)->{etherpadSessionId}){ |
|
|
|
if ($ec && $self->session($room) && $self->session($room)->{etherpadSessionId}){ |
|
|
|
$ec->delete_session($self->session($room)->{etherpadSessionId}); |
|
|
|
$ec->delete_session($self->session($room)->{etherpadSessionId}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if ($self->session('peer_id') && |
|
|
|
|
|
|
|
$peers->{$self->session('peer_id')} && |
|
|
|
|
|
|
|
$peers->{$self->session('peer_id')}->{socket}){ |
|
|
|
|
|
|
|
$peers->{$self->session('peer_id')}->{socket}->finish; |
|
|
|
|
|
|
|
} |
|
|
|
$self->session( expires => 1 ); |
|
|
|
$self->session( expires => 1 ); |
|
|
|
$self->app->log->info($self->session('name') . " logged out"); |
|
|
|
$self->app->log->info($self->session('name') . " logged out"); |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
@ -316,104 +321,17 @@ helper modify_room => sub { |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
# Add a participant in the database. Used by the signaling server to check |
|
|
|
|
|
|
|
# if user is allowed |
|
|
|
|
|
|
|
helper add_participant_to_room => sub { |
|
|
|
|
|
|
|
my $self = shift; |
|
|
|
|
|
|
|
my ($name,$participant) = @_; |
|
|
|
|
|
|
|
my $room = $self->get_room_by_name($name); |
|
|
|
|
|
|
|
if (!$room){ |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
my $sth = eval { |
|
|
|
|
|
|
|
$self->db->prepare('INSERT INTO `room_participants` |
|
|
|
|
|
|
|
(`room_id`,`participant`,`last_activity`) |
|
|
|
|
|
|
|
VALUES (?,?,CONVERT_TZ(NOW(), @@session.time_zone, \'+00:00\')) |
|
|
|
|
|
|
|
ON DUPLICATE KEY UPDATE `last_activity`=CONVERT_TZ(NOW(), @@session.time_zone, \'+00:00\')'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute( |
|
|
|
|
|
|
|
$room->{id}, |
|
|
|
|
|
|
|
$participant |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
$self->app->log->info($self->session('name') . " joined the room $name"); |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Remove participant from the DB |
|
|
|
|
|
|
|
# Takes two args: room name and user name |
|
|
|
|
|
|
|
helper remove_participant_from_room => sub { |
|
|
|
|
|
|
|
my $self = shift; |
|
|
|
|
|
|
|
my ($name,$participant) = @_; |
|
|
|
|
|
|
|
my $room = $self->get_room_by_name($name); |
|
|
|
|
|
|
|
if (!$room){ |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
my $sth = eval { |
|
|
|
|
|
|
|
$self->db->prepare('DELETE FROM `room_participants` |
|
|
|
|
|
|
|
WHERE `id`=? |
|
|
|
|
|
|
|
AND `participant`=?'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute( |
|
|
|
|
|
|
|
$room->{id}, |
|
|
|
|
|
|
|
$participant |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
$self->app->log->info($self->session('name') . " leaved the room $name"); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Get a list of participants of a room |
|
|
|
|
|
|
|
helper get_participants_list => sub { |
|
|
|
|
|
|
|
my $self = shift; |
|
|
|
|
|
|
|
my ($name) = @_; |
|
|
|
|
|
|
|
my $room = $self->get_room_by_name($name); |
|
|
|
|
|
|
|
if (!$room){ |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
my $sth = eval { |
|
|
|
|
|
|
|
$self->db->prepare('SELECT `participant`,`room_id` |
|
|
|
|
|
|
|
FROM `room_participants` |
|
|
|
|
|
|
|
WHERE `room_id`=?'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute($room->{id}); |
|
|
|
|
|
|
|
return $sth->fetchall_hashref('room_id'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the role of a peer |
|
|
|
# Set the role of a peer |
|
|
|
helper set_peer_role => sub { |
|
|
|
helper set_peer_role => sub { |
|
|
|
my $self = shift; |
|
|
|
my $self = shift; |
|
|
|
my ($data) = @_; |
|
|
|
my ($data) = @_; |
|
|
|
# Check if this ID isn't the one from another peer first |
|
|
|
# Check the peer exists and is already in the room |
|
|
|
my $sth = eval { |
|
|
|
if (!$data->{peer_id} || |
|
|
|
$self->db->prepare('SELECT COUNT(`p`.`id`) |
|
|
|
!$peers->{$data->{peer_id}}){ |
|
|
|
FROM `room_participants` `p` |
|
|
|
|
|
|
|
LEFT JOIN `rooms` `r` ON `p`.`room_id`=`r`.`id` |
|
|
|
|
|
|
|
WHERE `p`.`peer_id`=? |
|
|
|
|
|
|
|
AND `p`.`participant`!=? |
|
|
|
|
|
|
|
AND `r`.`name`=?'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute($data->{peer_id},$data->{name},$data->{room}); |
|
|
|
|
|
|
|
my $num; |
|
|
|
|
|
|
|
$sth->bind_columns(\$num); |
|
|
|
|
|
|
|
$sth->fetch; |
|
|
|
|
|
|
|
if ($num > 0){ |
|
|
|
|
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
$sth = eval { |
|
|
|
$peers->{$data->{peer_id}}->{role} = $data->{role}; |
|
|
|
$self->db->prepare('UPDATE `room_participants` `p` |
|
|
|
$self->app->log->info("Peer " . $data->{peer_id} . " has now the " . |
|
|
|
LEFT JOIN `rooms` `r` ON `p`.`room_id`=`r`.`id` |
|
|
|
|
|
|
|
SET `p`.`peer_id`=?, |
|
|
|
|
|
|
|
`p`.`role`=? |
|
|
|
|
|
|
|
WHERE `p`.`participant`=? |
|
|
|
|
|
|
|
AND `r`.`name`=?'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute( |
|
|
|
|
|
|
|
$data->{peer_id}, |
|
|
|
|
|
|
|
$data->{role}, |
|
|
|
|
|
|
|
$data->{name}, |
|
|
|
|
|
|
|
$data->{room} |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
$self->app->log->info("User " . $data->{name} . " (peer id " . |
|
|
|
|
|
|
|
$data->{peer_id} . ") has now the " . |
|
|
|
|
|
|
|
$data->{role} . " role in room " . $data->{room}); |
|
|
|
$data->{role} . " role in room " . $data->{room}); |
|
|
|
return 1; |
|
|
|
return 1; |
|
|
|
}; |
|
|
|
}; |
|
|
@ -422,75 +340,18 @@ helper set_peer_role => sub { |
|
|
|
helper get_peer_role => sub { |
|
|
|
helper get_peer_role => sub { |
|
|
|
my $self = shift; |
|
|
|
my $self = shift; |
|
|
|
my ($data) = @_; |
|
|
|
my ($data) = @_; |
|
|
|
my $sth = eval { |
|
|
|
return $peers->{$data->{peer_id}}->{role}; |
|
|
|
$self->db->prepare('SELECT `p`.`role` |
|
|
|
|
|
|
|
FROM `room_participants` `p` |
|
|
|
|
|
|
|
LEFT JOIN `rooms` `r` ON `p`.`room_id`=`r`.`id` |
|
|
|
|
|
|
|
WHERE `p`.`peer_id`=? |
|
|
|
|
|
|
|
AND `r`.`name`=? |
|
|
|
|
|
|
|
LIMIT 1'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute( |
|
|
|
|
|
|
|
$data->{peer_id}, |
|
|
|
|
|
|
|
$data->{room} |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
my $role; |
|
|
|
|
|
|
|
$sth->bind_columns(\$role); |
|
|
|
|
|
|
|
$sth->fetch; |
|
|
|
|
|
|
|
return $role; |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
# Promote a peer to owner |
|
|
|
# Promote a peer to owner |
|
|
|
helper promote_peer => sub { |
|
|
|
helper promote_peer => sub { |
|
|
|
my $self = shift; |
|
|
|
my $self = shift; |
|
|
|
my ($data) = @_; |
|
|
|
my ($data) = @_; |
|
|
|
my $sth = eval { |
|
|
|
return $self->set_peer_role({ |
|
|
|
$self->db->prepare('UPDATE `room_participants` `p` |
|
|
|
peer_id => $data->{peer_id}, |
|
|
|
LEFT JOIN `rooms` `r` ON `p`.`room_id`=`r`.`id` |
|
|
|
room => $data->{room}, |
|
|
|
SET `p`.`role`=\'owner\' |
|
|
|
role => 'owner' |
|
|
|
WHERE `p`.`peer_id`=? |
|
|
|
}); |
|
|
|
AND `r`.`name`=?'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute( |
|
|
|
|
|
|
|
$data->{peer_id}, |
|
|
|
|
|
|
|
$data->{room} |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Check if a participant has joined a room |
|
|
|
|
|
|
|
# Takes a hashref room => room name and name => session name |
|
|
|
|
|
|
|
helper has_joined => sub { |
|
|
|
|
|
|
|
my $self = shift; |
|
|
|
|
|
|
|
my ($data) = @_; |
|
|
|
|
|
|
|
my $sth = eval { |
|
|
|
|
|
|
|
$self->db->prepare('SELECT COUNT(`r`.`id`) |
|
|
|
|
|
|
|
FROM `rooms` `r` |
|
|
|
|
|
|
|
LEFT JOIN `room_participants` `p` ON `r`.`id`=`p`.`room_id` |
|
|
|
|
|
|
|
WHERE `r`.`name`=? |
|
|
|
|
|
|
|
AND `p`.`participant`=?'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute( |
|
|
|
|
|
|
|
$data->{room}, |
|
|
|
|
|
|
|
$data->{name} |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
my $num; |
|
|
|
|
|
|
|
$sth->bind_columns(\$num); |
|
|
|
|
|
|
|
$sth->fetch; |
|
|
|
|
|
|
|
return ($num == 1) ? 1 : 0 ; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Purge disconnected participants from the DB |
|
|
|
|
|
|
|
helper purge_participants => sub { |
|
|
|
|
|
|
|
my $self = shift; |
|
|
|
|
|
|
|
$self->app->log->debug('Removing inactive participants from the database'); |
|
|
|
|
|
|
|
my $sth = eval { |
|
|
|
|
|
|
|
$self->db->prepare('DELETE FROM `room_participants` |
|
|
|
|
|
|
|
WHERE `last_activity` < DATE_SUB(CONVERT_TZ(NOW(), @@session.time_zone, \'+00:00\'), INTERVAL 10 MINUTE) |
|
|
|
|
|
|
|
OR `last_activity` IS NULL'); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
$sth->execute; |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
# Purge api keys |
|
|
|
# Purge api keys |
|
|
@ -1174,7 +1035,7 @@ websocket '/socket.io/:ver/websocket/:id' => sub { |
|
|
|
my ($self, $code, $reason) = @_; |
|
|
|
my ($self, $code, $reason) = @_; |
|
|
|
$self->app->log->debug("Client id " . $id . " closed websocket connection"); |
|
|
|
$self->app->log->debug("Client id " . $id . " closed websocket connection"); |
|
|
|
foreach my $peer (keys %$peers){ |
|
|
|
foreach my $peer (keys %$peers){ |
|
|
|
next if ($peer eq $id); |
|
|
|
next if $peer eq $id; |
|
|
|
next if $peers->{$peer}->{room} ne $peers->{$id}->{room}; |
|
|
|
next if $peers->{$peer}->{room} ne $peers->{$id}->{room}; |
|
|
|
$self->app->log->debug("Notifying $peer that $id leaved"); |
|
|
|
$self->app->log->debug("Notifying $peer that $id leaved"); |
|
|
|
$peers->{$peer}->{socket}->send( |
|
|
|
$peers->{$peer}->{socket}->send( |
|
|
@ -1191,9 +1052,8 @@ websocket '/socket.io/:ver/websocket/:id' => sub { |
|
|
|
} |
|
|
|
} |
|
|
|
) |
|
|
|
) |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
# Remove this peer from our global hash |
|
|
|
|
|
|
|
delete $peers->{$id}; |
|
|
|
delete $peers->{$id}; |
|
|
|
|
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
# This is just the end of the initial handshake, we indicate the client we're ready |
|
|
|
# This is just the end of the initial handshake, we indicate the client we're ready |
|
|
@ -1206,9 +1066,14 @@ Mojo::IOLoop->recurring( 3 => sub { |
|
|
|
foreach my $peer ( keys %$peers ) { |
|
|
|
foreach my $peer ( keys %$peers ) { |
|
|
|
# If we had no reply from this peer in the last 15 sec |
|
|
|
# If we had no reply from this peer in the last 15 sec |
|
|
|
# (5 heartbeat without response), we consider it dead and remove it |
|
|
|
# (5 heartbeat without response), we consider it dead and remove it |
|
|
|
if ($peers->{$peer}->{last} < time - 15){ |
|
|
|
if (!$peers->{$peer}->{socket}){ |
|
|
|
|
|
|
|
app->log->debug("Garbage found in peers (peer $peer)\n" . Dumper($peers->{$peer})); |
|
|
|
|
|
|
|
delete $peers->{$peer}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
elsif ($peers->{$peer}->{last} < time - 15){ |
|
|
|
app->log->debug("Peer $peer didn't reply in 15 sec, disconnecting"); |
|
|
|
app->log->debug("Peer $peer didn't reply in 15 sec, disconnecting"); |
|
|
|
$peers->{$peer}->{socket}->finish; |
|
|
|
$peers->{$peer}->{socket}->finish; |
|
|
|
|
|
|
|
delete $peers->{$peer}; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
$peers->{$peer}->{socket}->send(Protocol::SocketIO::Message->new( type => 'heartbeat' )); |
|
|
|
$peers->{$peer}->{socket}->send(Protocol::SocketIO::Message->new( type => 'heartbeat' )); |
|
|
@ -1258,10 +1123,11 @@ post '/feedback' => sub { |
|
|
|
get '/goodbye/(:room)' => sub { |
|
|
|
get '/goodbye/(:room)' => sub { |
|
|
|
my $self = shift; |
|
|
|
my $self = shift; |
|
|
|
my $room = $self->stash('room'); |
|
|
|
my $room = $self->stash('room'); |
|
|
|
if ($self->get_room_by_name($room) && $self->session('name')){ |
|
|
|
if (!$self->get_room_by_name($room)){ |
|
|
|
$self->remove_participant_from_room( |
|
|
|
return $self->render('error', |
|
|
|
$room, |
|
|
|
err => 'ERROR_ROOM_s_DOESNT_EXIST', |
|
|
|
$self->session('name') |
|
|
|
msg => sprintf ($self->l("ERROR_ROOM_s_DOESNT_EXIST"), $room), |
|
|
|
|
|
|
|
room => $room |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
$self->logout($room); |
|
|
|
$self->logout($room); |
|
|
@ -1279,10 +1145,6 @@ get '/kicked/(:room)' => sub { |
|
|
|
room => $room |
|
|
|
room => $room |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
$self->remove_participant_from_room( |
|
|
|
|
|
|
|
$room, |
|
|
|
|
|
|
|
$self->session('name') |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
$self->logout($room); |
|
|
|
$self->logout($room); |
|
|
|
} => 'kicked'; |
|
|
|
} => 'kicked'; |
|
|
|
|
|
|
|
|
|
|
@ -1579,7 +1441,6 @@ any '/api' => sub { |
|
|
|
if ((int (rand 100)) <= 10){ |
|
|
|
if ((int (rand 100)) <= 10){ |
|
|
|
$self->purge_rooms; |
|
|
|
$self->purge_rooms; |
|
|
|
$self->purge_invitations; |
|
|
|
$self->purge_invitations; |
|
|
|
$self->purge_participants; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
# Check if we got any invitation response to process |
|
|
|
# Check if we got any invitation response to process |
|
|
|
my $invitations = $self->get_invitation_list($self->session('name')); |
|
|
|
my $invitations = $self->get_invitation_list($self->session('name')); |
|
|
@ -1865,7 +1726,6 @@ any '/api' => sub { |
|
|
|
} |
|
|
|
} |
|
|
|
my $res = $self->set_peer_role({ |
|
|
|
my $res = $self->set_peer_role({ |
|
|
|
room => $room->{name}, |
|
|
|
room => $room->{name}, |
|
|
|
name => $self->session('name'), |
|
|
|
|
|
|
|
peer_id => $peer_id, |
|
|
|
peer_id => $peer_id, |
|
|
|
role => $self->session($room->{name})->{role} |
|
|
|
role => $self->session($room->{name})->{role} |
|
|
|
}); |
|
|
|
}); |
|
|
@ -2117,14 +1977,6 @@ get '/:room' => sub { |
|
|
|
} |
|
|
|
} |
|
|
|
$self->create_etherpad_session($room); |
|
|
|
$self->create_etherpad_session($room); |
|
|
|
} |
|
|
|
} |
|
|
|
# Add this user to the participants table |
|
|
|
|
|
|
|
if (!$self->add_participant_to_room($room, $self->session('name'))){ |
|
|
|
|
|
|
|
return $self->render('error', |
|
|
|
|
|
|
|
msg => $self->l('ERROR_OCCURRED'), |
|
|
|
|
|
|
|
err => 'ERROR_OCCURRED', |
|
|
|
|
|
|
|
room => $room |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
# Now display the room page |
|
|
|
# Now display the room page |
|
|
|
return $self->render('join', |
|
|
|
return $self->render('join', |
|
|
|
moh => $self->choose_moh(), |
|
|
|
moh => $self->choose_moh(), |
|
|
|