|
33 | 33 | class SocketPool:
|
34 | 34 | """ESP32SPI SocketPool library"""
|
35 | 35 |
|
36 |
| - SOCK_STREAM = const(0) |
37 |
| - SOCK_DGRAM = const(1) |
| 36 | + # socketpool constants |
| 37 | + SOCK_STREAM = const(1) |
| 38 | + SOCK_DGRAM = const(2) |
38 | 39 | AF_INET = const(2)
|
39 |
| - NO_SOCKET_AVAIL = const(255) |
| 40 | + SOL_SOCKET = const(0xfff) |
| 41 | + SO_REUSEADDR = const(0x0004) |
40 | 42 |
|
| 43 | + # implementation specific constants |
| 44 | + NO_SOCKET_AVAIL = const(255) |
41 | 45 | MAX_PACKET = const(4000)
|
42 | 46 |
|
43 | 47 | def __new__(cls, iface: ESP_SPIcontrol):
|
@@ -81,14 +85,15 @@ def __init__( # pylint: disable=redefined-builtin,too-many-arguments,unused-arg
|
81 | 85 | type: int = SocketPool.SOCK_STREAM,
|
82 | 86 | proto: int = 0,
|
83 | 87 | fileno: Optional[int] = None,
|
| 88 | + socknum: Optional[int] = None, |
84 | 89 | ):
|
85 | 90 | if family != SocketPool.AF_INET:
|
86 | 91 | raise ValueError("Only AF_INET family supported")
|
87 | 92 | self._socket_pool = socket_pool
|
88 | 93 | self._interface = self._socket_pool._interface
|
89 | 94 | self._type = type
|
90 | 95 | self._buffer = b""
|
91 |
| - self._socknum = self._interface.get_socket() |
| 96 | + self._socknum = socknum if socknum is not None else self._interface.get_socket() |
92 | 97 | self.settimeout(0)
|
93 | 98 |
|
94 | 99 | def __enter__(self):
|
@@ -122,13 +127,14 @@ def send(self, data):
|
122 | 127 | conntype = self._interface.UDP_MODE
|
123 | 128 | else:
|
124 | 129 | conntype = self._interface.TCP_MODE
|
125 |
| - self._interface.socket_write(self._socknum, data, conn_mode=conntype) |
| 130 | + sent = self._interface.socket_write(self._socknum, data, conn_mode=conntype) |
126 | 131 | gc.collect()
|
| 132 | + return sent |
127 | 133 |
|
128 | 134 | def sendto(self, data, address):
|
129 | 135 | """Connect and send some data to the socket."""
|
130 | 136 | self.connect(address)
|
131 |
| - self.send(data) |
| 137 | + return self.send(data) |
132 | 138 |
|
133 | 139 | def recv(self, bufsize: int) -> bytes:
|
134 | 140 | """Reads some bytes from the connected remote address. Will only return
|
@@ -224,3 +230,42 @@ def _connected(self):
|
224 | 230 | def close(self):
|
225 | 231 | """Close the socket, after reading whatever remains"""
|
226 | 232 | self._interface.socket_close(self._socknum)
|
| 233 | + |
| 234 | + #################################################################### |
| 235 | + # WORK IN PROGRESS |
| 236 | + #################################################################### |
| 237 | + |
| 238 | + def setsockopt(self, *opts, **kwopts): |
| 239 | + """Dummy call for compatibility.""" |
| 240 | + # FIXME |
| 241 | + pass |
| 242 | + |
| 243 | + def listen(self, backlog): |
| 244 | + """Dummy call for compatibility.""" |
| 245 | + # FIXME |
| 246 | + # probably nothing to do actually |
| 247 | + # maybe check that we have called bind or something ? |
| 248 | + pass |
| 249 | + |
| 250 | + def setblocking(self, blocking): |
| 251 | + """Dummy call for compatibility.""" |
| 252 | + # FIXME |
| 253 | + # is this settimeout(0) ? (if True) or something else ? |
| 254 | + pass |
| 255 | + |
| 256 | + def bind(self, host_port): |
| 257 | + host, port = host_port |
| 258 | + self._interface.start_server(port, self._socknum) |
| 259 | + print(f"Binding to {self._socknum}") |
| 260 | + |
| 261 | + def accept(self): |
| 262 | + client_sock_num = self._interface.socket_available(self._socknum) |
| 263 | + if client_sock_num != SocketPool.NO_SOCKET_AVAIL: |
| 264 | + sock = Socket(self._socket_pool, socknum=client_sock_num) |
| 265 | + # get remote information (addr and port) |
| 266 | + remote = self._interface.get_remote_data(client_sock_num) |
| 267 | + IP_ADDRESS = "{}.{}.{}.{}".format(*remote['ip_addr']) |
| 268 | + PORT = remote['port'] |
| 269 | + client_address = (IP_ADDRESS, PORT) |
| 270 | + return sock, client_address |
| 271 | + raise OSError(errno.ECONNRESET) |
0 commit comments