~kxteam/xts/xts-server-trunk

« back to all changes in this revision

Viewing changes to src/xpra-wrapper.in

  • Committer: Joshua Mark Higgins
  • Date: 2013-04-07 23:05:16 UTC
  • Revision ID: joshiggins@gmail.com-20130407230516-185y1czvr2299ov0
Started xpra-wrapper, implemented basic functionality of selecting a display/port number, generating random password to secure session, starting Xpra and a simple idle watchdog to terminate Xpra if no clients have been connected for a certain amount of time

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
xpra-wrapper
4
4
 
5
5
    A wrapper for xpra with automatic display and port
6
 
    selection and a cleanup watchdog
 
6
    selection and a *simple* cleanup watchdog, which may or may not
 
7
    have to be invoked using something like 'nohup' to prevent it being killed
 
8
    if started through a remote session which subsequently terminates...
7
9
 
8
10
Copyright 2012 Joshua Higgins
9
11
 
26
28
 
27
29
import sys
28
30
sys.path.insert(1, '@pythondir@')
 
31
 
 
32
 
 
33
import os
 
34
import optparse
 
35
import socket
 
36
import random
 
37
import string
 
38
import subprocess
 
39
import time
 
40
 
 
41
 
 
42
class XpraWrapper:
 
43
    
 
44
    def __init__(self, opts):
 
45
        self.OPTS = opts
 
46
        self.run()
 
47
 
 
48
    def run(self):
 
49
        # select port, we also use this as the X display number
 
50
        self.port = self._get_open_port()
 
51
        # generate a random password to secure the Xpra session
 
52
        self._generate_xpra_password()
 
53
        # start xpra
 
54
        self._start_xpra()
 
55
        # start watchdog if applicable
 
56
        if self.OPTS.WATCHDOG:
 
57
            self._loop_cleanup_watchdog()
 
58
    
 
59
    def _get_open_port(self):
 
60
        if self.OPTS.IPV6:
 
61
            self.bindaddr = "[::]"
 
62
            s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
 
63
        else:
 
64
            self.bindaddr = "0.0.0.0"
 
65
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
66
        s.bind(("",0))
 
67
        s.listen(1)
 
68
        port = s.getsockname()[1]
 
69
        s.close()
 
70
        return port
 
71
 
 
72
    def _generate_xpra_password(self):
 
73
        word = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(64))
 
74
        f = open(os.path.expanduser("~/.xpra/xts-pass"), "w")
 
75
        f.write(word)
 
76
        f.close()
 
77
 
 
78
    def _start_xpra(self):
 
79
        xpra_cmd = 'xpra start :' \
 
80
            + str(self.port) \
 
81
            + ' --password-file="' + os.path.expanduser("~/.xpra/xts-pass") + '"'
 
82
        if self.OPTS.BIND:
 
83
            xpra_cmd = xpra_cmd + ' --bind-tcp="' + self.bindaddr + ':' + str(self.port) + '"'
 
84
        os.popen(xpra_cmd)
 
85
        time.sleep(2)
 
86
 
 
87
    def _loop_cleanup_watchdog(self):
 
88
        print "starting watchdog, xpra-wrapper will remain in foreground"
 
89
        idle = 0
 
90
        stop_cmd = 'xpra stop :' \
 
91
            + str(self.port) \
 
92
            + ' --password-file="' + os.path.expanduser("~/.xpra/xts-pass") + '"'
 
93
        info_cmd = "xpra info :" + str(self.port) \
 
94
            + ' --password-file="' + os.path.expanduser("~/.xpra/xts-pass") + '"' \
 
95
            + " | grep clients | head -n 1 | awk -F'=' '{print $2}'"
 
96
        while True:
 
97
            p = subprocess.Popen(info_cmd, shell=True, stdout=subprocess.PIPE)
 
98
            out = int(p.communicate()[0])
 
99
            if out > 0:
 
100
                idle = 0
 
101
                print "client is connected"
 
102
            else:
 
103
                idle = idle + 1
 
104
                print "client idle for", idle
 
105
                if idle >= self.OPTS.TIMEOUT:
 
106
                    subprocess.Popen(stop_cmd, shell=True).wait()
 
107
                    print "reached timeout, Xpra stopped"
 
108
                    raise SystemExit()
 
109
            time.sleep(1)
 
110
 
 
111
 
 
112
if __name__ == "__main__":
 
113
    parser = optparse.OptionParser()
 
114
    parser.add_option('-b', '--bind', help="Bind Xpra to a TCP port", default=False, action='store_true', dest='BIND')
 
115
    parser.add_option('-6', '--ipv6', help="Enable IPv6", default=False, action='store_true', dest='IPV6')
 
116
    parser.add_option('-w', '--watchdog', help="Enable cleanup watchdog", default=False, action='store_true', dest='WATCHDOG')
 
117
    parser.add_option("-t", "--timeout", help="Number of seconds after which the watchdog will stop Xpra if no client is connected, default is 30", metavar="SECONDS", type="int", default=30, dest='TIMEOUT')
 
118
    (opts, args) = parser.parse_args()
 
119
    w = XpraWrapper(opts)
 
 
b'\\ No newline at end of file'