Beispiel #1
0
def resolve(uri, hmac_key=None):
    """
    Resolve a 'magic' uri (PYRONAME, PYROMETA) into the direct PYRO uri.
    It finds a name server, and use that to resolve a PYRONAME uri into the direct PYRO uri pointing to the named object.
    If uri is already a PYRO uri, it is returned unmodified.
    You can consider this a shortcut function so that you don't have to locate and use a name server proxy yourself.
    Note: if you need to resolve more than a few names, consider using the name server directly instead of repeatedly
    calling this function, to avoid the name server lookup overhead from each call.
    """
    if isinstance(uri, basestring):
        uri = core.URI(uri)
    elif not isinstance(uri, core.URI):
        raise TypeError("can only resolve Pyro URIs")
    if uri.protocol == "PYRO":
        return uri
    log.debug("resolving %s", uri)
    if uri.protocol == "PYRONAME":
        with locateNS(uri.host, uri.port, hmac_key=hmac_key) as nameserver:
            return nameserver.lookup(uri.object)
    elif uri.protocol == "PYROMETA":
        with locateNS(uri.host, uri.port, hmac_key=hmac_key) as nameserver:
            candidates = nameserver.list(metadata_all=uri.object)
            if candidates:
                candidate = random.choice(list(candidates.values()))
                log.debug("resolved to candidate %s", candidate)
                return core.URI(candidate)
            raise NamingError(
                "no registrations available with desired metadata properties %s"
                % uri.object)
    else:
        raise PyroError("invalid uri protocol")
Beispiel #2
0
 def run(self):
     while not self.stop:
         time.sleep(self.loop_delay)
         time_since_last_autoclean = time.time() - self.last_cleaned
         if time_since_last_autoclean < config.NS_AUTOCLEAN:
             continue
         for name, uri in self.nameserver.list().items():
             if name in (constants.DAEMON_NAME, constants.NAMESERVER_NAME):
                 continue
             try:
                 uri_obj = core.URI(uri)
                 timeout = config.COMMTIMEOUT or 5
                 sock = socketutil.createSocket(connect=(uri_obj.host, uri_obj.port), timeout=timeout)
                 sock.close()
                 # if we get here, the listed server is still answering on its port
                 if name in self.unreachable:
                     del self.unreachable[name]
             except socket.error:
                 if name not in self.unreachable:
                     self.unreachable[name] = time.time()
                 if time.time() - self.unreachable[name] >= self.max_unreachable_time:
                     log.info("autoclean: unregistering %s; cannot connect uri %s for %d sec", name, uri, self.max_unreachable_time)
                     self.nameserver.remove(name)
                     del self.unreachable[name]
                     continue
         self.last_cleaned = time.time()
         if self.unreachable:
             log.debug("autoclean: %d/%d names currently unreachable", len(self.unreachable), self.nameserver.count())
Beispiel #3
0
 def processRequest(self):
     try:
         data, addr = self.sock.recvfrom(100)
         if data == b"GET_NSURI":
             responsedata = core.URI(self.nsUri)
             if responsedata.host == "0.0.0.0":
                 # replace INADDR_ANY address by the interface IP address that connects to the requesting client
                 try:
                     interface_ip = socketutil.getInterfaceAddress(addr[0])
                     responsedata.host = interface_ip
                 except socket.error:
                     pass
             log.debug(
                 "responding to broadcast request from %s: interface %s",
                 addr[0], responsedata.host)
             responsedata = str(responsedata).encode("iso-8859-1")
             self.sock.sendto(responsedata, 0, addr)
     except socket.error:
         pass
     except SystemError:
         if sys.platform == "cli" and not self.running:
             # ironpython throws these systemerrors when shutting down... we can ignore them.
             pass
         else:
             raise
Beispiel #4
0
 def lookup(self, name, return_metadata=False):
     """
     Lookup the given name, returns an URI if found.
     Returns tuple (uri, metadata) if return_metadata is True.
     """
     try:
         uri, metadata = self.storage[name]
         uri = core.URI(uri)
         if return_metadata:
             metadata = list(metadata) if metadata else []
             return uri, metadata
         return uri
     except KeyError:
         raise NamingError("unknown name: " + name)
Beispiel #5
0
 def register(self, name, uri, safe=False):
     """Register a name with an URI. If safe is true, name cannot be registered twice.
     The uri can be a string or an URI object."""
     if isinstance(uri, core.URI):
         uri = uri.asString()
     elif not isinstance(uri, basestring):
         raise TypeError("only URIs or strings can be registered")
     else:
         core.URI(uri)  # check if uri is valid
     if not isinstance(name, basestring):
         raise TypeError("name must be a str")
     if safe and name in self.namespace:
         raise NamingError("name already registered: " + name)
     with self.lock:
         self.namespace[name] = uri
Beispiel #6
0
def resolve(uri):
    """Resolve a 'magic' uri (PYRONAME) into the direct PYRO uri."""
    if isinstance(uri, basestring):
        uri = core.URI(uri)
    elif not isinstance(uri, core.URI):
        raise TypeError("can only resolve Pyro URIs")
    if uri.protocol == "PYRO":
        return uri
    log.debug("resolving %s", uri)
    if uri.protocol == "PYRONAME":
        nameserver = locateNS(uri.host, uri.port)
        uri = nameserver.lookup(uri.object)
        nameserver._pyroRelease()
        return uri
    else:
        raise PyroError("invalid uri protocol")
Beispiel #7
0
 def processRequest(self):
     try:
         data, addr = self.sock.recvfrom(100)
         if data == self.REQUEST_NSURI:
             responsedata = core.URI(self.nsUri)
             if responsedata.host == "0.0.0.0":
                 # replace INADDR_ANY address by the interface IP adress that connects to the requesting client
                 try:
                     interface_ip = socketutil.getInterfaceAddress(addr[0])
                     responsedata.host = interface_ip
                 except socket.error:
                     pass
             log.debug(
                 "responding to broadcast request from %s: interface %s",
                 addr[0], responsedata.host)
             responsedata = str(responsedata).encode("iso-8859-1")
             self.sock.sendto(responsedata, 0, addr)
     except socket.error:
         pass
Beispiel #8
0
 def register(self, name, uri, safe=False, metadata=None):
     """Register a name with an URI. If safe is true, name cannot be registered twice.
     The uri can be a string or an URI object. Metadata must be None, or a collection of strings."""
     if isinstance(uri, core.URI):
         uri = uri.asString()
     elif not isinstance(uri, basestring):
         raise TypeError("only URIs or strings can be registered")
     else:
         core.URI(uri)  # check if uri is valid
     if not isinstance(name, basestring):
         raise TypeError("name must be a str")
     if isinstance(metadata, basestring):
         raise TypeError("metadata should not be a str, but another iterable (set, list, etc)")
     metadata and iter(metadata)  # validate that metadata is iterable
     with self.lock:
         if safe and name in self.storage:
             raise NamingError("name already registered: " + name)
         if metadata:
             metadata = set(metadata)
         self.storage[name] = uri, metadata
Beispiel #9
0
def resolve(uri, hmac_key=None):
    """
    Resolve a 'magic' uri (PYRONAME) into the direct PYRO uri.
    It finds a name server, and use that to resolve a PYRONAME uri into the direct PYRO uri pointing to the named object.
    If uri is already a PYRO uri, it is returned unmodified.
    You can consider this a shortcut function so that you don't have to locate and use a name server proxy yourself.
    Note: if you need to resolve more than a few names, consider using the name server directly instead of repeatedly
    calling this function, to avoid the name server lookup overhead from each call.
    """
    if isinstance(uri, basestring):
        uri = core.URI(uri)
    elif not isinstance(uri, core.URI):
        raise TypeError("can only resolve Pyro URIs")
    if uri.protocol == "PYRO":
        return uri
    log.debug("resolving %s", uri)
    if uri.protocol == "PYRONAME":
        nameserver = locateNS(uri.host, uri.port, hmac_key=hmac_key)
        uri = nameserver.lookup(uri.object)
        nameserver._pyroRelease()
        return uri
    else:
        raise PyroError("invalid uri protocol")
Beispiel #10
0
def locateNS(host=None, port=None):
    """Get a proxy for a name server somewhere in the network."""
    if host is None:
        # first try localhost if we have a good chance of finding it there
        if Pyro4.config.NS_HOST in (
                "localhost", "::1") or Pyro4.config.NS_HOST.startswith("127."):
            host = Pyro4.config.NS_HOST
            if ":" in host:  # ipv6
                host = "[%s]" % host
            uristring = "PYRO:%s@%s:%d" % (constants.NAMESERVER_NAME, host,
                                           port or Pyro4.config.NS_PORT)
            log.debug("locating the NS: %s", uristring)
            proxy = core.Proxy(uristring)
            try:
                proxy.ping()
                log.debug("located NS")
                return proxy
            except PyroError:
                pass
        # broadcast lookup
        if not port:
            port = Pyro4.config.NS_BCPORT
        log.debug("broadcast locate")
        sock = Pyro4.socketutil.createBroadcastSocket(
            reuseaddr=Pyro4.config.SOCK_REUSE, timeout=0.7)
        for _ in range(3):
            try:
                for bcaddr in Pyro4.config.parseAddressesString(
                        Pyro4.config.BROADCAST_ADDRS):
                    try:
                        sock.sendto(BroadcastServer.REQUEST_NSURI, 0,
                                    (bcaddr, port))
                    except socket.error:
                        x = sys.exc_info()[1]
                        err = getattr(x, "errno", x.args[0])
                        if err not in Pyro4.socketutil.ERRNO_EADDRNOTAVAIL:  # yeah, windows likes to throw these...
                            if err not in Pyro4.socketutil.ERRNO_EADDRINUSE:  # and jython likes to throw thses...
                                raise
                data, _ = sock.recvfrom(100)
                try:
                    sock.shutdown(socket.SHUT_RDWR)
                except (OSError, socket.error):
                    pass
                sock.close()
                if sys.version_info >= (3, 0):
                    data = data.decode("iso-8859-1")
                log.debug("located NS: %s", data)
                return core.Proxy(data)
            except socket.timeout:
                continue
        try:
            sock.shutdown(socket.SHUT_RDWR)
        except (OSError, socket.error):
            pass
        sock.close()
        log.debug("broadcast locate failed, try direct connection on NS_HOST")
        # broadcast failed, try PYRO directly on specific host
        host = Pyro4.config.NS_HOST
        port = Pyro4.config.NS_PORT
    # pyro direct lookup
    if not port:
        port = Pyro4.config.NS_PORT
    if ":" in host:
        host = "[%s]" % host
    if core.URI.isUnixsockLocation(host):
        uristring = "PYRO:%s@%s" % (constants.NAMESERVER_NAME, host)
    else:
        uristring = "PYRO:%s@%s:%d" % (constants.NAMESERVER_NAME, host, port)
    uri = core.URI(uristring)
    log.debug("locating the NS: %s", uri)
    proxy = core.Proxy(uri)
    try:
        proxy.ping()
        log.debug("located NS")
        return proxy
    except PyroError as x:
        e = NamingError("Failed to locate the nameserver")
        e.__cause__ = x
        raise e
Beispiel #11
0
 def lookup(self, name):
     """Lookup the given name, returns an URI if found"""
     try:
         return core.URI(self.namespace[name])
     except KeyError:
         raise NamingError("unknown name: " + name)
Beispiel #12
0
def locateNS(host=None, port=None, broadcast=True, hmac_key=None):
    """Get a proxy for a name server somewhere in the network."""
    if host is None:
        # first try localhost if we have a good chance of finding it there
        if Pyro4.config.NS_HOST in (
                "localhost", "::1") or Pyro4.config.NS_HOST.startswith("127."):
            if ":" in Pyro4.config.NS_HOST:  # ipv6
                hosts = ["[%s]" % Pyro4.config.NS_HOST]
            else:
                # Some systems (Debian Linux) have 127.0.1.1 in the hosts file assigned to the hostname,
                # try this too for convenience sake (only if it's actually used as a valid ip address)
                try:
                    socket.gethostbyaddr("127.0.1.1")
                    hosts = [Pyro4.config.NS_HOST
                             ] if Pyro4.config.NS_HOST == "127.0.1.1" else [
                                 Pyro4.config.NS_HOST, "127.0.1.1"
                             ]
                except socket.error:
                    hosts = [Pyro4.config.NS_HOST]
            for host in hosts:
                uristring = "PYRO:%s@%s:%d" % (Pyro4.constants.NAMESERVER_NAME,
                                               host, port
                                               or Pyro4.config.NS_PORT)
                log.debug("locating the NS: %s", uristring)
                proxy = core.Proxy(uristring)
                proxy._pyroHmacKey = hmac_key
                try:
                    proxy._pyroBind()
                    log.debug("located NS")
                    return proxy
                except PyroError:
                    pass
        if broadcast:
            # broadcast lookup
            if not port:
                port = Pyro4.config.NS_BCPORT
            log.debug("broadcast locate")
            sock = Pyro4.socketutil.createBroadcastSocket(
                reuseaddr=Pyro4.config.SOCK_REUSE, timeout=0.7)
            for _ in range(3):
                try:
                    for bcaddr in Pyro4.config.parseAddressesString(
                            Pyro4.config.BROADCAST_ADDRS):
                        try:
                            sock.sendto(BroadcastServer.REQUEST_NSURI, 0,
                                        (bcaddr, port))
                        except socket.error:
                            x = sys.exc_info()[1]
                            err = getattr(x, "errno", x.args[0])
                            # handle some errno's that some platforms like to throw:
                            if err not in Pyro4.socketutil.ERRNO_EADDRNOTAVAIL and err not in Pyro4.socketutil.ERRNO_EADDRINUSE:
                                raise
                    data, _ = sock.recvfrom(100)
                    sock.close()
                    if sys.version_info >= (3, 0):
                        data = data.decode("iso-8859-1")
                    log.debug("located NS: %s", data)
                    proxy = core.Proxy(data)
                    proxy._pyroHmacKey = hmac_key
                    return proxy
                except socket.timeout:
                    continue
            try:
                sock.shutdown(socket.SHUT_RDWR)
            except (OSError, socket.error):
                pass
            sock.close()
            log.debug(
                "broadcast locate failed, try direct connection on NS_HOST")
        else:
            log.debug("skipping broadcast lookup")
        # broadcast failed or skipped, try PYRO directly on specific host
        host = Pyro4.config.NS_HOST
        port = Pyro4.config.NS_PORT
    # pyro direct lookup
    if not port:
        port = Pyro4.config.NS_PORT
    if core.URI.isUnixsockLocation(host):
        uristring = "PYRO:%s@%s" % (Pyro4.constants.NAMESERVER_NAME, host)
    else:
        # if not a unix socket, check for ipv6
        if ":" in host:
            host = "[%s]" % host
        uristring = "PYRO:%s@%s:%d" % (Pyro4.constants.NAMESERVER_NAME, host,
                                       port)
    uri = core.URI(uristring)
    log.debug("locating the NS: %s", uri)
    proxy = core.Proxy(uri)
    proxy._pyroHmacKey = hmac_key
    try:
        proxy._pyroBind()
        log.debug("located NS")
        return proxy
    except PyroError as x:
        e = NamingError("Failed to locate the nameserver")
        if sys.version_info >= (3, 0):
            e.__cause__ = x
        raise e