def invalid_connection(connection, peer): """ Execute this if the peer has returned the NULL_RESPONSE flag. :param connection: name of the connection requested :param peer: ``net.Peer`` or tuple :return: """ if isinstance(peer, tuple): host = peer[0] port = peer[1] connections = [ str(connection) for connection in net.Peer().registered_connections.keys() ] else: host = peer.host port = peer.port connections = peer.registered_connections raise Exception("Peer does not have the connection you are requesting.\n\t" "Peer: {0}@{1}\n\t" "Registered Connections: \n\t\t{3}\n\t" "Connection Requested: {2}".format( host, port, connection, '\n\t\t'.join(connections)))
def info(*args, **kwargs): """ Return information about the peer requested. .. code-block:: python friendly_information = net.info(peer='somepeer') :return: peer.friendly_id """ information = net.Peer() return { # friendly tag 'tag': str(information), # host 'host': information.host, 'port': information.port, # user 'user': getpass.getuser(), 'executable': sys.executable, # app 'group': information.group, 'hub': information.hub, # interfaces 'connections': sorted(list(information.registered_connections.keys())), 'subscriptions': sorted(list(information.registered_subscriptions.keys())), 'flags': sorted(list(information.registered_flags.keys())), }
def null(*args, **kwargs): """ Return a null response flag :return: NULL Flag """ return net.Peer().get_flag("NULL")
def connections(*args, **kwargs): """ Return the connections registered with the peer. .. code-block:: python friendly_information = net.connections(peer='somepeer') :return: peer.CONNECTIONS """ registered_connections = net.Peer().registered_connections return 'Connections on {1}:\n\t{0}'.format( '\n\n\t'.join([ '{0}\n\t\t{1}'.format(key, registered_connections[key]) for key in registered_connections.keys() ]), net.Peer().friendly_id)
def registry(func): @wraps(func) def handler(*args, **kwargs): return func(*args, **kwargs) # register the function with the peer handler net.Peer().register_flag(name, handler) return handler
def subscription_handler(event, host, port, connection, *args, **kwargs): """ Will register the incoming peer and connection with the local peers subscription of the event passed. This is for internal use only. :param event: event id :param host: foreign peer host :param port: foreign peer port :param connection: connection id """ net.Peer().register_subscriber(event, host, port, connection)
def handle(self): """ Handles all incoming requests to the server. """ raw = self.request.recv(1024) local_peer = net.Peer() # response codes null = local_peer.get_flag('NULL').encode('ascii') invalid_connection = local_peer.get_flag('INVALID_CONNECTION').encode( 'ascii') # if there is no data, bail and don't respond if not raw: self.request.sendall(null) return # convert from json try: data = raw.decode('ascii') try: data = json.loads(data) except Exception as err: net.LOGGER.info( "Could not decode server request data: {0}".format(err)) # skip if there is no data in the request if not data: self.request.sendall(null) return # Get the registered connection connection = local_peer.registered_connections.get( data['connection']) # throw invalid if the connection doesn't exist on this peer. if not connection: self.request.sendall(invalid_connection) return # execute the connection handler and send back response = connection(*data['args'], **data['kwargs']) self.request.sendall(json.dumps(response).encode('ascii')) except Exception as err: net.LOGGER.error(err) net.LOGGER.error(traceback.format_exc()) packet = {'payload': 'error', 'traceback': traceback.format_exc()} self.request.sendall(json.dumps(packet).encode('ascii'))
def peer_group(name=None, hubs_only=False, on_host=False): """ Get a list of peers that are have been detected by net. You can get all peers in the same group as the requesting peer just by calling this function with no filter name. You can also request to only get the hubs for a specific group. .. code-block:: python # Will get all peers in the same group that net.Peer() is in. peers = net.peer_group() # Peers in group1 peers = net.peer_group("group1") # Get the hubs only for the group net.Peer() is in. hubs = net.peer_group(hubs_only=True) # Get only the hubs in group1 hubs = net.peer_group("group1", hubs_only=True) :param name: name of the group :param hubs_only: bool :param on_host: bool :return: list of ``net.Peer`` """ group_peers = [] if not name: name = net.Peer().group found_peers = peers(groups=[name], hubs_only=hubs_only, on_host=on_host) group_data = found_peers.get(name) if group_data: return group_data return group_peers
def interface(*args, **kwargs): new_args, new_kwargs = func(*args, **kwargs) net.Peer().trigger_event(name, *new_args, **new_kwargs) return new_args, new_kwargs
def get_peers(groups, on_host, hubs_only): """ Get a list of all valid remote peers. :param groups: List of groups :param on_host: Search only localhost :param hubs_only: Get Hubs only :return: List of peer addresses """ global PEERS PEERS = { 'peers': {} } # get this peer for pinging peer = net.Peer() server = peer.server # create subnet network = [net.HOST_IP] if not on_host: network = local_network() # logging help total_hosts = len(network) total_ports = len(server.ports()) net.LOGGER.debug( "Calculated network sweep: {0} hosts X {1} ports = {2} pings".format( total_hosts, total_ports, total_hosts * total_ports ) ) # skip the threading integration if the environment does not call for it. if net.THREAD_LIMIT <= 0: return find_peers_in_block(network, groups, hubs_only) # calculate thread chunk. There should always be at least one thread chunk thread_chunks = max(int(math.ceil(total_hosts/net.THREAD_LIMIT)), 1) # loop over and spawn threads start = 0 threads = [] for chunk in range(0, net.THREAD_LIMIT): end = start + thread_chunks thread = threading.Thread( target=find_peers_in_block, args=(network[start:end], groups, hubs_only) ) thread.setName("Network_Scanner_" + str(chunk)) thread.daemon = True threads.append(thread) thread.start() start = end # wait for all worker threads to finish for thread in threads: thread.join() return PEERS
def find_peers_in_block(ips, groups=None, hubs_only=False): """ Sniffs out peers in the defined group based on the list of ip's :param ips: list of ip addresses :param groups: the list of groups you'd like to filter with. Defaults to the same as the current peer. :return: List of peer addresses """ global PEERS # pull in the local peer peer = net.Peer() server = peer.server if not groups: groups = [peer.group] # loop over all the addresses for address in ips: # loop over ports for port in server.ports(): # skip self if port == server.port and address == server.host: continue try: # ping the peer and if it responds with the proper info, # register it. Shut off the logger for this so we dont spam # the console. net.LOGGER.disabled = True info = net.info(peer=(address, port), time_out=0.1) net.LOGGER.disabled = False # skip registering this if the info is already in the # registry. if info['tag'] in PEERS['peers'].values(): continue # filter out peers that aren't in the groups requested. if info['group'] not in groups: continue # filter out non-hubs if that is what was requested if hubs_only and not info['hub']: continue # construct the peer representation new_peer = net.Peer( host=info['host'], port=info['port'], group=info['group'], hub=info['hub'], subscriptions=info['subscriptions'], connections=info['connections'], flags=info['flags'], ) # acquire the lock and register LOCK.acquire() # register with the general information per peer PEERS['peers'][info['tag']] = new_peer # register with the group registry group_registry = PEERS.setdefault(info['group'], []) group_registry.append(new_peer) # release the shared resource LOCK.release() except (PermissionError, ConnectionRefusedError, OSError) as err: net.LOGGER.disabled = False
def subscribe(event, groups=None, hubs_only=False, peers=None, on_host=None): """ Subscribe to an event on another peer or set of peers. When the peer triggers an event using ``net.event``, the peer will take the arguments passed and forward them to this function. By default, this will subscribe to all peers. You can also manually filter the peers by selectively passing in only the peers you want to subscribe to using the ``peers`` keyword argument. Subscribe to "some_event" on group1 peers only. .. code-block:: python group1_peers = net.peers(groups=['group1']) @net.subscribe("some_event", group1_peers) def your_function(subscription_args, subscription_kwarg=None): return some_value Subscribe to "some_event" on a single peer. .. code-block:: python peer = net.peers()[0] @net.subscribe("some_event", peer) def your_function(subscription_args, subscription_kwarg=None): return some_value Subscribe to "some_event" on all peers. .. code-block:: python @net.subscribe("some_event") def your_function(subscription_args, subscription_kwarg=None): return some_value """ this_peer = net.Peer() # handle peers arg if not peers: peers = net.peers( hubs_only=hubs_only, groups=groups, on_host=on_host )['peers'].values() else: if not isinstance(peers, (list, tuple)): peers = [peers] def wrapper(func): # build the connection id connection = this_peer.register_connection(func) # loop over all the requested peers for peer in peers: peer.subscription_handler(event, this_peer.host, this_peer.port, connection) return func return wrapper