# allocate_miniserv_websocket()
# Allocate a new websocket and
# stores it miniserv.conf file
sub allocate_miniserv_websocket
{
# Find ports already in use
&lock_file(&get_miniserv_config_file());
my %miniserv;
&get_miniserv_config(\%miniserv);
my %inuse;
foreach my $k (keys %miniserv) {
if ($k =~ /^websockets_/ && $miniserv{$k} =~ /port=(\d+)/) {
$inuse{$1} = 1;
}
}
# Pick a port and configure Webmin to proxy it
my $port = $config{'base_port'} || 555;
while(1) {
if (!$inuse{$port}) {
&open_socket("127.0.0.1", $port, my $fh, \$err);
last if ($err);
close($fh);
}
$port++;
}
my $wspath = "/$module_name/ws-".$port;
my $now = time();
$miniserv{'websockets_'.$wspath} = "host=127.0.0.1 port=$port wspath=/ user=$remote_user time=$now";
&put_miniserv_config(\%miniserv);
&unlock_file(&get_miniserv_config_file());
&reload_miniserv();
return $port;
}
# remove_miniserv_websocket(port)
# Remove old websocket
# from miniserv.conf
sub remove_miniserv_websocket
{
my ($port) = @_;
my %miniserv;
if ($port) {
&lock_file(&get_miniserv_config_file());
&get_miniserv_config(\%miniserv);
my $wspath = "/$module_name/ws-".$port;
if ($miniserv{'websockets_'.$wspath}) {
delete($miniserv{'websockets_'.$wspath});
&put_miniserv_config(\%miniserv);
&reload_miniserv();
}
&unlock_file(&get_miniserv_config_file());
}
}
# cleanup_miniserv_websockets([&skip-ports])
# Called by scheduled status collection to remove any
# websockets in miniserv.conf that are no longer used
sub cleanup_miniserv_websockets
{
my ($skip) = @_;
$skip ||= [ ];
&lock_file(&get_miniserv_config_file());
my %miniserv;
&get_miniserv_config(\%miniserv);
my $now = time();
my @clean;
foreach my $k (keys %miniserv) {
$k =~ /^websockets_\/$module_name\/ws-(\d+)$/ || next;
my $port = $1;
next if (&indexof($port, @$skip) >= 0);
my $when = 0;
if ($miniserv{$k} =~ /time=(\d+)/) {
$when = $1;
}
if ($now - $when > 60) {
# Has been open for a while, check if the port is still in use?
my $err;
&open_socket("127.0.0.1", $port, my $fh, \$err);
if ($err) {
# Closed now, can clean up
push(@clean, $k);
}
else {
# Still active
close($fh);
}
}
}
if (@clean) {
foreach my $k (@clean) {
delete($miniserv{$k});
}
&put_miniserv_config(\%miniserv);
&reload_miniserv();
}
&unlock_file(&get_miniserv_config_file());
}
1;