From 554ad88eff82d426a2d2cff720768b20a12993c6 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Mon, 6 Oct 2008 09:41:39 +0000 Subject: [PATCH] Starting work for IPv6 support of ecore_con. Use getaddrinfo and getnameinfo instead of gethostbyname. Patch from Arnaud de Turckheim. SVN revision: 36475 --- legacy/ecore/src/lib/ecore_con/Ecore_Con.h | 9 +- legacy/ecore/src/lib/ecore_con/Makefile.am | 1 + legacy/ecore/src/lib/ecore_con/ecore_con.c | 300 +++++++++++++++++- .../ecore/src/lib/ecore_con/ecore_con_info.c | 295 +++++++++++++++++ .../src/lib/ecore_con/ecore_con_private.h | 8 + 5 files changed, 604 insertions(+), 9 deletions(-) create mode 100644 legacy/ecore/src/lib/ecore_con/ecore_con_info.c diff --git a/legacy/ecore/src/lib/ecore_con/Ecore_Con.h b/legacy/ecore/src/lib/ecore_con/Ecore_Con.h index a1ab4d47f0..6e81ac566d 100644 --- a/legacy/ecore/src/lib/ecore_con/Ecore_Con.h +++ b/legacy/ecore/src/lib/ecore_con/Ecore_Con.h @@ -69,10 +69,11 @@ extern "C" { #endif - typedef struct _Ecore_Con_Server Ecore_Con_Server; /**< A connection handle */ - typedef struct _Ecore_Con_Client Ecore_Con_Client; /**< A connection handle */ - typedef struct _Ecore_Con_Url Ecore_Con_Url; - + typedef struct _Ecore_Con_Server Ecore_Con_Server; /**< A connection handle */ + typedef struct _Ecore_Con_Client Ecore_Con_Client; /**< A connection handle */ + typedef struct _Ecore_Con_Url Ecore_Con_Url; + typedef struct _Ecore_Con_Netinfo Ecore_Con_Netinfo; + typedef enum _Ecore_Con_Type { ECORE_CON_LOCAL_USER, diff --git a/legacy/ecore/src/lib/ecore_con/Makefile.am b/legacy/ecore/src/lib/ecore_con/Makefile.am index aa2e9b877a..b5260471c9 100644 --- a/legacy/ecore/src/lib/ecore_con/Makefile.am +++ b/legacy/ecore/src/lib/ecore_con/Makefile.am @@ -16,6 +16,7 @@ Ecore_Con.h libecore_con_la_SOURCES = \ ecore_con.c \ ecore_con_dns.c \ +ecore_con_info.c \ ecore_con_url.c \ ecore_con_private.h diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con.c b/legacy/ecore/src/lib/ecore_con/ecore_con.c index 677e995025..4c5d5e9800 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con.c +++ b/legacy/ecore/src/lib/ecore_con/ecore_con.c @@ -28,6 +28,10 @@ static void _ecore_con_cb_dns_lookup(void *data, struct hostent *he); static void _ecore_con_cb_udp_dns_lookup(void *data, struct hostent *he); +static void _ecore_con_cb_tcp_connect(void *data, Ecore_Con_Netinfo *info); +static void _ecore_con_cb_udp_connect(void *data, Ecore_Con_Netinfo *info); +static void _ecore_con_cb_tcp_listen(void *data, Ecore_Con_Netinfo *info); +static void _ecore_con_cb_udp_listen(void *data, Ecore_Con_Netinfo *info); static void _ecore_con_server_free(Ecore_Con_Server *svr); static void _ecore_con_client_free(Ecore_Con_Client *cl); static int _ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler); @@ -88,6 +92,7 @@ ecore_con_init(void) /* TODO Remember return value, if it fails, use gethostbyname() */ ecore_con_dns_init(); + ecore_con_info_init(); servers = ecore_list_new(); @@ -110,6 +115,7 @@ ecore_con_shutdown(void) ecore_list_destroy(servers); servers = NULL; + ecore_con_info_shutdown(); ecore_con_dns_shutdown(); ecore_shutdown(); @@ -386,7 +392,7 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port, svr->name = strdup(name); if (!svr->name) goto error; - svr->type = type; + svr->type = compl_type; svr->port = port; svr->data = (void *)data; svr->created = 1; @@ -560,13 +566,11 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port, if (type == ECORE_CON_REMOTE_TCP) { - if (!ecore_con_dns_lookup(svr->name, _ecore_con_cb_dns_lookup, svr)) - goto error; + if (!ecore_con_info_tcp_connect(svr, _ecore_con_cb_tcp_connect, svr)) goto error; } else if (type == ECORE_CON_REMOTE_UDP) { - if (!ecore_con_dns_lookup(svr->name, _ecore_con_cb_udp_dns_lookup, svr)) - goto error; + if (!ecore_con_info_udp_connect(svr, _ecore_con_cb_udp_connect, svr)) goto error; } return svr; @@ -1313,6 +1317,292 @@ _ecore_con_cb_udp_dns_lookup(void *data, struct hostent *he) kill_server(svr); } +static void +_ecore_con_cb_tcp_listen(void *data, Ecore_Con_Netinfo *net_info) +{ + Ecore_Con_Server *svr; + struct linger lin; + + svr = data; + + if(!net_info) goto error; + + svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol); + if (svr->fd < 0) goto error; + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + lin.l_onoff = 1; + lin.l_linger = 0; + if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0) goto error; +/* socket_addr.sin_family = AF_INET; */ +/* socket_addr.sin_port = htons(port); */ +/* socket_addr.sin_addr.s_addr = htonl(INADDR_ANY); */ + if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) goto error; + if (listen(svr->fd, 4096) < 0) goto error; + svr->fd_handler = + ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ, + _ecore_con_svr_handler, svr, NULL, NULL); + if (!svr->fd_handler) goto error; + +#if USE_OPENSSL + if (svr->type & ECORE_CON_SSL) + { + if (!ssl_init_count) + { + SSL_library_init(); + SSL_load_error_strings(); + } + ssl_init_count++; + + switch (svr->type & ECORE_CON_SSL) + { + case ECORE_CON_USE_SSL2: + if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method()))) + goto error; + break; + case ECORE_CON_USE_SSL3: + if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method()))) + goto error; + break; + case ECORE_CON_USE_TLS: + if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) + goto error; + break; + } + + if (!(svr->ssl = SSL_new(svr->ssl_ctx))) + goto error; + + SSL_set_fd(svr->ssl, svr->fd); + } +#endif + + return; + + error: +#if USE_OPENSSL + if (svr->ssl) SSL_free(svr->ssl); + if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx); +#endif + kill_server(svr); +} + +static void +_ecore_con_cb_mcast_listen(void *data, Ecore_Con_Netinfo *net_info) +{ + Ecore_Con_Server *svr; + struct ip_mreq mreq; + struct ipv6_mreq mreq6; + const int on=1; + + svr = data; + + if (!net_info) goto error; + + svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol); + if(svr->fd < 0) goto error; + if (net_info->info.ai_family == AF_INET) + { + if (!inet_pton(net_info->info.ai_family, net_info->ip, &mreq.imr_multiaddr)) goto error; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,sizeof(mreq)) != 0) goto error; + } + else if (net_info->info.ai_family == AF_INET6) + { + if (!inet_pton(net_info->info.ai_family, net_info->ip, &mreq6.ipv6mr_multiaddr)) goto error; + mreq6.ipv6mr_interface = htonl(INADDR_ANY); + if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq6,sizeof(mreq6)) != 0) goto error; + } + if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &on,sizeof(on)) != 0) goto error; + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) goto error; + svr->fd_handler = + ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ, + _ecore_con_svr_udp_handler, svr, NULL, NULL); + if (!svr->fd_handler) goto error; + +#if USE_OPENSSL + if (svr->type & ECORE_CON_SSL) + { + if (!ssl_init_count) + { + SSL_library_init(); + SSL_load_error_strings(); + } + ssl_init_count++; + + switch (svr->type & ECORE_CON_SSL) + { + case ECORE_CON_USE_SSL2: + if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method()))) + goto error; + break; + case ECORE_CON_USE_SSL3: + if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method()))) + goto error; + break; + case ECORE_CON_USE_TLS: + if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) + goto error; + break; + } + + if (!(svr->ssl = SSL_new(svr->ssl_ctx))) + goto error; + + SSL_set_fd(svr->ssl, svr->fd); + } +#endif + + return; + + error: +#if USE_OPENSSL + if (svr->ssl) SSL_free(svr->ssl); + if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx); +#endif + kill_server(svr); +} + +static void +_ecore_con_cb_udp_listen(void *data, Ecore_Con_Netinfo *net_info) +{ + //FIXME SSL + Ecore_Con_Server *svr; + struct sockaddr_in socket_addr; + int curstate = 0; + char buf[64]; + + svr = data; + + if (!net_info) goto error; + svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol); + if (svr->fd < 0) goto error; + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) + goto error; + if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) + goto error; + else + svr->fd_handler = + ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE, + _ecore_con_cl_udp_handler, svr, NULL, NULL); + if (!svr->fd_handler) goto error; + svr->ip = strdup(net_info->ip); + + return; + + error: + kill_server(svr); +} + +static void +_ecore_con_cb_tcp_connect(void *data, Ecore_Con_Netinfo *net_info) +{ + Ecore_Con_Server *svr; + struct sockaddr_in socket_addr; + int curstate = 0; + char buf[64]; + + svr = data; + + if (!net_info) goto error; + svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol); + if (svr->fd < 0) goto error; + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) + goto error; + if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) + { + if (errno != EINPROGRESS) + goto error; + svr->connecting = 1; + svr->fd_handler = + ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE, + _ecore_con_cl_handler, svr, NULL, NULL); + } + else + svr->fd_handler = + ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ, + _ecore_con_cl_handler, svr, NULL, NULL); + + if (!svr->fd_handler) goto error; + svr->ip = strdup(net_info->ip); + +#if USE_OPENSSL + if (svr->type & ECORE_CON_SSL) + { + if (!ssl_init_count) + { + SSL_library_init(); + SSL_load_error_strings(); + } + ssl_init_count++; + + switch (svr->type & ECORE_CON_SSL) + { + case ECORE_CON_USE_SSL2: + if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method()))) + goto error; + break; + case ECORE_CON_USE_SSL3: + if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method()))) + goto error; + break; + case ECORE_CON_USE_TLS: + if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method()))) + goto error; + break; + } + + if (!(svr->ssl = SSL_new(svr->ssl_ctx))) + goto error; + + SSL_set_fd(svr->ssl, svr->fd); + } +#endif + + return; + + error: + kill_server(svr); +} + +static void +_ecore_con_cb_udp_connect(void *data, Ecore_Con_Netinfo *net_info) +{ + Ecore_Con_Server *svr; + struct sockaddr_in socket_addr; + int curstate = 0; + char buf[64]; + + svr = data; + + if (!net_info) goto error; + svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol); + if (svr->fd < 0) goto error; + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) + goto error; + if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) + goto error; + else + svr->fd_handler = + ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE, + _ecore_con_cl_udp_handler, svr, NULL, NULL); + if (!svr->fd_handler) goto error; + svr->ip = strdup(net_info->ip); + + return; + + error: + kill_server(svr); +} + static Ecore_Con_State svr_try_connect_plain(Ecore_Con_Server *svr) { diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con_info.c b/legacy/ecore/src/lib/ecore_con/ecore_con_info.c new file mode 100644 index 0000000000..3da72b8bf6 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_info.c @@ -0,0 +1,295 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +/* + * getaddrinfo with callback + * + * man getaddrinfo + * + */ +#include "ecore_private.h" +#include "Ecore.h" +#include "ecore_con_private.h" + +#include +#include +#include +#include +#include +#include + +typedef struct _CB_Data CB_Data; + +typedef void (*CB_Func)(void *data, Ecore_Con_Netinfo *infos); + +struct _CB_Data +{ + Ecore_List2 __list_data; + CB_Func cb_done; + void *data; + Ecore_Fd_Handler *fdh; + pid_t pid; + Ecore_Event_Handler *handler; + int fd2; +}; + + +static int _ecore_con_info_get(Ecore_Con_Server *svr, CB_Func done_cb, void *data); +static void _ecore_con_info_readdata(CB_Data *cbdata); +static void _ecore_con_info_slave_free(CB_Data *cbdata); +static int _ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event); + +static int info_init = 0; +static Ecore_List2 *info_slaves = NULL; +static struct addrinfo hints; + +int +ecore_con_info_init(void) +{ + info_init++; + return info_init; +} + +int +ecore_con_info_shutdown(void) +{ + info_init--; + if (info_init == 0) + { + while (info_slaves) _ecore_con_info_slave_free((CB_Data *)info_slaves); + } + return info_init; +} + +int +ecore_con_info_tcp_connect(Ecore_Con_Server *svr, + CB_Func done_cb, + void *data) +{ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + hints.ai_addr = NULL; + + return _ecore_con_info_get(svr, done_cb, data); +} + +int +ecore_con_info_tcp_listen(Ecore_Con_Server *svr, + CB_Func done_cb, + void *data) +{ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + hints.ai_addr = NULL; + + return _ecore_con_info_get(svr, done_cb, data); +} + +int +ecore_con_info_udp_connect(Ecore_Con_Server *svr, + CB_Func done_cb, + void *data) +{ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_CANONNAME; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + hints.ai_addr = NULL; + + return _ecore_con_info_get(svr, done_cb, data); +} + +int +ecore_con_info_udp_listen(Ecore_Con_Server *svr, + CB_Func done_cb, + void *data) +{ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + hints.ai_addr = NULL; + + return _ecore_con_info_get(svr, done_cb, data); +} + +int +ecore_con_pre_mcast_listen(Ecore_Con_Server *svr, + CB_Func done_cb, + void *data) +{ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = 0; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_canonname = NULL; + hints.ai_next = NULL; + hints.ai_addr = NULL; + + return _ecore_con_info_get(svr, done_cb, data); +} + +static int +_ecore_con_info_get(Ecore_Con_Server *svr, + CB_Func done_cb, + void *data) +{ + CB_Data *cbdata; + int fd[2]; + + if (pipe(fd) < 0) return 0; + cbdata = calloc(1, sizeof(CB_Data)); + if (!cbdata) + { + close(fd[0]); + close(fd[1]); + return 0; + } + cbdata->cb_done = done_cb; + cbdata->data = data; + cbdata->fd2 = fd[1]; + if (!(cbdata->fdh = ecore_main_fd_handler_add(fd[0], ECORE_FD_READ, + _ecore_con_info_data_handler, + cbdata, + NULL, NULL))) + { + free(cbdata); + close(fd[0]); + close(fd[1]); + return 0; + } + + if ((cbdata->pid = fork()) == 0) + { + Ecore_Con_Netinfo container; + struct addrinfo *result; + char service[NI_MAXSERV]; + char hbuf[NI_MAXHOST]; + char sbuf[NI_MAXSERV]; + + /* FIXME with EINA */ + snprintf(service, NI_MAXSERV, "%i", svr->port); + /* CHILD */ + if (!getaddrinfo(svr->name, service, &hints, &result) && result) + { + memcpy(&container.info, result, sizeof(struct addrinfo)); + container.info.ai_canonname = NULL; + container.info.ai_next = NULL; + memcpy(&container.addr, result->ai_addr, sizeof(struct sockaddr)); + if (!getnameinfo(&container.addr, container.info.ai_addrlen, + hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), + NI_NUMERICHOST | NI_NUMERICSERV)) + { + memcpy(container.ip, hbuf, sizeof(container.ip)); + memcpy(container.service, sbuf, sizeof(container.service)); + } + else + { + memset(container.ip, 0, sizeof(container.ip)); + memset(container.service, 0, sizeof(container.service)); + } + write(fd[1], &container, sizeof(container)); + } + else + write(fd[1], "", 1); + + close(fd[1]); +# ifdef __USE_ISOC99 + _Exit(0); +# else + _exit(0); +# endif + } + /* PARENT */ + cbdata->handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_con_info_exit_handler, cbdata); + close(fd[1]); + if (!cbdata->handler) + { + ecore_main_fd_handler_del(cbdata->fdh); + free(cbdata); + close(fd[0]); + return 0; + } + info_slaves = _ecore_list2_append(info_slaves, cbdata); + return 1; +} + +static void +_ecore_con_info_readdata(CB_Data *cbdata) +{ + Ecore_Con_Netinfo container; + ssize_t size; + + size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container, + sizeof(Ecore_Con_Netinfo)); + if (size == sizeof(Ecore_Con_Netinfo)) + { + container.info.ai_addr = &container.addr; + cbdata->cb_done(cbdata->data, &container); + } + else + cbdata->cb_done(cbdata->data, NULL); + cbdata->cb_done = NULL; +} + +static void +_ecore_con_info_slave_free(CB_Data *cbdata) +{ + info_slaves = _ecore_list2_remove(info_slaves, cbdata); + close(ecore_main_fd_handler_fd_get(cbdata->fdh)); + ecore_main_fd_handler_del(cbdata->fdh); + ecore_event_handler_del(cbdata->handler); + free(cbdata); +} + +static int +_ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler) +{ + CB_Data *cbdata; + + cbdata = data; + if (cbdata->cb_done) + { + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) + _ecore_con_info_readdata(cbdata); + else + { + cbdata->cb_done(cbdata->data, NULL); + cbdata->cb_done = NULL; + } + } + _ecore_con_info_slave_free(cbdata); + return 0; +} + +static int +_ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event) +{ + CB_Data *cbdata; + Ecore_Exe_Event_Del *ev; + + ev = event; + cbdata = data; + if (cbdata->pid != ev->pid) return 1; + return 0; + _ecore_con_info_slave_free(cbdata); + return 0; +} diff --git a/legacy/ecore/src/lib/ecore_con/ecore_con_private.h b/legacy/ecore/src/lib/ecore_con/ecore_con_private.h index c656097983..ceff35bc14 100644 --- a/legacy/ecore/src/lib/ecore_con/ecore_con_private.h +++ b/legacy/ecore/src/lib/ecore_con/ecore_con_private.h @@ -95,6 +95,14 @@ struct _Ecore_Con_Url }; #endif +struct _Ecore_Con_Netinfo +{ + struct addrinfo info; + struct sockaddr addr; + char ip[NI_MAXHOST]; + char service[NI_MAXSERV]; +}; + /* from ecore_con_dns.c */ int ecore_con_dns_init(void); int ecore_con_dns_shutdown(void);