cengal.io.asock_io.versions.v_1.tcp_link

  1#!/usr/bin/env python
  2# coding=utf-8
  3
  4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>
  5# 
  6# Licensed under the Apache License, Version 2.0 (the "License");
  7# you may not use this file except in compliance with the License.
  8# You may obtain a copy of the License at
  9# 
 10#     http://www.apache.org/licenses/LICENSE-2.0
 11# 
 12# Unless required by applicable law or agreed to in writing, software
 13# distributed under the License is distributed on an "AS IS" BASIS,
 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15# See the License for the specific language governing permissions and
 16# limitations under the License.
 17
 18import socket
 19from contextlib import contextmanager
 20from cengal.base.classes import BaseClassSettings
 21from .base import *
 22
 23"""
 24Module Docstring
 25Docstrings: http://www.python.org/dev/peps/pep-0257/
 26"""
 27
 28__author__ = "ButenkoMS <gtalk@butenkoms.space>"
 29__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>"
 30__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ]
 31__license__ = "Apache License, Version 2.0"
 32__version__ = "4.4.1"
 33__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>"
 34__email__ = "gtalk@butenkoms.space"
 35# __status__ = "Prototype"
 36__status__ = "Development"
 37# __status__ = "Production"
 38
 39
 40class SimpleTcpLinkError(SimpleNetworkError):
 41    pass
 42
 43
 44class SimpleTcpLink:
 45    """
 46    1 to 1 TCP connection.
 47    """
 48    def __init__(self, settings: ConnectionSettings):
 49        """
 50        Port should not be open to a external world!
 51        :param settings: ConnectionSettings()
 52        :return:
 53        """
 54        self.settings = settings
 55        self.settings.check()
 56        self._block_state = True
 57        self._gate = None
 58        self._conn = None
 59        self._addr = None
 60
 61        self.message_size_len = MESSAGE_SIZE_LEN
 62        self.server_answer__keyword_accepted = SERVER_ANSWER__KEYWORD_ACCEPTED
 63        self.use_nodelay_inet = False
 64        pass
 65
 66    def connect(self):
 67        if ConnectionType.passive == self.settings.connection_type:
 68            self._gate = socket.socket(self.settings.socket_family, self.settings.socket_type,
 69                                       self.settings.socket_protocol, self.settings.socket_fileno)
 70            self._gate.bind(self.settings.socket_address)
 71            self._gate.listen(1)
 72            self._conn, self._addr = self._gate.accept()
 73            print('Connected by', self._addr)
 74            keyword_length_raw = self._conn.recv(self.message_size_len)
 75            keyword_length = int.from_bytes(keyword_length_raw, 'little')
 76            keyword = self._conn.recv(keyword_length)
 77            if keyword == self.settings.keyword:
 78                self._conn.sendall(self._pack_message(self.server_answer__keyword_accepted))
 79            else:
 80                # if we'll use loop, hang will be possible.
 81                raise SimpleTcpLinkError('Wrong keyword: {}. Should be: {}.'.format(
 82                    keyword, self.settings.keyword))
 83        elif ConnectionType.active_connected == self.settings.connection_type:
 84            self._conn = socket.socket(self.settings.socket_family, self.settings.socket_type,
 85                                       self.settings.socket_protocol, self.settings.socket_fileno)
 86            self._conn.connect(self.settings.socket_address)
 87            self.send_message_b(self.settings.keyword)
 88            if self.read_message_b() != self.server_answer__keyword_accepted:
 89                raise SimpleTcpLinkError('Server rejected the keyword: {}.'.format(
 90                    self.settings.keyword))
 91        else:
 92            raise NotImplementedError('Unknown ConnectionType.')
 93
 94        if self.use_nodelay_inet and (self._conn.family in INET_TYPE_CONNECTIONS):
 95            self._conn.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
 96
 97    def send_message_b(self, data):
 98        self._conn.sendall(len(data).to_bytes(self.message_size_len, 'little') + data)
 99
100    def read_message_b(self):
101        return self._conn.recv(int.from_bytes(self._conn.recv(self.message_size_len), 'little'))
102
103    def send_message(self, data):
104        if self._block_state:
105            self.send_message_b(data)
106        else:
107            pass
108        pass
109
110    def read_message(self):
111        if self._block_state:
112            return self.read_message_b()
113        else:
114            pass
115
116    def message_io_iteration(self):
117        pass
118
119    def set_blocking(self, set_blocking_mode=True):
120        pass
121
122    def close(self):
123        if self._conn is not None:
124            self._conn.close()
125        if self._gate is not None:
126            self._gate.close()
127
128    def _pack_message(self, data):
129        return len(data).to_bytes(self.message_size_len, 'little') + data
130
131
132@contextmanager
133def simple_tcp_link_connect(simple_tcp_obj):
134    try:
135        simple_tcp_obj.connect()
136        yield simple_tcp_obj
137    except:
138        raise
139    finally:
140        simple_tcp_obj.close()
class SimpleTcpLinkError(cengal.io.asock_io.versions.v_1.base.SimpleNetworkError):
41class SimpleTcpLinkError(SimpleNetworkError):
42    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args