We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
webapp remote-connection create fails if specifying --port on version 0.2.7
### Extension name (the extension in question)
webapp

### Description of issue (in as much detail as possible)
The following command will fail when specifying --port after updating to version 0.2.7. Works fine in 0.2.6.
```
webapp remote-connection create --resource-group rg --name name --port xxx 
```
with the following message:
```
connect_ex() takes exactly one argument (2 given)
Traceback (most recent call last):
  File "C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\Lib\site-packages\knack\cli.py", line 197, in invoke
    cmd_result = self.invocation.execute(args)
  File "C:\Users\troyd\AppData\Local\Temp\pip-install-_jje8pgf\azure-cli-core\azure\cli\core\commands\__init__.py", line 369, in execute
  File "C:\Program Files (x86)\Microsoft SDKs\Azure\CLI2\Lib\site-packages\six.py", line 693, in reraise
    raise value
  File "C:\Users\troyd\AppData\Local\Temp\pip-install-_jje8pgf\azure-cli-core\azure\cli\core\commands\__init__.py", line 343, in execute
  File "C:\Users\troyd\AppData\Local\Temp\pip-install-_jje8pgf\azure-cli-core\azure\cli\core\commands\__init__.py", line 182, in __call__
  File "C:\Users\troyd\AppData\Local\Temp\pip-install-_jje8pgf\azure-cli-core\azure\cli\core\__init__.py", line 436, in default_command_handler
  File "C:\Users\xxx\.azure\cliextensions\webapp\azext_webapp\custom.py", line 254, in create_tunnel
    tunnel_server = TunnelServer('', port, host_name, user_name, user_password)
  File "C:\Users\xxx\.azure\cliextensions\webapp\azext_webapp\tunnel.py", line 42, in __init__
    if self.local_port != 0 and not self.is_port_open():
  File "C:\Users\xxx\.azure\cliextensions\webapp\azext_webapp\tunnel.py", line 69, in is_port_open
    if sock.connect_ex('', self.local_port) == 0:
TypeError: connect_ex() takes exactly one argument (2 given)
```
-----



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/webapp/azext_webapp/tunnel.py`
Content:
```
1 # --------------------------------------------------------------------------------------------
2 # Copyright (c) Microsoft Corporation. All rights reserved.
3 # Licensed under the MIT License. See License.txt in the project root for license information.
4 # --------------------------------------------------------------------------------------------
5 
6 # pylint: disable=import-error,unused-import
7 import sys
8 import ssl
9 import socket
10 import time
11 import traceback
12 import logging as logs
13 from contextlib import closing
14 from datetime import datetime
15 from threading import Thread
16 
17 import websocket
18 from websocket import create_connection, WebSocket
19 
20 from knack.util import CLIError
21 from knack.log import get_logger
22 logger = get_logger(__name__)
23 
24 
25 class TunnelWebSocket(WebSocket):
26     def recv_frame(self):
27         frame = super(TunnelWebSocket, self).recv_frame()
28         logger.info('Received frame: %s', frame)
29         return frame
30 
31     def recv(self):
32         data = super(TunnelWebSocket, self).recv()
33         logger.info('Received websocket data: %s', data)
34         return data
35 
36 
37 # pylint: disable=no-member,too-many-instance-attributes,bare-except,no-self-use
38 class TunnelServer(object):
39     def __init__(self, local_addr, local_port, remote_addr, remote_user_name, remote_password):
40         self.local_addr = local_addr
41         self.local_port = local_port
42         if self.local_port != 0 and not self.is_port_open():
43             raise CLIError('Defined port is currently unavailable')
44         self.remote_addr = remote_addr
45         self.remote_user_name = remote_user_name
46         self.remote_password = remote_password
47         self.client = None
48         self.ws = None
49         logger.info('Creating a socket on port: %s', self.local_port)
50         self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
51         logger.info('Setting socket options')
52         self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
53         logger.info('Binding to socket on local address and port')
54         self.sock.bind((self.local_addr, self.local_port))
55         if self.local_port == 0:
56             self.local_port = self.sock.getsockname()[1]
57             logger.warning('Auto-selecting port: %s', self.local_port)
58         logger.info('Finished initialization')
59 
60     def create_basic_auth(self):
61         from base64 import b64encode
62         basic_auth_string = '{}:{}'.format(self.remote_user_name, self.remote_password).encode()
63         basic_auth_string = b64encode(basic_auth_string).decode('utf-8')
64         return basic_auth_string
65 
66     def is_port_open(self):
67         is_port_open = False
68         with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
69             if sock.connect_ex('', self.local_port) == 0:
70                 logger.info('Port %s is NOT open', self.local_port)
71             else:
72                 logger.warning('Port %s is open', self.local_port)
73                 is_port_open = True
74             return is_port_open
75 
76     def is_port_set_to_default(self):
77         import certifi
78         import urllib3
79         try:
80             import urllib3.contrib.pyopenssl
81             urllib3.contrib.pyopenssl.inject_into_urllib3()
82         except ImportError:
83             pass
84 
85         http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
86         headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(self.remote_user_name, self.remote_password))
87         url = 'https://{}{}'.format(self.remote_addr, '.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx?GetStatus')
88         r = http.request(
89             'GET',
90             url,
91             headers=headers,
92             preload_content=False
93         )
94         if r.status != 200:
95             raise CLIError("Failed to connect to '{}' with status code '{}' and reason '{}'".format(
96                 url, r.status, r.reason))
97         msg = r.read().decode('utf-8')
98         logger.info('Status response message: %s', msg)
99         if 'FAIL' in msg.upper():
100             logger.warning('WARNING - Remote debugging may not be setup properly. Reponse content: %s', msg)
101         if '2222' in msg:
102             return True
103         return False
104 
105     def _listen(self):
106         self.sock.listen(100)
107         index = 0
108         basic_auth_string = self.create_basic_auth()
109         while True:
110             self.client, _address = self.sock.accept()
111             self.client.settimeout(1800)
112             host = 'wss://{}{}'.format(self.remote_addr, '.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx')
113             basic_auth_header = 'Authorization: Basic {}'.format(basic_auth_string)
114             cli_logger = get_logger()  # get CLI logger which has the level set through command lines
115             is_verbose = any(handler.level <= logs.INFO for handler in cli_logger.handlers)
116             if is_verbose:
117                 logger.info('Websocket tracing enabled')
118                 websocket.enableTrace(True)
119             else:
120                 logger.warning('Websocket tracing disabled, use --verbose flag to enable')
121                 websocket.enableTrace(False)
122             self.ws = create_connection(host,
123                                         sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),),
124                                         class_=TunnelWebSocket,
125                                         header=[basic_auth_header],
126                                         sslopt={'cert_reqs': ssl.CERT_NONE},
127                                         enable_multithread=True)
128             logger.info('Websocket, connected status: %s', self.ws.connected)
129             index = index + 1
130             logger.info('Got debugger connection... index: %s', index)
131             debugger_thread = Thread(target=self._listen_to_client, args=(self.client, self.ws, index))
132             web_socket_thread = Thread(target=self._listen_to_web_socket, args=(self.client, self.ws, index))
133             debugger_thread.start()
134             web_socket_thread.start()
135             logger.info('Both debugger and websocket threads started...')
136             logger.warning('Successfully connected to local server..')
137             debugger_thread.join()
138             web_socket_thread.join()
139             logger.info('Both debugger and websocket threads stopped...')
140             logger.warning('Stopped local server..')
141 
142     def _listen_to_web_socket(self, client, ws_socket, index):
143         while True:
144             try:
145                 logger.info('Waiting for websocket data, connection status: %s, index: %s', ws_socket.connected, index)
146                 data = ws_socket.recv()
147                 logger.info('Received websocket data: %s, index: %s', data, index)
148                 if data:
149                     # Set the response to echo back the recieved data
150                     response = data
151                     logger.info('Sending to debugger, response: %s, index: %s', response, index)
152                     client.sendall(response)
153                     logger.info('Done sending to debugger, index: %s', index)
154                 else:
155                     logger.info('Client disconnected!, index: %s', index)
156                     client.close()
157                     ws_socket.close()
158                     break
159             except:
160                 traceback.print_exc(file=sys.stdout)
161                 client.close()
162                 ws_socket.close()
163                 return False
164 
165     def _listen_to_client(self, client, ws_socket, index):
166         while True:
167             try:
168                 logger.info('Waiting for debugger data, index: %s', index)
169                 buf = bytearray(4096)
170                 nbytes = client.recv_into(buf, 4096)
171                 logger.info('Received debugger data, nbytes: %s, index: %s', nbytes, index)
172                 if nbytes > 0:
173                     responseData = buf[0:nbytes]
174                     logger.info('Sending to websocket, response data: %s, index: %s', responseData, index)
175                     ws_socket.send_binary(responseData)
176                     logger.info('Done sending to websocket, index: %s', index)
177                 else:
178                     logger.warn('Client disconnected %s', index)
179                     client.close()
180                     ws_socket.close()
181                     break
182             except:
183                 traceback.print_exc(file=sys.stdout)
184                 client.close()
185                 ws_socket.close()
186                 return False
187 
188     def start_server(self):
189         logger.warning('Start your favorite client and connect to port %s', self.local_port)
190         self._listen()
191
```

Path: `src/webapp/setup.py`
Content:
```
1 #!/usr/bin/env python
2 
3 # --------------------------------------------------------------------------------------------
4 # Copyright (c) Microsoft Corporation. All rights reserved.
5 # Licensed under the MIT License. See License.txt in the project root for license information.
6 # --------------------------------------------------------------------------------------------
7 
8 from codecs import open
9 from setuptools import setup, find_packages
10 
11 VERSION = "0.2.9"
12 
13 CLASSIFIERS = [
14     'Development Status :: 4 - Beta',
15     'Intended Audience :: Developers',
16     'Intended Audience :: System Administrators',
17     'Programming Language :: Python',
18     'Programming Language :: Python :: 2',
19     'Programming Language :: Python :: 2.7',
20     'Programming Language :: Python :: 3',
21     'Programming Language :: Python :: 3.4',
22     'Programming Language :: Python :: 3.5',
23     'Programming Language :: Python :: 3.6',
24     'License :: OSI Approved :: MIT License',
25 ]
26 
27 DEPENDENCIES = []
28 
29 setup(
30     name='webapp',
31     version=VERSION,
32     description='Additional commands for Azure AppService.',
33     long_description='An Azure CLI Extension to manage appservice resources',
34     license='MIT',
35     author='Sisira Panchagnula',
36     author_email='sisirap@microsoft.com',
37     url='https://github.com/Azure/azure-cli-extensions',
38     classifiers=CLASSIFIERS,
39     package_data={'azext_webapp': ['azext_metadata.json']},
40     packages=find_packages(exclude=["tests"]),
41     install_requires=DEPENDENCIES
42 )
43
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/webapp/azext_webapp/tunnel.py b/src/webapp/azext_webapp/tunnel.py
--- a/src/webapp/azext_webapp/tunnel.py
+++ b/src/webapp/azext_webapp/tunnel.py
@@ -66,7 +66,7 @@
     def is_port_open(self):
         is_port_open = False
         with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
-            if sock.connect_ex('', self.local_port) == 0:
+            if sock.connect_ex(('', self.local_port)) == 0:
                 logger.info('Port %s is NOT open', self.local_port)
             else:
                 logger.warning('Port %s is open', self.local_port)
diff --git a/src/webapp/setup.py b/src/webapp/setup.py
--- a/src/webapp/setup.py
+++ b/src/webapp/setup.py
@@ -8,7 +8,7 @@
 from codecs import open
 from setuptools import setup, find_packages
 
-VERSION = "0.2.9"
+VERSION = "0.2.10"
 
 CLASSIFIERS = [
     'Development Status :: 4 - Beta',

{"golden_diff": "diff --git a/src/webapp/azext_webapp/tunnel.py b/src/webapp/azext_webapp/tunnel.py\n--- a/src/webapp/azext_webapp/tunnel.py\n+++ b/src/webapp/azext_webapp/tunnel.py\n@@ -66,7 +66,7 @@\n     def is_port_open(self):\n         is_port_open = False\n         with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:\n-            if sock.connect_ex('', self.local_port) == 0:\n+            if sock.connect_ex(('', self.local_port)) == 0:\n                 logger.info('Port %s is NOT open', self.local_port)\n             else:\n                 logger.warning('Port %s is open', self.local_port)\ndiff --git a/src/webapp/setup.py b/src/webapp/setup.py\n--- a/src/webapp/setup.py\n+++ b/src/webapp/setup.py\n@@ -8,7 +8,7 @@\n from codecs import open\n from setuptools import setup, find_packages\n \n-VERSION = \"0.2.9\"\n+VERSION = \"0.2.10\"\n \n CLASSIFIERS = [\n     'Development Status :: 4 - Beta',\n", "issue": "webapp remote-connection create fails if specifying --port on version 0.2.7\n### Extension name (the extension in question)\r\nwebapp\r\n\r\n### Description of issue (in as much detail as possible)\r\nThe following command will fail when specifying --port after updating to version 0.2.7. Works fine in 0.2.6.\r\n```\r\nwebapp remote-connection create --resource-group rg --name name --port xxx \r\n```\r\nwith the following message:\r\n```\r\nconnect_ex() takes exactly one argument (2 given)\r\nTraceback (most recent call last):\r\n  File \"C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\CLI2\\Lib\\site-packages\\knack\\cli.py\", line 197, in invoke\r\n    cmd_result = self.invocation.execute(args)\r\n  File \"C:\\Users\\troyd\\AppData\\Local\\Temp\\pip-install-_jje8pgf\\azure-cli-core\\azure\\cli\\core\\commands\\__init__.py\", line 369, in execute\r\n  File \"C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\CLI2\\Lib\\site-packages\\six.py\", line 693, in reraise\r\n    raise value\r\n  File \"C:\\Users\\troyd\\AppData\\Local\\Temp\\pip-install-_jje8pgf\\azure-cli-core\\azure\\cli\\core\\commands\\__init__.py\", line 343, in execute\r\n  File \"C:\\Users\\troyd\\AppData\\Local\\Temp\\pip-install-_jje8pgf\\azure-cli-core\\azure\\cli\\core\\commands\\__init__.py\", line 182, in __call__\r\n  File \"C:\\Users\\troyd\\AppData\\Local\\Temp\\pip-install-_jje8pgf\\azure-cli-core\\azure\\cli\\core\\__init__.py\", line 436, in default_command_handler\r\n  File \"C:\\Users\\xxx\\.azure\\cliextensions\\webapp\\azext_webapp\\custom.py\", line 254, in create_tunnel\r\n    tunnel_server = TunnelServer('', port, host_name, user_name, user_password)\r\n  File \"C:\\Users\\xxx\\.azure\\cliextensions\\webapp\\azext_webapp\\tunnel.py\", line 42, in __init__\r\n    if self.local_port != 0 and not self.is_port_open():\r\n  File \"C:\\Users\\xxx\\.azure\\cliextensions\\webapp\\azext_webapp\\tunnel.py\", line 69, in is_port_open\r\n    if sock.connect_ex('', self.local_port) == 0:\r\nTypeError: connect_ex() takes exactly one argument (2 given)\r\n```\r\n-----\r\n\r\n\n", "before_files": [{"content": "# --------------------------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. See License.txt in the project root for license information.\n# --------------------------------------------------------------------------------------------\n\n# pylint: disable=import-error,unused-import\nimport sys\nimport ssl\nimport socket\nimport time\nimport traceback\nimport logging as logs\nfrom contextlib import closing\nfrom datetime import datetime\nfrom threading import Thread\n\nimport websocket\nfrom websocket import create_connection, WebSocket\n\nfrom knack.util import CLIError\nfrom knack.log import get_logger\nlogger = get_logger(__name__)\n\n\nclass TunnelWebSocket(WebSocket):\n    def recv_frame(self):\n        frame = super(TunnelWebSocket, self).recv_frame()\n        logger.info('Received frame: %s', frame)\n        return frame\n\n    def recv(self):\n        data = super(TunnelWebSocket, self).recv()\n        logger.info('Received websocket data: %s', data)\n        return data\n\n\n# pylint: disable=no-member,too-many-instance-attributes,bare-except,no-self-use\nclass TunnelServer(object):\n    def __init__(self, local_addr, local_port, remote_addr, remote_user_name, remote_password):\n        self.local_addr = local_addr\n        self.local_port = local_port\n        if self.local_port != 0 and not self.is_port_open():\n            raise CLIError('Defined port is currently unavailable')\n        self.remote_addr = remote_addr\n        self.remote_user_name = remote_user_name\n        self.remote_password = remote_password\n        self.client = None\n        self.ws = None\n        logger.info('Creating a socket on port: %s', self.local_port)\n        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        logger.info('Setting socket options')\n        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        logger.info('Binding to socket on local address and port')\n        self.sock.bind((self.local_addr, self.local_port))\n        if self.local_port == 0:\n            self.local_port = self.sock.getsockname()[1]\n            logger.warning('Auto-selecting port: %s', self.local_port)\n        logger.info('Finished initialization')\n\n    def create_basic_auth(self):\n        from base64 import b64encode\n        basic_auth_string = '{}:{}'.format(self.remote_user_name, self.remote_password).encode()\n        basic_auth_string = b64encode(basic_auth_string).decode('utf-8')\n        return basic_auth_string\n\n    def is_port_open(self):\n        is_port_open = False\n        with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:\n            if sock.connect_ex('', self.local_port) == 0:\n                logger.info('Port %s is NOT open', self.local_port)\n            else:\n                logger.warning('Port %s is open', self.local_port)\n                is_port_open = True\n            return is_port_open\n\n    def is_port_set_to_default(self):\n        import certifi\n        import urllib3\n        try:\n            import urllib3.contrib.pyopenssl\n            urllib3.contrib.pyopenssl.inject_into_urllib3()\n        except ImportError:\n            pass\n\n        http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())\n        headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(self.remote_user_name, self.remote_password))\n        url = 'https://{}{}'.format(self.remote_addr, '.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx?GetStatus')\n        r = http.request(\n            'GET',\n            url,\n            headers=headers,\n            preload_content=False\n        )\n        if r.status != 200:\n            raise CLIError(\"Failed to connect to '{}' with status code '{}' and reason '{}'\".format(\n                url, r.status, r.reason))\n        msg = r.read().decode('utf-8')\n        logger.info('Status response message: %s', msg)\n        if 'FAIL' in msg.upper():\n            logger.warning('WARNING - Remote debugging may not be setup properly. Reponse content: %s', msg)\n        if '2222' in msg:\n            return True\n        return False\n\n    def _listen(self):\n        self.sock.listen(100)\n        index = 0\n        basic_auth_string = self.create_basic_auth()\n        while True:\n            self.client, _address = self.sock.accept()\n            self.client.settimeout(1800)\n            host = 'wss://{}{}'.format(self.remote_addr, '.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx')\n            basic_auth_header = 'Authorization: Basic {}'.format(basic_auth_string)\n            cli_logger = get_logger()  # get CLI logger which has the level set through command lines\n            is_verbose = any(handler.level <= logs.INFO for handler in cli_logger.handlers)\n            if is_verbose:\n                logger.info('Websocket tracing enabled')\n                websocket.enableTrace(True)\n            else:\n                logger.warning('Websocket tracing disabled, use --verbose flag to enable')\n                websocket.enableTrace(False)\n            self.ws = create_connection(host,\n                                        sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),),\n                                        class_=TunnelWebSocket,\n                                        header=[basic_auth_header],\n                                        sslopt={'cert_reqs': ssl.CERT_NONE},\n                                        enable_multithread=True)\n            logger.info('Websocket, connected status: %s', self.ws.connected)\n            index = index + 1\n            logger.info('Got debugger connection... index: %s', index)\n            debugger_thread = Thread(target=self._listen_to_client, args=(self.client, self.ws, index))\n            web_socket_thread = Thread(target=self._listen_to_web_socket, args=(self.client, self.ws, index))\n            debugger_thread.start()\n            web_socket_thread.start()\n            logger.info('Both debugger and websocket threads started...')\n            logger.warning('Successfully connected to local server..')\n            debugger_thread.join()\n            web_socket_thread.join()\n            logger.info('Both debugger and websocket threads stopped...')\n            logger.warning('Stopped local server..')\n\n    def _listen_to_web_socket(self, client, ws_socket, index):\n        while True:\n            try:\n                logger.info('Waiting for websocket data, connection status: %s, index: %s', ws_socket.connected, index)\n                data = ws_socket.recv()\n                logger.info('Received websocket data: %s, index: %s', data, index)\n                if data:\n                    # Set the response to echo back the recieved data\n                    response = data\n                    logger.info('Sending to debugger, response: %s, index: %s', response, index)\n                    client.sendall(response)\n                    logger.info('Done sending to debugger, index: %s', index)\n                else:\n                    logger.info('Client disconnected!, index: %s', index)\n                    client.close()\n                    ws_socket.close()\n                    break\n            except:\n                traceback.print_exc(file=sys.stdout)\n                client.close()\n                ws_socket.close()\n                return False\n\n    def _listen_to_client(self, client, ws_socket, index):\n        while True:\n            try:\n                logger.info('Waiting for debugger data, index: %s', index)\n                buf = bytearray(4096)\n                nbytes = client.recv_into(buf, 4096)\n                logger.info('Received debugger data, nbytes: %s, index: %s', nbytes, index)\n                if nbytes > 0:\n                    responseData = buf[0:nbytes]\n                    logger.info('Sending to websocket, response data: %s, index: %s', responseData, index)\n                    ws_socket.send_binary(responseData)\n                    logger.info('Done sending to websocket, index: %s', index)\n                else:\n                    logger.warn('Client disconnected %s', index)\n                    client.close()\n                    ws_socket.close()\n                    break\n            except:\n                traceback.print_exc(file=sys.stdout)\n                client.close()\n                ws_socket.close()\n                return False\n\n    def start_server(self):\n        logger.warning('Start your favorite client and connect to port %s', self.local_port)\n        self._listen()\n", "path": "src/webapp/azext_webapp/tunnel.py"}, {"content": "#!/usr/bin/env python\n\n# --------------------------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. See License.txt in the project root for license information.\n# --------------------------------------------------------------------------------------------\n\nfrom codecs import open\nfrom setuptools import setup, find_packages\n\nVERSION = \"0.2.9\"\n\nCLASSIFIERS = [\n    'Development Status :: 4 - Beta',\n    'Intended Audience :: Developers',\n    'Intended Audience :: System Administrators',\n    'Programming Language :: Python',\n    'Programming Language :: Python :: 2',\n    'Programming Language :: Python :: 2.7',\n    'Programming Language :: Python :: 3',\n    'Programming Language :: Python :: 3.4',\n    'Programming Language :: Python :: 3.5',\n    'Programming Language :: Python :: 3.6',\n    'License :: OSI Approved :: MIT License',\n]\n\nDEPENDENCIES = []\n\nsetup(\n    name='webapp',\n    version=VERSION,\n    description='Additional commands for Azure AppService.',\n    long_description='An Azure CLI Extension to manage appservice resources',\n    license='MIT',\n    author='Sisira Panchagnula',\n    author_email='sisirap@microsoft.com',\n    url='https://github.com/Azure/azure-cli-extensions',\n    classifiers=CLASSIFIERS,\n    package_data={'azext_webapp': ['azext_metadata.json']},\n    packages=find_packages(exclude=[\"tests\"]),\n    install_requires=DEPENDENCIES\n)\n", "path": "src/webapp/setup.py"}], "after_files": [{"content": "# --------------------------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. See License.txt in the project root for license information.\n# --------------------------------------------------------------------------------------------\n\n# pylint: disable=import-error,unused-import\nimport sys\nimport ssl\nimport socket\nimport time\nimport traceback\nimport logging as logs\nfrom contextlib import closing\nfrom datetime import datetime\nfrom threading import Thread\n\nimport websocket\nfrom websocket import create_connection, WebSocket\n\nfrom knack.util import CLIError\nfrom knack.log import get_logger\nlogger = get_logger(__name__)\n\n\nclass TunnelWebSocket(WebSocket):\n    def recv_frame(self):\n        frame = super(TunnelWebSocket, self).recv_frame()\n        logger.info('Received frame: %s', frame)\n        return frame\n\n    def recv(self):\n        data = super(TunnelWebSocket, self).recv()\n        logger.info('Received websocket data: %s', data)\n        return data\n\n\n# pylint: disable=no-member,too-many-instance-attributes,bare-except,no-self-use\nclass TunnelServer(object):\n    def __init__(self, local_addr, local_port, remote_addr, remote_user_name, remote_password):\n        self.local_addr = local_addr\n        self.local_port = local_port\n        if self.local_port != 0 and not self.is_port_open():\n            raise CLIError('Defined port is currently unavailable')\n        self.remote_addr = remote_addr\n        self.remote_user_name = remote_user_name\n        self.remote_password = remote_password\n        self.client = None\n        self.ws = None\n        logger.info('Creating a socket on port: %s', self.local_port)\n        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        logger.info('Setting socket options')\n        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        logger.info('Binding to socket on local address and port')\n        self.sock.bind((self.local_addr, self.local_port))\n        if self.local_port == 0:\n            self.local_port = self.sock.getsockname()[1]\n            logger.warning('Auto-selecting port: %s', self.local_port)\n        logger.info('Finished initialization')\n\n    def create_basic_auth(self):\n        from base64 import b64encode\n        basic_auth_string = '{}:{}'.format(self.remote_user_name, self.remote_password).encode()\n        basic_auth_string = b64encode(basic_auth_string).decode('utf-8')\n        return basic_auth_string\n\n    def is_port_open(self):\n        is_port_open = False\n        with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:\n            if sock.connect_ex(('', self.local_port)) == 0:\n                logger.info('Port %s is NOT open', self.local_port)\n            else:\n                logger.warning('Port %s is open', self.local_port)\n                is_port_open = True\n            return is_port_open\n\n    def is_port_set_to_default(self):\n        import certifi\n        import urllib3\n        try:\n            import urllib3.contrib.pyopenssl\n            urllib3.contrib.pyopenssl.inject_into_urllib3()\n        except ImportError:\n            pass\n\n        http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())\n        headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format(self.remote_user_name, self.remote_password))\n        url = 'https://{}{}'.format(self.remote_addr, '.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx?GetStatus')\n        r = http.request(\n            'GET',\n            url,\n            headers=headers,\n            preload_content=False\n        )\n        if r.status != 200:\n            raise CLIError(\"Failed to connect to '{}' with status code '{}' and reason '{}'\".format(\n                url, r.status, r.reason))\n        msg = r.read().decode('utf-8')\n        logger.info('Status response message: %s', msg)\n        if 'FAIL' in msg.upper():\n            logger.warning('WARNING - Remote debugging may not be setup properly. Reponse content: %s', msg)\n        if '2222' in msg:\n            return True\n        return False\n\n    def _listen(self):\n        self.sock.listen(100)\n        index = 0\n        basic_auth_string = self.create_basic_auth()\n        while True:\n            self.client, _address = self.sock.accept()\n            self.client.settimeout(1800)\n            host = 'wss://{}{}'.format(self.remote_addr, '.scm.azurewebsites.net/AppServiceTunnel/Tunnel.ashx')\n            basic_auth_header = 'Authorization: Basic {}'.format(basic_auth_string)\n            cli_logger = get_logger()  # get CLI logger which has the level set through command lines\n            is_verbose = any(handler.level <= logs.INFO for handler in cli_logger.handlers)\n            if is_verbose:\n                logger.info('Websocket tracing enabled')\n                websocket.enableTrace(True)\n            else:\n                logger.warning('Websocket tracing disabled, use --verbose flag to enable')\n                websocket.enableTrace(False)\n            self.ws = create_connection(host,\n                                        sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),),\n                                        class_=TunnelWebSocket,\n                                        header=[basic_auth_header],\n                                        sslopt={'cert_reqs': ssl.CERT_NONE},\n                                        enable_multithread=True)\n            logger.info('Websocket, connected status: %s', self.ws.connected)\n            index = index + 1\n            logger.info('Got debugger connection... index: %s', index)\n            debugger_thread = Thread(target=self._listen_to_client, args=(self.client, self.ws, index))\n            web_socket_thread = Thread(target=self._listen_to_web_socket, args=(self.client, self.ws, index))\n            debugger_thread.start()\n            web_socket_thread.start()\n            logger.info('Both debugger and websocket threads started...')\n            logger.warning('Successfully connected to local server..')\n            debugger_thread.join()\n            web_socket_thread.join()\n            logger.info('Both debugger and websocket threads stopped...')\n            logger.warning('Stopped local server..')\n\n    def _listen_to_web_socket(self, client, ws_socket, index):\n        while True:\n            try:\n                logger.info('Waiting for websocket data, connection status: %s, index: %s', ws_socket.connected, index)\n                data = ws_socket.recv()\n                logger.info('Received websocket data: %s, index: %s', data, index)\n                if data:\n                    # Set the response to echo back the recieved data\n                    response = data\n                    logger.info('Sending to debugger, response: %s, index: %s', response, index)\n                    client.sendall(response)\n                    logger.info('Done sending to debugger, index: %s', index)\n                else:\n                    logger.info('Client disconnected!, index: %s', index)\n                    client.close()\n                    ws_socket.close()\n                    break\n            except:\n                traceback.print_exc(file=sys.stdout)\n                client.close()\n                ws_socket.close()\n                return False\n\n    def _listen_to_client(self, client, ws_socket, index):\n        while True:\n            try:\n                logger.info('Waiting for debugger data, index: %s', index)\n                buf = bytearray(4096)\n                nbytes = client.recv_into(buf, 4096)\n                logger.info('Received debugger data, nbytes: %s, index: %s', nbytes, index)\n                if nbytes > 0:\n                    responseData = buf[0:nbytes]\n                    logger.info('Sending to websocket, response data: %s, index: %s', responseData, index)\n                    ws_socket.send_binary(responseData)\n                    logger.info('Done sending to websocket, index: %s', index)\n                else:\n                    logger.warn('Client disconnected %s', index)\n                    client.close()\n                    ws_socket.close()\n                    break\n            except:\n                traceback.print_exc(file=sys.stdout)\n                client.close()\n                ws_socket.close()\n                return False\n\n    def start_server(self):\n        logger.warning('Start your favorite client and connect to port %s', self.local_port)\n        self._listen()\n", "path": "src/webapp/azext_webapp/tunnel.py"}, {"content": "#!/usr/bin/env python\n\n# --------------------------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. See License.txt in the project root for license information.\n# --------------------------------------------------------------------------------------------\n\nfrom codecs import open\nfrom setuptools import setup, find_packages\n\nVERSION = \"0.2.10\"\n\nCLASSIFIERS = [\n    'Development Status :: 4 - Beta',\n    'Intended Audience :: Developers',\n    'Intended Audience :: System Administrators',\n    'Programming Language :: Python',\n    'Programming Language :: Python :: 2',\n    'Programming Language :: Python :: 2.7',\n    'Programming Language :: Python :: 3',\n    'Programming Language :: Python :: 3.4',\n    'Programming Language :: Python :: 3.5',\n    'Programming Language :: Python :: 3.6',\n    'License :: OSI Approved :: MIT License',\n]\n\nDEPENDENCIES = []\n\nsetup(\n    name='webapp',\n    version=VERSION,\n    description='Additional commands for Azure AppService.',\n    long_description='An Azure CLI Extension to manage appservice resources',\n    license='MIT',\n    author='Sisira Panchagnula',\n    author_email='sisirap@microsoft.com',\n    url='https://github.com/Azure/azure-cli-extensions',\n    classifiers=CLASSIFIERS,\n    package_data={'azext_webapp': ['azext_metadata.json']},\n    packages=find_packages(exclude=[\"tests\"]),\n    install_requires=DEPENDENCIES\n)\n", "path": "src/webapp/setup.py"}]}