""" Module for sending and receiving data over a socket connection with the RaSCSI backend """ import logging from time import sleep from flask import abort from flask_babel import _ def send_pb_command(payload): """ Takes a (str) containing a serialized protobuf as argument. Establishes a socket connection with RaSCSI. """ # Host and port number where rascsi is listening for socket connections host = 'localhost' port = 6868 counter = 0 tries = 20 error_msg = "" import socket while counter < tries: try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: sock.connect((host, port)) return send_over_socket(sock, payload) except socket.error as error: counter += 1 logging.warning("The RaSCSI service is not responding - attempt %s/%s", str(counter), str(tries)) error_msg = str(error) sleep(0.2) logging.error(error_msg) # After failing all attempts, throw a 404 error abort(404, _( u"The RaSCSI Web Interface failed to connect to RaSCSI at %(host)s:%(port)s " u"with error: %(error_msg)s. The RaSCSI process is not running or may have crashed.", host=host, port=port, error_msg=error_msg, ) ) def send_over_socket(sock, payload): """ Takes a socket object and (str) payload with serialized protobuf. Sends payload to RaSCSI over socket and captures the response. Tries to extract and interpret the protobuf header to get response size. Reads data from socket in 2048 bytes chunks until all data is received. """ from struct import pack, unpack # Sending the magic word "RASCSI" to authenticate with the server sock.send(b"RASCSI") # Prepending a little endian 32bit header with the message size sock.send(pack("= 4: # Extracting the response header to get the length of the response message response_length = unpack("