Anorov/PySocks

Proxied UDP sockets do not work when Gevent used

HelloZeroNet opened this issue · 0 comments

Python 3.7.1
PySocks: 1.7.0
Gevent: 1.4.0

import socket
import gevent
import gevent.monkey
gevent.monkey.patch_all()
import socks

s = socks.socksocket(socket.AF_INET, socket.SOCK_DGRAM)
s.set_proxy(socks.SOCKS5, "127.0.0.1", 8080)
s.settimeout(1)
s.sendto(b"test", ("127.0.0.1", 12000))

data, server = s.recvfrom(1024)
Traceback (most recent call last):
  File "E:\Web\2019-08-15\test2.py", line 10, in <module>
    s.sendto(b"test", ("127.0.0.1", 12000))
  File "C:\python3\lib\site-packages\socks.py", line 367, in sendto
    self.bind(("", 0))
  File "C:\python3\lib\site-packages\socks.py", line 340, in bind
    super(socksocket, self).bind(*pos, **kw)
AttributeError: 'super' object has no attribute 'bind'

Comment from a similar issue (Socks5 proxy and gevent error AttributeError: 'super' object has no attribute 'getpeername'):

The implication being that if the class also defines a __getattr__ or __getattribute__, then super won't work as expected. :/
Without having given it much thought, my next suggestion would be for PySocks to avoid subclassing the socket and delegate to it instead, much like gevent does. There are a bunch of workarounds in PySocks to make subclassing a socket work, but it's not clear that socket objects are really meant to be subclassed (indeed, the documentation only refers to socket.socket as a function, not a class. (In fact at one time gevent did subclass the socket, but that had so many portability issues that delegation turned out to be the better---only---option, IIRC)
It's not clear to me that there's anything gevent can or should do here.