/*
 * Copyright (C) 2008 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#include <sys/cdefs.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>
#include "resolv_private.h"
#include "resolv_cache.h"
#include <pthread.h>
#include <stdlib.h>
#include <string.h>


/* Set to 1 to enable debug traces */
#define DEBUG 0

#if DEBUG
#  include <async_safe/log.h>
#  include <unistd.h>  /* for gettid() */
#  define D(...) async_safe_format_log(ANDROID_LOG_DEBUG,"libc", __VA_ARGS__)
#else
#  define D(...)  do{}while(0)
#endif

typedef struct {
    int                  _h_errno;
    // TODO: Have one __res_state per network so we don't have to repopulate frequently.
    struct __res_state  _nres[1];
    struct res_static   _rstatic[1];
} _res_thread;

static _res_thread*
_res_thread_alloc(void)
{
    _res_thread*  rt = calloc(1, sizeof(*rt));

    if (rt) {
        rt->_h_errno = 0;
        memset(rt->_rstatic, 0, sizeof rt->_rstatic);
    }
    return rt;
}

static void
_res_static_done(struct res_static* rs)
{
    /* fortunately, there is nothing to do here, since the
     * points in h_addr_ptrs and host_aliases should all
     * point to 'hostbuf'
     */
    if (rs->hostf) {  /* should not happen in theory, but just be safe */
        fclose(rs->hostf);
        rs->hostf = NULL;
    }
    free(rs->servent.s_aliases);
}

static void
_res_thread_free( void*  _rt )
{
    _res_thread*  rt = _rt;

    D("%s: rt=%p for thread=%d", __FUNCTION__, rt, gettid());

    _res_static_done(rt->_rstatic);
    res_ndestroy(rt->_nres);
    free(rt);
}

static pthread_key_t _res_key;

__attribute__((constructor)) static void __res_key_init() {
    pthread_key_create(&_res_key, _res_thread_free);
}

static _res_thread*
_res_thread_get(void)
{
    _res_thread*  rt;
    rt = pthread_getspecific( _res_key );

    if (rt != NULL) {
        return rt;
    }

    /* It is the first time this function is called in this thread,
     * we need to create a new thread-specific DNS resolver state. */
    rt = _res_thread_alloc();
    if (rt == NULL) {
        return NULL;
    }
    pthread_setspecific( _res_key, rt );
    D("%s: tid=%d Created new DNS state rt=%p",
      __FUNCTION__, gettid(), rt);

    /* Reset the state, note that res_ninit() can now properly reset
     * an existing state without leaking memory.
     */
    D("%s: tid=%d, rt=%p, setting DNS state (options RES_INIT=%d)",
      __FUNCTION__, gettid(), rt, (rt->_nres->options & RES_INIT) != 0);
    if ( res_ninit( rt->_nres ) < 0 ) {
        /* This should not happen */
        D("%s: tid=%d rt=%p, woot, res_ninit() returned < 0",
          __FUNCTION__, gettid(), rt);
        _res_thread_free(rt);
        pthread_setspecific( _res_key, NULL );
        return NULL;
    }
    return rt;
}

int*
__get_h_errno(void)
{
    _res_thread*  rt    = _res_thread_get();
    static int    panic = NETDB_INTERNAL;

    return rt ? &rt->_h_errno : &panic;
}

res_state
__res_get_state(void)
{
    _res_thread*  rt = _res_thread_get();

    return rt ? rt->_nres : NULL;
}

void
__res_put_state(res_state res __unused)
{
    /* nothing to do */
}

struct res_static* __res_get_static(void) {
    _res_thread*  rt = _res_thread_get();

    return rt ? rt->_rstatic : NULL;
}
