def call(self, *commands): ''' Helper function that implements a (subset of) the RESP protocol used by Redis >= 1.2 ''' cm = context.get_context().connection_mgr sock = BufferedSocket(cm.get_connection(self.address)) # ARRAY: first byte *, decimal length, \r\n, contents out = ['*' + str(len(commands))] + \ ["${0}\r\n{1}".format(len(e), e) for e in commands] out = "\r\n".join(out) + "\r\n" sock.send(out) fbyte = sock.peek(1) if fbyte == "-": # error string raise RedisError(sock.recv_until('\r\n')) elif fbyte == '+': # simple string resp = sock.recv_until('\r\n')[1:] elif fbyte == '$': # bulk string length = int(sock.recv_until('\r\n')[1:]) if length == -1: resp = None else: resp = sock.recv_size(length) cm.release_connection(sock) return resp
def handle_client(self, sock, addr): 'Make sockets available to next process.' bsock = BufferedSocket(sock) secret = bsock.recv_size(len(self.secret)) if secret != self.secret: bsock.send('BAD SECRET.') sock.close() return send_socks = [] for server_sock in self.sockets.values(): if sock.getsockname() == server_sock.getsockname(): continue # exclude the socket-passing-socket send_socks.append(server_sock) sock.send(str(len(send_socks)) + '.') for server_sock in send_socks: sendfileobj.sendfileobj(sock, server_sock) sock.close()
class BlueToothGateway(BanyanBase, threading.Thread): """ This class implements Bluetooth an RFCOMM server or client, configurable from command line options. usage: bluetooth_gateway.py [-h] [-a SERVER_BT_ADDRESS] [-b BACK_PLANE_IP_ADDRESS] [-g GATEWAY_TYPE] [-j JSON_DATA] [-l PUBLISH_TOPIC] [-m SUBSCRIBER_LIST [SUBSCRIBER_LIST ...]] [-n PROCESS_NAME] [-p PUBLISHER_PORT] [-s SUBSCRIBER_PORT] [-t LOOP_TIME] [-u UUID] optional arguments: -h, --help show this help message and exit -a SERVER_BT_ADDRESS Bluetooth MAC Address of Bluetooth Gateway -b BACK_PLANE_IP_ADDRESS None or IP address used by Back Plane -g GATEWAY_TYPE Type of Gateway : server or client -j JSON_DATA Bluetooth packets json encoded True or False -l PUBLISH_TOPIC Banyan publisher topic -m SUBSCRIBER_LIST [SUBSCRIBER_LIST ...] Banyan topics space delimited: topic1 topic2 topic3 -n PROCESS_NAME Set process name in banner -p PUBLISHER_PORT Publisher IP port -s SUBSCRIBER_PORT Subscriber IP port -t LOOP_TIME Event Loop Timer in seconds -u UUID Bluetooth UUID """ # gateway types BTG_SERVER = 0 BTG_CLIENT = 1 def __init__(self, back_plane_ip_address=None, subscriber_port='43125', publisher_port='43124', process_name=None, loop_time=.001, gateway_type=BTG_SERVER, publish_topic=None, uuid='e35d6386-1802-414f-b2b9-375c92fa23e0', server_bt_address=None, subscriber_list=None, json_data=False): """ This method initialize the class for operation """ # save input parameters as instance variables self.back_plane_ip_address = back_plane_ip_address self.subscriber_port = subscriber_port self.publisher_port = publisher_port self.loop_time = loop_time self.gateway_type = gateway_type # set the name for the banner depending upon client or server if process_name is None: if self.gateway_type == self.BTG_CLIENT: self.process_name = 'BanyanBluetoothClient' else: self.process_name = 'BanyanBluetoothServer' else: self.process_name = process_name self.publish_topic = publish_topic self.uuid = uuid self.server_bt_address = server_bt_address self.json_data = json_data # initialize the parent super(BlueToothGateway, self).__init__(back_plane_ip_address=self.back_plane_ip_address, subscriber_port=self.subscriber_port, publisher_port=self.publisher_port, process_name=self.process_name, loop_time=self.loop_time) self.subscriber_list = subscriber_list for topic in self.subscriber_list: self.set_subscriber_topic(topic) print('Subscribed to: ', topic) print('Publish to : ', self.publish_topic) mac = self.find_local_mac_address() if mac: print('Local Bluetooth MAC Address: ', mac) else: print('No Bluetooth Interface Found - Exiting') sys.exit(0) if self.gateway_type == self.BTG_SERVER: self.server_sock = BluetoothSocket(RFCOMM) self.server_sock.bind(("", PORT_ANY)) self.server_sock.listen(1) port = self.server_sock.getsockname()[1] advertise_service( self.server_sock, "BanyanBlueToothServer", service_id=uuid, service_classes=[uuid, SERIAL_PORT_CLASS], profiles=[SERIAL_PORT_PROFILE], ) print("Waiting for connection on RFCOMM channel %d" % port) try: self.client_sock, self.client_info = self.server_sock.accept() except KeyboardInterrupt: self.clean_up() sys.exit(0) print("Accepted connection from ", self.client_info) else: service_matches = find_service(uuid=self.uuid, address=self.server_bt_address) if len(service_matches) == 0: print("Could not find the remote Bluetooth server - exiting") self.clean_up() sys.exit(0) first_match = service_matches[0] port = first_match["port"] name = first_match["name"] host = first_match["host"] print("connecting to \"%s\" on %s" % (name, host)) # Create the client socket self.client_sock = BluetoothSocket(RFCOMM) self.client_sock.connect((host, port)) # wrap the socket for both client and server self.bsock = BufferedSocket(self.client_sock) # create a thread to handle receipt of bluetooth data threading.Thread.__init__(self) self.daemon = True # start the thread self.start() # this will keep the program running forever try: self.receive_loop() except KeyboardInterrupt: self.clean_up() sys.exit(0) def incoming_message_processing(self, topic, payload): """ Process the incoming Banyan message to be sent to the Bluetooth network :param topic: topic string :param payload: payload data """ # if the bluetooth device requires json encoding if self.json_data: data_out = json.dumps(payload) data_out = data_out.encode('utf-8') try: self.bsock.send(data_out) except Exception as e: self.clean_up() raise RuntimeError('Write Error') else: # convert the payload to a string data_out = str(payload['report']) data_out = data_out.encode('utf-8') self.client_sock.send(data_out) def find_local_mac_address(self): """ Get the local bluetooth mac address :return: mac address string or None """ proc = subprocess.Popen(['hcitool', 'dev'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) data = proc.communicate() data = data[0].decode() data = data.split('\t') if len(data) < 2: return None else: return data[2].strip() def run(self): """ This is thread that receives packets from the bluetooth interface :return: """ while True: # if json encoding look for termination character # used for a dictionary if self.json_data: try: data = self.bsock.recv_until(b'}', timeout=0, with_delimiter=True) except KeyboardInterrupt: self.clean_up() sys.exit(0) except Exception as e: continue data = data.decode() data = json.loads(data) self.publish_payload(data, self.publish_topic) # data is not json encoded else: try: data = (self.client_sock.recv(1)).decode() except KeyboardInterrupt: self.clean_up() sys.exit(0) payload = {'command': data} self.publish_payload(payload, self.publish_topic)