Example #1
0
def ping(config_file_path, logger=None):
    #lets a connector ping a remote connector peer
    if not logger:
        logger = aioconnectors.get_logger(logger_name='ping', first_run=True)    
    logger.info('Creating connector api with config file '+config_file_path)    
    connector_api = aioconnectors.ConnectorAPI(config_file_path=config_file_path)
    destination_id = None
    if connector_api.is_server:
        destination_id = input('\nPlease type the name of your remote client\n')
        
    loop = asyncio.get_event_loop()
    
    async def send_messages(destination_id):
        index = 0
        while True:
            index += 1
            print(f'\nSENDING PING to peer {destination_id or connector_api.server_sockaddr} with index {index}')
            response = await connector_api.send_message_await_response(data=f'PING {str(index)*5}', data_is_json=False, 
                                                destination_id=destination_id, message_type='_ping', request_id=index)
                                                    #response_id=None, binary=b'\x01\x02\x03\x04\x05', with_file=None, wait_for_ack=False)
            if response:
                try:
                    transport_json, data, binary = response
                except Exception as exc:
                    print(exc)
                    return
                print(f'RECEIVING REPLY from peer {destination_id or connector_api.server_sockaddr} with data {data}')                                                        
            await asyncio.sleep(2)
                    
    task_send = loop.create_task(send_messages(destination_id))
    try:
        loop.run_forever()
    except:
        task_send.cancel()
        print('ping stopped !')
Example #2
0
def test_receive_messages(config_file_path, logger=None):
    if not logger:
        logger = aioconnectors.get_logger(logger_name='test_receive_messages', first_run=True)    
    print('Warning : No other application should be receiving events from this connector')
    logger.info('Creating connector api with config file '+config_file_path)
    connector_api = aioconnectors.ConnectorAPI(config_file_path=config_file_path)
    loop = asyncio.get_event_loop()
    tasks_waiting_for_messages = []
    
    async def message_received_cb(logger, transport_json , data, binary):
        logger.info(f'RECEIVED MESSAGE {transport_json}')
        print(f'RECEIVED MESSAGE {transport_json}')
        if data:
            print(f'\tWith data {data.decode()}')
        if binary:
            print(f'\tWith binary {binary}')
    
    for message_type in connector_api.recv_message_types:
        task_api = loop.create_task(connector_api.start_waiting_for_messages(message_type=message_type, 
                                                                             message_received_cb=message_received_cb))
        tasks_waiting_for_messages.append(task_api)
    try:
        loop.run_forever()
    except:
        for message_type in connector_api.recv_message_types:
            connector_api.stop_waiting_for_messages(message_type=message_type)            
        #for task_api in tasks_waiting_for_messages:
        #    task_api.cancel()
        print('test_receive_messages stopped !')
Example #3
0
def test_publish_messages(config_file_path, logger=None):
    if not logger:
        logger = aioconnectors.get_logger(logger_name='test_publish_messages', first_run=True)    
    logger.info('Creating connector api with config file '+config_file_path)
    connector_api = aioconnectors.ConnectorAPI(config_file_path=config_file_path)
    destination_id = None
    if connector_api.is_server:
        destination_id = input('\nPlease type the name of your remote client\n')
        
    loop = asyncio.get_event_loop()
    
    async def send_messages(destination_id):
        index = 0
        while True:
            index += 1
            for message_type in connector_api.send_message_types:
                if message_type == '_pubsub':
                    continue
                print(f'PUBLISHING MESSAGE to peer {destination_id or connector_api.server_sockaddr} of type '
                      f'{message_type} and index {index}')
                response = await connector_api.publish_message(data=f'"TEST_MESSAGE {str(index)*5}"', data_is_json=False,
                                                                                  destination_id=destination_id,
                                                        message_type=message_type, await_response=False, request_id=index)
                                                        #response_id=None, binary=b'\x01\x02\x03\x04\x05', with_file=None, wait_for_ack=False)        
            await asyncio.sleep(2)
                    
    task_send = loop.create_task(send_messages(destination_id))
    try:
        loop.run_forever()
    except:
        task_send.cancel()
        print('test_publish_messages stopped !')
Example #4
0
def chat(args, logger=None):
    #chat supports sending messages and files/directories between 2 connectors
    if not logger:
        logger = aioconnectors.get_logger(logger_name='chat', first_run=True)
    custom_prompt = 'aioconnectors>> '        
    chat_client_name = 'chat_client'
    CONNECTOR_FILES_DIRPATH = aioconnectors.get_tmp_dir()
    delete_connector_dirpath_later = not os.path.exists(CONNECTOR_FILES_DIRPATH)
    is_server = not args.target
    accept_all_clients = args.accept
    loop = asyncio.get_event_loop()
    cwd = os.getcwd()
    
        
    class AuthClient:
        #helper for client authentication on server connector
        perform_client_authentication = False
        authenticate = asyncio.Event()
        allow = False
        
        @staticmethod
        def update_allow(status):
            #User chooses the value of "allow", which is sent back to server connector
            AuthClient.allow = status
            AuthClient.perform_client_authentication = False
            AuthClient.authenticate.set()
        
        @staticmethod
        async def authenticate_client(client_name):
            #called as a hook by server when receiving new connection
            #waits for user input
            AuthClient.perform_client_authentication = True
            print(f'Accept client {client_name} ? y/n')
            await AuthClient.authenticate.wait()
            AuthClient.authenticate.clear()
            return AuthClient.allow

    
    if is_server:
        listening_ip = args.bind_server_ip or '0.0.0.0'
        if '.' not in listening_ip:
            listening_ip = aioconnectors.iface_to_ip(listening_ip)
        server_sockaddr = (listening_ip, int(args.port or 0) or aioconnectors.core.Connector.SERVER_ADDR[1])
        connector_files_dirpath = CONNECTOR_FILES_DIRPATH
        aioconnectors.ssl_helper.create_certificates(logger, certificates_directory_path=connector_files_dirpath)           
        connector_manager = aioconnectors.ConnectorManager(is_server=True, server_sockaddr=server_sockaddr, 
                                                           use_ssl=True, ssl_allow_all=True,
                                                           connector_files_dirpath=connector_files_dirpath, 
                                                           certificates_directory_path=connector_files_dirpath,
                                                           send_message_types=['any'], recv_message_types=['any'], 
                                                           file_recv_config={'any': {'target_directory':cwd}},
                                                           hook_server_auth_client=None if accept_all_clients else \
                                                           AuthClient.authenticate_client)
                    
        connector_api = aioconnectors.ConnectorAPI(is_server=True, server_sockaddr=server_sockaddr, 
                                                   connector_files_dirpath=connector_files_dirpath,
                                                           send_message_types=['any'], recv_message_types=['any'], 
                                                           default_logger_log_level='INFO',
                                                           default_logger_rotate=True)
        destination_id = chat_client_name
    else:
        server_sockaddr = (args.target, args.port or aioconnectors.core.Connector.SERVER_ADDR[1])
        connector_files_dirpath = CONNECTOR_FILES_DIRPATH
        aioconnectors.ssl_helper.create_certificates(logger, certificates_directory_path=connector_files_dirpath)            
        connector_manager = aioconnectors.ConnectorManager(is_server=False, server_sockaddr=server_sockaddr, 
                                                           use_ssl=True, ssl_allow_all=True,
                                                           connector_files_dirpath=connector_files_dirpath, 
                                                           certificates_directory_path=connector_files_dirpath,
                                                           send_message_types=['any'], recv_message_types=['any'], 
                                                           file_recv_config={'any': {'target_directory':cwd}},
                                                           client_name=chat_client_name, enable_client_try_reconnect=False)

        connector_api = aioconnectors.ConnectorAPI(is_server=False, server_sockaddr=server_sockaddr, 
                                                   connector_files_dirpath=connector_files_dirpath, 
                                                   client_name=chat_client_name,
                                                   send_message_types=['any'], recv_message_types=['any'], 
                                                   default_logger_log_level='INFO',
                                                   default_logger_rotate=True)
        destination_id = None
        
        
    task_manager = loop.create_task(connector_manager.start_connector())
    #run_until_complete now, in order to exit in case of exception
    #for example because of already existing socket
    loop.run_until_complete(task_manager)  
    
    task_recv = task_console = task_send_file = None
    
    async def message_received_cb(logger, transport_json , data, binary):
        #callback when a message is received from peer
        if transport_json.get('await_response'):
            #this response is necessary in args.upload mode, to know when to exit
            #it is in fact used also in chat mode by send_file, even if not mandatory
            loop.create_task(connector_api.send_message(data=data, data_is_json=False, message_type='any', 
                                                        response_id=transport_json['request_id'],
                                                        destination_id=transport_json['source_id']))
        if data:
            #display message received from peer
            print(data.decode())
            print(custom_prompt,end='', flush=True)                

    if not args.upload:  
        task_recv = loop.create_task(connector_api.start_waiting_for_messages(message_type='any', 
                                                                              message_received_cb=message_received_cb))
        
    async def send_file(data, destination_id, with_file, delete_after_upload):
        #upload file to peer. uses await_response always, mandatory for upload mode
        await connector_api.send_message(data=data, data_is_json=False, destination_id=destination_id, 
                                         await_response=True, request_id=random.randint(1,1000),
                                         message_type='any', with_file=with_file)
        if delete_after_upload:
            os.remove(delete_after_upload)
        
    class InputProtocolFactory(asyncio.Protocol):
        #hook user input : sends message to peer, and support special cases (!)

        def connection_made(self, *args, **kwargs):
            super().connection_made(*args, **kwargs)
            print(custom_prompt,end='', flush=True)
            
        def data_received(self, data):
            data = data.decode().strip()
            if AuthClient.perform_client_authentication:
                if data == 'y':
                    AuthClient.update_allow(True)
                else:# data == 'n':
                    AuthClient.update_allow(False)
                print(custom_prompt,end='', flush=True)
                return
            
            if data == '!exit':
                os.kill(os.getpid(), signal.SIGINT)
                return
            
            if data.startswith('!upload '):
                try:
                    with_file = None
                    delete_after_upload = False                    
                    upload_path = data[len('!upload '):]
                    
                    if not os.path.exists(upload_path):
                        raise Exception(upload_path + ' does not exist')
                    if os.path.isdir(upload_path):
                        upload_path_zip = f'{upload_path}.zip'
                        if not os.path.exists(upload_path_zip):
                            shutil.make_archive(upload_path, 'zip', upload_path)
                            delete_after_upload = upload_path_zip   
                        upload_path = upload_path_zip
                        #if zip already exists, don't override it, just send it (even if it may not be the correct zip)
                    
                    data = f'Receiving {upload_path}'
                    with_file={'src_path':upload_path,'dst_type':'any', 'dst_name':os.path.basename(upload_path), 
                               'delete':False}                   
                    loop.create_task(send_file(data, destination_id, with_file, delete_after_upload))
                except Exception as exc:
                    res = str(exc)
                    print(custom_prompt,end='', flush=True)
                    print(res)                        
                print(custom_prompt,end='', flush=True)
                return
            
            if data.startswith('!dezip '):
                try:
                    target = data.split('!dezip ')[1]
                    #copy target to cwd
                    #shutil.copy(os.path.join(CONNECTOR_FILES_DIRPATH, target), target)
                    target_dir = target.split('.zip')[0]
                    with zipfile.ZipFile(target) as zf:
                        zf.extractall(path=target_dir)
                except Exception as exc:
                    res = str(exc)
                    print(custom_prompt,end='', flush=True)
                    print(res)
                print(custom_prompt,end='', flush=True)
                return                        
                    
            elif data.startswith('!'):
                data_shell = data[1:]
                if data_shell:
                    try:
                        res = subprocess.check_output(data_shell, stderr=subprocess.PIPE, shell=True)
                        res = res.decode().strip()
                    except subprocess.CalledProcessError as exc:
                        res = str(exc)
                    print(custom_prompt,end='', flush=True)
                    print(res)
                    print(custom_prompt,end='', flush=True)
                    return

            loop.create_task(connector_api.send_message(data=data, data_is_json=False, destination_id=destination_id, 
                                                        message_type='any'))                   
            print(custom_prompt,end='', flush=True)
        
    async def connect_pipe_to_stdin(loop, connector_manager):
        #hook user input       
        if not is_server:
            print('Connector waiting to connect ... (Ctrl+C to quit)')

            while True:
                await asyncio.sleep(1)                
                if connector_manager.show_connected_peers():
                    print('Connected !')
                    break                  
        
        transport, protocol = await loop.connect_read_pipe(InputProtocolFactory, sys.stdin)        
    
    async def upload_file(args, destination_id):
        #called when client uses the upload mode, which uploads and disconnects, without opening a chat
        await asyncio.sleep(3)    #wait for connection      
        upload_path = args.upload
        delete_after_upload = False
        if os.path.isdir(upload_path):
            upload_path_zip = f'{upload_path}.zip'
            if not os.path.exists(upload_path_zip):
                shutil.make_archive(upload_path, 'zip', upload_path)
                delete_after_upload = upload_path_zip    
            upload_path = upload_path_zip
            #if zip already exists, don't override it, just send it (even if it may not be the correct zip)
            
        with_file={'src_path':upload_path,'dst_type':'any', 'dst_name':os.path.basename(upload_path), 'delete':False}    
        await send_file('', destination_id, with_file, delete_after_upload)
            
    if not args.upload:
        #chat mode, hook stdin
        task_console = loop.create_task(connect_pipe_to_stdin(loop, connector_manager))
    else:
        #upload mode, upload and exit
        task_send_file = loop.create_task(upload_file(args, destination_id))
        task_send_file.add_done_callback(lambda inp:os.kill(os.getpid(), signal.SIGINT))

    try:
        loop.run_forever()
    except:    
        print('Connector stopped !')

    task_stop = loop.create_task(connector_manager.stop_connector(delay=None, hard=False, shutdown=True))            
    loop.run_until_complete(task_stop)
    if task_console:
        del task_console
    if task_recv:
        connector_api.stop_waiting_for_messages(message_type='any')
        del task_recv
    del task_stop
    del task_manager
    del connector_manager
    if delete_connector_dirpath_later and os.path.exists(connector_files_dirpath):
        shutil.rmtree(connector_files_dirpath)
Example #5
0
            except:
                task_stop = loop.create_task(
                    connector_manager.stop_connector(shutdown=True))
                loop.run_until_complete(task_stop)
                del connector_manager
                print('Client stopped !')

        elif sys.argv[1] == 'send2client':
            print('Started send2client')
            own_source_id = local_name or CLIENT_NAMES[0]

            connector_api = aioconnectors.ConnectorAPI(
                default_logger_log_level=DEFAULT_LOGGER_LOG_LEVEL,
                server_sockaddr=SERVER_SOCKADDR,
                client_name=own_source_id,
                is_server=False,
                send_message_types=CLIENT_MESSAGE_TYPES,
                recv_message_types=SERVER_MESSAGE_TYPES,
                uds_path_send_preserve_socket=UDS_PATH_SEND_PRESERVE_SOCKET
            )  #, uds_path_receive_preserve_socket=UDS_PATH_RECEIVE_PRESERVE_SOCKET)
            loop = asyncio.get_event_loop()

            if TEST_COMMANDER_CLIENT:
                loop.create_task(connector_api.delete_client_certificate())

            async def client_cb_type1(logger, transport_json, data, binary):
                peer_id = transport_json['source_id']
                increment_result(own_source_id, peer_id, 'type1', 'recv')

            async def client_cb_type2(logger, transport_json, data, binary):
                peer_id = transport_json['source_id']