Fix entrance and perhaps exquisite too.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 9 Oct 2008 12:30:19 +0000 (12:30 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 9 Oct 2008 12:30:19 +0000 (12:30 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/ecore@36545 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/ecore_con/Ecore_Con.h
src/lib/ecore_con/Makefile.am
src/lib/ecore_con/ecore_con.c
src/lib/ecore_con/ecore_con_info.c [new file with mode: 0644]
src/lib/ecore_con/ecore_con_private.h

index a1ab4d4..d5e0f2c 100644 (file)
  * There are two main objects in the @c Ecore_Con library: the @c
  * Ecore_Con_Server and the @c Ecore_Con_Client.
  *
- * The @c Ecore_Con_Server represents a server that can be connected to.  
- * It is used regardless of whether the program is acting as a server or 
+ * The @c Ecore_Con_Server represents a server that can be connected to.
+ * It is used regardless of whether the program is acting as a server or
  * client itself.
  *
  * To create a listening server, call @c ecore_con_server_add().
  *
  * To connect to a server, call @c ecore_con_server_connect().  Data can
  * then be sent to the server using the @c ecore_con_server_send().
- * 
+ *
  * Whenever a client connection is made to an @c Ecore_Con_Server, a
  * @c ECORE_CON_CLIENT_ADD event is emitted.  Any event callbacks that are
  * called receive a @c Ecore_Con_Client object, which represents a
 #ifdef __cplusplus
 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_Info    Ecore_Con_Info;
+
+   typedef void (*Ecore_Con_Info_Cb)(void *data, Ecore_Con_Info *infos);
+
    typedef enum _Ecore_Con_Type
      {
        ECORE_CON_LOCAL_USER,
@@ -125,28 +128,28 @@ extern "C" {
      {
        Ecore_Con_Server *server;
      };
-   
+
    struct _Ecore_Con_Event_Client_Data
      {
        Ecore_Con_Client *client;
        void             *data;
        int               size;
      };
-   
+
    struct _Ecore_Con_Event_Server_Data
      {
        Ecore_Con_Server *server;
        void             *data;
        int               size;
      };
-   
+
    struct _Ecore_Con_Event_Url_Data
      {
        Ecore_Con_Url    *url_con;
        int               size;
        unsigned char     data[1];
      };
-        
+
    struct _Ecore_Con_Event_Url_Complete
      {
        Ecore_Con_Url    *url_con;
@@ -175,12 +178,12 @@ extern "C" {
    EAPI extern int ECORE_CON_EVENT_URL_DATA;
    EAPI extern int ECORE_CON_EVENT_URL_COMPLETE;
    EAPI extern int ECORE_CON_EVENT_URL_PROGRESS;
-   
+
    EAPI int               ecore_con_init(void);
    EAPI int               ecore_con_shutdown(void);
-   
+
    EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type, const char *name, int port, const void *data);
-   
+
    EAPI Ecore_Con_Server *ecore_con_server_connect(Ecore_Con_Type type, const char *name, int port, const void *data);
    EAPI void             *ecore_con_server_del(Ecore_Con_Server *svr);
    EAPI void             *ecore_con_server_data_get(Ecore_Con_Server *svr);
@@ -190,7 +193,7 @@ extern "C" {
    EAPI void              ecore_con_server_client_limit_set(Ecore_Con_Server *svr, int client_limit, char reject_excess_clients);
    EAPI char             *ecore_con_server_ip_get(Ecore_Con_Server *svr);
    EAPI void              ecore_con_server_flush(Ecore_Con_Server *svr);
-   
+
    EAPI int               ecore_con_client_send(Ecore_Con_Client *cl, const void *data, int size);
    EAPI Ecore_Con_Server *ecore_con_client_server_get(Ecore_Con_Client *cl);
    EAPI void             *ecore_con_client_del(Ecore_Con_Client *cl);
@@ -198,7 +201,7 @@ extern "C" {
    EAPI void             *ecore_con_client_data_get(Ecore_Con_Client *cl);
    EAPI char             *ecore_con_client_ip_get(Ecore_Con_Client *cl);
    EAPI void              ecore_con_client_flush(Ecore_Con_Client *cl);
-   
+
    EAPI int               ecore_con_ssl_available_get(void);
 
    EAPI int               ecore_con_url_init(void);
@@ -217,8 +220,9 @@ extern "C" {
    EAPI int               ecore_con_dns_lookup(const char *name,
                                               void (*done_cb)(void *data, struct hostent *hostent),
                                               void *data);
+   EAPI int              ecore_con_info_get(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data, struct addrinfo *hints);
 #endif
-                                              
+
    EAPI int              ecore_con_url_ftp_upload(Ecore_Con_Url *url_con, char *filename, char *user, char *pass, char *upload_dir);
    EAPI void             ecore_con_url_verbose_set(Ecore_Con_Url *url_con, int verbose);
    EAPI void             ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con, int use_epsv);
index aa2e9b8..b434a88 100644 (file)
@@ -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
 
@@ -33,5 +34,6 @@ endif
 EXTRA_DIST = \
 ecore_con.c \
 ecore_con_dns.c \
+ecore_con_info.c \
 ecore_con_url.c \
 ecore_con_private.h
index 0589ab5..b0d1efe 100644 (file)
 # include <winsock2.h>
 #endif
 
-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_Info *info);
+static void _ecore_con_cb_udp_connect(void *data, Ecore_Con_Info *info);
+static void _ecore_con_cb_tcp_listen(void *data, Ecore_Con_Info *info);
+static void _ecore_con_cb_udp_listen(void *data, Ecore_Con_Info *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);
 static int _ecore_con_cl_handler(void *data, Ecore_Fd_Handler *fd_handler);
 static int _ecore_con_cl_udp_handler(void *data, Ecore_Fd_Handler *fd_handler);
-static int _ecore_con_mcast_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_svr_udp_handler(void *data, Ecore_Fd_Handler *fd_handler);
 static int _ecore_con_svr_cl_handler(void *data, Ecore_Fd_Handler *fd_handler);
+
 static void _ecore_con_server_flush(Ecore_Con_Server *svr);
 static void _ecore_con_client_flush(Ecore_Con_Client *cl);
+
 static void _ecore_con_event_client_add_free(void *data, void *ev);
 static void _ecore_con_event_client_del_free(void *data, void *ev);
 static void _ecore_con_event_client_data_free(void *data, void *ev);
@@ -53,8 +59,26 @@ EAPI int ECORE_CON_EVENT_SERVER_DATA = 0;
 
 static Ecore_List *servers = NULL;
 static int init_count = 0;
+
 #if USE_OPENSSL
 static int ssl_init_count = 0;
+static int _ecore_con_init_ssl(Ecore_Con_Server *svr);
+static int _ecore_con_shutdown_ssl(Ecore_Con_Server *svr);
+static int _ecore_con_free_ssl(Ecore_Con_Server *svr);
+
+# define INIT_SSL(svr) _ecore_con_init_ssl(svr)
+# define SHUTDOWN_SSL(svr) _ecore_con_shutdown_ssl(svr)
+# define FREE_SSL(svr) _ecore_con_free_ssl(svr)
+# define UNSET_SSL(svr)                \
+  do {                         \
+    svr->ssl = NULL;           \
+    svr->ssl_ctx = NULL;       \
+  } while (0)
+#else
+# define INIT_SSL(svr) 0
+# define SHUTDOWN_SSL(svr) 0
+# define FREE_SSL(svr) 0
+# define UNSET_SSL(svr) 0
 #endif
 
 #define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
@@ -88,6 +112,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 +135,7 @@ ecore_con_shutdown(void)
    ecore_list_destroy(servers);
    servers = NULL;
 
+   ecore_con_info_shutdown();
    ecore_con_dns_shutdown();
 
    ecore_shutdown();
@@ -157,10 +183,9 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
    Ecore_Con_Type      type;
    struct sockaddr_in  socket_addr;
    struct sockaddr_un  socket_unix;
-   struct ip_mreq      mreq;
    struct linger       lin;
    char                buf[4096];
-   const int           on=1;
+   mode_t             pmode;
 
    if (port < 0) return NULL;
    /* local  user   socket: FILE:   ~/.ecore/[name]/[port] */
@@ -169,18 +194,27 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
    svr = calloc(1, sizeof(Ecore_Con_Server));
    if (!svr) return NULL;
 
-   type = compl_type;
-#if USE_OPENSSL
-   /* unset the SSL flag for the following checks */
-   type &= ECORE_CON_TYPE;
-#endif
+   svr->name = strdup(name);
+   if (!svr->name) goto error;
+   svr->type = compl_type;
+   svr->port = port;
+   svr->data = (void *)data;
+   svr->created = 1;
+   svr->reject_excess_clients = 0;
+   svr->client_limit = -1;
+   svr->clients = ecore_list_new();
+   svr->ppid = getpid();
+   /* Set ssl and ssl_ctx fields to NULL */
+   UNSET_SSL(svr);
+
+   type = compl_type & ECORE_CON_TYPE;
 
    if ((type == ECORE_CON_LOCAL_USER) || (type == ECORE_CON_LOCAL_SYSTEM) ||
        (type == ECORE_CON_LOCAL_ABSTRACT))
      {
        const char *homedir;
        struct stat st;
-       mode_t pmode, mask;
+       mode_t mask;
        int socket_unix_len;
 
        if (!name) goto error;
@@ -217,28 +251,12 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
        pmode = umask(mask);
        start:
        svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
-       if (svr->fd < 0)
-         {
-            umask(pmode);
-            goto error;
-         }
-       if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
-         {
-            umask(pmode);
-            goto error;
-         }
-       if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
-         {
-            umask(pmode);
-            goto error;
-         }
+       if (svr->fd < 0) goto error_umask;
+       if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error_umask;
+       if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error_umask;
        lin.l_onoff = 1;
        lin.l_linger = 0;
-       if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
-         {
-            umask(pmode);
-            goto error;
-         }
+       if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0) goto error_umask;
        socket_unix.sun_family = AF_UNIX;
        if (type == ECORE_CON_LOCAL_ABSTRACT)
          {
@@ -250,8 +268,7 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
             socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix, name);
 #else
             fprintf(stderr, "Your system does not support abstract sockets!\n");
-            umask(pmode);
-            goto error;
+            goto error_umask;
 #endif
          }
        else
@@ -261,135 +278,43 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
          }
        if (bind(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
          {
-            if (connect(svr->fd, (struct sockaddr *)&socket_unix,
-                        socket_unix_len) < 0)
-              {
-                 if ((type == ECORE_CON_LOCAL_USER) || 
-                     (type == ECORE_CON_LOCAL_SYSTEM))
-                   {
-                      if (unlink(buf) < 0)
-                        {
-                           umask(pmode);
-                           goto error;
-                        }
-                      else
-                        goto start;
-                   }
-                 else
-                   {
-                      umask(pmode);
-                      goto error;
-                   }
-              }
-            else
-              {
-                 umask(pmode);
-                 goto error;
-              }
-         }
-       if (listen(svr->fd, 4096) < 0)
-         {
-            umask(pmode);
-            goto error;
+           if ((type == ECORE_CON_LOCAL_USER) || (type == ECORE_CON_LOCAL_SYSTEM) &&
+               (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) &&
+               (unlink(buf) >= 0))
+             goto start;
+           else
+             goto error_umask;
          }
+       if (listen(svr->fd, 4096) < 0) goto error_umask;
        svr->path = strdup(buf);
-       if (!svr->path)
-         {
-            umask(pmode);
-            goto error;
-         }
-       svr->fd_handler = 
+       if (!svr->path) goto error_umask;
+       svr->fd_handler =
          ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
                                    _ecore_con_svr_handler, svr, NULL, NULL);
        umask(pmode);
        if (!svr->fd_handler) goto error;
+
+       INIT_SSL(svr);
      }
-   else if (type == ECORE_CON_REMOTE_TCP)
-     {
-       svr->fd = socket(AF_INET, SOCK_STREAM, 0);
-       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, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 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;
-     }
-   else if (type == ECORE_CON_REMOTE_MCAST)
+
+   if (type == ECORE_CON_REMOTE_TCP)
      {
-       svr->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-       if(svr->fd < 0) goto error;
-       mreq.imr_multiaddr.s_addr = inet_addr(name);
-       mreq.imr_interface.s_addr = htonl(INADDR_ANY);
-       if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,sizeof(mreq)) != 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;
-       socket_addr.sin_family = AF_INET;
-       socket_addr.sin_port = htons(port);
-       socket_addr.sin_addr.s_addr = inet_addr(name);
-       if (bind(svr->fd, (struct sockaddr *)&socket_addr,sizeof(struct sockaddr_in)) < 0) goto error;
-       svr->fd_handler =
-        ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
-                                  _ecore_con_mcast_handler, svr, NULL, NULL);
-       if (!svr->fd_handler) goto error;
+        /* TCP */
+        if (!ecore_con_info_tcp_listen(svr, _ecore_con_cb_tcp_listen, svr)) goto error;
      }
-
-#if USE_OPENSSL
-   if (compl_type & ECORE_CON_SSL)
+   else if (type == ECORE_CON_REMOTE_MCAST || type == ECORE_CON_REMOTE_UDP)
      {
-       if (!ssl_init_count)
-         {
-            SSL_library_init();
-            SSL_load_error_strings();
-         }
-       ssl_init_count++;
-
-       switch (compl_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);
+        /* UDP and MCAST */
+        if (!ecore_con_info_udp_listen(svr, _ecore_con_cb_udp_listen, svr)) goto error;
      }
-#endif
 
-   svr->name = strdup(name);
-   if (!svr->name) goto error;
-   svr->type = type;
-   svr->port = port;
-   svr->data = (void *)data;
-   svr->created = 1;
-   svr->reject_excess_clients = 0;
-   svr->client_limit = -1;
-   svr->clients = ecore_list_new();
-   svr->ppid = getpid();
    ecore_list_append(servers, svr);
    ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
+
    return svr;
 
+   error_umask:
+   umask(pmode);
    error:
    if (svr->name) free(svr->name);
    if (svr->path) free(svr->path);
@@ -397,10 +322,7 @@ ecore_con_server_add(Ecore_Con_Type compl_type, const char *name, int port,
    if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
    if (svr->write_buf) free(svr->write_buf);
    if (svr->ip) free(svr->ip);
-#if USE_OPENSSL
-   if (svr->ssl) SSL_free(svr->ssl);
-   if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
-#endif
+   FREE_SSL(svr);
    free(svr);
    return NULL;
 }
@@ -449,11 +371,19 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port,
    svr = calloc(1, sizeof(Ecore_Con_Server));
    if (!svr) return NULL;
 
-   type = compl_type;
-#if USE_OPENSSL
-   /* unset the SSL flag for the following checks */
-   type &= ECORE_CON_TYPE;
-#endif
+   svr->name = strdup(name);
+   if (!svr->name) goto error;
+   svr->type = compl_type;
+   svr->port = port;
+   svr->data = (void *)data;
+   svr->created = 0;
+   svr->reject_excess_clients = 0;
+   svr->client_limit = -1;
+   svr->clients = ecore_list_new();
+   UNSET_SSL(svr);
+
+   type = compl_type & ECORE_CON_TYPE;
+
    if ((type == ECORE_CON_REMOTE_TCP || type == ECORE_CON_REMOTE_UDP) && (port < 0)) return NULL;
 
    if ((type == ECORE_CON_LOCAL_USER) || (type == ECORE_CON_LOCAL_SYSTEM) ||
@@ -514,10 +444,14 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port,
             socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
          }
 
-       if (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) goto error;
+       if (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
+         {
+           perror("connect()");
+           goto error;
+         }
        svr->path = strdup(buf);
        if (!svr->path) goto error;
-       svr->fd_handler = 
+       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;
@@ -538,29 +472,20 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port,
          }
      }
 
-   svr->name = strdup(name);
-   if (!svr->name) goto error;
-   svr->type = compl_type;
-   svr->port = port;
-   svr->data = (void *)data;
-   svr->created = 0;
-   svr->reject_excess_clients = 0;
-   svr->client_limit = -1;
-   svr->clients = ecore_list_new();
-   ecore_list_append(servers, svr);
-   ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
-
    if (type == ECORE_CON_REMOTE_TCP)
      {
-       if (!ecore_con_dns_lookup(svr->name, _ecore_con_cb_dns_lookup, svr))
-         goto error;
+        /* TCP */
+        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;
+        /* UDP and MCAST */
+        if (!ecore_con_info_udp_connect(svr, _ecore_con_cb_udp_connect, svr)) goto error;
      }
 
+   ecore_list_append(servers, svr);
+   ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
+
    return svr;
 
    error:
@@ -568,10 +493,7 @@ ecore_con_server_connect(Ecore_Con_Type compl_type, const char *name, int port,
    if (svr->path) free(svr->path);
    if (svr->fd >= 0) close(svr->fd);
    if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
-#if USE_OPENSSL
-   if (svr->ssl) SSL_free(svr->ssl);
-   if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
-#endif
+   FREE_SSL(svr);
    free(svr);
    return NULL;
 }
@@ -806,15 +728,20 @@ ecore_con_client_send(Ecore_Con_Client *cl, const void *data, int size)
    if (size < 1) return 0;
    if (cl->fd_handler)
      ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
-   if (cl->buf)
+
+   if(cl->server && cl->server->type == ECORE_CON_REMOTE_UDP)
      {
-       unsigned char *newbuf;
+       sendto(cl->server->fd, data, size, 0, (struct sockaddr *) cl->data, sizeof(struct sockaddr_in));
+     }
+   else if (cl->buf)
+     {
+       unsigned char *newbuf;
 
-       newbuf = realloc(cl->buf, cl->buf_size + size);
-       if (newbuf) cl->buf = newbuf;
-       else return 0;
-       memcpy(cl->buf + cl->buf_size, data, size);
-       cl->buf_size += size;
+       newbuf = realloc(cl->buf, cl->buf_size + size);
+       if (newbuf) cl->buf = newbuf;
+       else return 0;
+       memcpy(cl->buf + cl->buf_size, data, size);
+       cl->buf_size += size;
      }
    else
      {
@@ -853,14 +780,20 @@ ecore_con_client_server_get(Ecore_Con_Client *cl)
 EAPI void *
 ecore_con_client_del(Ecore_Con_Client *cl)
 {
-   void *data;
+   void *data = NULL;
 
    if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
      {
        ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_del");
        return NULL;
      }
-   data = cl->data;
+
+   if(cl->data && cl->server && (cl->server->type == ECORE_CON_REMOTE_UDP ||
+                                cl->server->type == ECORE_CON_REMOTE_MCAST))
+     free(cl->data);
+   else
+     data = cl->data;
+
    cl->data = NULL;
    cl->delete_me = 1;
    if (cl->event_count > 0)
@@ -991,17 +924,11 @@ _ecore_con_server_free(Ecore_Con_Server *svr)
    while (!ecore_list_empty_is(svr->clients))
      _ecore_con_client_free(ecore_list_first_remove(svr->clients));
    ecore_list_destroy(svr->clients);
-   if ((svr->created) && (svr->path) && (svr->ppid == getpid())) 
+   if ((svr->created) && (svr->path) && (svr->ppid == getpid()))
      unlink(svr->path);
    if (svr->fd >= 0) close(svr->fd);
-#if USE_OPENSSL
-   if (svr->ssl)
-     {
-       SSL_shutdown(svr->ssl);
-       SSL_free(svr->ssl);
-     }
-   if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
-#endif
+   SHUTDOWN_SSL(svr);
+   FREE_SSL(svr);
    if (svr->name) free(svr->name);
    if (svr->path) free(svr->path);
    if (svr->ip) free(svr->ip);
@@ -1076,7 +1003,7 @@ _ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__)
        fcntl(new_fd, F_SETFD, FD_CLOEXEC);
        cl->fd = new_fd;
        cl->server = svr;
-       cl->fd_handler = 
+       cl->fd_handler =
          ecore_main_fd_handler_add(cl->fd, ECORE_FD_READ,
                                    _ecore_con_svr_cl_handler, cl, NULL, NULL);
        ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
@@ -1165,132 +1092,170 @@ kill_server(Ecore_Con_Server *svr)
 }
 
 static void
-_ecore_con_cb_dns_lookup(void *data, struct hostent *he)
+_ecore_con_cb_tcp_listen(void *data, Ecore_Con_Info *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;
+   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 (INIT_SSL(svr))
+     goto error;
+
+   return;
+
+   error:
+   FREE_SSL(svr);
+   kill_server(svr);
+}
+
+static void
+_ecore_con_cb_udp_listen(void *data, Ecore_Con_Info *net_info)
+{
+   Ecore_Con_Server *svr;
+   Ecore_Con_Type type;
+   struct ip_mreq mreq;
+   struct ipv6_mreq mreq6;
+   const int on = 1;
+
+   svr = data;
+   type = svr->type;
+   type &= ECORE_CON_TYPE;
+
+   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 (type == ECORE_CON_REMOTE_MCAST)
+     {
+       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;
+   svr->ip = strdup(net_info->ip);
+
+   if (INIT_SSL(svr))
+     goto error;
+
+   return;
+
+   error:
+   FREE_SSL(svr);
+   kill_server(svr);
+}
+
+static void
+_ecore_con_cb_tcp_connect(void *data, Ecore_Con_Info *net_info)
 {
    Ecore_Con_Server   *svr;
    struct sockaddr_in  socket_addr;
    int                 curstate = 0;
    char                buf[64];
-   uint32_t            ip;
 
    svr = data;
 
-   if (!he) goto error;
-   svr->fd = socket(AF_INET, SOCK_STREAM, 0);
+   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) 
+   if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0)
      goto error;
-   socket_addr.sin_family = AF_INET;
-   socket_addr.sin_port = htons(svr->port);
-   memcpy((struct in_addr *)&socket_addr.sin_addr,
-         he->h_addr, sizeof(struct in_addr));
-   if (connect(svr->fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0)
+   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 = 
+       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 = 
+     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;
-   ip = socket_addr.sin_addr.s_addr;
-   snprintf(buf, sizeof(buf),
-           "%i.%i.%i.%i",
-           (ip      ) & 0xff,
-           (ip >> 8 ) & 0xff,
-           (ip >> 16) & 0xff,
-           (ip >> 24) & 0xff);
-   svr->ip = strdup(buf);
-
-#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;
-         }
+   svr->ip = strdup(net_info->ip);
 
-       if (!(svr->ssl = SSL_new(svr->ssl_ctx)))
-         goto error;
-
-       SSL_set_fd(svr->ssl, svr->fd);
-     }
-#endif
+   if (INIT_SSL(svr))
+     goto error;
 
    return;
 
    error:
+   FREE_SSL(svr);
    kill_server(svr);
 }
 
 static void
-_ecore_con_cb_udp_dns_lookup(void *data, struct hostent *he)
+_ecore_con_cb_udp_connect(void *data, Ecore_Con_Info *net_info)
 {
    Ecore_Con_Server   *svr;
    struct sockaddr_in  socket_addr;
    int                 curstate = 0;
    char                buf[64];
-   uint32_t            ip;
 
    svr = data;
 
-   if (!he) goto error;
-   svr->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+   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) 
+   if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0)
      goto error;
-   socket_addr.sin_family = AF_INET;
-   socket_addr.sin_port = htons(svr->port);
-   memcpy((struct in_addr *)&socket_addr.sin_addr,
-         he->h_addr, sizeof(struct in_addr));
-   if (connect(svr->fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0)
+   if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
      goto error;
    else
-     svr->fd_handler = 
+     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;
-   ip = socket_addr.sin_addr.s_addr;
-   snprintf(buf, sizeof(buf),
-           "%i.%i.%i.%i",
-           (ip      ) & 0xff,
-           (ip >> 8 ) & 0xff,
-           (ip >> 16) & 0xff,
-           (ip >> 24) & 0xff);
-   svr->ip = strdup(buf);
+   svr->ip = strdup(net_info->ip);
+
+   if (INIT_SSL(svr))
+     goto error;
 
    return;
 
    error:
+   FREE_SSL(svr);
    kill_server(svr);
 }
 
@@ -1504,7 +1469,7 @@ _ecore_con_cl_udp_handler(void *data, Ecore_Fd_Handler *fd_handler)
      {
        unsigned char buf[65536];
        int           num = 0;
-       
+
        errno = 0;
        num = read(svr->fd, buf, 65536);
        if (num > 0)
@@ -1535,41 +1500,78 @@ _ecore_con_cl_udp_handler(void *data, Ecore_Fd_Handler *fd_handler)
      }
    else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
        _ecore_con_server_flush(svr);
-   
+
    return 1;
 }
 
 static int
-_ecore_con_mcast_handler(void *data, Ecore_Fd_Handler *fd_handler)
+_ecore_con_svr_udp_handler(void *data, Ecore_Fd_Handler *fd_handler)
 {
-   Ecore_Con_Client   *cl;
+   Ecore_Con_Server   *svr;
+   Ecore_Con_Client *cl;
 
-   cl = data;
-   if (cl->dead) return 1;
-   if (cl->delete_me) return 1;
+   svr = data;
+   if (svr->dead) return 1;
+   if (svr->delete_me) return 1;
    if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
      {
-       unsigned char buf[65536];
-       int num;
+       unsigned char buf[READBUFSIZ];
+       struct sockaddr_in client_addr;
+       int num, client_addr_len = sizeof(client_addr);
 
        errno = 0;
-       num = read(cl->fd, buf, 65536);
+       num = recvfrom(svr->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*) &client_addr, &client_addr_len);
+
        if (num > 0)
         {
-          if (!cl->delete_me)
+          if (!svr->delete_me)
             {
               Ecore_Con_Event_Client_Data *e;
               unsigned char *inbuf;
+              uint32_t ip;
+              char ipbuf[64];
+
+              /* Create a new client for use in the client data event */
+              cl = calloc(1, sizeof(Ecore_Con_Client));
+              if(cl == NULL)
+                return 1;
+              cl->buf = NULL;
+              cl->fd = 0;
+              cl->fd_handler = NULL;
+              cl->server = svr;
+              cl->data = calloc(1, sizeof(client_addr));
+              if(cl->data == NULL)
+                {
+                  free(cl);
+                  return 1;
+                }
+              memcpy(cl->data,  &client_addr, sizeof(client_addr));
+              ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
+              ecore_list_append(svr->clients, cl);
+
+              ip = client_addr.sin_addr.s_addr;
+              snprintf(ipbuf, sizeof(ipbuf),
+                       "%i.%i.%i.%i",
+                       (ip      ) & 0xff,
+                       (ip >> 8 ) & 0xff,
+                       (ip >> 16) & 0xff,
+                       (ip >> 24) & 0xff);
+              cl->ip = strdup(ipbuf);
 
               inbuf = malloc(num);
               if(inbuf == NULL)
-                return 1;
+                {
+                  free(cl->data);
+                  free(cl);
+                  return 1;
+                }
+
               memcpy(inbuf, buf, num);
-       
+
               e = calloc(1, sizeof(Ecore_Con_Event_Client_Data));
               if (e)
                 {
-                  cl->event_count++;
+                  svr->event_count++;
                   e->client = cl;
                   e->data = inbuf;
                   e->size = num;
@@ -1577,30 +1579,44 @@ _ecore_con_mcast_handler(void *data, Ecore_Fd_Handler *fd_handler)
                                   _ecore_con_event_client_data_free,
                                   NULL);
                 }
+
+              if(!cl->delete_me)
+                {
+                  Ecore_Con_Event_Client_Add *add;
+
+                  add = calloc(1, sizeof(Ecore_Con_Event_Client_Add));
+                  if(add)
+                    {
+                      /*cl->event_count++;*/
+                      add->client = cl;
+                      ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, add,
+                                      _ecore_con_event_client_add_free, NULL);
+                    }
+                }
             }
           if ((errno == EIO) ||  (errno == EBADF) ||
               (errno == EPIPE) || (errno == EINVAL) ||
               (errno == ENOSPC) || (num == 0)/* is num == 0 right? */)
             {
-              if (!cl->delete_me)
+              if (!svr->delete_me)
                 {
                   /* we lost our client! */
                   Ecore_Con_Event_Client_Del *e;
-               
+
                   e = calloc(1, sizeof(Ecore_Con_Event_Client_Del));
                   if (e)
                     {
-                      cl->event_count++;
+                      svr->event_count++;
                       e->client = cl;
                       ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e,
                                       _ecore_con_event_client_del_free,
                                       NULL);
                     }
                 }
-              cl->dead = 1;
-              if (cl->fd_handler)
-                ecore_main_fd_handler_del(cl->fd_handler);
-              cl->fd_handler = NULL;
+              svr->dead = 1;
+              if (svr->fd_handler)
+                ecore_main_fd_handler_del(svr->fd_handler);
+              svr->fd_handler = NULL;
             }
         }
      }
@@ -1700,9 +1716,9 @@ _ecore_con_server_flush(Ecore_Con_Server *svr)
    if (!svr->write_buf) return;
 
    /* check whether we need to write anything at all.
-       * we must not write zero bytes with SSL_write() since it
-       * causes undefined behaviour
-       */
+    * we must not write zero bytes with SSL_write() since it
+    * causes undefined behaviour
+    */
    if (svr->write_buf_size == svr->write_buf_offset)
       return;
 
@@ -1842,7 +1858,9 @@ _ecore_con_event_client_data_free(void *data __UNUSED__, void *ev)
    e = ev;
    e->client->event_count--;
    if (e->data) free(e->data);
-   if ((e->client->event_count == 0) && (e->client->delete_me))
+   if ((e->client->event_count == 0) && (e->client->delete_me) ||
+       (e->client->server && (e->client->server->type == ECORE_CON_REMOTE_UDP ||
+                             e->client->server->type == ECORE_CON_REMOTE_MCAST)))
      ecore_con_client_del(e->client);
    free(e);
 }
@@ -1883,3 +1901,60 @@ _ecore_con_event_server_data_free(void *data __UNUSED__, void *ev)
      ecore_con_server_del(e->server);
    free(e);
 }
+
+#if USE_OPENSSL
+
+static int
+_ecore_con_init_ssl(Ecore_Con_Server *svr)
+{
+  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())))
+           return 1;
+         break;
+       case ECORE_CON_USE_SSL3:
+         if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
+           return 1;
+         break;
+       case ECORE_CON_USE_TLS:
+         if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
+           return 1;
+         break;
+       }
+
+      if (!(svr->ssl = SSL_new(svr->ssl_ctx)))
+       return 1;
+
+      SSL_set_fd(svr->ssl, svr->fd);
+    }
+  return 0;
+}
+
+static int
+_ecore_con_shutdown_ssl(Ecore_Con_Server *svr)
+{
+  if (svr->ssl) SSL_shutdown(svr->ssl);
+  return 0;
+}
+
+static int
+_ecore_con_free_ssl(Ecore_Con_Server *svr)
+{
+  if (svr->ssl) SSL_free(svr->ssl);
+  if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
+  UNSET_SSL(svr);
+
+  return 0;
+}
+
+#endif
diff --git a/src/lib/ecore_con/ecore_con_info.c b/src/lib/ecore_con/ecore_con_info.c
new file mode 100644 (file)
index 0000000..c47711a
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * 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 <ctype.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+
+typedef struct _CB_Data CB_Data;
+
+struct _CB_Data
+{
+   Ecore_List2 __list_data;
+   Ecore_Con_Info_Cb cb_done;
+   void *data;
+   Ecore_Fd_Handler *fdh;
+   pid_t pid;
+   Ecore_Event_Handler *handler;
+   int fd2;
+};
+
+
+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;
+
+EAPI int
+ecore_con_info_init(void)
+{
+   info_init++;
+   return info_init;
+}
+
+EAPI 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,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   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, &hints);
+}
+
+int
+ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
+                         Ecore_Con_Info_Cb done_cb,
+                         void *data)
+{
+   struct addrinfo hints;
+
+   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, &hints);
+}
+
+int
+ecore_con_info_udp_connect(Ecore_Con_Server *svr,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   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, &hints);
+}
+
+int
+ecore_con_info_udp_listen(Ecore_Con_Server *svr,
+                         Ecore_Con_Info_Cb done_cb,
+                         void *data)
+{
+   struct addrinfo hints;
+
+   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, &hints);
+}
+
+int
+ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
+                          Ecore_Con_Info_Cb done_cb,
+                          void *data)
+{
+   struct addrinfo hints;
+
+   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, &hints);
+}
+
+EAPI int
+ecore_con_info_get(Ecore_Con_Server *svr,
+                  Ecore_Con_Info_Cb done_cb,
+                  void *data,
+                  struct addrinfo *hints)
+{
+   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_Info 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));
+           memset(container.ip, 0, sizeof(container.ip));
+           memset(container.service, 0, sizeof(container.service));
+           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));
+             }
+           write(fd[1], &container, sizeof(Ecore_Con_Info));
+         }
+       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_Info container;
+   ssize_t size;
+
+   size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container,
+              sizeof(Ecore_Con_Info));
+   if (size == sizeof(Ecore_Con_Info))
+     {
+        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;
+}
index c656097..2ea0d33 100644 (file)
@@ -95,7 +95,23 @@ struct _Ecore_Con_Url
 };
 #endif
 
+struct _Ecore_Con_Info
+{
+   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);
+/* from ecore_con_info.c */
+int ecore_con_info_init(void);
+int ecore_con_info_shutdown(void);
+int ecore_con_info_tcp_connect(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+int ecore_con_info_tcp_listen(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+int ecore_con_info_udp_connect(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+int ecore_con_info_mcast_listen(Ecore_Con_Server *svr, Ecore_Con_Info_Cb done_cb, void *data);
+
 #endif