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:
@@ -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').")
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user