socket_protocol (Socket Protocol)¶
Author:
Dirk Alders <sudo-dirk@mount-mockery.de>
Description:
This Module supports point to point communication for client-server issues.
Submodules:
Unittest:
See also the
unittest
documentation.
Module Documentation:
- socket_protocol.AUTH_STATE_KEY_TRANSFERRED = 3¶
Authentification Status for ‘Key has been sent’
- socket_protocol.AUTH_STATE_SEED_REQUESTED = 1¶
Authentification Status for ‘Seed was requested’
- socket_protocol.AUTH_STATE_SEED_TRANSFERRED = 2¶
Authentification Status for ‘Seed has been sent’
- socket_protocol.AUTH_STATE_TRUSTED_CONNECTION = 4¶
Authentification Status for a ‘Trusted Connection’
- socket_protocol.AUTH_STATE_UNTRUSTED_CONNECTION = 0¶
Authentification Status for an ‘Untrusted Connection’
- socket_protocol.AUTH_STATE__NAMES = {0: 'Untrusted Connection', 1: 'Seed was requested', 2: 'Seed has been sent', 3: 'Key has been sent', 4: 'Trusted Connection'}¶
Authentification Status names for previous defined authentification states
- socket_protocol.DID_AUTH_KEY = 1¶
DID for authentification (key)
- socket_protocol.DID_AUTH_SEED = 0¶
DID for authentification (seed)
- socket_protocol.DID_CHANNEL_NAME = 0¶
DID for channel name
- exception socket_protocol.RequestSidExistsError¶
- exception socket_protocol.ResponseSidExistsError¶
- socket_protocol.SID_AUTH_REQUEST = 0¶
SID for authentification request
- socket_protocol.SID_AUTH_RESPONSE = 1¶
SID for authentification response
- socket_protocol.SID_CHANNEL_NAME_REQUEST = 8¶
SID for channel name exchange request
- socket_protocol.SID_CHANNEL_NAME_RESPONSE = 9¶
SID for channel name exchange response
- socket_protocol.SID_EXECUTE_REQUEST = 30¶
SID for a execute request
- socket_protocol.SID_EXECUTE_RESPONSE = 31¶
SID for a execute response
- socket_protocol.SID_READ_REQUEST = 10¶
SID for a read data request
- socket_protocol.SID_READ_RESPONSE = 11¶
SID for read data response
- socket_protocol.SID_WRITE_REQUEST = 20¶
SID for a write data request
- socket_protocol.SID_WRITE_RESPONSE = 21¶
SID for a write data response
- socket_protocol.STATUS_AUTH_REQUIRED = 3¶
Status for ‘authentification is required’
- socket_protocol.STATUS_BUFFERING_UNHANDLED_REQUEST = 1¶
Status for ‘unhandled request’
- socket_protocol.STATUS_CALLBACK_ERROR = 2¶
Status for ‘callback errors’
- socket_protocol.STATUS_CHECKSUM_ERROR = 5¶
Status for ‘checksum error’
- socket_protocol.STATUS_LOG_LVL = {0: 20, 1: 30, 2: 40, 3: 30, 4: 40, 5: 40, 6: 30}¶
Status depending log level for messages
- socket_protocol.STATUS_OKAY = 0¶
Status for ‘okay’
- socket_protocol.STATUS_OPERATION_NOT_PERMITTED = 6¶
Status for ‘operation not permitted’
- socket_protocol.STATUS_SERVICE_OR_DATA_UNKNOWN = 4¶
Status for ‘service or data unknown’
- class socket_protocol.data_storage(*args, **kwargs)¶
This is a storage object for socket_protocol messages.
- Parameters:
status (int) – The message status.
service_id (int) – The Service-ID.
data_id (int) – The Data-ID.
data (any) – The transfered data.
- get_data(default=None)¶
This Method returns the message data.
- Parameters:
default – The default value, if no data is available.
- get_data_id(default=None)¶
This Method returns the message Data-ID.
- Parameters:
default – The default value, if no data is available.
- get_service_id(default=None)¶
This Method returns the message Service-ID.
- Parameters:
default – The default value, if no data is available.
- get_status(default=None)¶
This Method returns the message status.
- Parameters:
default – The default value, if no data is available.
- class socket_protocol.pure_json_protocol(comm_instance, secret=None, auto_auth=False, channel_name=None)¶
This class supports to transfer a message and it’s data.
- Parameters:
comm_instance (instance) – A communication instance.
secret (str) – An optinal secret (e.g. created by
binascii.hexlify(os.urandom(24))
).auto_auth (bool) – An optional parameter to enable (True) automatic authentification, otherwise you need to do it manually, if needed.
channel_name (str) – An optional parameter to set a channel name for logging of the communication.
Hint
The Service-ID is designed to identify the type of the communication (e.g.
READ_REQUEST
,WRITE_REQUEST
,READ_RESPONSE
,WRITE_RESPONSE
, …)The Data-ID is designed to identify the requests / responses using the same Service_ID.
Note
The
comm_instance
needs to have at least the following interface:A Method
comm_instance.init_channel_name()
to set the channel name.A Constant
comm_instance.IS_CLIENT
to identify that thecomm_instance
is a client (True) or a server (False).A Method
comm_instance.is_connected()
to identify if the instance is connected (True) or not (False).A Method
comm_instance.reconnect()
to initiate a reconnect.A Method
comm_instance.register_callback()
to register a data available callback.A Method
comm_instance.register_connect_callback()
to register a connect callback.A Method
comm_instance.register_disconnect_callback()
to register a disconnect callback.A Method
comm_instance.send()
to send data via thecomm_instance
.
Note
The parameter
auto_auth
is only relevant, if a secret is given and thecomm_instance
is a client. The authentification is initiated directly after the connection is established.Note
The
channel_name
-exchange will be initiated by the client directly after the the connection is established.If a channel_name is given at both communication sides and they are different, the client name is taken over and the server will log a warning message.
Example:
import sys sys.path.append('../..') import report import socket_protocol from socket_protocol_server import example_protocol, DID_ASC_TIME import tcp_socket import time if __name__ == '__main__': report.stdoutLoggingConfigure(log_name_lvl=[('root', 'INFO'), ]) c = tcp_socket.tcp_client_stp('127.0.0.1', 17017) sp = example_protocol(c, channel_name='example_client') sp.send(socket_protocol.SID_READ_REQUEST, DID_ASC_TIME, None) print('The Client received: %s' % repr(sp.receive(socket_protocol.SID_READ_RESPONSE, 0).get_data()))
and
import sys sys.path.append('../..') import report import socket_protocol import tcp_socket import time DID_ASC_TIME = 0 class example_protocol(socket_protocol.pure_json_protocol): def __init__(self, *args, **kwargs): socket_protocol.pure_json_protocol.__init__(self, *args, **kwargs) # self.add_data((socket_protocol.SID_READ_REQUEST, socket_protocol.SID_READ_RESPONSE), DID_ASC_TIME, 'asc_time') # if not self.__comm_inst__.IS_CLIENT: self.register_callback(socket_protocol.SID_READ_REQUEST, 0, self.time_callback) def time_callback(self, msg): if msg.get_status() == socket_protocol.STATUS_OKAY: return socket_protocol.STATUS_OKAY, time.asctime() else: return socket_protocol.STATUS_OPERATION_NOT_PERMITTED, None if __name__ == '__main__': report.stdoutLoggingConfigure(log_name_lvl=[('root', 'INFO'), ]) s = tcp_socket.tcp_server_stp('127.0.0.1', 17017) sp = example_protocol(s, channel_name='example_server') i = 0 while not s.is_connected() and i <= 20: i += 1 time.sleep(.1) # wait for a connection i = 0 while s.is_connected() and i <= 20: i += 1 time.sleep(.1) # wait for disconnect
Will result to the following output:
2024-12-26 00:00:42,804: INFO - socket_protocol.example_client - prot-client: Resetting authentification state to AUTH_STATE_UNTRUSTED_CONNECTION 2024-12-26 00:00:42,804: INFO - socket_protocol.example_client - prot-client: Initialisation finished. 2024-12-26 00:00:42,804: INFO - socket_protocol.example_client - prot-client: TX -> service: read data request, data_id: asc_time, status: okay, data: "None" 2024-12-26 00:00:42,955: INFO - tcp_socket.example_client - comm-client: Connection established... (to 127.0.0.1:17017) 2024-12-26 00:00:42,955: INFO - socket_protocol.example_client - prot-client: TX -> service: channel name request, data_id: name, status: okay, data: "'example_client'" 2024-12-26 00:00:42,956: INFO - tcp_socket.example_client - comm-client: TX -> "(74): 7b 22 64 61 74 61 5f 69 64 22 3a 20 30 2c 20 22 73 65 72 76 69 63 65 5f 69 64 22 3a 20 38 2c 20 22 73 74 61 74 75 73 22 3a 20 30 2c 20 22 64 61 74 61 22 3a 20 22 65 78 61 6d 70 6c 65 5f 63 6c 69 65 6e 74 22 7d f5 cd dd e7" 2024-12-26 00:00:43,006: INFO - tcp_socket.example_client - comm-client: RX <- "(62): 7b 22 64 61 74 61 5f 69 64 22 3a 20 30 2c 20 22 73 65 72 76 69 63 65 5f 69 64 22 3a 20 39 2c 20 22 73 74 61 74 75 73 22 3a 20 30 2c 20 22 64 61 74 61 22 3a 20 6e 75 6c 6c 7d 30 59 be 2f" 2024-12-26 00:00:43,007: INFO - socket_protocol.example_client - prot-client: RX <- service: channel name response, data_id: name, status: okay, data: "None" 2024-12-26 00:00:43,007: INFO - tcp_socket.example_client - comm-client: TX -> "(63): 7b 22 64 61 74 61 5f 69 64 22 3a 20 30 2c 20 22 73 65 72 76 69 63 65 5f 69 64 22 3a 20 31 30 2c 20 22 73 74 61 74 75 73 22 3a 20 30 2c 20 22 64 61 74 61 22 3a 20 6e 75 6c 6c 7d 45 05 7b b4" 2024-12-26 00:00:43,057: INFO - tcp_socket.example_client - comm-client: RX <- "(85): 7b 22 64 61 74 61 5f 69 64 22 3a 20 30 2c 20 22 73 65 72 76 69 63 65 5f 69 64 22 3a 20 31 31 2c 20 22 73 74 61 74 75 73 22 3a 20 30 2c 20 22 64 61 74 61 22 3a 20 22 54 68 75 20 44 65 63 20 32 36 20 30 30 3a 30 30 3a 34 33 20 32 30 32 34 22 7d c8 54 5a b2" 2024-12-26 00:00:43,057: INFO - socket_protocol.example_client - prot-client: RX <- service: read data response, data_id: asc_time, status: okay, data: "'Thu Dec 26 00:00:43 2024'" The Client received: 'Thu Dec 26 00:00:43 2024'
- add_data(service_id, data_id, name)¶
Method to add a name for a specific message.
- Parameters:
service_id (int or list of ints) – The Service-ID of the message. See class definitions starting with
SID_
.data_id (int) – The Data-ID of the message.
name (str) – The Name for the transfered message.
- add_msg_to_auth_whitelist_(service_id, data_id)¶
Method to add a specific message to the list, where no authentification is required.
- Parameters:
service_id (int) – The Service-ID of the message. See class definitions starting with
SID_
.data_id (int) – The Data-ID of the message.
- add_service(req_sid, resp_sid, req_name=None, resp_name=None)¶
Method to add a Service defined by Request- and Response Serivce-ID.
- Parameters:
req_sid (int) – The Request Service-ID.
resp_sid (int) – The Response Service-ID.
- add_status(status, name)¶
Method to add a name for a status.
- Parameters:
status (int) – The Status. See class definitions starting with
STATUS_
.name (str) – The Name for the Status.
- authentificate(timeout=2)¶
This method authetificates the client at the server.
- Parameters:
timeout (float) – The timeout for the authentification (requesting seed, sending key and getting authentification_feedback).
- Returns:
True, if authentification was successfull; False, if not.
- Return type:
bool
Note
An authentification will only processed, if a secret had been given on initialisation.
Note
Client and Server needs to use the same secret.
- check_authentification_state()¶
This Method return the Authitification State as boolean value.
- Returns:
True, if authentification state is okay, otherwise False
- Return type:
bool
- connection_established()¶
This Method returns the Connection state including authentification as a boolean value.
- Returns:
True, if the connection is established (incl. authentification, if a secret has been given)
- Return type:
bool
- is_connected()¶
This Methods returns Connection state of the Communication Instance
comm_instance.is_connected()
.- Returns:
True if the
comm_instance
is connected, otherwise False..- Return type:
bool
- receive(service_id, data_id, timeout=1)¶
This Method returns a message object for a defined message or None, if this message is not available after the given timout.
- Parameters:
service_id (int) – The Service-ID for the message. See class definitions starting with
SID_
.data_id (int) – The Data-ID for the message.
timeout (float) – The timeout for receiving.
- Returns:
The received data storage object or None, if no data was received.
- Return type:
- reconnect()¶
This methods initiates a reconnect by calling
comm_instance.reconnect()
.
- register_callback(service_id, data_id, callback, *args, **kwargs)¶
This method registers a callback for the given parameters. Giving
None
means, that all Service-IDs or all Data-IDs are used. If a message hitting these parameters has been received, the callback will be executed.- Parameters:
service_id (int) – The Service-ID for the message. See class definitions starting with
SID_
.data_id (int) – The Data-ID for the message.
Note
The
callback()
is priorised in the following order:Callbacks with defined Service-ID and Data-ID.
Callbacks with a defined Service-ID and all Data-IDs.
Callbacks with a defined Data-ID and all Service-IDs.
Unspecific Callbacks.
Note
The
callback()
is executed with these arguments:Parameters given at the callback call:
The first Arguments is the received message as
data_storage
object.Further arguments given at registration.
Further keyword arguments given at registration.
Return value of the callback:
If the Callback is a Request Callback for a registered Service, the return value has to be a tuple or list with
response_status
: The response status (see class definitions starting withSTA_*
.response_data
: A JSON iterable object to be used as data for the response.
Note
Only registered services will respond via the callbacks return values with the same data_id.
- send(service_id, data_id, data, status=0, timeout=2)¶
This methods sends out a message with the given content.
- Parameters:
service_id (int) – The Service-ID for the message. See class definitions starting with
SERVICE_
.data_id (int) – The Data-ID for the message.
data (str) – The data to be transfered. The data needs to be json compatible.
status (int) – The Status for the message. All requests should have
STATUS_OKAY
.timeout (float) – The timeout for sending data (e.g. time to establish new connection).
- Returns:
True if data had been sent, otherwise False.
- Return type:
bool
- class socket_protocol.struct_json_protocol(*args, **kwargs)¶
This Class has the same functionality like
pure_json_protocol
. The message length is less than forpure_json_protocol
, but the functionality and compatibility is reduced. See also parentpure_json_protocol
.Note
This class is depreceated and here for compatibility reasons (to support old clients or servers). Usage of
pure_json_protocol
is recommended.