prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Undocumented behaviour of sni kwarg of remote()
  In `remote()` 'server_hostname' ssl arg can be set like this:
  ```python
  remote('172.22.0.2', 9090, ssl=True, sni='example.com')
  ```
  This behaviour of `sni` kwarg is undocumented. Currently only behaviour of passing a bool in documented.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pwnlib/tubes/remote.py`
  Content:
  ```
  1 from __future__ import absolute_import
  2 from __future__ import division
  3 
  4 import socket
  5 import socks
  6 
  7 from pwnlib.log import getLogger
  8 from pwnlib.timeout import Timeout
  9 from pwnlib.tubes.sock import sock
  10 
  11 log = getLogger(__name__)
  12 
  13 class remote(sock):
  14     r"""Creates a TCP or UDP-connection to a remote host. It supports
  15     both IPv4 and IPv6.
  16 
  17     The returned object supports all the methods from
  18     :class:`pwnlib.tubes.sock` and :class:`pwnlib.tubes.tube`.
  19 
  20     Arguments:
  21         host(str): The host to connect to.
  22         port(int): The port to connect to.
  23         fam: The string "any", "ipv4" or "ipv6" or an integer to pass to :func:`socket.getaddrinfo`.
  24         typ: The string "tcp" or "udp" or an integer to pass to :func:`socket.getaddrinfo`.
  25         timeout: A positive number, None or the string "default".
  26         ssl(bool): Wrap the socket with SSL
  27         ssl_context(ssl.SSLContext): Specify SSLContext used to wrap the socket.
  28         sni: Set 'server_hostname' in ssl_args based on the host parameter.
  29         sock(socket.socket): Socket to inherit, rather than connecting
  30         ssl_args(dict): Pass ssl.wrap_socket named arguments in a dictionary.
  31 
  32     Examples:
  33 
  34         >>> r = remote('google.com', 443, ssl=True)
  35         >>> r.send(b'GET /\r\n\r\n')
  36         >>> r.recvn(4)
  37         b'HTTP'
  38 
  39         If a connection cannot be made, an exception is raised.
  40 
  41         >>> r = remote('127.0.0.1', 1)
  42         Traceback (most recent call last):
  43         ...
  44         PwnlibException: Could not connect to 127.0.0.1 on port 1
  45 
  46         You can also use :meth:`.remote.fromsocket` to wrap an existing socket.
  47 
  48         >>> import socket
  49         >>> s = socket.socket()
  50         >>> s.connect(('google.com', 80))
  51         >>> s.send(b'GET /' + b'\r\n'*2)
  52         9
  53         >>> r = remote.fromsocket(s)
  54         >>> r.recvn(4)
  55         b'HTTP'
  56     """
  57 
  58     def __init__(self, host, port,
  59                  fam = "any", typ = "tcp",
  60                  ssl=False, sock=None, ssl_context=None, ssl_args=None, sni=True,
  61                  *args, **kwargs):
  62         super(remote, self).__init__(*args, **kwargs)
  63 
  64         # convert port to string for sagemath support
  65         self.rport  = str(port)
  66         self.rhost  = host
  67 
  68         if sock:
  69             self.family = sock.family
  70             self.type   = sock.type
  71             self.proto  = sock.proto
  72             self.sock   = sock
  73 
  74         else:
  75             typ = self._get_type(typ)
  76             fam = self._get_family(fam)
  77             try:
  78                 self.sock   = self._connect(fam, typ)
  79             except socket.gaierror as e:
  80                 if e.errno != socket.EAI_NONAME:
  81                     raise
  82                 self.error('Could not resolve hostname: %r', host)
  83         if self.sock:
  84             self.settimeout(self.timeout)
  85             self.lhost, self.lport = self.sock.getsockname()[:2]
  86 
  87             if ssl:
  88                 # Deferred import to save startup time
  89                 import ssl as _ssl
  90 
  91                 ssl_args = ssl_args or {}
  92                 ssl_context = ssl_context or _ssl.SSLContext(_ssl.PROTOCOL_TLSv1_2)
  93                 if isinstance(sni, str):
  94                     ssl_args["server_hostname"] = sni
  95                 elif sni:
  96                     ssl_args["server_hostname"] = host
  97                 self.sock = ssl_context.wrap_socket(self.sock,**ssl_args)
  98 
  99     def _connect(self, fam, typ):
  100         sock    = None
  101         timeout = self.timeout
  102 
  103         with self.waitfor('Opening connection to %s on port %s' % (self.rhost, self.rport)) as h:
  104             for res in socket.getaddrinfo(self.rhost, self.rport, fam, typ, 0, socket.AI_PASSIVE):
  105                 self.family, self.type, self.proto, _canonname, sockaddr = res
  106 
  107                 if self.type not in [socket.SOCK_STREAM, socket.SOCK_DGRAM]:
  108                     continue
  109 
  110                 h.status("Trying %s", sockaddr[0])
  111 
  112                 sock = socket.socket(self.family, self.type, self.proto)
  113 
  114                 if timeout is not None and timeout <= 0:
  115                     sock.setblocking(0)
  116                 else:
  117                     sock.setblocking(1)
  118                     sock.settimeout(timeout)
  119 
  120                 try:
  121                     sock.connect(sockaddr)
  122                     return sock
  123                 except socks.ProxyError:
  124                     raise
  125                 except socket.error:
  126                     pass
  127             self.error("Could not connect to %s on port %s", self.rhost, self.rport)
  128 
  129     @classmethod
  130     def fromsocket(cls, socket):
  131         """
  132         Helper method to wrap a standard python socket.socket with the
  133         tube APIs.
  134 
  135         Arguments:
  136             socket: Instance of socket.socket
  137 
  138         Returns:
  139             Instance of pwnlib.tubes.remote.remote.
  140         """
  141         s = socket
  142         host, port = s.getpeername()
  143         return remote(host, port, fam=s.family, typ=s.type, sock=s)
  144 
  145 class tcp(remote):
  146     __doc__ = remote.__doc__
  147     def __init__(self, host, port, *a, **kw):
  148         return super(tcp, self).__init__(host, port, typ="tcp", *a, **kw)
  149 
  150 class udp(remote):
  151     __doc__ = remote.__doc__
  152     def __init__(self, host, port, *a, **kw):
  153         return super(udp, self).__init__(host, port, typ="udp", *a, **kw)
  154 
  155 class connect(remote):
  156     __doc__ = remote.__doc__
  157
  ```
  --- 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/pwnlib/tubes/remote.py b/pwnlib/tubes/remote.py
  --- a/pwnlib/tubes/remote.py
  +++ b/pwnlib/tubes/remote.py
  @@ -23,11 +23,11 @@
           fam: The string "any", "ipv4" or "ipv6" or an integer to pass to :func:`socket.getaddrinfo`.
           typ: The string "tcp" or "udp" or an integer to pass to :func:`socket.getaddrinfo`.
           timeout: A positive number, None or the string "default".
  +        sock(:class:`socket.socket`): Socket to inherit, rather than connecting
           ssl(bool): Wrap the socket with SSL
           ssl_context(ssl.SSLContext): Specify SSLContext used to wrap the socket.
  -        sni: Set 'server_hostname' in ssl_args based on the host parameter.
  -        sock(socket.socket): Socket to inherit, rather than connecting
  -        ssl_args(dict): Pass ssl.wrap_socket named arguments in a dictionary.
  +        ssl_args(dict): Pass :func:`ssl.wrap_socket` named arguments in a dictionary.
  +        sni(str,bool): Set 'server_hostname' in ssl_args. Set to True to set it based on the host argument. Set to False to not provide any value. Default is True.
   
       Examples:
   
  @@ -57,7 +57,7 @@
   
       def __init__(self, host, port,
                    fam = "any", typ = "tcp",
  -                 ssl=False, sock=None, ssl_context=None, ssl_args=None, sni=True,
  +                 sock=None, ssl=False, ssl_context=None, ssl_args=None, sni=True,
                    *args, **kwargs):
           super(remote, self).__init__(*args, **kwargs)
  
verification_info: {"golden_diff": "diff --git a/pwnlib/tubes/remote.py b/pwnlib/tubes/remote.py\n--- a/pwnlib/tubes/remote.py\n+++ b/pwnlib/tubes/remote.py\n@@ -23,11 +23,11 @@\n         fam: The string \"any\", \"ipv4\" or \"ipv6\" or an integer to pass to :func:`socket.getaddrinfo`.\n         typ: The string \"tcp\" or \"udp\" or an integer to pass to :func:`socket.getaddrinfo`.\n         timeout: A positive number, None or the string \"default\".\n+        sock(:class:`socket.socket`): Socket to inherit, rather than connecting\n         ssl(bool): Wrap the socket with SSL\n         ssl_context(ssl.SSLContext): Specify SSLContext used to wrap the socket.\n-        sni: Set 'server_hostname' in ssl_args based on the host parameter.\n-        sock(socket.socket): Socket to inherit, rather than connecting\n-        ssl_args(dict): Pass ssl.wrap_socket named arguments in a dictionary.\n+        ssl_args(dict): Pass :func:`ssl.wrap_socket` named arguments in a dictionary.\n+        sni(str,bool): Set 'server_hostname' in ssl_args. Set to True to set it based on the host argument. Set to False to not provide any value. Default is True.\n \n     Examples:\n \n@@ -57,7 +57,7 @@\n \n     def __init__(self, host, port,\n                  fam = \"any\", typ = \"tcp\",\n-                 ssl=False, sock=None, ssl_context=None, ssl_args=None, sni=True,\n+                 sock=None, ssl=False, ssl_context=None, ssl_args=None, sni=True,\n                  *args, **kwargs):\n         super(remote, self).__init__(*args, **kwargs)\n", "issue": "Undocumented behaviour of sni kwarg of remote()\nIn `remote()` 'server_hostname' ssl arg can be set like this:\r\n```python\r\nremote('172.22.0.2', 9090, ssl=True, sni='example.com')\r\n```\r\nThis behaviour of `sni` kwarg is undocumented. Currently only behaviour of passing a bool in documented.\n", "before_files": [{"content": "from __future__ import absolute_import\nfrom __future__ import division\n\nimport socket\nimport socks\n\nfrom pwnlib.log import getLogger\nfrom pwnlib.timeout import Timeout\nfrom pwnlib.tubes.sock import sock\n\nlog = getLogger(__name__)\n\nclass remote(sock):\n    r\"\"\"Creates a TCP or UDP-connection to a remote host. It supports\n    both IPv4 and IPv6.\n\n    The returned object supports all the methods from\n    :class:`pwnlib.tubes.sock` and :class:`pwnlib.tubes.tube`.\n\n    Arguments:\n        host(str): The host to connect to.\n        port(int): The port to connect to.\n        fam: The string \"any\", \"ipv4\" or \"ipv6\" or an integer to pass to :func:`socket.getaddrinfo`.\n        typ: The string \"tcp\" or \"udp\" or an integer to pass to :func:`socket.getaddrinfo`.\n        timeout: A positive number, None or the string \"default\".\n        ssl(bool): Wrap the socket with SSL\n        ssl_context(ssl.SSLContext): Specify SSLContext used to wrap the socket.\n        sni: Set 'server_hostname' in ssl_args based on the host parameter.\n        sock(socket.socket): Socket to inherit, rather than connecting\n        ssl_args(dict): Pass ssl.wrap_socket named arguments in a dictionary.\n\n    Examples:\n\n        >>> r = remote('google.com', 443, ssl=True)\n        >>> r.send(b'GET /\\r\\n\\r\\n')\n        >>> r.recvn(4)\n        b'HTTP'\n\n        If a connection cannot be made, an exception is raised.\n\n        >>> r = remote('127.0.0.1', 1)\n        Traceback (most recent call last):\n        ...\n        PwnlibException: Could not connect to 127.0.0.1 on port 1\n\n        You can also use :meth:`.remote.fromsocket` to wrap an existing socket.\n\n        >>> import socket\n        >>> s = socket.socket()\n        >>> s.connect(('google.com', 80))\n        >>> s.send(b'GET /' + b'\\r\\n'*2)\n        9\n        >>> r = remote.fromsocket(s)\n        >>> r.recvn(4)\n        b'HTTP'\n    \"\"\"\n\n    def __init__(self, host, port,\n                 fam = \"any\", typ = \"tcp\",\n                 ssl=False, sock=None, ssl_context=None, ssl_args=None, sni=True,\n                 *args, **kwargs):\n        super(remote, self).__init__(*args, **kwargs)\n\n        # convert port to string for sagemath support\n        self.rport  = str(port)\n        self.rhost  = host\n\n        if sock:\n            self.family = sock.family\n            self.type   = sock.type\n            self.proto  = sock.proto\n            self.sock   = sock\n\n        else:\n            typ = self._get_type(typ)\n            fam = self._get_family(fam)\n            try:\n                self.sock   = self._connect(fam, typ)\n            except socket.gaierror as e:\n                if e.errno != socket.EAI_NONAME:\n                    raise\n                self.error('Could not resolve hostname: %r', host)\n        if self.sock:\n            self.settimeout(self.timeout)\n            self.lhost, self.lport = self.sock.getsockname()[:2]\n\n            if ssl:\n                # Deferred import to save startup time\n                import ssl as _ssl\n\n                ssl_args = ssl_args or {}\n                ssl_context = ssl_context or _ssl.SSLContext(_ssl.PROTOCOL_TLSv1_2)\n                if isinstance(sni, str):\n                    ssl_args[\"server_hostname\"] = sni\n                elif sni:\n                    ssl_args[\"server_hostname\"] = host\n                self.sock = ssl_context.wrap_socket(self.sock,**ssl_args)\n\n    def _connect(self, fam, typ):\n        sock    = None\n        timeout = self.timeout\n\n        with self.waitfor('Opening connection to %s on port %s' % (self.rhost, self.rport)) as h:\n            for res in socket.getaddrinfo(self.rhost, self.rport, fam, typ, 0, socket.AI_PASSIVE):\n                self.family, self.type, self.proto, _canonname, sockaddr = res\n\n                if self.type not in [socket.SOCK_STREAM, socket.SOCK_DGRAM]:\n                    continue\n\n                h.status(\"Trying %s\", sockaddr[0])\n\n                sock = socket.socket(self.family, self.type, self.proto)\n\n                if timeout is not None and timeout <= 0:\n                    sock.setblocking(0)\n                else:\n                    sock.setblocking(1)\n                    sock.settimeout(timeout)\n\n                try:\n                    sock.connect(sockaddr)\n                    return sock\n                except socks.ProxyError:\n                    raise\n                except socket.error:\n                    pass\n            self.error(\"Could not connect to %s on port %s\", self.rhost, self.rport)\n\n    @classmethod\n    def fromsocket(cls, socket):\n        \"\"\"\n        Helper method to wrap a standard python socket.socket with the\n        tube APIs.\n\n        Arguments:\n            socket: Instance of socket.socket\n\n        Returns:\n            Instance of pwnlib.tubes.remote.remote.\n        \"\"\"\n        s = socket\n        host, port = s.getpeername()\n        return remote(host, port, fam=s.family, typ=s.type, sock=s)\n\nclass tcp(remote):\n    __doc__ = remote.__doc__\n    def __init__(self, host, port, *a, **kw):\n        return super(tcp, self).__init__(host, port, typ=\"tcp\", *a, **kw)\n\nclass udp(remote):\n    __doc__ = remote.__doc__\n    def __init__(self, host, port, *a, **kw):\n        return super(udp, self).__init__(host, port, typ=\"udp\", *a, **kw)\n\nclass connect(remote):\n    __doc__ = remote.__doc__\n", "path": "pwnlib/tubes/remote.py"}], "after_files": [{"content": "from __future__ import absolute_import\nfrom __future__ import division\n\nimport socket\nimport socks\n\nfrom pwnlib.log import getLogger\nfrom pwnlib.timeout import Timeout\nfrom pwnlib.tubes.sock import sock\n\nlog = getLogger(__name__)\n\nclass remote(sock):\n    r\"\"\"Creates a TCP or UDP-connection to a remote host. It supports\n    both IPv4 and IPv6.\n\n    The returned object supports all the methods from\n    :class:`pwnlib.tubes.sock` and :class:`pwnlib.tubes.tube`.\n\n    Arguments:\n        host(str): The host to connect to.\n        port(int): The port to connect to.\n        fam: The string \"any\", \"ipv4\" or \"ipv6\" or an integer to pass to :func:`socket.getaddrinfo`.\n        typ: The string \"tcp\" or \"udp\" or an integer to pass to :func:`socket.getaddrinfo`.\n        timeout: A positive number, None or the string \"default\".\n        sock(:class:`socket.socket`): Socket to inherit, rather than connecting\n        ssl(bool): Wrap the socket with SSL\n        ssl_context(ssl.SSLContext): Specify SSLContext used to wrap the socket.\n        ssl_args(dict): Pass :func:`ssl.wrap_socket` named arguments in a dictionary.\n        sni(str,bool): Set 'server_hostname' in ssl_args. Set to True to set it based on the host argument. Set to False to not provide any value. Default is True.\n\n    Examples:\n\n        >>> r = remote('google.com', 443, ssl=True)\n        >>> r.send(b'GET /\\r\\n\\r\\n')\n        >>> r.recvn(4)\n        b'HTTP'\n\n        If a connection cannot be made, an exception is raised.\n\n        >>> r = remote('127.0.0.1', 1)\n        Traceback (most recent call last):\n        ...\n        PwnlibException: Could not connect to 127.0.0.1 on port 1\n\n        You can also use :meth:`.remote.fromsocket` to wrap an existing socket.\n\n        >>> import socket\n        >>> s = socket.socket()\n        >>> s.connect(('google.com', 80))\n        >>> s.send(b'GET /' + b'\\r\\n'*2)\n        9\n        >>> r = remote.fromsocket(s)\n        >>> r.recvn(4)\n        b'HTTP'\n    \"\"\"\n\n    def __init__(self, host, port,\n                 fam = \"any\", typ = \"tcp\",\n                 sock=None, ssl=False, ssl_context=None, ssl_args=None, sni=True,\n                 *args, **kwargs):\n        super(remote, self).__init__(*args, **kwargs)\n\n        # convert port to string for sagemath support\n        self.rport  = str(port)\n        self.rhost  = host\n\n        if sock:\n            self.family = sock.family\n            self.type   = sock.type\n            self.proto  = sock.proto\n            self.sock   = sock\n\n        else:\n            typ = self._get_type(typ)\n            fam = self._get_family(fam)\n            try:\n                self.sock   = self._connect(fam, typ)\n            except socket.gaierror as e:\n                if e.errno != socket.EAI_NONAME:\n                    raise\n                self.error('Could not resolve hostname: %r', host)\n        if self.sock:\n            self.settimeout(self.timeout)\n            self.lhost, self.lport = self.sock.getsockname()[:2]\n\n            if ssl:\n                # Deferred import to save startup time\n                import ssl as _ssl\n\n                ssl_args = ssl_args or {}\n                ssl_context = ssl_context or _ssl.SSLContext(_ssl.PROTOCOL_TLSv1_2)\n                if isinstance(sni, str):\n                    ssl_args[\"server_hostname\"] = sni\n                elif sni:\n                    ssl_args[\"server_hostname\"] = host\n                self.sock = ssl_context.wrap_socket(self.sock,**ssl_args)\n\n    def _connect(self, fam, typ):\n        sock    = None\n        timeout = self.timeout\n\n        with self.waitfor('Opening connection to %s on port %s' % (self.rhost, self.rport)) as h:\n            for res in socket.getaddrinfo(self.rhost, self.rport, fam, typ, 0, socket.AI_PASSIVE):\n                self.family, self.type, self.proto, _canonname, sockaddr = res\n\n                if self.type not in [socket.SOCK_STREAM, socket.SOCK_DGRAM]:\n                    continue\n\n                h.status(\"Trying %s\", sockaddr[0])\n\n                sock = socket.socket(self.family, self.type, self.proto)\n\n                if timeout is not None and timeout <= 0:\n                    sock.setblocking(0)\n                else:\n                    sock.setblocking(1)\n                    sock.settimeout(timeout)\n\n                try:\n                    sock.connect(sockaddr)\n                    return sock\n                except socks.ProxyError:\n                    raise\n                except socket.error:\n                    pass\n            self.error(\"Could not connect to %s on port %s\", self.rhost, self.rport)\n\n    @classmethod\n    def fromsocket(cls, socket):\n        \"\"\"\n        Helper method to wrap a standard python socket.socket with the\n        tube APIs.\n\n        Arguments:\n            socket: Instance of socket.socket\n\n        Returns:\n            Instance of pwnlib.tubes.remote.remote.\n        \"\"\"\n        s = socket\n        host, port = s.getpeername()\n        return remote(host, port, fam=s.family, typ=s.type, sock=s)\n\nclass tcp(remote):\n    __doc__ = remote.__doc__\n    def __init__(self, host, port, *a, **kw):\n        return super(tcp, self).__init__(host, port, typ=\"tcp\", *a, **kw)\n\nclass udp(remote):\n    __doc__ = remote.__doc__\n    def __init__(self, host, port, *a, **kw):\n        return super(udp, self).__init__(host, port, typ=\"udp\", *a, **kw)\n\nclass connect(remote):\n    __doc__ = remote.__doc__\n", "path": "pwnlib/tubes/remote.py"}]}