Index: xpra/net/websocket.py
===================================================================
--- xpra/net/websocket.py	(revision 12705)
+++ xpra/net/websocket.py	(working copy)
@@ -30,6 +30,7 @@
         server = AdHocStruct()
         server.logger = log
         server.run_once = True
+        server.verbose = os.environ.get("XPRA_WEBSOCKIFY_DEBUG", "0")=="1"
         WebSocketRequestHandler.__init__(self, sock, addr, server)
 
     def new_websocket_client(self):
Index: xpra/scripts/config.py
===================================================================
--- xpra/scripts/config.py	(revision 12709)
+++ xpra/scripts/config.py	(working copy)
@@ -340,6 +340,8 @@
                     "speaker"           : str,
                     "sound-source"      : str,
                     "html"              : str,
+                    "ssl-cert"          : str,
+                    "ssl-key"           : str,
                     "socket-permissions": str,
                     "exec-wrapper"      : str,
                     "dbus-launch"       : str,
@@ -523,6 +525,8 @@
                     "input-method"      : "none",
                     "sound-source"      : "",
                     "html"              : "auto",
+                    "ssl-cert"          : "",
+                    "ssl-key"           : "",
                     "socket-permissions": "600",
                     "exec-wrapper"      : "",
                     "dbus-launch"       : "dbus-launch --close-stderr",
Index: xpra/scripts/main.py
===================================================================
--- xpra/scripts/main.py	(revision 12709)
+++ xpra/scripts/main.py	(working copy)
@@ -310,9 +310,21 @@
                           dest="html", default=defaults.html,
                           metavar="on|off|[HOST:]PORT",
                           help="Enable the web server and the html5 client. Default: '%default'.")
+        group.add_option("--ssl-cert", action="store",
+                          dest="ssl_cert", default=defaults.ssl_cert,
+                          metavar="/path/to/cert.pem",
+                          help="Certificate file to use for SSL traffic. Default: '%default'.")
+        group.add_option("--ssl-key", action="store",
+                          dest="ssl_key", default=defaults.ssl_key,
+                          metavar="/path/to/key.pem",
+                          help="Key file to use for SSL traffic. Default: '%default'.")
     else:
-        ignore({"tcp_proxy" : "",
-                "html"      : ""})
+        ignore({
+                "tcp_proxy" : "",
+                "html"      : "",
+                "ssl-cert"  : "",
+                "ssl-key"   : "",
+                })
     legacy_bool_parse("daemon")
     if (supports_server or supports_shadow) and CAN_DAEMONIZE:
         group.add_option("--daemon", action="store", metavar="yes|no",
Index: xpra/server/gtk_server_base.py
===================================================================
--- xpra/server/gtk_server_base.py	(revision 12705)
+++ xpra/server/gtk_server_base.py	(working copy)
@@ -66,7 +66,7 @@
         log("do_run() end of gtk.main()")
 
     def add_listen_socket(self, socktype, sock):
-        sock.listen(5)
+        sock.listen(100)
         glib.io_add_watch(sock, glib.IO_IN, self._new_connection, sock)
         self.socket_types[sock] = socktype
 
Index: xpra/server/server_core.py
===================================================================
--- xpra/server/server_core.py	(revision 12705)
+++ xpra/server/server_core.py	(working copy)
@@ -149,6 +149,8 @@
         self._tcp_proxy = ""
         self._html = False
         self._www_dir = None
+        self._ssl_cert = None
+        self._ssl_key = None
         self._aliases = {}
         self._reverse_aliases = {}
         self.socket_types = {}
@@ -206,6 +208,9 @@
         self.init_auth(opts)
 
     def init_html_proxy(self, opts):
+        self._ssl_cert = opts.ssl_cert
+        self._ssl_key = opts.ssl_key or self._ssl_cert
+
         self._tcp_proxy = opts.tcp_proxy
         #opts.html can contain a boolean, "auto" or the path to the webroot
         www_dir = None
@@ -509,6 +514,13 @@
             netlog.error("too many connections (%s), ignoring new one", len(self._potential_protocols))
             sock.close()
             return True
+
+        def threaded_accept():
+            self.accept_socket(socktype, sock, address)
+        make_thread(threaded_accept, "%s-%s" % (socktype, address), daemon=True).start()
+        return True
+
+    def accept_socket(self, socktype, sock, address):
         try:
             peername = sock.getpeername()
         except:
@@ -516,7 +528,7 @@
         sockname = sock.getsockname()
         target = peername or sockname
         sock.settimeout(self._socket_timeout)
-        netlog("new_connection(%s) sock=%s, timeout=%s, sockname=%s, address=%s, peername=%s", args, sock, self._socket_timeout, sockname, address, peername)
+        netlog("accept_socket(%s) timeout=%s, sockname=%s, peername=%s", (socktype, sock, address), self._socket_timeout, sockname, peername)
         conn = SocketConnection(sock, sockname, address, target, socktype)
         netlog("socket connection: %s", conn)
         if peername:
@@ -532,30 +544,51 @@
         if socktype=="tcp" and self._html or self._tcp_proxy:
             #see if the packet data is actually xpra or something else
             #that we need to handle via a tcp proxy or the websockify adapter:
-            conn._socket.settimeout(25)
+            sock.settimeout(5)
+            #sock.setblocking(True)
             v = conn.peek(128)
-            netlog("peek()=%s", nonl(v))
+            netlog("peek()=%s", repr_ellipsized(v))
             if v and v[0] not in ("P", ord("P")):
+                netlog("peek() first character=%s / %s", nonl(v[0]), hex(ord(v[0])))
+                #SSL?
+                ssl_sock = None
+                if v[0] in ("\x16", "\x80", 22, 128):
+                    netlog("peek() SSL traffic, trying cert=%s, key=%s", self._ssl_cert, self._ssl_key)
+                    if self._ssl_cert and self._ssl_key:
+                        try:
+                            import ssl
+                            ssl_sock = ssl.wrap_socket(sock, server_side=True, certfile=self._ssl_cert, keyfile=self._ssl_key)
+                            netlog("wrapped socket %s using SSL: %s", sock, ssl_sock)
+                            conn._socket = ssl_sock
+                            ssl_sock.settimeout(5)
+                            ssl_sock.do_handshake(False)
+                            v = conn.peek(128)
+                            netlog("handshake complete, ssl peek: %s", repr_ellipsized(v))
+                        except Exception as e:
+                            netlog.error("Error: cannot wrap SSL socket:")
+                            netlog.error(" %s", e)
+                            return
+                    else:
+                        log.warn("Warning: no SSL certificate configured, cannot parse this request")
+
                 if self._html:
-                    line1 = v.splitlines()[0]
-                    if line1.find("HTTP/")>0:
+                    line1 = ""
+                    if v:
+                        line1 = v.splitlines()[0]
+                    if line1.find("HTTP/")>0 or ssl_sock:
                         if line1.startswith("GET ") or line1.startswith("POST "):
                             parts = line1.split(" ")
-                            netlog.info("New http %s request received from %s for '%s'", parts[0], frominfo, parts[1])
-                            tname = "%s-request" % parts[0]
+                            netlog.info("New %s %s request received from %s for '%s'", ["http", "https"][ssl_sock is not None], parts[0], frominfo, parts[1])
                         else:
-                            netlog.info("New http connection received from %s", frominfo)
-                            tname = "websockify-proxy"
-                        def run_websockify():
-                            self.start_websockify(conn, frominfo)
-                        make_thread(run_websockify, "%s-for-%s" % (tname, frominfo), daemon=True).start()
-                        return True
+                            netlog.info("New %s connection received from %s", ["http", "https"][ssl_sock is not None], frominfo)
+                        self.start_websockify(conn, frominfo)
+                        return
                 elif self._tcp_proxy:
                     netlog.info("New tcp proxy connection received from %s", frominfo)
                     def run_proxy():
                         self.start_tcp_proxy(conn, frominfo)
                     make_thread(run_proxy, "tcp-proxy-for-%s" % frominfo, daemon=True).start()
-                    return True
+                    return
         else:
             v = conn.peek(128)
         netlog("%s.peek(128)=%s", conn, v)
@@ -570,9 +603,9 @@
                 conn.close()
             except Exception as e:
                 netlog("error sending '%s': %s", nonl(msg), e)
-            return True
+            return
         netlog.info(info_msg)
-        return self.make_protocol(socktype, conn, frominfo)
+        self.make_protocol(socktype, conn, frominfo)
 
     def make_protocol(self, socktype, conn, frominfo=""):
         protocol = Protocol(self, conn, self.process_packet)
@@ -601,7 +634,6 @@
             protocol.set_cipher_in(protocol.encryption, DEFAULT_IV, password, DEFAULT_SALT, DEFAULT_ITERATIONS, INITIAL_PADDING)
         protocol.start()
         self.timeout_add(SOCKET_TIMEOUT*1000, self.verify_connection_accepted, protocol)
-        return True
 
     def invalid_header(self, proto, data):
         netlog("invalid_header(%s, %s bytes: '%s') input_packetcount=%s, tcp_proxy=%s, html=%s", proto, len(data or ""), repr_ellipsized(data), proto.input_packetcount, self._tcp_proxy, self._html)
@@ -617,8 +649,8 @@
                 netlog("new_websocket_client(%s)", wsh)
                 wsc = WebSocketConnection(conn._socket, conn.local, conn.remote, conn.target, conn.info, wsh)
                 self.make_protocol("tcp", wsc, frominfo)
-            WSRequestHandler(conn._socket, frominfo, new_websocket_client, self._www_dir)
-            return
+            wsrh = WSRequestHandler(conn._socket, frominfo, new_websocket_client, self._www_dir)
+            netlog("WSRequestHandler=%s", wsrh)
         except IOError as e:
             netlog.error("Error: http failure responding to %s:", frominfo)
             netlog.error(" %s", e)
@@ -626,6 +658,10 @@
         except Exception as e:
             netlog.error("Error: http failure responding to %s:", frominfo, exc_info=True)
         try:
+            try:
+                conn._socket.shutdown(socket.SHUT_RDWR)
+            except Exception as ce:
+                netlog("error closing connection following error: %s", ce)            
             conn.close()
         except Exception as ce:
             netlog("error closing connection following error: %s", ce)
