We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
OpenMined.org Demo Broken
On our homepage - we link to colabs which implement a simple SocketWorker demo - as the new version of PySyft has no SocketWorker - the demo fails to work.

https://colab.research.google.com/drive/1-Jb_E_nDuBGHIJ_psI95k-ukh-P_aly-

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `syft/workers/websocket_server.py`
Content:
```
1 import binascii
2 from typing import Union
3 from typing import List
4 
5 import asyncio
6 import torch
7 import websockets
8 import ssl
9 import sys
10 import tblib.pickling_support
11 
12 tblib.pickling_support.install()
13 
14 import syft as sy
15 from syft.frameworks.torch.tensors.interpreters import AbstractTensor
16 from syft.workers.virtual import VirtualWorker
17 from syft.exceptions import GetNotPermittedError
18 from syft.exceptions import ResponseSignatureError
19 from syft.federated import FederatedClient
20 
21 
22 class WebsocketServerWorker(VirtualWorker, FederatedClient):
23     def __init__(
24         self,
25         hook,
26         host: str,
27         port: int,
28         id: Union[int, str] = 0,
29         log_msgs: bool = False,
30         verbose: bool = False,
31         data: List[Union[torch.Tensor, AbstractTensor]] = None,
32         loop=None,
33         cert_path: str = None,
34         key_path: str = None,
35     ):
36         """This is a simple extension to normal workers wherein
37         all messages are passed over websockets. Note that because
38         BaseWorker assumes a request/response paradigm, this worker
39         enforces this paradigm by default.
40 
41         Args:
42             hook (sy.TorchHook): a normal TorchHook object
43             id (str or id): the unique id of the worker (string or int)
44             log_msgs (bool): whether or not all messages should be
45                 saved locally for later inspection.
46             verbose (bool): a verbose option - will print all messages
47                 sent/received to stdout
48             host (str): the host on which the server should be run
49             port (int): the port on which the server should be run
50             data (dict): any initial tensors the server should be
51                 initialized with (such as datasets)
52             loop: the asyncio event loop if you want to pass one in
53                 yourself
54             cert_path: path to used secure certificate, only needed for secure connections
55             key_path: path to secure key, only needed for secure connections
56         """
57 
58         self.port = port
59         self.host = host
60         self.cert_path = cert_path
61         self.key_path = key_path
62 
63         if loop is None:
64             loop = asyncio.new_event_loop()
65 
66         # this queue is populated when messages are received
67         # from a client
68         self.broadcast_queue = asyncio.Queue()
69 
70         # this is the asyncio event loop
71         self.loop = loop
72 
73         # call BaseWorker constructor
74         super().__init__(hook=hook, id=id, data=data, log_msgs=log_msgs, verbose=verbose)
75 
76     async def _consumer_handler(self, websocket: websockets.WebSocketCommonProtocol):
77         """This handler listens for messages from WebsocketClientWorker
78         objects.
79 
80         Args:
81             websocket: the connection object to receive messages from and
82                 add them into the queue.
83 
84         """
85         while True:
86             msg = await websocket.recv()
87             await self.broadcast_queue.put(msg)
88 
89     async def _producer_handler(self, websocket: websockets.WebSocketCommonProtocol):
90         """This handler listens to the queue and processes messages as they
91         arrive.
92 
93         Args:
94             websocket: the connection object we use to send responses
95                 back to the client.
96 
97         """
98         while True:
99 
100             # get a message from the queue
101             message = await self.broadcast_queue.get()
102 
103             # convert that string message to the binary it represent
104             message = binascii.unhexlify(message[2:-1])
105 
106             # process the message
107             response = self._recv_msg(message)
108 
109             # convert the binary to a string representation
110             # (this is needed for the websocket library)
111             response = str(binascii.hexlify(response))
112 
113             # send the response
114             await websocket.send(response)
115 
116     def _recv_msg(self, message: bin) -> bin:
117         try:
118             return self.recv_msg(message)
119         except (ResponseSignatureError, GetNotPermittedError) as e:
120             return sy.serde.serialize(e)
121 
122     async def _handler(self, websocket: websockets.WebSocketCommonProtocol, *unused_args):
123         """Setup the consumer and producer response handlers with asyncio.
124 
125         Args:
126             websocket: the websocket connection to the client
127 
128         """
129 
130         asyncio.set_event_loop(self.loop)
131         consumer_task = asyncio.ensure_future(self._consumer_handler(websocket))
132         producer_task = asyncio.ensure_future(self._producer_handler(websocket))
133 
134         done, pending = await asyncio.wait(
135             [consumer_task, producer_task], return_when=asyncio.FIRST_COMPLETED
136         )
137 
138         for task in pending:
139             task.cancel()
140 
141     def start(self):
142         """Start the server"""
143         # Secure behavior: adds a secure layer applying cryptography and authentication
144         if not (self.cert_path is None) and not (self.key_path is None):
145             ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
146             ssl_context.load_cert_chain(self.cert_path, self.key_path)
147             start_server = websockets.serve(
148                 self._handler,
149                 self.host,
150                 self.port,
151                 ssl=ssl_context,
152                 max_size=None,
153                 ping_timeout=None,
154                 close_timeout=None,
155             )
156         else:
157             # Insecure
158             start_server = websockets.serve(
159                 self._handler,
160                 self.host,
161                 self.port,
162                 max_size=None,
163                 ping_timeout=None,
164                 close_timeout=None,
165             )
166 
167         asyncio.get_event_loop().run_until_complete(start_server)
168         asyncio.get_event_loop().run_forever()
169 
170     def list_objects(self, *args):
171         return str(self._objects)
172 
173     def objects_count(self, *args):
174         return len(self._objects)
175
```
--- 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/syft/workers/websocket_server.py b/syft/workers/websocket_server.py
--- a/syft/workers/websocket_server.py
+++ b/syft/workers/websocket_server.py
@@ -8,6 +8,8 @@
 import ssl
 import sys
 import tblib.pickling_support
+import socket
+import logging
 
 tblib.pickling_support.install()
 
@@ -165,7 +167,11 @@
             )
 
         asyncio.get_event_loop().run_until_complete(start_server)
-        asyncio.get_event_loop().run_forever()
+        print("Serving. Press CTRL-C to stop.")
+        try:
+            asyncio.get_event_loop().run_forever()
+        except KeyboardInterrupt:
+            logging.info("Websocket server stopped.")
 
     def list_objects(self, *args):
         return str(self._objects)

{"golden_diff": "diff --git a/syft/workers/websocket_server.py b/syft/workers/websocket_server.py\n--- a/syft/workers/websocket_server.py\n+++ b/syft/workers/websocket_server.py\n@@ -8,6 +8,8 @@\n import ssl\n import sys\n import tblib.pickling_support\n+import socket\n+import logging\n \n tblib.pickling_support.install()\n \n@@ -165,7 +167,11 @@\n             )\n \n         asyncio.get_event_loop().run_until_complete(start_server)\n-        asyncio.get_event_loop().run_forever()\n+        print(\"Serving. Press CTRL-C to stop.\")\n+        try:\n+            asyncio.get_event_loop().run_forever()\n+        except KeyboardInterrupt:\n+            logging.info(\"Websocket server stopped.\")\n \n     def list_objects(self, *args):\n         return str(self._objects)\n", "issue": "OpenMined.org Demo Broken\nOn our homepage - we link to colabs which implement a simple SocketWorker demo - as the new version of PySyft has no SocketWorker - the demo fails to work.\r\n\r\nhttps://colab.research.google.com/drive/1-Jb_E_nDuBGHIJ_psI95k-ukh-P_aly-\n", "before_files": [{"content": "import binascii\nfrom typing import Union\nfrom typing import List\n\nimport asyncio\nimport torch\nimport websockets\nimport ssl\nimport sys\nimport tblib.pickling_support\n\ntblib.pickling_support.install()\n\nimport syft as sy\nfrom syft.frameworks.torch.tensors.interpreters import AbstractTensor\nfrom syft.workers.virtual import VirtualWorker\nfrom syft.exceptions import GetNotPermittedError\nfrom syft.exceptions import ResponseSignatureError\nfrom syft.federated import FederatedClient\n\n\nclass WebsocketServerWorker(VirtualWorker, FederatedClient):\n    def __init__(\n        self,\n        hook,\n        host: str,\n        port: int,\n        id: Union[int, str] = 0,\n        log_msgs: bool = False,\n        verbose: bool = False,\n        data: List[Union[torch.Tensor, AbstractTensor]] = None,\n        loop=None,\n        cert_path: str = None,\n        key_path: str = None,\n    ):\n        \"\"\"This is a simple extension to normal workers wherein\n        all messages are passed over websockets. Note that because\n        BaseWorker assumes a request/response paradigm, this worker\n        enforces this paradigm by default.\n\n        Args:\n            hook (sy.TorchHook): a normal TorchHook object\n            id (str or id): the unique id of the worker (string or int)\n            log_msgs (bool): whether or not all messages should be\n                saved locally for later inspection.\n            verbose (bool): a verbose option - will print all messages\n                sent/received to stdout\n            host (str): the host on which the server should be run\n            port (int): the port on which the server should be run\n            data (dict): any initial tensors the server should be\n                initialized with (such as datasets)\n            loop: the asyncio event loop if you want to pass one in\n                yourself\n            cert_path: path to used secure certificate, only needed for secure connections\n            key_path: path to secure key, only needed for secure connections\n        \"\"\"\n\n        self.port = port\n        self.host = host\n        self.cert_path = cert_path\n        self.key_path = key_path\n\n        if loop is None:\n            loop = asyncio.new_event_loop()\n\n        # this queue is populated when messages are received\n        # from a client\n        self.broadcast_queue = asyncio.Queue()\n\n        # this is the asyncio event loop\n        self.loop = loop\n\n        # call BaseWorker constructor\n        super().__init__(hook=hook, id=id, data=data, log_msgs=log_msgs, verbose=verbose)\n\n    async def _consumer_handler(self, websocket: websockets.WebSocketCommonProtocol):\n        \"\"\"This handler listens for messages from WebsocketClientWorker\n        objects.\n\n        Args:\n            websocket: the connection object to receive messages from and\n                add them into the queue.\n\n        \"\"\"\n        while True:\n            msg = await websocket.recv()\n            await self.broadcast_queue.put(msg)\n\n    async def _producer_handler(self, websocket: websockets.WebSocketCommonProtocol):\n        \"\"\"This handler listens to the queue and processes messages as they\n        arrive.\n\n        Args:\n            websocket: the connection object we use to send responses\n                back to the client.\n\n        \"\"\"\n        while True:\n\n            # get a message from the queue\n            message = await self.broadcast_queue.get()\n\n            # convert that string message to the binary it represent\n            message = binascii.unhexlify(message[2:-1])\n\n            # process the message\n            response = self._recv_msg(message)\n\n            # convert the binary to a string representation\n            # (this is needed for the websocket library)\n            response = str(binascii.hexlify(response))\n\n            # send the response\n            await websocket.send(response)\n\n    def _recv_msg(self, message: bin) -> bin:\n        try:\n            return self.recv_msg(message)\n        except (ResponseSignatureError, GetNotPermittedError) as e:\n            return sy.serde.serialize(e)\n\n    async def _handler(self, websocket: websockets.WebSocketCommonProtocol, *unused_args):\n        \"\"\"Setup the consumer and producer response handlers with asyncio.\n\n        Args:\n            websocket: the websocket connection to the client\n\n        \"\"\"\n\n        asyncio.set_event_loop(self.loop)\n        consumer_task = asyncio.ensure_future(self._consumer_handler(websocket))\n        producer_task = asyncio.ensure_future(self._producer_handler(websocket))\n\n        done, pending = await asyncio.wait(\n            [consumer_task, producer_task], return_when=asyncio.FIRST_COMPLETED\n        )\n\n        for task in pending:\n            task.cancel()\n\n    def start(self):\n        \"\"\"Start the server\"\"\"\n        # Secure behavior: adds a secure layer applying cryptography and authentication\n        if not (self.cert_path is None) and not (self.key_path is None):\n            ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n            ssl_context.load_cert_chain(self.cert_path, self.key_path)\n            start_server = websockets.serve(\n                self._handler,\n                self.host,\n                self.port,\n                ssl=ssl_context,\n                max_size=None,\n                ping_timeout=None,\n                close_timeout=None,\n            )\n        else:\n            # Insecure\n            start_server = websockets.serve(\n                self._handler,\n                self.host,\n                self.port,\n                max_size=None,\n                ping_timeout=None,\n                close_timeout=None,\n            )\n\n        asyncio.get_event_loop().run_until_complete(start_server)\n        asyncio.get_event_loop().run_forever()\n\n    def list_objects(self, *args):\n        return str(self._objects)\n\n    def objects_count(self, *args):\n        return len(self._objects)\n", "path": "syft/workers/websocket_server.py"}], "after_files": [{"content": "import binascii\nfrom typing import Union\nfrom typing import List\n\nimport asyncio\nimport torch\nimport websockets\nimport ssl\nimport sys\nimport tblib.pickling_support\nimport socket\nimport logging\n\ntblib.pickling_support.install()\n\nimport syft as sy\nfrom syft.frameworks.torch.tensors.interpreters import AbstractTensor\nfrom syft.workers.virtual import VirtualWorker\nfrom syft.exceptions import GetNotPermittedError\nfrom syft.exceptions import ResponseSignatureError\nfrom syft.federated import FederatedClient\n\n\nclass WebsocketServerWorker(VirtualWorker, FederatedClient):\n    def __init__(\n        self,\n        hook,\n        host: str,\n        port: int,\n        id: Union[int, str] = 0,\n        log_msgs: bool = False,\n        verbose: bool = False,\n        data: List[Union[torch.Tensor, AbstractTensor]] = None,\n        loop=None,\n        cert_path: str = None,\n        key_path: str = None,\n    ):\n        \"\"\"This is a simple extension to normal workers wherein\n        all messages are passed over websockets. Note that because\n        BaseWorker assumes a request/response paradigm, this worker\n        enforces this paradigm by default.\n\n        Args:\n            hook (sy.TorchHook): a normal TorchHook object\n            id (str or id): the unique id of the worker (string or int)\n            log_msgs (bool): whether or not all messages should be\n                saved locally for later inspection.\n            verbose (bool): a verbose option - will print all messages\n                sent/received to stdout\n            host (str): the host on which the server should be run\n            port (int): the port on which the server should be run\n            data (dict): any initial tensors the server should be\n                initialized with (such as datasets)\n            loop: the asyncio event loop if you want to pass one in\n                yourself\n            cert_path: path to used secure certificate, only needed for secure connections\n            key_path: path to secure key, only needed for secure connections\n        \"\"\"\n\n        self.port = port\n        self.host = host\n        self.cert_path = cert_path\n        self.key_path = key_path\n\n        if loop is None:\n            loop = asyncio.new_event_loop()\n\n        # this queue is populated when messages are received\n        # from a client\n        self.broadcast_queue = asyncio.Queue()\n\n        # this is the asyncio event loop\n        self.loop = loop\n\n        # call BaseWorker constructor\n        super().__init__(hook=hook, id=id, data=data, log_msgs=log_msgs, verbose=verbose)\n\n    async def _consumer_handler(self, websocket: websockets.WebSocketCommonProtocol):\n        \"\"\"This handler listens for messages from WebsocketClientWorker\n        objects.\n\n        Args:\n            websocket: the connection object to receive messages from and\n                add them into the queue.\n\n        \"\"\"\n        while True:\n            msg = await websocket.recv()\n            await self.broadcast_queue.put(msg)\n\n    async def _producer_handler(self, websocket: websockets.WebSocketCommonProtocol):\n        \"\"\"This handler listens to the queue and processes messages as they\n        arrive.\n\n        Args:\n            websocket: the connection object we use to send responses\n                back to the client.\n\n        \"\"\"\n        while True:\n\n            # get a message from the queue\n            message = await self.broadcast_queue.get()\n\n            # convert that string message to the binary it represent\n            message = binascii.unhexlify(message[2:-1])\n\n            # process the message\n            response = self._recv_msg(message)\n\n            # convert the binary to a string representation\n            # (this is needed for the websocket library)\n            response = str(binascii.hexlify(response))\n\n            # send the response\n            await websocket.send(response)\n\n    def _recv_msg(self, message: bin) -> bin:\n        try:\n            return self.recv_msg(message)\n        except (ResponseSignatureError, GetNotPermittedError) as e:\n            return sy.serde.serialize(e)\n\n    async def _handler(self, websocket: websockets.WebSocketCommonProtocol, *unused_args):\n        \"\"\"Setup the consumer and producer response handlers with asyncio.\n\n        Args:\n            websocket: the websocket connection to the client\n\n        \"\"\"\n\n        asyncio.set_event_loop(self.loop)\n        consumer_task = asyncio.ensure_future(self._consumer_handler(websocket))\n        producer_task = asyncio.ensure_future(self._producer_handler(websocket))\n\n        done, pending = await asyncio.wait(\n            [consumer_task, producer_task], return_when=asyncio.FIRST_COMPLETED\n        )\n\n        for task in pending:\n            task.cancel()\n\n    def start(self):\n        \"\"\"Start the server\"\"\"\n        # Secure behavior: adds a secure layer applying cryptography and authentication\n        if not (self.cert_path is None) and not (self.key_path is None):\n            ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)\n            ssl_context.load_cert_chain(self.cert_path, self.key_path)\n            start_server = websockets.serve(\n                self._handler,\n                self.host,\n                self.port,\n                ssl=ssl_context,\n                max_size=None,\n                ping_timeout=None,\n                close_timeout=None,\n            )\n        else:\n            # Insecure\n            start_server = websockets.serve(\n                self._handler,\n                self.host,\n                self.port,\n                max_size=None,\n                ping_timeout=None,\n                close_timeout=None,\n            )\n\n        asyncio.get_event_loop().run_until_complete(start_server)\n        print(\"Serving. Press CTRL-C to stop.\")\n        try:\n            asyncio.get_event_loop().run_forever()\n        except KeyboardInterrupt:\n            logging.info(\"Websocket server stopped.\")\n\n    def list_objects(self, *args):\n        return str(self._objects)\n\n    def objects_count(self, *args):\n        return len(self._objects)\n", "path": "syft/workers/websocket_server.py"}]}