def atlas_peer_getinfo( peer_hostport, timeout=None, peer_table=None ):
    """
    Get host info
    Return the rpc_getinfo() response on success
    Return None on error
    """

    if timeout is None:
        timeout = atlas_ping_timeout()

    host, port = url_to_host_port( peer_hostport )
    RPC = get_rpc_client_class()
    rpc = RPC( host, port, timeout=timeout )

    assert not atlas_peer_table_is_locked_by_me()

    log.debug("getinfo %s" % peer_hostport)
    res = None

    try:
        res = blockstack_getinfo( proxy=rpc )
        if 'error' in res:
            log.error("Failed to getinfo on %s: %s" % (peer_hostport, res['error']))

        if 'last_block_processed' not in res:
            log.error("Missing last_block_processed response from {}".format(peer_hostport))
            res = {'error': 'Remote peer {} did not rely last_block_processed'.format(peer_hostport)}

        if 'stale' in res and res['stale']:
            log.error("Remote host {} is well behind the chain tip".format(peer_hostport))
            res = {'error': 'Remote peer {} is well behind the chain tip'.format(peer_hostport)}

        if 'testnet' in res:
            if (res['testnet'] and not BLOCKSTACK_TEST and not BLOCKSTACK_PUBLIC_TESTNET) or (not res['testnet'] and (BLOCKSTACK_TEST or BLOCKSTACK_PUBLIC_TESTNET)):
                if BLOCKSTACK_TEST or BLOCKSTACK_PUBLIC_TESTNET:
                    log.error("Remote host {} is a mainnet host, and we're testnet".format(peer_hostport))
                    res = {'error': 'Remote peer {} is a mainnet host, and we\'re testnet'.format(peer_hostport)}
                else:
                    log.error("Remote host {} is a testnet host".format(peer_hostport))
                    res = {'error': 'Remote peer {} is a testnet host'.format(peer_hostport)}

        else:
            # assume mainnet 
            if BLOCKSTACK_TEST or BLOCKSTACK_PUBLIC_TESTNET:
                log.error("Remote host {} is a mainnet host, and we're testnet".format(peer_hostport))
                res = {'error': 'Remote peer {} is a mainnet host, and we\'re testnet'.format(peer_hostport)}

    except (socket.timeout, socket.gaierror, socket.herror, socket.error), se:
        atlas_log_socket_error( "getinfo(%s)" % peer_hostport, peer_hostport, se )

    except AssertionError, ae:
        log.exception(ae)
        log.error("Invalid server reply for getinfo from %s" % peer_hostport)

    except Exception, e:
        log.exception(e)
        log.error("Failed to get response from %s" % peer_hostport)
  
    if res is not None:
        err = False
        if json_is_error(res):
            log.error("Failed to contact {}: replied error '{}'".format(peer_hostport, res['error']))
            err = True
    
        if 'stale' in res and res['stale']:
            # peer is behind the chain tip
            log.warning("Peer {} reports that it is too far behind the chain tip.  Ignoring for now.".format(peer_hostport))
            err = True

        if err:
            res = None

    else:
        log.error("Failed to contact {}: no response".format(peer_hostport))

    # update health
    with AtlasPeerTableLocked(peer_table) as ptbl:
        if ptbl.has_key(peer_hostport):
            atlas_peer_update_health( peer_hostport, (res is not None), peer_table=ptbl )

    return res
Get host info
    Return the rpc_getinfo() response on success
    Return None on error