-
Notifications
You must be signed in to change notification settings - Fork 14
Description
This may be related to #99 and #81. I'm seeing that connections are not being reused when HA reaches out to the adapter.
192.168.1.199 is one of my adapters and 192.168.1.4 is my HA instance. Ignore the entries related to DNS, I have my firewall setup to enforce everything to go to my own DNS server so clients cannot break out of what is given to them via DHCP. Of course Fujitsu does not honor what the local DHCP server pushes out 😠
There are dozens and dozens and dozens more states on this page than what the screenshot shows. What's interesting (and annoying) is that the adapter doesn't seem to support connection reuse:
curl -v 192.168.1.199 192.168.1.199 > /dev/null
* Established connection to 192.168.1.199 (192.168.1.199 port 80) from 192.168.1.63 port 64507
...
* Connection #0 to host 192.168.1.199:80 left intact
* Connection 0 seems to be dead
* shutting down connection #0
* Hostname 192.168.1.199 was found in DNS cache
* Trying 192.168.1.199:80...
* Established connection to 192.168.1.199 (192.168.1.199 port 80) from 192.168.1.63 port 64508
...
The amount of ever-accumulating (but old ones eventually aging out) half-closed connections (FIN_WAIT_2) seems to cause instability with my adapters over time. I'm guessing since they are cheap little things they choke on handling even a small-ish amount of connections (the TCP/IP stack on the adapter itself should have these states) that pile up over time. I don't really know why all of these connections are in a half-closed state. Is it due to something the underlying library is doing?
I have an idea for working around the dumb adapters not supporting connection reuse. I threw this together to show a working example:
import socket
import time
SOURCE_IP = '0.0.0.0'
SOURCE_PORT = 20091
DESTINATION_HOST = '192.168.1.199'
DESTINATION_PORT = 80
while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind((SOURCE_IP, SOURCE_PORT))
s.connect((DESTINATION_HOST, DESTINATION_PORT))
print(f"Connected from source port {SOURCE_PORT} to {DESTINATION_HOST}:{DESTINATION_PORT}")
s.sendall("GET / HTTP/1.1\r\nHost: 192.168.1.199\r\nConnection: keep-alive\r\n\r\n".encode()) # This gives back a 200
# We can't keep using the socket since the adapter forcefully closes the connection at this point.
# Start over with a new connection via our loop but use the same source port that we did before.
except Exception as e:
print(f"Error binding to port or connecting: {e}")
time.sleep(1)
Now if you run this you'll see that there are no more lingering half-closed connections, and the mess of accumulating half-closed connections are gone:

