From d473f4b6d16b5007eac9c6fbd6bed206c4c55965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20de=20Saint=20Martin?= Date: Fri, 24 Jun 2011 18:30:11 +0200 Subject: [PATCH 1/8] Use ipv6 socket when requested --- websocket.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/websocket.py b/websocket.py index 78e275a..c34d480 100755 --- a/websocket.py +++ b/websocket.py @@ -686,8 +686,12 @@ Sec-WebSocket-Accept: %s\r is a WebSockets client then call new_client() method (which must be overridden) for each new client connection. """ - - lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + + lsock = None + if self.ipv6: + socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + else: + socket.socket(socket.AF_INET6, socket.SOCK_STREAM) lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) lsock.bind((self.listen_host, self.listen_port)) lsock.listen(100) From 8ae73adbb75f994c14d97b6db85d36ef54ac0422 Mon Sep 17 00:00:00 2001 From: Algervivien Date: Fri, 24 Jun 2011 19:01:47 +0200 Subject: [PATCH 2/8] Corrected wrong INET type in else condition --- websocket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocket.py b/websocket.py index c34d480..71bff4f 100755 --- a/websocket.py +++ b/websocket.py @@ -691,7 +691,7 @@ Sec-WebSocket-Accept: %s\r if self.ipv6: socket.socket(socket.AF_INET6, socket.SOCK_STREAM) else: - socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + socket.socket(socket.AF_INET, socket.SOCK_STREAM) lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) lsock.bind((self.listen_host, self.listen_port)) lsock.listen(100) From 8d71c243b1ec1ef089f14b91efad82b18bf82a1d Mon Sep 17 00:00:00 2001 From: Algervivien Date: Mon, 27 Jun 2011 09:45:49 +0200 Subject: [PATCH 3/8] Modified parsing for ipv6 support --- websockify | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/websockify b/websockify index 34acecd..2e63fae 100755 --- a/websockify +++ b/websockify @@ -276,7 +276,7 @@ if __name__ == '__main__': # Parse host:port and convert ports to numbers if args[0].count(':') > 0: - opts.listen_host, opts.listen_port = args[0].split(':') + opts.listen_host, opts.listen_port = ":".join(args[0].split(':')[:len(args[0].split(':')) - 1]), args[0].split(':')[len(args[0].split(':')) - 1] else: opts.listen_host, opts.listen_port = '', args[0] try: opts.listen_port = int(opts.listen_port) @@ -287,7 +287,7 @@ if __name__ == '__main__': opts.target_port = None else: if args[1].count(':') > 0: - opts.target_host, opts.target_port = args[1].split(':') + opts.target_host, opts.target_port = ":".join(args[1].split(':')[:len(args[1].split(':')) - 1]), args[1].split(':')[len(args[1].split(':')) - 1] else: parser.error("Error parsing target") try: opts.target_port = int(opts.target_port) From a09d18b234f6ec3714c45233c70c7a09ff61ad32 Mon Sep 17 00:00:00 2001 From: Algervivien Date: Mon, 27 Jun 2011 10:21:20 +0200 Subject: [PATCH 4/8] Added ipv6 related attributes --- websockify | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/websockify b/websockify index 2e63fae..ced3906 100755 --- a/websockify +++ b/websockify @@ -279,15 +279,25 @@ if __name__ == '__main__': opts.listen_host, opts.listen_port = ":".join(args[0].split(':')[:len(args[0].split(':')) - 1]), args[0].split(':')[len(args[0].split(':')) - 1] else: opts.listen_host, opts.listen_port = '', args[0] + if opts.listen_host.count(':') > 0: + opts.source_is_ipv6 = True + else: + opts.source_is_ipv6 = False + try: opts.listen_port = int(opts.listen_port) except: parser.error("Error parsing listen port") - + if opts.wrap_cmd: opts.target_host = None opts.target_port = None else: if args[1].count(':') > 0: opts.target_host, opts.target_port = ":".join(args[1].split(':')[:len(args[1].split(':')) - 1]), args[1].split(':')[len(args[1].split(':')) - 1] + if opts.target_host.count(':') > 0: + opts.target_is_ipv6 = True + else: + opts.target_is_ipv6 = False + else: parser.error("Error parsing target") try: opts.target_port = int(opts.target_port) From eb62b2af6e1878237136adf3c820892288c894ae Mon Sep 17 00:00:00 2001 From: Algervivien Date: Mon, 27 Jun 2011 11:01:01 +0200 Subject: [PATCH 5/8] Added data attributes and ipv6 condition for target --- websocket.py | 22 +++++++++++----------- websockify | 14 +++++++++----- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/websocket.py b/websocket.py index 71bff4f..cd94fde 100755 --- a/websocket.py +++ b/websocket.py @@ -87,17 +87,18 @@ Sec-WebSocket-Accept: %s\r class EClose(Exception): pass - def __init__(self, listen_host='', listen_port=None, + def __init__(self, listen_host='', listen_port=None, source_is_ipv6=False, verbose=False, cert='', key='', ssl_only=None, daemon=False, record='', web=''): # settings - self.verbose = verbose - self.listen_host = listen_host - self.listen_port = listen_port - self.ssl_only = ssl_only - self.daemon = daemon - self.handler_id = 1 + self.verbose = verbose + self.listen_host = listen_host + self.listen_port = listen_port + self.source_is_ipv6 = source_is_ipv6 + self.ssl_only = ssl_only + self.daemon = daemon + self.handler_id = 1 # Make paths settings absolute self.cert = os.path.abspath(cert) @@ -687,11 +688,10 @@ Sec-WebSocket-Accept: %s\r be overridden) for each new client connection. """ - lsock = None - if self.ipv6: - socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + if self.source_is_ipv6: + lsock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) else: - socket.socket(socket.AF_INET, socket.SOCK_STREAM) + lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) lsock.bind((self.listen_host, self.listen_port)) lsock.listen(100) diff --git a/websockify b/websockify index ced3906..1204a4c 100755 --- a/websockify +++ b/websockify @@ -39,10 +39,11 @@ Traffic Legend: def __init__(self, *args, **kwargs): # Save off proxy specific options - self.target_host = kwargs.pop('target_host') - self.target_port = kwargs.pop('target_port') - self.wrap_cmd = kwargs.pop('wrap_cmd') - self.wrap_mode = kwargs.pop('wrap_mode') + self.target_host = kwargs.pop('target_host') + self.target_port = kwargs.pop('target_port') + self.target_is_ipv6 = kwargs.pop('target_is_ipv6') + self.wrap_cmd = kwargs.pop('wrap_cmd') + self.wrap_mode = kwargs.pop('wrap_mode') # Last 3 timestamps command was run self.wrap_times = [0, 0, 0] @@ -150,7 +151,10 @@ Traffic Legend: # Connect to the target self.msg("connecting to: %s:%s" % ( self.target_host, self.target_port)) - tsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + if self.target_is_ipv6: + tsock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + else: + tsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tsock.connect((self.target_host, self.target_port)) if self.verbose and not self.daemon: From 077279fe0fecbf9e216c65211388a110def693bf Mon Sep 17 00:00:00 2001 From: Algervivien Date: Mon, 27 Jun 2011 17:07:29 +0200 Subject: [PATCH 6/8] Refactoring of parsing --- websockify | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/websockify b/websockify index 1204a4c..126f7ec 100755 --- a/websockify +++ b/websockify @@ -280,7 +280,7 @@ if __name__ == '__main__': # Parse host:port and convert ports to numbers if args[0].count(':') > 0: - opts.listen_host, opts.listen_port = ":".join(args[0].split(':')[:len(args[0].split(':')) - 1]), args[0].split(':')[len(args[0].split(':')) - 1] + opts.listen_host, sep, opts.listen_port = args[0].rpartition(':') else: opts.listen_host, opts.listen_port = '', args[0] if opts.listen_host.count(':') > 0: @@ -296,7 +296,7 @@ if __name__ == '__main__': opts.target_port = None else: if args[1].count(':') > 0: - opts.target_host, opts.target_port = ":".join(args[1].split(':')[:len(args[1].split(':')) - 1]), args[1].split(':')[len(args[1].split(':')) - 1] + opts.target_host, sep, opts.target_port = args[1].rpartition(':') if opts.target_host.count(':') > 0: opts.target_is_ipv6 = True else: From 30681a701869b0d8431354184f1c5106eacdf5c2 Mon Sep 17 00:00:00 2001 From: Algervivien Date: Mon, 27 Jun 2011 18:49:01 +0200 Subject: [PATCH 7/8] Use of socket.getaddrinfo() to replace ipv6 attributes. Corrected error with ssl-only option --- websocket.py | 21 ++++++++++----------- websockify | 24 +++++++----------------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/websocket.py b/websocket.py index cd94fde..78fc586 100755 --- a/websocket.py +++ b/websocket.py @@ -95,7 +95,6 @@ Sec-WebSocket-Accept: %s\r self.verbose = verbose self.listen_host = listen_host self.listen_port = listen_port - self.source_is_ipv6 = source_is_ipv6 self.ssl_only = ssl_only self.daemon = daemon self.handler_id = 1 @@ -114,7 +113,7 @@ Sec-WebSocket-Accept: %s\r os.chdir(self.web) # Sanity checks - if ssl and self.ssl_only: + if not ssl and self.ssl_only: raise Exception("No 'ssl' module and SSL-only specified") if self.daemon and not resource: raise Exception("Module 'resource' required to daemonize") @@ -512,6 +511,7 @@ Sec-WebSocket-Accept: %s\r if not os.path.exists(self.cert): raise self.EClose("SSL connection but '%s' not found" % self.cert) + retsock = None try: retsock = ssl.wrap_socket( sock, @@ -687,15 +687,14 @@ Sec-WebSocket-Accept: %s\r is a WebSockets client then call new_client() method (which must be overridden) for each new client connection. """ - - if self.source_is_ipv6: - lsock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - else: - lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - lsock.bind((self.listen_host, self.listen_port)) - lsock.listen(100) - + for res in socket.getaddrinfo(self.listen_host, self.listen_port, 0, socket.SOCK_STREAM, 6): + af, socktype, proto, canonname, sa = res + lsock = socket.socket(af, socktype) + lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + lsock.bind((self.listen_host, self.listen_port)) + lsock.listen(100) + break + if self.daemon: self.daemonize(keepfd=lsock.fileno(), chdir=self.web) diff --git a/websockify b/websockify index 126f7ec..8d1fe0f 100755 --- a/websockify +++ b/websockify @@ -41,7 +41,6 @@ Traffic Legend: # Save off proxy specific options self.target_host = kwargs.pop('target_host') self.target_port = kwargs.pop('target_port') - self.target_is_ipv6 = kwargs.pop('target_is_ipv6') self.wrap_cmd = kwargs.pop('wrap_cmd') self.wrap_mode = kwargs.pop('wrap_mode') # Last 3 timestamps command was run @@ -151,12 +150,12 @@ Traffic Legend: # Connect to the target self.msg("connecting to: %s:%s" % ( self.target_host, self.target_port)) - if self.target_is_ipv6: - tsock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - else: - tsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - tsock.connect((self.target_host, self.target_port)) - + for res in socket.getaddrinfo(self.target_host, self.target_port, 0, socket.SOCK_STREAM, 6): + af, socktype, proto, canonname, sa = res + tsock = socket.socket(af, socktype) + tsock.connect((self.target_host, self.target_port)) + break + if self.verbose and not self.daemon: print(self.traffic_legend) @@ -283,11 +282,7 @@ if __name__ == '__main__': opts.listen_host, sep, opts.listen_port = args[0].rpartition(':') else: opts.listen_host, opts.listen_port = '', args[0] - if opts.listen_host.count(':') > 0: - opts.source_is_ipv6 = True - else: - opts.source_is_ipv6 = False - + try: opts.listen_port = int(opts.listen_port) except: parser.error("Error parsing listen port") @@ -297,11 +292,6 @@ if __name__ == '__main__': else: if args[1].count(':') > 0: opts.target_host, sep, opts.target_port = args[1].rpartition(':') - if opts.target_host.count(':') > 0: - opts.target_is_ipv6 = True - else: - opts.target_is_ipv6 = False - else: parser.error("Error parsing target") try: opts.target_port = int(opts.target_port) From 78697b966335e8481903e650dcc14dacac457d90 Mon Sep 17 00:00:00 2001 From: Vivien Alger Date: Wed, 29 Jun 2011 10:19:52 +0200 Subject: [PATCH 8/8] Added static method addrinfo() --- websocket.py | 25 +++++++++++++++++-------- websockify | 10 ++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/websocket.py b/websocket.py index 78fc586..f203c3e 100755 --- a/websocket.py +++ b/websocket.py @@ -140,6 +140,17 @@ Sec-WebSocket-Accept: %s\r # # WebSocketServer static methods # + + @staticmethod + def addrinfo(host, port=None): + """ Resolve a host (and optional port) to an IPv4 or IPv6 address. + Returns: family, socktype, proto, canonname, sockaddr + """ + addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM, socket.IPPROTO_TCP) + if not addrs: + raise Exception("Could resolve host '%s'" % self.target_host) + return addrs[0] + @staticmethod def daemonize(keepfd=None, chdir='/'): os.umask(0) @@ -687,14 +698,12 @@ Sec-WebSocket-Accept: %s\r is a WebSockets client then call new_client() method (which must be overridden) for each new client connection. """ - for res in socket.getaddrinfo(self.listen_host, self.listen_port, 0, socket.SOCK_STREAM, 6): - af, socktype, proto, canonname, sa = res - lsock = socket.socket(af, socktype) - lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - lsock.bind((self.listen_host, self.listen_port)) - lsock.listen(100) - break - + addr = WebSocketServer.addrinfo(self.listen_host, self.listen_port) + lsock = socket.socket(addr[0], addr[1]) + lsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + lsock.bind((self.listen_host, self.listen_port)) + lsock.listen(100) + if self.daemon: self.daemonize(keepfd=lsock.fileno(), chdir=self.web) diff --git a/websockify b/websockify index 8d1fe0f..a68bbe0 100755 --- a/websockify +++ b/websockify @@ -150,12 +150,10 @@ Traffic Legend: # Connect to the target self.msg("connecting to: %s:%s" % ( self.target_host, self.target_port)) - for res in socket.getaddrinfo(self.target_host, self.target_port, 0, socket.SOCK_STREAM, 6): - af, socktype, proto, canonname, sa = res - tsock = socket.socket(af, socktype) - tsock.connect((self.target_host, self.target_port)) - break - + addr = WebSocketServer.addrinfo(self.target_host, self.target_port) + tsock = socket.socket(addr[0], addr[1]) + tsock.connect((self.target_host, self.target_port)) + if self.verbose and not self.daemon: print(self.traffic_legend)