#define ARES_DEFAULT_TRY 4
#define DEFAULT_TEST_URL "www.tizen.org"
+typedef enum {
+ INM_SOCK_TYPE_READ,
+ INM_SOCK_TYPE_WRITE,
+} inm_sock_type_e;
+
+typedef struct {
+ ares_channel ares_ch;
+ inm_sock_type_e sock_type;
+ ares_socket_t fd;
+ GIOChannel *sock_io_channel;
+ guint sock_source_id;
+} inm_gio_channel_s;
+
typedef struct {
ares_channel channel;
struct ares_options *ch_options;
+ GSList *gio_data_list;
guint timer_source_id;
+ gboolean is_lookup_finished;
inm_default_dns_lookup_callback cb;
gpointer cb_user_data;
} inm_dns_lookup_s;
static inm_dns_lookup_s *g_default_dns_lookup_data;
-static inline void __destroy_default_dns_lookup_data();
+static void __destroy_sock_gio_channel(gpointer data)
+{
+ inm_gio_channel_s *gio_channel;
+ if (!data)
+ return;
+
+ gio_channel = (inm_gio_channel_s *)data;
+ INM_LOGI("Destroy %d", gio_channel->fd);
+ inm_util_destroy_gio_channel(gio_channel->sock_io_channel, FALSE);
+ gio_channel->sock_io_channel = NULL;
+
+ REMOVE_G_SOURCE(gio_channel->sock_source_id);
+
+ g_free(gio_channel);
+}
+
+static inline void __deinit_ares_channel(inm_dns_lookup_s *dns_lookup_data)
+{
+ __INM_FUNC_ENTER__;
+
+ if (!dns_lookup_data) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ g_free(dns_lookup_data->ch_options);
+ ares_destroy(dns_lookup_data->channel);
+ dns_lookup_data->channel = NULL;
+
+ __INM_FUNC_EXIT__;
+ return;
+}
+
+static inline void __destroy_default_dns_lookup_data()
+{
+ inm_dns_lookup_s *dns_lookup_data;
+
+ __INM_FUNC_ENTER__;
+ if (!g_default_dns_lookup_data) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+ dns_lookup_data = g_default_dns_lookup_data;
+ g_default_dns_lookup_data = NULL;
+
+ REMOVE_G_SOURCE(dns_lookup_data->timer_source_id);
+
+ g_slist_free_full(dns_lookup_data->gio_data_list,
+ __destroy_sock_gio_channel);
+
+ __deinit_ares_channel(dns_lookup_data);
+ g_free(dns_lookup_data);
+
+ __INM_FUNC_EXIT__;
+ return;
+}
+
+static gboolean __sock_channel_io_cb(GIOChannel *source,
+ GIOCondition condition, gpointer data)
+{
+ inm_gio_channel_s *gio_channel;
+ ares_socket_t read_fd = ARES_SOCKET_BAD;
+ ares_socket_t write_fd = ARES_SOCKET_BAD;
+
+ __INM_FUNC_ENTER__;
+ if (!g_default_dns_lookup_data || !data) {
+ INM_LOGI("default DNS lookup not valid");
+ return FALSE;
+ }
+
+ gio_channel = (inm_gio_channel_s *)data;
+ if (condition & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
+ INM_LOGI("GIO condition error for %d", gio_channel->fd);
+ gio_channel->sock_io_channel = 0;
+ return FALSE;
+ }
+
+ if (gio_channel->sock_type == INM_SOCK_TYPE_READ)
+ read_fd = gio_channel->fd;
+ else
+ write_fd = gio_channel->fd;
+
+ /* We should think about when do we call this? */
+ ares_process_fd(gio_channel->ares_ch, read_fd, write_fd);
+
+ if (g_default_dns_lookup_data->is_lookup_finished)
+ __destroy_default_dns_lookup_data();
+
+ __INM_FUNC_EXIT__;
+ return TRUE;
+}
+
+static int __create_sock_gio_channel(inm_dns_lookup_s *dns_lookup, inm_gio_channel_s **gio_channel)
+{
+ inm_gio_channel_s *p_gio_channel = NULL;
+
+ if (!gio_channel)
+ return -1;
+
+ p_gio_channel = g_try_malloc0(sizeof(inm_gio_channel_s));
+ if (!p_gio_channel)
+ return -1;
+
+ dns_lookup->gio_data_list = g_slist_prepend(dns_lookup->gio_data_list,
+ p_gio_channel);
+
+ *gio_channel = p_gio_channel;
+
+ return 0;
+}
+
+static int __init_sock_gio_channel(inm_sock_type_e sock_type,
+ ares_socket_t fd,
+ inm_gio_channel_s *gio_channel)
+{
+ int ret = 0;
+
+ if (!gio_channel)
+ return -1;
+
+ gio_channel->sock_type = sock_type;
+ gio_channel->fd = fd;
+ ret = inm_util_create_gio_channel(fd, &(gio_channel->sock_io_channel));
+ if (ret != 0)
+ return -1;
+
+ gio_channel->sock_source_id =
+ g_io_add_watch(gio_channel->sock_io_channel,
+ G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+ __sock_channel_io_cb,
+ (gpointer)gio_channel);
+
+ if (!gio_channel->sock_source_id) {
+ inm_util_destroy_gio_channel(gio_channel->sock_io_channel, FALSE);
+ gio_channel->sock_io_channel = NULL;
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static void __remove_sock_gio_channel(inm_dns_lookup_s *dns_lookup, inm_gio_channel_s *gio_channel)
+{
+ if (!dns_lookup || !gio_channel)
+ return;
+
+ INM_LOGI("Remove %d", gio_channel->fd);
+ dns_lookup->gio_data_list =
+ g_slist_remove(dns_lookup->gio_data_list, gio_channel);
+}
+
+static gint __compare_sock_fd(gconstpointer dst, gconstpointer user_data)
+{
+ inm_gio_channel_s *gio_channel_dst;
+ gint32 fd;
+
+ if (!dst)
+ return -1;
+
+ fd = GPOINTER_TO_INT(user_data);
+ gio_channel_dst = (inm_gio_channel_s *)dst;
+
+ return (gio_channel_dst->fd - fd);
+}
+
+static inm_gio_channel_s *__find_gio_channel_data(gint32 fd, inm_dns_lookup_s *dns_lookup_data)
+{
+ GSList *list_node = NULL;
+
+ list_node = g_slist_find_custom(dns_lookup_data->gio_data_list,
+ GINT_TO_POINTER(fd),
+ __compare_sock_fd);
+
+ return list_node ? (inm_gio_channel_s *)list_node->data : NULL;
+}
+
+static void __sock_state_cb(void *data, int fd, int read, int write)
+{
+ inm_dns_lookup_s *dns_lookup;
+ inm_gio_channel_s *gio_channel;
+ int ret;
+
+ __INM_FUNC_ENTER__;
+ INM_LOGI("Change state fd %d read:%d write:%d\n", fd, read, write);
+ if (!g_default_dns_lookup_data || !data) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ dns_lookup = data;
+ gio_channel = __find_gio_channel_data(fd, dns_lookup);
+
+ if (read == 0 && write == 0) {
+ __remove_sock_gio_channel(dns_lookup, gio_channel);
+ __destroy_sock_gio_channel(gio_channel);
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ if (gio_channel) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ ret = __create_sock_gio_channel(dns_lookup, &gio_channel);
+ if (ret < 0) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ ret = __init_sock_gio_channel(read ? INM_SOCK_TYPE_READ : INM_SOCK_TYPE_WRITE,
+ fd,
+ gio_channel);
+ if (ret != 0) {
+ __remove_sock_gio_channel(dns_lookup, gio_channel);
+ __destroy_sock_gio_channel(gio_channel);
+ INM_LOGE("Failed to initialize gio channel");
+ return;
+ }
+ gio_channel->ares_ch = dns_lookup->channel;
+
+ __INM_FUNC_EXIT__;
+ return;
+}
static int __ares_set_opt(inm_dns_lookup_s *lookup_data)
{
return -1;
}
+ p_opts->sock_state_cb = __sock_state_cb;
+ p_opts->sock_state_cb_data = (void *)lookup_data;
p_opts->timeout = ARES_DEFAULT_TIMEOUT_MS;
p_opts->tries = ARES_DEFAULT_TRY;
return -1;
}
+ dns_lookup_data->is_lookup_finished = FALSE;
g_default_dns_lookup_data = dns_lookup_data;
return 0;
}
-static inline void __deinit_ares_channel(inm_dns_lookup_s *dns_lookup_data)
-{
- __INM_FUNC_ENTER__;
-
- if (!dns_lookup_data) {
- __INM_FUNC_EXIT__;
- return;
- }
-
- g_free(dns_lookup_data->ch_options);
- ares_destroy(dns_lookup_data->channel);
- dns_lookup_data->channel = NULL;
-
- __INM_FUNC_EXIT__;
- return;
-}
-
-static inline void __destroy_default_dns_lookup_data()
-{
- inm_dns_lookup_s *dns_lookup_data;
-
- __INM_FUNC_ENTER__;
- if (!g_default_dns_lookup_data) {
- __INM_FUNC_EXIT__;
- return;
- }
- dns_lookup_data = g_default_dns_lookup_data;
- g_default_dns_lookup_data = NULL;
-
- REMOVE_G_SOURCE(dns_lookup_data->timer_source_id);
-
- __deinit_ares_channel(dns_lookup_data);
- g_free(dns_lookup_data);
-
- __INM_FUNC_EXIT__;
- return;
-}
-
static void __ares_host_cb(void *arg, int status, int timeouts, struct hostent *p_host)
{
inm_dns_lookup_s *dns_lookup_data;
result,
p_host ? p_host->h_name : NULL,
dns_lookup_data->cb_user_data);
+ dns_lookup_data->is_lookup_finished = TRUE;
__INM_FUNC_EXIT__;
}