trayicon starts client rest server
authorOliver Maurhart <oliver.maurhart@ait.ac.at>
Wed, 30 Apr 2014 12:06:22 +0200
changeset 136ac117cd7bab1
parent 135 c9499f5166c7
child 137 a135e468b623
trayicon starts client rest server
.hgignore
OpenSecurity/bin/opensecurity_client_restful_server.py
OpenSecurity/bin/opensecurity_tray.pyw
     1.1 --- a/.hgignore	Tue Apr 29 15:40:48 2014 +0100
     1.2 +++ b/.hgignore	Wed Apr 30 12:06:22 2014 +0200
     1.3 @@ -4,6 +4,12 @@
     1.4  # no python compiles
     1.5  *.pyc
     1.6  
     1.7 +# no VIM swap files
     1.8 +*.swp
     1.9 +
    1.10 +# no VM image
    1.11 +*.ova
    1.12 +
    1.13  # no generated setup files
    1.14  OpenSecurity?Setup?*.exe
    1.15  OpenSecurity?Setup?Manifest.txt
     2.1 --- a/OpenSecurity/bin/opensecurity_client_restful_server.py	Tue Apr 29 15:40:48 2014 +0100
     2.2 +++ b/OpenSecurity/bin/opensecurity_client_restful_server.py	Wed Apr 30 12:06:22 2014 +0200
     2.3 @@ -35,6 +35,7 @@
     2.4  import json
     2.5  import os
     2.6  import os.path
     2.7 +import socket
     2.8  import subprocess
     2.9  import sys
    2.10  import urllib
    2.11 @@ -65,6 +66,14 @@
    2.12  
    2.13  
    2.14  # ------------------------------------------------------------
    2.15 +# vars
    2.16 +
    2.17 +
    2.18 +"""The REST server object"""
    2.19 +server = None
    2.20 +
    2.21 +
    2.22 +# ------------------------------------------------------------
    2.23  # code
    2.24  
    2.25  
    2.26 @@ -95,7 +104,7 @@
    2.27          process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)        
    2.28          
    2.29          # run process result handling in seprate thread (not to block main one)
    2.30 -        bouncer = UserResultBouncer(process, remote_ip, '/credentials')
    2.31 +        bouncer = ProcessResultBouncer(process, remote_ip, '/credentials')
    2.32          bouncer.start()
    2.33           
    2.34          return 'user queried for credentials'
    2.35 @@ -128,7 +137,7 @@
    2.36          process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)        
    2.37          
    2.38          # run process result handling in seprate thread (not to block main one)
    2.39 -        bouncer = UserResultBouncer(process, remote_ip, '/keyfile')
    2.40 +        bouncer = ProcessResultBouncer(process, remote_ip, '/keyfile')
    2.41          bouncer.start()
    2.42           
    2.43          return 'user queried for password and keyfile'
    2.44 @@ -193,7 +202,7 @@
    2.45          process = subprocess.Popen(process_command, shell = False, stdout = subprocess.PIPE)        
    2.46          
    2.47          # run process result handling in seprate thread (not to block main one)
    2.48 -        bouncer = UserResultBouncer(process, remote_ip, '/password')
    2.49 +        bouncer = ProcessResultBouncer(process, remote_ip, '/password')
    2.50          bouncer.start()
    2.51          
    2.52          return 'user queried for password'
    2.53 @@ -250,9 +259,9 @@
    2.54          return res
    2.55  
    2.56  
    2.57 -class UserResultBouncer(threading.Thread):
    2.58 +class ProcessResultBouncer(threading.Thread):
    2.59  
    2.60 -    """A class to spawn off user I/O waiting and push the data back to the requesting services."""
    2.61 +    """A class to post the result of a given process - assuming it to be in JSON - to a REST Api."""
    2.62  
    2.63      def __init__(self, process, remote_ip, resource): 
    2.64  
    2.65 @@ -299,8 +308,78 @@
    2.66              return 
    2.67  
    2.68  
    2.69 -# start
    2.70 -if __name__ == "__main__":
    2.71 +class RESTServerThread(threading.Thread):
    2.72 +
    2.73 +    """Thread for serving the REST API."""
    2.74 +
    2.75 +    def __init__(self, port): 
    2.76 +
    2.77 +        """ctor"""
    2.78 +        threading.Thread.__init__(self)
    2.79 +        self._port = port 
    2.80 +    
    2.81 +    def stop(self):
    2.82 +
    2.83 +        """stop thread"""
    2.84 +        self.running = False
    2.85 +        
    2.86 +    
    2.87 +    def run(self):
    2.88 +
    2.89 +        """run the thread"""
    2.90 +        _serve(self._port)
    2.91 +
    2.92 +
    2.93 +
    2.94 +def is_already_running(port = 8090):
    2.95 +
    2.96 +    """check if this is started twice"""
    2.97 +
    2.98 +    try:
    2.99 +        s = socket.create_connection(('127.0.0.1', port), 0.5)
   2.100 +    except:
   2.101 +        return False
   2.102 +
   2.103 +    return True
   2.104 +
   2.105 +
   2.106 +def _serve(port):
   2.107 +
   2.108 +    """Start the REST server"""
   2.109 +
   2.110 +    global server
   2.111 +
   2.112 +    # trick the web.py server 
   2.113 +    sys.argv = [__file__, str(port)]
   2.114      server = web.application(opensecurity_urls, globals())
   2.115      server.run()
   2.116  
   2.117 +
   2.118 +def serve(port = 8090, background = False):
   2.119 +
   2.120 +    """Start serving the REST Api
   2.121 +    port ... port number to listen on
   2.122 +    background ... cease into background (spawn thread) and return immediately"""
   2.123 +
   2.124 +    # start threaded or direct version
   2.125 +    if background == True:
   2.126 +        t = RESTServerThread(port)
   2.127 +        t.start()
   2.128 +    else:
   2.129 +        _serve(port)
   2.130 +
   2.131 +def stop():
   2.132 +
   2.133 +    """Stop serving the REST Api"""
   2.134 +
   2.135 +    global server
   2.136 +    if server is None:
   2.137 +        return
   2.138 +
   2.139 +    server.stop()
   2.140 +
   2.141 +
   2.142 +# start
   2.143 +if __name__ == "__main__":
   2.144 +    serve()
   2.145 +
     3.1 --- a/OpenSecurity/bin/opensecurity_tray.pyw	Tue Apr 29 15:40:48 2014 +0100
     3.2 +++ b/OpenSecurity/bin/opensecurity_tray.pyw	Wed Apr 30 12:06:22 2014 +0200
     3.3 @@ -45,6 +45,7 @@
     3.4  if sys.platform == 'win32' or sys.platform == 'cygwin':
     3.5      from cygwin import Cygwin
     3.6  
     3.7 +import opensecurity_client_restful_server 
     3.8  from ui import AboutDialog
     3.9  from ui import ConfigureDialog
    3.10  from ui import opensecurity_rc
    3.11 @@ -136,6 +137,7 @@
    3.12  
    3.13      def clicked_exit(self):
    3.14          """clicked exit"""
    3.15 +        opensecurity_client_restful_server.stop()
    3.16          sys.exit(0)
    3.17      
    3.18  
    3.19 @@ -186,16 +188,32 @@
    3.20          self.acAbout.triggered.connect(self.clicked_about)
    3.21          self.acExit.triggered.connect(self.clicked_exit)
    3.22          
    3.23 -        
    3.24 +
    3.25  def main():
    3.26      
    3.27 +    # parse arguments
    3.28 +    parser = argparse.ArgumentParser(description = 'OpenSecurity Tray Icon.')
    3.29 +    parser.add_argument('-p', '--port', type=int, default=8090, help='port number of the REST API this instance will listen on.')
    3.30 +    args = parser.parse_args()
    3.31 +
    3.32 +    # get up Qt
    3.33      a = QtGui.QApplication(sys.argv)
    3.34  
    3.35 +    # enforce singelton process
    3.36 +    if opensecurity_client_restful_server.is_already_running(args.port):
    3.37 +        QtGui.QMessageBox.critical(None, 'OpenSecurity Error', 'OpenSecurity Tray Instance already launched.\nClose previous instance first.')
    3.38 +        sys.exit(1)
    3.39 +
    3.40 +    # start serving
    3.41 +    opensecurity_client_restful_server.serve(args.port, True)
    3.42 +
    3.43 +    # init tray icon widget
    3.44      w = QtGui.QWidget()
    3.45      icon = QtGui.QIcon()
    3.46      icon.addPixmap(QtGui.QPixmap(QtCore.QString.fromUtf8(":/opensecurity/gfx/opensecurity_icon_64.png")), QtGui.QIcon.Normal, QtGui.QIcon.Off)
    3.47      trayIcon = OpenSecurityTrayIcon(icon)
    3.48  
    3.49 +    # go!
    3.50      trayIcon.show()
    3.51      a.setQuitOnLastWindowClosed(False)
    3.52      sys.exit(a.exec_())