hub: implement listen as native

The function is largely inspired by the one in eventlet.
That is said, there are nothing exceptional.

Related-bug: #2087939
Change-Id: Ife65518531393fd6ad06730ef8fead02cdb1eb0f
Signed-off-by: Sahid Orentino Ferdjaoui <sahid.ferdjaoui@industrialdiscipline.com>
This commit is contained in:
Sahid Orentino Ferdjaoui
2025-01-10 10:23:33 +01:00
parent f73ecd127a
commit cd8977ee8e
2 changed files with 106 additions and 0 deletions

View File

@@ -18,6 +18,7 @@ import logging
import os
import ssl
import socket
import sys
import traceback
from os_ken.lib import ip
@@ -365,6 +366,26 @@ elif HUB_TYPE == 'native':
except queue.Empty:
pass
def listen(addr, family=socket.AF_INET, backlog=50, reuse_addr=True,
reuse_port=None):
"""
Largely inspired by:
https://github.com/eventlet/eventlet/../eventlet/convenience.py
"""
sock = socket.socket(family, socket.SOCK_STREAM)
if reuse_addr and sys.platform[:3] != 'win':
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
elif reuse_port is None:
reuse_port = True
if reuse_port and hasattr(socket, 'SO_REUSEPORT'):
try:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except Exception:
# Not supported by the platform
pass
sock.bind(addr)
sock.listen(backlog)
return sock
else:
raise NotImplementedError(
"Invalid OSKEN_HUB_TYPE. Expected one of ('eventlet', 'native').")

View File

@@ -264,3 +264,88 @@ class TestThreadManagementNative(unittest.TestCase):
@mock.patch.dict(os.environ, {"OSKEN_HUB_TYPE": "native"})
def setUp(self):
self.hub = importlib.reload(os_ken.lib.hub)
class TestListenEventlet(unittest.TestCase):
@mock.patch.dict(os.environ, {"OSKEN_HUB_TYPE": "eventlet"})
def setUp(self):
self.hub = importlib.reload(os_ken.lib.hub)
self.patcher = mock.patch('eventlet.green.socket.socket')
self.mock_socket = self.patcher.start()
self.sock = mock.MagicMock()
self.mock_socket.return_value = self.sock
class TestListenEventlet(unittest.TestCase):
@mock.patch.dict(os.environ, {"OSKEN_HUB_TYPE": "eventlet"})
def setUp(self):
self.hub = importlib.reload(os_ken.lib.hub)
self.patcher = mock.patch('eventlet.green.socket.socket')
self.mock_socket = self.patcher.start()
self.sock = mock.MagicMock()
self.mock_socket.return_value = self.sock
def tearDown(self):
self.patcher.stop()
def test_default_socket_creation(self):
addr = ('127.0.0.1', 8080)
sock = self.hub.listen(addr)
self.mock_socket.assert_called_once_with(
socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt.assert_has_calls([
mock.call(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1),
mock.call(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1),
])
self.sock.bind.assert_called_once_with(addr)
self.sock.listen.assert_called_once_with(50)
self.assertEqual(self.sock, sock)
def test_socket_with_ipv6(self):
addr = ('::1', 8080)
sock = self.hub.listen(addr, family=socket.AF_INET6)
self.mock_socket.assert_called_once_with(
socket.AF_INET6, socket.SOCK_STREAM)
self.sock.setsockopt.assert_has_calls([
mock.call(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1),
mock.call(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1),
])
self.sock.bind.assert_called_once_with(addr)
self.sock.listen.assert_called_once_with(50)
self.assertEqual(self.sock, sock)
def test_reuse_port_enabled(self):
addr = ('127.0.0.1', 8081)
sock = self.hub.listen(addr, reuse_port=True)
self.sock.setsockopt.assert_any_call(
socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
self.sock.bind.assert_called_once_with(addr)
class TestListenNative(unittest.TestCase):
@mock.patch.dict(os.environ, {"OSKEN_HUB_TYPE": "native"})
def setUp(self):
self.hub = importlib.reload(os_ken.lib.hub)
self.patcher = mock.patch('socket.socket')
self.mock_socket = self.patcher.start()
self.sock = mock.MagicMock()
self.mock_socket.return_value = self.sock