prompt: 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()
  
  ```
  
golden_diff: 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)
  
verification_info: {"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"}]}