Skip to content

Commit 61fbc89

Browse files
committed
conn: create from socket fd
This patch adds the ability to create Tarantool connection using an existing socket fd. Closes #304
1 parent 3c8eb9d commit 61fbc89

File tree

4 files changed

+38
-4
lines changed

4 files changed

+38
-4
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## Unreleased
8+
9+
### Added
10+
- The ability to connect to the Tarantool using an existing socket fd (#304).
11+
712
## 1.1.2 - 2023-09-20
813

914
### Fixed

tarantool/__init__.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
__version__ = '0.0.0-dev'
5252

5353

54-
def connect(host="localhost", port=33013, user=None, password=None,
54+
def connect(host="localhost", port=33013, user=None, password=None, use_socket_fd=False,
5555
encoding=ENCODING_DEFAULT, transport=DEFAULT_TRANSPORT,
5656
ssl_key_file=DEFAULT_SSL_KEY_FILE,
5757
ssl_cert_file=DEFAULT_SSL_CERT_FILE,
@@ -69,6 +69,9 @@ def connect(host="localhost", port=33013, user=None, password=None,
6969
:param password: Refer to
7070
:paramref:`~tarantool.Connection.params.password`.
7171
72+
:param use_socket_fd: Refer to
73+
:paramref:`~tarantool.Connection.params.use_socket_fd`.
74+
7275
:param encoding: Refer to
7376
:paramref:`~tarantool.Connection.params.encoding`.
7477
@@ -104,7 +107,8 @@ def connect(host="localhost", port=33013, user=None, password=None,
104107
ssl_key_file=ssl_key_file,
105108
ssl_cert_file=ssl_cert_file,
106109
ssl_ca_file=ssl_ca_file,
107-
ssl_ciphers=ssl_ciphers)
110+
ssl_ciphers=ssl_ciphers,
111+
use_socket_fd=use_socket_fd)
108112

109113

110114
def connectmesh(addrs=({'host': 'localhost', 'port': 3301},), user=None,

tarantool/connection.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ class Connection(ConnectionInterface):
595595
"""
596596

597597
def __init__(self, host, port,
598+
use_socket_fd=False,
598599
user=None,
599600
password=None,
600601
socket_timeout=SOCKET_TIMEOUT,
@@ -626,6 +627,9 @@ def __init__(self, host, port,
626627
:param port: Server port or Unix socket path.
627628
:type port: :obj:`int` or :obj:`str`
628629
630+
:param use_socket_fd: If ``True``, port is treated as socket fd.
631+
:type use_socket_fd: :obj:`bool`, optional
632+
629633
:param user: User name for authentication on the Tarantool
630634
server.
631635
:type user: :obj:`str` or :obj:`None`, optional
@@ -865,6 +869,7 @@ def __init__(self, host, port,
865869
self._server_features = None
866870
self.required_protocol_version = required_protocol_version
867871
self.required_features = copy(required_features)
872+
self.use_socket_fd = use_socket_fd
868873

869874
if connect_now:
870875
self.connect()
@@ -941,9 +946,13 @@ def connect_unix(self):
941946
self.connected = True
942947
if self._socket:
943948
self._socket.close()
944-
self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
949+
if self.use_socket_fd:
950+
# Use an existing fd to create a socket, take ownership.
951+
self._socket = socket.socket(fileno=self.port)
952+
else:
953+
self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
954+
self._socket.connect(self.port)
945955
self._socket.settimeout(self.connection_timeout)
946-
self._socket.connect(self.port)
947956
self._socket.settimeout(self.socket_timeout)
948957
except socket.error as exc:
949958
self.connected = False

test/suites/test_dml.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
This module tests basic data operations.
33
"""
4+
import socket
45
# pylint: disable=missing-class-docstring,missing-function-docstring,protected-access,fixme,too-many-public-methods,duplicate-code
56

67
import sys
@@ -430,6 +431,21 @@ def test_16_extra_error_info_fields(self):
430431
else:
431432
self.fail('Expected error')
432433

434+
def test_17_unix_socket_fd_connect(self):
435+
if sys.platform.startswith("win"):
436+
self.skipTest("Skip UNIX socket tests on Windows since it uses remote server")
437+
438+
# pylint: disable=E1101
439+
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
440+
sock.connect(self.sock_srv.args['primary'])
441+
442+
sock_con = tarantool.connect(self.sock_srv.host, sock.fileno(), use_socket_fd=True)
443+
sock.detach()
444+
try:
445+
self.assertEqual(sock_con.ping(notime=True), "Success")
446+
finally:
447+
sock_con.close()
448+
433449
@classmethod
434450
def tearDownClass(cls):
435451
cls.con.close()

0 commit comments

Comments
 (0)