NOEXPORT unsigned idx_cache_retrieve(CLI *c) {
    unsigned i;
    SOCKADDR_UNION addr, *ptr;
    socklen_t len;
    char *addr_txt;

    if(c->ssl && SSL_session_reused(c->ssl)) {
        SSL_SESSION *sess=SSL_get1_session(c->ssl);
        if(sess) {
            CRYPTO_THREAD_read_lock(stunnel_locks[LOCK_ADDR]);
            ptr=SSL_SESSION_get_ex_data(sess, index_session_connect_address);
            if(ptr) {
                len=addr_len(ptr);
                memcpy(&addr, ptr, (size_t)len);
                CRYPTO_THREAD_unlock(stunnel_locks[LOCK_ADDR]);
                SSL_SESSION_free(sess);
                /* address was copied, ptr itself is no longer valid */
                for(i=0; i<c->connect_addr.num; ++i) {
                    if(addr_len(&c->connect_addr.addr[i])==len &&
                            !memcmp(&c->connect_addr.addr[i],
                                &addr, (size_t)len)) {
                        addr_txt=s_ntop(&addr, len);
                        s_log(LOG_INFO, "persistence: %s reused", addr_txt);
                        str_free(addr_txt);
                        return i;
                    }
                }
                addr_txt=s_ntop(&addr, len);
                s_log(LOG_INFO, "persistence: %s not available", addr_txt);
                str_free(addr_txt);
            } else {
                CRYPTO_THREAD_unlock(stunnel_locks[LOCK_ADDR]);
                SSL_SESSION_free(sess);
                s_log(LOG_NOTICE, "persistence: No cached address found");
            }
        }
    }

    if(c->opt->failover==FAILOVER_RR) {
        i=(c->connect_addr.start+c->rr)%c->connect_addr.num;
        s_log(LOG_INFO, "failover: round-robin, starting at entry #%d", i);
    } else {
        i=0;
        s_log(LOG_INFO, "failover: priority, starting at entry #0");
    }
    return i;
}
NOEXPORT unsigned idx_cache_retrieve(CLI *c) {
    unsigned i;
    SOCKADDR_UNION addr, *ptr;
    socklen_t len;
    char *addr_txt;

    if(c->ssl && SSL_session_reused(c->ssl)) {
        SSL_SESSION *sess=SSL_get1_session(c->ssl);
        if(sess) {
            CRYPTO_THREAD_read_lock(stunnel_locks[LOCK_ADDR]);
            ptr=SSL_SESSION_get_ex_data(sess, index_session_connect_address);
            if(ptr) {
                len=addr_len(ptr);
                memcpy(&addr, ptr, (size_t)len);
                CRYPTO_THREAD_unlock(stunnel_locks[LOCK_ADDR]);
                SSL_SESSION_free(sess);
                 
                for(i=0; i<c->connect_addr.num; ++i) {
                    if(addr_len(&c->connect_addr.addr[i])==len &&
                            !memcmp(&c->connect_addr.addr[i],
                                &addr, (size_t)len)) {
                        addr_txt=s_ntop(&addr, len);
                        s_log(LOG_INFO, "persistence: %s reused", addr_txt);
                        str_free(addr_txt);
                        return i;
                    }
                }
                addr_txt=s_ntop(&addr, len);
                s_log(LOG_INFO, "persistence: %s not available", addr_txt);
                str_free(addr_txt);
            } else {
                CRYPTO_THREAD_unlock(stunnel_locks[LOCK_ADDR]);
                SSL_SESSION_free(sess);
                s_log(LOG_NOTICE, "persistence: No cached address found");
            }
        }
    }

    if(c->opt->failover==FAILOVER_RR) {
        i=(c->connect_addr.start+c->rr)%c->connect_addr.num;
        s_log(LOG_INFO, "failover: round-robin, starting at entry #%d", i);
    } else {
        i=0;
        s_log(LOG_INFO, "failover: priority, starting at entry #0");
    }
    return i;
}