[X2Go-Commits] x2goserver.git - build-main (branch) updated: 3.0.99.10-2-g63556d2
X2Go dev team
git-admin at x2go.org
Wed Dec 4 06:18:07 CET 2013
The branch, build-main has been updated
via 63556d25c3a86f187d16b0e44a5beef76a27bc84 (commit)
from dc0e5721b977a248c2b1e0b7e26b4549ed996d92 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
debian/changelog | 11 ++++
x2goserver/bin/x2goresume-session | 67 ++++++++++++++++++++++++-
x2goserver/bin/x2gostartagent | 17 +++----
x2goserver/lib/x2godbwrapper.pm | 56 +++++++++++++++------
x2goserver/lib/x2goresume | 5 +-
x2goserver/lib/{x2goinsertport => x2gormport} | 3 +-
x2goserver/lib/x2gosqlitewrapper.pl | 18 ++++++-
x2goserver/sbin/x2godbadmin | 4 +-
8 files changed, 149 insertions(+), 32 deletions(-)
copy x2goserver/lib/{x2goinsertport => x2gormport} (95%)
The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index 41e44b5..c7e72b0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,7 +1,18 @@
x2goserver (3.1.0.0-0~x2go1) UNRELEASED; urgency=low
+ [ Mike Gabriel ]
* Continue development...
+ [ Oleksandr Shneyder ]
+ * New upstream version (3.1.0.0)
+ - remove ports used by X2Go session from database after session was finished
+ if postgres backend is used.
+ - before resuming X2Go session check if reserved ports still available
+ in other case find new free ports, save them in database and send to
+ x2goclient
+ - run netstat -tl --all to find free ports for graphic, sound and sshfs
+ tunnels in x2gostartagent and x2goresume-session
+
-- Mike Gabriel <mike.gabriel at das-netzwerkteam.de> Wed, 01 Feb 2012 13:45:00 +0100
x2goserver (3.0.99.10-0~x2go1) unstable; urgency=low
diff --git a/x2goserver/bin/x2goresume-session b/x2goserver/bin/x2goresume-session
index 9023e86..009fd1d 100755
--- a/x2goserver/bin/x2goresume-session
+++ b/x2goserver/bin/x2goresume-session
@@ -54,6 +54,65 @@ then
X2GO_FULLSCREEN=1
fi
+
+SESSIONINFO=`x2golistsessions | grep ${SESSION_NAME} | sed "s/|/,/g"`
+
+GR_PORT=`echo "$SESSIONINFO" | awk -F, {'print $9'}`
+SOUND_PORT=`echo "$SESSIONINFO" | awk -F, {'print $10'}`
+FS_PORT=`echo "$SESSIONINFO" | awk -F, {'print $14'}`
+SERVER=`echo "$SESSIONINFO" | awk -F, {'print $4'}`
+
+$X2GO_LIB_PATH/x2gosyslog "$0" "debug" "old ports: $GR_PORT, $SOUND_PORT, $FS_PORT"
+
+#Get all used in system ports from netstat output
+SYSTEM_PORTS=`netstat -nt -all | awk '{ n=split($0,lines,"\n"); for(i=1;i<=n;i++){split (lines[i],words," ");delim=split(words[4],ports,":"); if(delim>1)printf ("|%s|\n",ports[delim])} }'`
+
+#check if saved in DB ports free
+if grep -q "|${GR_PORT}|" <<<$SYSTEM_PORTS ; then
+ $X2GO_LIB_PATH/x2gosyslog "$0" "debug" "port $GR_PORT is already in use"
+ $X2GO_LIB_PATH/x2gormport $HOSTNAME $SESSION_NAME $GR_PORT
+ GR_PORT=""
+fi
+if grep -q "|${SOUND_PORT}|" <<<$SYSTEM_PORTS ; then
+ $X2GO_LIB_PATH/x2gosyslog "$0" "debug" "port $SOUND_PORT is already in use"
+ $X2GO_LIB_PATH/x2gormport $HOSTNAME $SESSION_NAME $SOUND_PORT
+ SOUND_PORT=""
+fi
+if grep -q "|${FS_PORT}|" <<<$SYSTEM_PORTS ; then
+ $X2GO_LIB_PATH/x2gosyslog "$0" "debug" "port $FS_PORT is already in use"
+ $X2GO_LIB_PATH/x2gormport $HOSTNAME $SESSION_NAME $FS_PORT
+ FS_PORT=""
+fi
+
+SSH_PORT=30000 #First ssh port 30001
+
+#Get all used in system ports from X2Go database and netstat output
+USED_PORTS=`$X2GO_LIB_PATH/x2gogetports $HOSTNAME ; netstat -nt -all | awk '{ n=split($0,lines,"\n"); for(i=1;i<=n;i++){split (lines[i],words," ");delim=split(words[4],ports,":"); if(delim>1)printf ("|%s|\n",ports[delim])} }'`
+
+while [ "$GR_PORT" == "" ] || [ "$SOUND_PORT" == "" ] || [ "$FS_PORT" == "" ]; do
+ OUTPUT=""
+ while [ "$OUTPUT" != "inserted" ]; do
+ SSH_PORT=$(($SSH_PORT + 1))
+
+ #get free port
+ SSH_PORT=`echo "for(\\$i=$SSH_PORT;\\$br ne \"true\";\\$i++){ if(\"$USED_PORTS\" =~ m/\\|\\$i\\|/){\\$br=\"false\";}else{\\$br=\"true\";print \\$i;}}"|perl`
+
+ #check if port in /etc/services
+ SERV=`grep $SSH_PORT /etc/services`
+ if [ "$SERV" == "" ]; then
+ OUTPUT=`$X2GO_LIB_PATH/x2goinsertport $HOSTNAME $SESSION_NAME $SSH_PORT`
+ fi
+ done
+ if [ "$GR_PORT" == "" ]; then
+ GR_PORT=$SSH_PORT
+ elif [ "$SOUND_PORT" == "" ]; then
+ SOUND_PORT=$SSH_PORT
+ else
+ FS_PORT=$SSH_PORT
+ fi
+done
+
+
SESSION_DIR=${X2GO_ROOT}/C-${SESSION_NAME}
OPTIONS=`cat ${SESSION_DIR}/options`
@@ -63,6 +122,8 @@ FSTR=`echo "$OPTIONS" | awk -F, {'print $15'}`
LSTR=`echo "$OPTIONS" | awk -F, {'print $2'}`
PSTR=`echo "$OPTIONS" | awk -F, {'print $3'}`
KTSTR=`echo "$OPTIONS" | awk -F, {'print $12'}`
+LISTSTR=`echo "$OPTIONS" | awk -F, {'print $17'}`
+
KTSTR=`echo $KTSTR | sed "s/\//\\\\\\\\\//"`
X2GO_KBD_TYPE=`echo $X2GO_KBD_TYPE | sed "s/\//\\\\\\\\\//"`
@@ -77,6 +138,7 @@ NEWOPTIONS=`echo "$OPTIONS" | sed -e "s/$LSTR/link=$X2GO_LINK/"\
-e "s/$KTSTR/kbtype=$X2GO_KBD_TYPE/"\
-e "s/$GSTR/geometry=$X2GO_GEOMETRY/"\
-e "s/$RSTR/resize=$X2GO_RESIZE/"\
+ -e "s/$LISTSTR/listen=$GR_PORT/"\
-e "s/$FSTR/fullscreen=$X2GO_FULLSCREEN/"`
X2GO_CLIENT=`echo $SSH_CLIENT | awk '{print $1}'`
@@ -87,7 +149,7 @@ fi
echo "$NEWOPTIONS" >${SESSION_DIR}/options
-$X2GO_LIB_PATH/x2goresume $X2GO_CLIENT $SESSION_NAME > /dev/null
+$X2GO_LIB_PATH/x2goresume $X2GO_CLIENT $SESSION_NAME $GR_PORT $SOUND_PORT $FS_PORT > /dev/null
# run x2goserver-extensions for pre-resume
x2gofeature X2GO_RUN_EXTENSIONS &>/dev/null && x2goserver-run-extensions $SESSION_NAME pre-resume || true
@@ -115,3 +177,6 @@ kill -HUP $X2GO_AGENT_PID &>/dev/null && {
}
+echo "gr_port=$GR_PORT"
+echo "sound_port=$SOUND_PORT"
+echo "fs_port=$FS_PORT"
diff --git a/x2goserver/bin/x2gostartagent b/x2goserver/bin/x2gostartagent
index a4952bc..3b802b4 100755
--- a/x2goserver/bin/x2gostartagent
+++ b/x2goserver/bin/x2gostartagent
@@ -116,6 +116,9 @@ fi
USED_DISPLAYS=`$X2GO_LIB_PATH/x2gogetdisplays $HOSTNAME`
+#Get all used in system ports from X2Go database and netstat output
+USED_PORTS=`$X2GO_LIB_PATH/x2gogetports $HOSTNAME ; netstat -nt -all | awk '{ n=split($0,lines,"\n"); for(i=1;i<=n;i++){split (lines[i],words," ");delim=split(words[4],ports,":"); if(delim>1)printf ("|%s|\n",ports[delim])} }'`
+
while [ "$OUTPUT" != "inserted" ]; do
X2GO_PORT=$(($X2GO_PORT + 1))
@@ -125,7 +128,7 @@ while [ "$OUTPUT" != "inserted" ]; do
NX_PORT=$(($X2GO_PORT + 6000))
if [ -e "/tmp/.X${X2GO_PORT}-lock" ] ||
[ -e "/tmp/.X11-unix/X${X2GO_PORT}" ] ||
- netstat -ntl 2>/dev/null | grep -q ":${NX_PORT} "; then
+ grep -q "|${NX_PORT}|" <<<$USED_PORTS ; then
OUTPUT="XXX"
else
SESSION_NAME=${USER}-${X2GO_PORT}-`date +"%s"`
@@ -138,24 +141,18 @@ while [ "$OUTPUT" != "inserted" ]; do
done
-USED_PORTS=`$X2GO_LIB_PATH/x2gogetports $HOSTNAME`
-
-
while [ "$GR_PORT" == "" ] || [ "$SOUND_PORT" == "" ] || [ "$FS_PORT" == "" ]; do
OUTPUT=""
while [ "$OUTPUT" != "inserted" ]; do
SSH_PORT=$(($SSH_PORT + 1))
- #check if port in /etc/services
+ #get free port
SSH_PORT=`echo "for(\\$i=$SSH_PORT;\\$br ne \"true\";\\$i++){ if(\"$USED_PORTS\" =~ m/\\|\\$i\\|/){\\$br=\"false\";}else{\\$br=\"true\";print \\$i;}}"|perl`
+ #check if port in /etc/services
SERV=`grep $SSH_PORT /etc/services`
if [ "$SERV" == "" ]; then
- CR=`echo "use IO::Socket; \\$sock = new IO::Socket::INET ( LocalAddr => 'localhost',LocalPort => \"$SSH_PORT\",\
- Proto => 'tcp',Listen => 1,Reuse =>1 ) or die ;print \"OK\";close(\\$sock);"|perl 2>/dev/null`
- if [ "$CR" == "OK" ]; then
- OUTPUT=`$X2GO_LIB_PATH/x2goinsertport $HOSTNAME $SESSION_NAME $SSH_PORT`
- fi
+ OUTPUT=`$X2GO_LIB_PATH/x2goinsertport $HOSTNAME $SESSION_NAME $SSH_PORT`
fi
done
if [ "$GR_PORT" == "" ]; then
diff --git a/x2goserver/lib/x2godbwrapper.pm b/x2goserver/lib/x2godbwrapper.pm
index df707df..aec0294 100644
--- a/x2goserver/lib/x2godbwrapper.pm
+++ b/x2goserver/lib/x2godbwrapper.pm
@@ -86,7 +86,7 @@ if ($backend eq 'postgres')
use base 'Exporter';
our @EXPORT=('db_listsessions','db_listsessions_all', 'db_getservers', 'db_getagent', 'db_resume', 'db_changestatus',
- 'db_getdisplays', 'db_insertsession', 'db_getports', 'db_insertport', 'db_createsession', 'db_insertmount',
+ 'db_getdisplays', 'db_insertsession', 'db_getports', 'db_insertport', 'db_rmport', 'db_createsession', 'db_insertmount',
'db_getmounts', 'db_deletemount', 'db_getdisplay', 'dbsys_getmounts', 'dbsys_listsessionsroot',
'dbsys_listsessionsroot_all', 'dbsys_rmsessionsroot');
@@ -100,6 +100,8 @@ sub dbsys_rmsessionsroot
my $sth=$dbh->prepare("delete from sessions where session_id='$sid'");
$sth->execute() or die;
+ $sth=$dbh->prepare("delete from used_ports where session_id='$sid'");
+ $sth->execute() or die;
}
if($backend eq 'sqlite')
{
@@ -230,7 +232,7 @@ sub db_deletemount
my $path=shift or die "argument \"path\" missed";
if ($backend eq 'postgres')
{
- my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
+ my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
my $sth=$dbh->prepare("delete from mounts_view where session_id='$sid' and path='$path'");
$sth->execute();
$sth->finish();
@@ -251,7 +253,7 @@ sub db_insertmount
my $res_ok=0;
if ($backend eq 'postgres')
{
- my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
+ my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
my $sth=$dbh->prepare("insert into mounts (session_id,path,client) values ('$sid','$path','$client')");
$sth->execute();
if (!$sth->err())
@@ -279,7 +281,7 @@ sub db_insertsession
my $sid=shift or die "argument \"session_id\" missed";
if ($backend eq 'postgres')
{
- my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
+ my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
my $sth=$dbh->prepare("insert into sessions (display,server,uname,session_id) values ('$display','$server','$uname','$sid')");
$sth->execute()or die $_;
$sth->finish();
@@ -307,7 +309,7 @@ sub db_createsession
my $sid=shift or die "argument \"session_id\" missed";
if ($backend eq 'postgres')
{
- my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
+ my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
my $sth=$dbh->prepare("update sessions_view set status='R',last_time=now(),
cookie='$cookie',agent_pid='$pid',client='$client',gr_port='$gr_port',
sound_port='$snd_port',fs_port='$fs_port' where session_id='$sid'");
@@ -333,7 +335,7 @@ sub db_insertport
my $sshport=shift or die "argument \"port\" missed";
if ($backend eq 'postgres')
{
- my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
+ my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
my $sth=$dbh->prepare("insert into used_ports (server,session_id,port) values ('$server','$sid','$sshport')");
$sth->execute()or die;
$sth->finish();
@@ -346,32 +348,56 @@ sub db_insertport
syslog('debug', "db_insertport called, session ID: $sid, server: $server, SSH port: $sshport");
}
+sub db_rmport
+{
+ my $server=shift or die "argument \"server\" missed";
+ my $sid=shift or die "argument \"session_id\" missed";
+ my $sshport=shift or die "argument \"port\" missed";
+ if ($backend eq 'postgres')
+ {
+ my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
+ my $sth=$dbh->prepare("delete from used_ports where server='$server' and session_id='$sid' and port='$sshport'");
+ $sth->execute()or die;
+ $sth->finish();
+ $dbh->disconnect();
+ }
+ if ($backend eq 'sqlite')
+ {
+ `$x2go_lib_path/x2gosqlitewrapper rmport $server $sid $sshport`;
+ }
+ syslog('debug', "db_rmport called, session ID: $sid, server: $server, SSH port: $sshport");
+}
+
sub db_resume
{
my $client=shift or die "argument \"client\" missed";
- my $sid=shift or die "argument \"session_id\" missed";
+ my $sid=shift or die "argument \"session_id\" missed";
+ my $gr_port=shift or die "argument \"gr_port\" missed";
+ my $sound_port=shift or die "argument \"sound_port\" missed";
+ my $fs_port=shift or die "argument \"fs_port\" missed";
if ($backend eq 'postgres')
{
- my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
- my $sth=$dbh->prepare("update sessions_view set last_time=now(),status='R',client='$client' where session_id = '$sid'");
+ my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
+ my $sth=$dbh->prepare("update sessions_view set last_time=now(),status='R',client='$client',gr_port='$gr_port',
+ sound_port='$sound_port',fs_port='$fs_port' where session_id = '$sid'");
$sth->execute()or die;
$sth->finish();
$dbh->disconnect();
}
if ($backend eq 'sqlite')
{
- `$x2go_lib_path/x2gosqlitewrapper resume $client $sid`;
+ `$x2go_lib_path/x2gosqlitewrapper resume $client $sid $gr_port $sound_port $fs_port`;
}
- syslog('debug', "db_resume called, session ID: $sid, client: $client");
+ syslog('debug', "db_resume called, session ID: $sid, client: $client, gr_port: $gr_port, sound_port: $sound_port, fs_port: $fs_port");
}
sub db_changestatus
{
my $status=shift or die "argument \"status\" missed";
- my $sid=shift or die "argument \"session_id\" missed";
+ my $sid=shift or die "argument \"session_id\" missed";
if ($backend eq 'postgres')
{
- my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
+ my $dbh=DBI->connect("dbi:Pg:dbname=$db;host=$host;port=$port;sslmode=$sslmode", "$dbuser", "$dbpass",{AutoCommit => 1}) or die $_;
my $sth=$dbh->prepare("update sessions_view set last_time=now(),status='$status' where session_id = '$sid'");
$sth->execute()or die;
$sth->finish();
@@ -388,7 +414,7 @@ sub db_getdisplays
{
my @displays;
#ignore $server
- my $server=shift or die "argument \"server\" missed";
+ my $server=shift or die "argument \"server\" missed";
if ($backend eq 'postgres')
{
my @strings;
@@ -418,7 +444,7 @@ sub db_getports
{
my @ports;
#ignore $server
- my $server=shift or die "argument \"server\" missed";
+ my $server=shift or die "argument \"server\" missed";
if ($backend eq 'postgres')
{
my @strings;
diff --git a/x2goserver/lib/x2goresume b/x2goserver/lib/x2goresume
index 2e64542..7391cd3 100755
--- a/x2goserver/lib/x2goresume
+++ b/x2goserver/lib/x2goresume
@@ -33,8 +33,11 @@ setlogmask( LOG_UPTO(x2gologlevel()) );
my $client=shift or die;
my $sid=shift or die;
+my $gr_port=shift or die;
+my $snd_port=shift or die;
+my $fs_port=shift or die;
-db_resume($client, $sid);
+db_resume($client, $sid, $gr_port, $snd_port, $fs_port);
# closing syslog
closelog;
diff --git a/x2goserver/lib/x2goinsertport b/x2goserver/lib/x2gormport
similarity index 95%
copy from x2goserver/lib/x2goinsertport
copy to x2goserver/lib/x2gormport
index bc18d96..4ba632d 100755
--- a/x2goserver/lib/x2goinsertport
+++ b/x2goserver/lib/x2gormport
@@ -35,8 +35,7 @@ my $server=shift or die;
my $sid=shift or die;
my $port=shift or die;
-db_insertport($server,$sid,$port);
-print "inserted";
+db_rmport($server,$sid,$port);
# closing syslog
closelog;
\ No newline at end of file
diff --git a/x2goserver/lib/x2gosqlitewrapper.pl b/x2goserver/lib/x2gosqlitewrapper.pl
index 53041f8..ac8a7c6 100755
--- a/x2goserver/lib/x2gosqlitewrapper.pl
+++ b/x2goserver/lib/x2gosqlitewrapper.pl
@@ -153,14 +153,28 @@ elsif($cmd eq "insertport")
$sth->finish();
}
+elsif($cmd eq "rmport")
+{
+ my $server=shift or die "argument \"server\" missed";
+ my $sid=shift or die "argument \"session_id\" missed";
+ my $sshport=shift or die "argument \"port\" missed";
+ my $sth=$dbh->prepare("delete from used_ports where server=? and session_id=? and port=?");
+ check_user($sid);
+ $sth->execute($server, $sid, $sshport) or die;
+ $sth->finish();
+}
+
elsif($cmd eq "resume")
{
my $client=shift or die "argument \"client\" missed";
my $sid=shift or die "argument \"session_id\" missed";
+ my $gr_port=shift or die "argument \"gr_port\" missed";
+ my $sound_port=shift or die "argument \"sound_port\" missed";
+ my $fs_port=shift or die "argument \"fs_port\" missed";
check_user($sid);
my $sth=$dbh->prepare("update sessions set last_time=datetime('now','localtime'),status='R',
- client=? where session_id = ? and uname=?");
- $sth->execute($client, $sid, $realuser) or die;
+ client=?,gr_port=?,sound_port=?,fs_port=? where session_id = ? and uname=?");
+ $sth->execute($client, $gr_port, $sound_port, $fs_port, $sid, $realuser) or die;
$sth->finish();
}
diff --git a/x2goserver/sbin/x2godbadmin b/x2goserver/sbin/x2godbadmin
index 84dfc5d..fc86ca8 100755
--- a/x2goserver/sbin/x2godbadmin
+++ b/x2goserver/sbin/x2godbadmin
@@ -333,6 +333,9 @@ sub add_user()
$sth=$dbh->prepare("GRANT INSERT, UPDATE, DELETE ON sessions, used_ports, mounts TO \"x2gouser_$user\"");
$sth->execute();
+ $sth=$dbh->prepare("GRANT SELECT ON used_ports TO \"x2gouser_$user\"");
+ $sth->execute();
+
$sth=$dbh->prepare("GRANT SELECT, UPDATE, DELETE ON sessions_view, mounts_view, servers_view, ports_view TO \"x2gouser_$user\"");
$sth->execute();
$sth->finish();
@@ -455,7 +458,6 @@ sub create_tables()
");
$sth->execute() or die;
-
$sth=$dbh->prepare("
create or replace RULE insert_port_priv AS ON INSERT
TO used_ports where NEW.creator_id <> current_user and current_user <> '$x2goadmin'
hooks/post-receive
--
x2goserver.git (X2Go Server)
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "x2goserver.git" (X2Go Server).
More information about the x2go-commits
mailing list