From b485aab7e71c1625cfc27e0f92c9509f42378458 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 5 May 2024 13:19:16 +0200 Subject: Adding upstream version 1.45.3+dfsg. Signed-off-by: Daniel Baumann --- .../bases/FrameworkServices/SocketService.py | 336 --------------------- 1 file changed, 336 deletions(-) delete mode 100644 collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py (limited to 'collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py') diff --git a/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py b/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py deleted file mode 100644 index d6c755058..000000000 --- a/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py +++ /dev/null @@ -1,336 +0,0 @@ -# -*- coding: utf-8 -*- -# Description: -# Author: Pawel Krupa (paulfantom) -# Author: Ilya Mashchenko (ilyam8) -# SPDX-License-Identifier: GPL-3.0-or-later - -import errno -import socket - -try: - import ssl -except ImportError: - _TLS_SUPPORT = False -else: - _TLS_SUPPORT = True - -if _TLS_SUPPORT: - try: - PROTOCOL_TLS = ssl.PROTOCOL_TLS - except AttributeError: - PROTOCOL_TLS = ssl.PROTOCOL_SSLv23 - -from bases.FrameworkServices.SimpleService import SimpleService - - -DEFAULT_CONNECT_TIMEOUT = 2.0 -DEFAULT_READ_TIMEOUT = 2.0 -DEFAULT_WRITE_TIMEOUT = 2.0 - - -class SocketService(SimpleService): - def __init__(self, configuration=None, name=None): - self._sock = None - self._keep_alive = False - self.host = 'localhost' - self.port = None - self.unix_socket = None - self.dgram_socket = False - self.request = '' - self.tls = False - self.cert = None - self.key = None - self.__socket_config = None - self.__empty_request = "".encode() - SimpleService.__init__(self, configuration=configuration, name=name) - self.connect_timeout = configuration.get('connect_timeout', DEFAULT_CONNECT_TIMEOUT) - self.read_timeout = configuration.get('read_timeout', DEFAULT_READ_TIMEOUT) - self.write_timeout = configuration.get('write_timeout', DEFAULT_WRITE_TIMEOUT) - - def _socket_error(self, message=None): - if self.unix_socket is not None: - self.error('unix socket "{socket}": {message}'.format(socket=self.unix_socket, - message=message)) - else: - if self.__socket_config is not None: - _, _, _, _, sa = self.__socket_config - self.error('socket to "{address}" port {port}: {message}'.format(address=sa[0], - port=sa[1], - message=message)) - else: - self.error('unknown socket: {0}'.format(message)) - - def _connect2socket(self, res=None): - """ - Connect to a socket, passing the result of getaddrinfo() - :return: boolean - """ - if res is None: - res = self.__socket_config - if res is None: - self.error("Cannot create socket to 'None':") - return False - - af, sock_type, proto, _, sa = res - try: - self.debug('Creating socket to "{address}", port {port}'.format(address=sa[0], port=sa[1])) - self._sock = socket.socket(af, sock_type, proto) - except socket.error as error: - self.error('Failed to create socket "{address}", port {port}, error: {error}'.format(address=sa[0], - port=sa[1], - error=error)) - self._sock = None - self.__socket_config = None - return False - - if self.tls: - try: - self.debug('Encapsulating socket with TLS') - self.debug('Using keyfile: {0}, certfile: {1}, cert_reqs: {2}, ssl_version: {3}'.format( - self.key, self.cert, ssl.CERT_NONE, PROTOCOL_TLS - )) - self._sock = ssl.wrap_socket(self._sock, - keyfile=self.key, - certfile=self.cert, - server_side=False, - cert_reqs=ssl.CERT_NONE, - ssl_version=PROTOCOL_TLS, - ) - except (socket.error, ssl.SSLError, IOError, OSError) as error: - self.error('failed to wrap socket : {0}'.format(repr(error))) - self._disconnect() - self.__socket_config = None - return False - - try: - self.debug('connecting socket to "{address}", port {port}'.format(address=sa[0], port=sa[1])) - self._sock.settimeout(self.connect_timeout) - self.debug('set socket connect timeout to: {0}'.format(self._sock.gettimeout())) - self._sock.connect(sa) - except (socket.error, ssl.SSLError) as error: - self.error('Failed to connect to "{address}", port {port}, error: {error}'.format(address=sa[0], - port=sa[1], - error=error)) - self._disconnect() - self.__socket_config = None - return False - - self.debug('connected to "{address}", port {port}'.format(address=sa[0], port=sa[1])) - self.__socket_config = res - return True - - def _connect2unixsocket(self): - """ - Connect to a unix socket, given its filename - :return: boolean - """ - if self.unix_socket is None: - self.error("cannot connect to unix socket 'None'") - return False - - try: - self.debug('attempting DGRAM unix socket "{0}"'.format(self.unix_socket)) - self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) - self._sock.settimeout(self.connect_timeout) - self.debug('set socket connect timeout to: {0}'.format(self._sock.gettimeout())) - self._sock.connect(self.unix_socket) - self.debug('connected DGRAM unix socket "{0}"'.format(self.unix_socket)) - return True - except socket.error as error: - self.debug('Failed to connect DGRAM unix socket "{socket}": {error}'.format(socket=self.unix_socket, - error=error)) - - try: - self.debug('attempting STREAM unix socket "{0}"'.format(self.unix_socket)) - self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self._sock.settimeout(self.connect_timeout) - self.debug('set socket connect timeout to: {0}'.format(self._sock.gettimeout())) - self._sock.connect(self.unix_socket) - self.debug('connected STREAM unix socket "{0}"'.format(self.unix_socket)) - return True - except socket.error as error: - self.debug('Failed to connect STREAM unix socket "{socket}": {error}'.format(socket=self.unix_socket, - error=error)) - self._sock = None - return False - - def _connect(self): - """ - Recreate socket and connect to it since sockets cannot be reused after closing - Available configurations are IPv6, IPv4 or UNIX socket - :return: - """ - try: - if self.unix_socket is not None: - self._connect2unixsocket() - - else: - if self.__socket_config is not None: - self._connect2socket() - else: - if self.dgram_socket: - sock_type = socket.SOCK_DGRAM - else: - sock_type = socket.SOCK_STREAM - for res in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, sock_type): - if self._connect2socket(res): - break - - except Exception as error: - self.error('unhandled exception during connect : {0}'.format(repr(error))) - self._sock = None - self.__socket_config = None - - def _disconnect(self): - """ - Close socket connection - :return: - """ - if self._sock is not None: - try: - self.debug('closing socket') - self._sock.shutdown(2) # 0 - read, 1 - write, 2 - all - self._sock.close() - except Exception as error: - if not (hasattr(error, 'errno') and error.errno == errno.ENOTCONN): - self.error(error) - self._sock = None - - def _send(self, request=None): - """ - Send request. - :return: boolean - """ - # Send request if it is needed - if self.request != self.__empty_request: - try: - self.debug('set socket write timeout to: {0}'.format(self._sock.gettimeout())) - self._sock.settimeout(self.write_timeout) - self.debug('sending request: {0}'.format(request or self.request)) - self._sock.send(request or self.request) - except Exception as error: - self._socket_error('error sending request: {0}'.format(error)) - self._disconnect() - return False - return True - - def _receive(self, raw=False): - """ - Receive data from socket - :param raw: set `True` to return bytes - :type raw: bool - :return: decoded str or raw bytes - :rtype: str/bytes - """ - data = "" if not raw else b"" - while True: - self.debug('receiving response') - try: - self.debug('set socket read timeout to: {0}'.format(self._sock.gettimeout())) - self._sock.settimeout(self.read_timeout) - buf = self._sock.recv(4096) - except Exception as error: - self._socket_error('failed to receive response: {0}'.format(error)) - self._disconnect() - break - - if buf is None or len(buf) == 0: # handle server disconnect - if data == "" or data == b"": - self._socket_error('unexpectedly disconnected') - else: - self.debug('server closed the connection') - self._disconnect() - break - - self.debug('received data') - data += buf.decode('utf-8', 'ignore') if not raw else buf - if self._check_raw_data(data): - break - - self.debug(u'final response: {0}'.format(data if not raw else u'binary data')) - return data - - def _get_raw_data(self, raw=False, request=None): - """ - Get raw data with low-level "socket" module. - :param raw: set `True` to return bytes - :type raw: bool - :return: decoded data (str) or raw data (bytes) - :rtype: str/bytes - """ - if self._sock is None: - self._connect() - if self._sock is None: - return None - - # Send request if it is needed - if not self._send(request): - return None - - data = self._receive(raw) - - if not self._keep_alive: - self._disconnect() - - return data - - @staticmethod - def _check_raw_data(data): - """ - Check if all data has been gathered from socket - :param data: str - :return: boolean - """ - return bool(data) - - def _parse_config(self): - """ - Parse configuration data - :return: boolean - """ - try: - self.unix_socket = str(self.configuration['socket']) - except (KeyError, TypeError): - self.debug('No unix socket specified. Trying TCP/IP socket.') - self.unix_socket = None - try: - self.host = str(self.configuration['host']) - except (KeyError, TypeError): - self.debug('No host specified. Using: "{0}"'.format(self.host)) - try: - self.port = int(self.configuration['port']) - except (KeyError, TypeError): - self.debug('No port specified. Using: "{0}"'.format(self.port)) - - self.tls = bool(self.configuration.get('tls', self.tls)) - if self.tls and not _TLS_SUPPORT: - self.warning('TLS requested but no TLS module found, disabling TLS support.') - self.tls = False - if _TLS_SUPPORT and not self.tls: - self.debug('No TLS preference specified, not using TLS.') - - if self.tls and _TLS_SUPPORT: - self.key = self.configuration.get('tls_key_file') - self.cert = self.configuration.get('tls_cert_file') - if not self.cert: - # If there's not a valid certificate, clear the key too. - self.debug('No valid TLS client certificate configuration found.') - self.key = None - self.cert = None - elif not self.key: - # If a key isn't listed, the config may still be - # valid, because there may be a key attached to the - # certificate. - self.info('No TLS client key specified, assuming it\'s attached to the certificate.') - self.key = None - - try: - self.request = str(self.configuration['request']) - except (KeyError, TypeError): - self.debug('No request specified. Using: "{0}"'.format(self.request)) - - self.request = self.request.encode() - - def check(self): - self._parse_config() - return SimpleService.check(self) -- cgit v1.2.3