Use the FQDN for xvm-remote instead of an unqualified name.
[invirt/scripts/vnc-client.git] / invirt-vnc-client
index a4a9570..63d3999 100755 (executable)
@@ -1,8 +1,8 @@
 #!/usr/bin/python
-from twisted.internet import reactor, ssl, protocol
+from twisted.internet import reactor, ssl, protocol, error
 from OpenSSL import SSL
 import base64, pickle
-import getopt, sys
+import getopt, sys, os, time
 
 verbose = False
 
@@ -10,7 +10,8 @@ def usage():
     print """%s [-v] [-l [HOST:]PORT] {-a AUTHTOKEN|VMNAME}
  -l, --listen [HOST:]PORT  port (and optionally host) to listen on for
                            connections (default is 127.0.0.1 and a randomly
-                           chosen port)
+                           chosen port). Use an empty HOST to listen on all
+                           interfaces (INSECURE!)
  -a, --authtoken AUTHTOKEN Authentication token for connecting to the VNC server
  VMNAME                    VM name to connect to (automatically fetches an
                            authentication token using remctl)
@@ -19,10 +20,13 @@ def usage():
 class ClientContextFactory(ssl.ClientContextFactory):
 
     def _verify(self, connection, x509, errnum, errdepth, ok):
-        print '_verify (ok=%d):' % ok
-        print '  subject:', x509.get_subject()
-        print '  issuer:', x509.get_issuer()
-        print '  errnum %s, errdepth %d' % (errnum, errdepth)
+        if verbose:
+            print '_verify (ok=%d):' % ok
+            print '  subject:', x509.get_subject()
+            print '  issuer:', x509.get_issuer()
+            print '  errnum %s, errdepth %d' % (errnum, errdepth)
+        if errnum == 10:
+            print 'The VNC server certificate has expired. Please contact xvm@mit.edu.'
         return ok
 
     def getContext(self):
@@ -59,16 +63,18 @@ class ProxyClient(Proxy):
         self.transport.write(data)
         if verbose: print "ProxyClient: connection made"
     def dataReceived(self, data):
-        if not ready:
+        if not self.ready:
             if verbose: print 'ProxyClient: received data "%s"' % data
             if data.startswith("VNCProxy/1.0 200 "):
-                ready = True
+                self.ready = True
                 if "\n" in data:
-                    self.peer.transport.write(data[data.find("\n")+1:])
+                    self.peer.transport.write(data[data.find("\n")+3:])
                 self.peer.transport.resumeProducing() # Allow reading
             else:
                 print "Failed to connect: %s" % data
                 self.transport.loseConnection()
+        else:
+            self.peer.transport.write(data)
 
 class ProxyClientFactory(protocol.ClientFactory):
     protocol = ProxyClient
@@ -136,8 +142,9 @@ def main():
         elif o in ("-l", "--listen"):
             if ":" in a:
                 listen = a.split(":", 2)
+                listen[1] = int(listen[1])
             else:
-                listen[1] = a
+                listen[1] = int(a)
         elif o in ("-a", "--authtoken"):
             authtoken = a
         else:
@@ -152,12 +159,12 @@ def main():
             sys.exit(2)
         from subprocess import PIPE, Popen
         try:
-            p = Popen(["remctl", "remote", "control", args[0], "vnctoken"],
+            p = Popen(["remctl", "xvm-remote.mit.edu", "control", args[0], "vnctoken"],
                       stdout=PIPE)
         except OSError:
             if verbose: print "remctl not found in path. Trying remctl locker."
             p = Popen(["athrun", "remctl", "remctl",
-                       "remote", "control", args[0], "vnctoken"],
+                       "xvm-remote.mit.edu", "control", args[0], "vnctoken"],
                       stdout=PIPE)
         authtoken = p.communicate()[0]
         if p.returncode != 0:
@@ -182,11 +189,21 @@ def main():
         sys.exit(1)
     
     if verbose: print "Will connect to %s:%s" % (connect_host, connect_port) 
+    if listen[1] is None:
+        listen[1] = 5900
+        ready = False
+        while not ready and listen[1] < 6000:
+            try:
+                reactor.listenTCP(listen[1], ProxyFactory(connect_host, connect_port, authtoken, machine), interface=listen[0])
+                ready = True
+            except error.CannotListenError:
+                listen[1] += 1
+    else:
+        reactor.listenTCP(listen[1], ProxyFactory(connect_host, connect_port, authtoken, machine))
     
-    listen[1] = 10003
-    reactor.listenTCP(listen[1], ProxyFactory(connect_host, connect_port, authtoken, machine))
-    
-    print "Ready to connect. Connect to %s:%s now with your VNC client. The password is 'moocow'." % (listen[0], listen[1])
+    print "Ready to connect. Connect to %s:%s (display %d) now with your VNC client. The password is 'moocow'." % (listen[0], listen[1], listen[1]-5900)
+    print "You must connect before your authentication token expires at %s." % \
+          (time.ctime(token_expires))
     
     reactor.run()