Ecore: ecore_con : make ecore_con work on Windows
authorcaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 14 May 2011 17:52:30 +0000 (17:52 +0000)
committercaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sat, 14 May 2011 17:52:30 +0000 (17:52 +0000)
The ecore_con module needed a port of the local connections
with named pipes. The other connections (TCP, UDP) are using
BSD sockets, which are also used on Windows.

No abstract sockets on Windows.

NB: Should I backport that commit to 1.0 ?

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@59385 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
configure.ac
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_local_win32.c [new file with mode: 0644]
src/lib/ecore_con/ecore_con_private.h

index c783ae6..9266d94 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
 2011-05-12  Carsten Haitzler (The Rasterman)
 
-        * Add a custom Ecore Aniamtor source and tick ability to be able
+        * Add a custom Ecore Animator source and tick ability to be able
         to plug in external animator tick sources like vblank interrupts
         and so on.
 
 2011-05-14  Cedric Bail
 
        * Sync GNUTLS threads activation with Eina.
+
+2011-05-14  Vincent Torri
+
+       * Make ecore_con work on Windows (only the local connections
+       need a port)
index 838e632..aabb223 100644 (file)
@@ -172,7 +172,6 @@ case "$host_os" in
       want_notify_win32="yes"
       want_curl="yes"
       want_glib="auto"
-      want_ecore_con="no"
       want_ecore_imf="yes"
       want_ecore_win32="yes"
       want_ecore_evas_software_gdi="yes"
@@ -271,14 +270,14 @@ AC_ARG_ENABLE([abstract-sockets],
    [AC_HELP_STRING([--disable-abstract-sockets], [disable abstract sockets.])],
    [
     if test "x${enableval}" = "xyes" ; then
-       want_abstract_sockets="yes"
+       want_ecore_con_abstract_sockets="yes"
     else
-       want_abstract_sockets="no"
+       want_ecore_con_abstract_sockets="no"
     fi
    ],
-   [want_abstract_sockets="yes"])
+   [want_ecore_con_abstract_sockets=${want_abstract_sockets}])
 
-if test "x${want_abstract_sockets}" = "xyes" ; then
+if test "x${want_ecore_con_abstract_sockets}" = "xyes" ; then
    AC_DEFINE([HAVE_ABSTRACT_SOCKETS], [1], [Have abstract sockets namespace])
 fi
 
@@ -361,8 +360,9 @@ case "$host_os" in
       requirements_ecore_imf="evil ${requirements_ecore_imf}"
       requirements_ecore_imf_evas="evil ${requirements_ecore_imf_evas}"
       EFL_ECORE_BUILD="-DEFL_ECORE_BUILD"
-      EFL_ECORE_FILE_BUILD="-DEFL_ECORE_FILE_BUILD"
+      EFL_ECORE_CON_BUILD="-DEFL_ECORE_CON_BUILD"
       EFL_ECORE_EVAS_BUILD="-DEFL_ECORE_EVAS_BUILD"
+      EFL_ECORE_FILE_BUILD="-DEFL_ECORE_FILE_BUILD"
       EFL_ECORE_IMF_BUILD="-DEFL_ECORE_IMF_BUILD"
       EFL_ECORE_IMF_EVAS_BUILD="-DEFL_ECORE_IMF_EVAS_BUILD"
       EFL_ECORE_INPUT_BUILD="-DEFL_ECORE_INPUT_BUILD"
@@ -388,8 +388,9 @@ case "$host_os" in
 esac
 
 AC_SUBST(EFL_ECORE_BUILD)
-AC_SUBST(EFL_ECORE_FILE_BUILD)
+AC_SUBST(EFL_ECORE_CON_BUILD)
 AC_SUBST(EFL_ECORE_EVAS_BUILD)
+AC_SUBST(EFL_ECORE_FILE_BUILD)
 AC_SUBST(EFL_ECORE_IMF_BUILD)
 AC_SUBST(EFL_ECORE_IMF_EVAS_BUILD)
 AC_SUBST(EFL_ECORE_INPUT_BUILD)
index 60c3eba..4d9460f 100644 (file)
 # undef EAPI
 #endif
 
-#ifdef _MSC_VER
-# ifdef BUILDING_DLL
-#  define EAPI __declspec(dllexport)
+#ifdef _WIN32
+# ifdef EFL_ECORE_CON_BUILD
+#  ifdef DLL_EXPORT
+#   define EAPI __declspec(dllexport)
+#  else
+#   define EAPI
+#  endif
 # else
 #  define EAPI __declspec(dllimport)
 # endif
index e2969bd..128c47c 100644 (file)
@@ -5,6 +5,7 @@ AM_CPPFLAGS = \
 -I$(top_builddir)/src/lib/ecore_con \
 -I$(top_srcdir)/src/lib/ecore \
 -I$(top_srcdir)/src/lib/ecore_con \
+@EFL_ECORE_CON_BUILD@ \
 @SSL_CFLAGS@ \
 @CURL_CFLAGS@ \
 @EINA_CFLAGS@ \
@@ -19,8 +20,13 @@ includesdir = $(includedir)/ecore-@VMAJ@
 libecore_con_la_SOURCES = \
 ecore_con.c \
 ecore_con_ssl.c \
-ecore_con_url.c \
-ecore_con_local.c
+ecore_con_url.c
+
+if ECORE_HAVE_WIN32
+libecore_con_la_SOURCES += ecore_con_local_win32.c
+else
+libecore_con_la_SOURCES += ecore_con_local.c
+endif
 
 if HAVE_CARES
 libecore_con_la_SOURCES += ecore_con_ares.c
index 13a4517..6450781 100644 (file)
@@ -351,8 +351,13 @@ ecore_con_server_add(Ecore_Con_Type compl_type,
        (type == ECORE_CON_LOCAL_SYSTEM) ||
        (type == ECORE_CON_LOCAL_ABSTRACT))
      /* Local */
+#ifdef _WIN32
+     if (!ecore_con_local_listen(svr))
+       goto error;
+#else
      if (!ecore_con_local_listen(svr, _ecore_con_svr_tcp_handler, svr))
        goto error;
+#endif
 
    if ((type == ECORE_CON_REMOTE_TCP) ||
        (type == ECORE_CON_REMOTE_NODELAY))
@@ -470,10 +475,17 @@ ecore_con_server_connect(Ecore_Con_Type compl_type,
        (type == ECORE_CON_LOCAL_SYSTEM) ||
        (type == ECORE_CON_LOCAL_ABSTRACT))
      /* Local */
+#ifdef _WIN32
+     if (!ecore_con_local_connect(svr, _ecore_con_cl_handler,
+                                  _ecore_con_event_server_add_free))
+       goto
+       error;
+#else
      if (!ecore_con_local_connect(svr, _ecore_con_cl_handler, svr,
                                   _ecore_con_event_server_add_free))
        goto
        error;
+#endif
 
    if ((type == ECORE_CON_REMOTE_TCP) ||
        (type == ECORE_CON_REMOTE_NODELAY))
@@ -1191,7 +1203,7 @@ ecore_con_event_server_del(Ecore_Con_Server *svr)
 }
 
 void
-ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num)
+ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num, Eina_Bool duplicate)
 {
    Ecore_Con_Event_Server_Data *e;
 
@@ -1200,14 +1212,19 @@ ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num)
 
    svr->event_count++;
    e->server = svr;
-   e->data = malloc(num);
-   if (!e->data)
+   if (duplicate)
      {
-        ERR("alloc!");
-        free(e);
-        return;
+        e->data = malloc(num);
+        if (!e->data)
+          {
+             ERR("alloc!");
+             free(e);
+             return;
+          }
+        memcpy(e->data, buf, num);
      }
-   memcpy(e->data, buf, num);
+   else
+     e->data = buf;
    e->size = num;
    ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e,
                    _ecore_con_event_server_data_free, NULL);
@@ -1250,7 +1267,7 @@ ecore_con_event_client_del(Ecore_Con_Client *cl)
 }
 
 void
-ecore_con_event_client_data(Ecore_Con_Client *cl, unsigned char *buf, int num)
+ecore_con_event_client_data(Ecore_Con_Client *cl, unsigned char *buf, int num, Eina_Bool duplicate)
 {
    Ecore_Con_Event_Client_Data *e;
    e = malloc(sizeof(Ecore_Con_Event_Client_Data));
@@ -1260,15 +1277,19 @@ ecore_con_event_client_data(Ecore_Con_Client *cl, unsigned char *buf, int num)
    cl->event_count++;
    _ecore_con_cl_timer_update(cl);
    e->client = cl;
-   e->data = malloc(num);
-   if (!e->data)
+   if (duplicate)
      {
-        free(cl->client_addr);
-        free(cl);
-        return;
+        e->data = malloc(num);
+        if (!e->data)
+          {
+             free(cl->client_addr);
+             free(cl);
+             return;
+          }
+        memcpy(e->data, buf, num);
      }
-
-   memcpy(e->data, buf, num);
+   else
+     e->data = buf;
    e->size = num;
    ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e,
                    (Ecore_End_Cb)_ecore_con_event_client_data_free, cl->host_server);
@@ -1349,6 +1370,10 @@ _ecore_con_server_free(Ecore_Con_Server *svr)
           }
      }
 
+#ifdef _WIN32
+   ecore_con_local_win32_server_del(svr);
+#endif
+
    if (svr->write_buf)
      free(svr->write_buf);
 
@@ -1410,6 +1435,11 @@ _ecore_con_client_free(Ecore_Con_Client *cl)
              break;
           }
      }
+
+#ifdef _WIN32
+   ecore_con_local_win32_client_del(cl);
+#endif
+
    if (cl->buf)
      free(cl->buf);
 
@@ -2060,7 +2090,7 @@ _ecore_con_cl_read(Ecore_Con_Server *svr)
      }
 
    if ((!svr->delete_me) && (num > 0))
-     ecore_con_event_server_data(svr, buf, num);
+     ecore_con_event_server_data(svr, buf, num, EINA_TRUE);
 
    if (lost_server)
       _ecore_con_server_kill(svr);
@@ -2146,7 +2176,7 @@ _ecore_con_cl_udp_handler(void             *data,
    num = read(svr->fd, buf, READBUFSIZ);
 
    if ((!svr->delete_me) && (num > 0))
-     ecore_con_event_server_data(svr, buf, num);
+     ecore_con_event_server_data(svr, buf, num, EINA_TRUE);
 
    if (num < 0 && (errno != EAGAIN) && (errno != EINTR))
      {
@@ -2229,7 +2259,7 @@ _ecore_con_svr_udp_handler(void             *data,
    svr->client_count++;
 
    ecore_con_event_client_add(cl);
-   ecore_con_event_client_data(cl, buf, num);
+   ecore_con_event_client_data(cl, buf, num, EINA_TRUE);
 
    return ECORE_CALLBACK_RENEW;
 }
@@ -2237,11 +2267,12 @@ _ecore_con_svr_udp_handler(void             *data,
 static void
 _ecore_con_svr_cl_read(Ecore_Con_Client *cl)
 {
-   DBG("cl=%p", cl);
    int num = 0;
    Eina_Bool lost_client = EINA_TRUE;
    unsigned char buf[READBUFSIZ];
 
+   DBG("cl=%p", cl);
+
    if (cl->handshaking)
      {
         /* add an extra handshake attempt just before read, even though
@@ -2271,7 +2302,7 @@ _ecore_con_svr_cl_read(Ecore_Con_Client *cl)
      }
 
    if ((!cl->delete_me) && (num > 0))
-     ecore_con_event_client_data(cl, buf, num);
+     ecore_con_event_client_data(cl, buf, num, EINA_TRUE);
 
    if (lost_client)
      {
@@ -2327,6 +2358,11 @@ _ecore_con_server_flush(Ecore_Con_Server *svr)
 {
    int count, num;
 
+#ifdef _WIN32
+   if (ecore_con_local_win32_server_flush(svr))
+     return;
+#endif
+
    if (!svr->write_buf && svr->fd_handler)
      {
         ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
@@ -2386,6 +2422,11 @@ _ecore_con_client_flush(Ecore_Con_Client *cl)
 {
    int num, count = 0;
 
+#ifdef _WIN32
+   if (ecore_con_local_win32_client_flush(cl))
+     return;
+#endif
+
    if (!cl->buf && cl->fd_handler)
      {
         ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
diff --git a/src/lib/ecore_con/ecore_con_local_win32.c b/src/lib/ecore_con/ecore_con_local_win32.c
new file mode 100644 (file)
index 0000000..ed634bb
--- /dev/null
@@ -0,0 +1,784 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <process.h>
+
+#include <Evil.h>
+#include <Ecore.h>
+
+#include "Ecore_Con.h"
+#include "ecore_con_private.h"
+
+#define BUFSIZE 512
+
+
+static int _ecore_con_local_init_count = 0;
+
+int
+ecore_con_local_init(void)
+{
+   if (++_ecore_con_local_init_count != 1)
+     return _ecore_con_local_init_count;
+
+   return _ecore_con_local_init_count;
+}
+
+int
+ecore_con_local_shutdown(void)
+{
+   if (--_ecore_con_local_init_count != 0)
+     return _ecore_con_local_init_count;
+
+   return _ecore_con_local_init_count;
+}
+
+
+static Eina_Bool
+_ecore_con_local_win32_server_read_client_handler(void *data, Ecore_Win32_Handler *wh)
+{
+  Ecore_Con_Client *cl;
+  void *buf;
+  DWORD n;
+  Eina_Bool broken_pipe = EINA_FALSE;
+
+  cl = (Ecore_Con_Client *)data;
+
+  if (!ResetEvent(cl->host_server->event_read))
+    return ECORE_CALLBACK_RENEW;
+
+  buf = malloc(cl->host_server->nbr_bytes);
+  if (!buf)
+    return ECORE_CALLBACK_RENEW;
+
+  if (ReadFile(cl->host_server->pipe, buf, cl->host_server->nbr_bytes, &n, NULL))
+    {
+       if (!cl->delete_me)
+         ecore_con_event_client_data(cl, buf, cl->host_server->nbr_bytes, EINA_FALSE);
+       cl->host_server->want_write = 1;
+    }
+  else
+    {
+      if (GetLastError() == ERROR_BROKEN_PIPE)
+        broken_pipe = EINA_TRUE;
+    }
+
+  if (broken_pipe)
+    {
+#if 0
+       char *msg;
+
+       msg = evil_last_error_get();
+       if (msg)
+         {
+            ecore_con_event_client_error(cl, msg);
+            free(msg);
+         }
+#endif
+       if (!cl->delete_me)
+         ecore_con_event_client_del(cl);
+       cl->dead = EINA_TRUE;
+       return ECORE_CALLBACK_CANCEL;
+    }
+
+  if (cl->host_server->want_write)
+    ecore_con_local_win32_client_flush(cl);
+
+   ecore_main_win32_handler_del(wh);
+
+  return ECORE_CALLBACK_DONE;
+}
+
+static Eina_Bool
+_ecore_con_local_win32_server_peek_client_handler(void *data, Ecore_Win32_Handler *wh)
+{
+   Ecore_Con_Client *cl;
+#if 0
+   char *msg;
+#endif
+
+   cl = (Ecore_Con_Client *)data;
+
+   if (!ResetEvent(cl->host_server->event_peek))
+     return ECORE_CALLBACK_RENEW;
+
+#if 0
+   msg = evil_last_error_get();
+   if (msg)
+     {
+        ecore_con_event_server_error(cl->host_server, msg);
+        free(msg);
+     }
+#endif
+   if (!cl->host_server->delete_me)
+     ecore_con_event_server_del(cl->host_server);
+   cl->host_server->dead = EINA_TRUE;
+   return ECORE_CALLBACK_CANCEL;
+
+   ecore_main_win32_handler_del(wh);
+
+   return ECORE_CALLBACK_DONE;
+}
+
+static Eina_Bool
+_ecore_con_local_win32_client_peek_server_handler(void *data, Ecore_Win32_Handler *wh)
+{
+   Ecore_Con_Server *svr;
+#if 0
+   char *msg;
+#endif
+
+   svr = (Ecore_Con_Server *)data;
+
+   if (!ResetEvent(svr->event_peek))
+     return ECORE_CALLBACK_RENEW;
+#if 0
+   msg = evil_last_error_get();
+   if (msg)
+     {
+        ecore_con_event_server_error(svr, msg);
+        free(msg);
+     }
+#endif
+   if (!svr->delete_me)
+     ecore_con_event_server_del(svr);
+   svr->dead = EINA_TRUE;
+   return ECORE_CALLBACK_CANCEL;
+
+   ecore_main_win32_handler_del(wh);
+
+   return ECORE_CALLBACK_DONE;
+}
+
+static Eina_Bool
+_ecore_con_local_win32_client_read_server_handler(void *data, Ecore_Win32_Handler *wh)
+{
+  Ecore_Con_Server *svr;
+  void *buf;
+  DWORD n;
+  Eina_Bool broken_pipe = EINA_FALSE;
+
+  svr = (Ecore_Con_Server *)data;
+
+  if (!ResetEvent(svr->event_read))
+    return ECORE_CALLBACK_RENEW;
+
+  buf = malloc(svr->nbr_bytes);
+  if (!buf)
+    return ECORE_CALLBACK_RENEW;
+
+  if (ReadFile(svr->pipe, buf, svr->nbr_bytes, &n, NULL))
+    {
+       if (!svr->delete_me)
+         ecore_con_event_server_data(svr, buf, svr->nbr_bytes, EINA_FALSE);
+       svr->want_write = 1;
+    }
+  else
+    {
+      if (GetLastError() == ERROR_BROKEN_PIPE)
+        broken_pipe = EINA_TRUE;
+    }
+
+  if (broken_pipe)
+    {
+#if 0
+       char *msg;
+
+       msg = evil_last_error_get();
+       if (msg)
+         {
+            ecore_con_event_server_error(svr, msg);
+            free(msg);
+         }
+#endif
+       if (!svr->delete_me)
+         ecore_con_event_server_del(svr);
+       svr->dead = EINA_TRUE;
+       return ECORE_CALLBACK_CANCEL;
+    }
+
+  if (svr->want_write)
+    ecore_con_local_win32_server_flush(svr);
+
+   ecore_main_win32_handler_del(wh);
+
+  return ECORE_CALLBACK_DONE;
+}
+
+/* thread to read data sent by the server to the client */
+static unsigned int __stdcall
+_ecore_con_local_win32_client_read_server_thread(void *data)
+{
+   Ecore_Con_Server *svr;
+   DWORD nbr_bytes = 0;
+
+   svr = (Ecore_Con_Server *)data;
+
+   svr->read_stopped = EINA_FALSE;
+
+   while (!svr->read_stop)
+     {
+        if (PeekNamedPipe(svr->pipe, NULL, 0, NULL, &nbr_bytes, NULL))
+          {
+             if (nbr_bytes <= 0)
+               continue;
+
+             svr->nbr_bytes = nbr_bytes;
+             if (!SetEvent(svr->event_read))
+               continue;
+          }
+        else
+          {
+             if (GetLastError() == ERROR_BROKEN_PIPE)
+               {
+                  if (!SetEvent(svr->event_peek))
+                    continue;
+                  break;
+               }
+          }
+     }
+
+   printf(" ### %s\n", __FUNCTION__);
+   svr->read_stopped = EINA_TRUE;
+   _endthreadex(0);
+   return 0;
+}
+
+/* thread to read data sent by the client to the server */
+static unsigned int __stdcall
+_ecore_con_local_win32_server_read_client_thread(void *data)
+{
+   Ecore_Con_Client *cl;
+   DWORD nbr_bytes = 0;
+
+   cl = (Ecore_Con_Client *)data;
+
+   cl->host_server->read_stopped = EINA_FALSE;
+
+   while (!cl->host_server->read_stop)
+     {
+        if (PeekNamedPipe(cl->host_server->pipe, NULL, 0, NULL, &nbr_bytes, NULL))
+          {
+             if (nbr_bytes <= 0)
+               continue;
+
+             cl->host_server->nbr_bytes = nbr_bytes;
+             if (!SetEvent(cl->host_server->event_read))
+               continue;
+          }
+        else
+          {
+             if (GetLastError() == ERROR_BROKEN_PIPE)
+               {
+                  if (!SetEvent(cl->host_server->event_peek))
+                    continue;
+                  break;
+               }
+          }
+     }
+
+   printf(" ### %s\n", __FUNCTION__);
+   cl->host_server->read_stopped = EINA_TRUE;
+   _endthreadex(0);
+   return 0;
+}
+
+static Eina_Bool
+_ecore_con_local_win32_client_add(void *data, Ecore_Win32_Handler *wh)
+{
+   Ecore_Con_Client *cl = NULL;
+   Ecore_Con_Server *svr;
+   Ecore_Win32_Handler *handler_read;
+   Ecore_Win32_Handler *handler_peek;
+
+   svr = (Ecore_Con_Server *)data;
+
+   if (!svr->pipe)
+     return ECORE_CALLBACK_CANCEL;
+
+   if (svr->dead)
+     return ECORE_CALLBACK_CANCEL;
+
+   if (svr->delete_me)
+     return ECORE_CALLBACK_CANCEL;
+
+   if ((svr->client_limit >= 0) && (!svr->reject_excess_clients) &&
+       (svr->client_count >= (unsigned int)svr->client_limit))
+     return ECORE_CALLBACK_CANCEL;
+
+   cl = calloc(1, sizeof(Ecore_Con_Client));
+   if (!cl)
+     {
+        ERR("allocation failed");
+        return ECORE_CALLBACK_CANCEL;
+     }
+
+   cl->host_server = svr;
+   ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
+
+   cl->host_server->event_read = CreateEvent(NULL, TRUE, FALSE, NULL);
+   if (!cl->host_server->event_read)
+     {
+        ERR("Can not create event read");
+        goto free_cl;
+     }
+
+   handler_read = ecore_main_win32_handler_add(cl->host_server->event_read,
+                                               _ecore_con_local_win32_server_read_client_handler,
+                                               cl);
+   if (!handler_read)
+     {
+        ERR("Can not create handler read");
+        goto close_event_read;
+     }
+
+   cl->host_server->event_peek = CreateEvent(NULL, TRUE, FALSE, NULL);
+   if (!cl->host_server->event_peek)
+     {
+        ERR("Can not create event peek");
+        goto del_handler_read;
+     }
+
+   handler_peek = ecore_main_win32_handler_add(cl->host_server->event_peek,
+                                               _ecore_con_local_win32_server_peek_client_handler,
+                                               cl);
+   if (!handler_peek)
+     {
+        ERR("Can not create handler peek");
+        goto close_event_peek;
+     }
+
+   cl->host_server->read_stopped = EINA_TRUE;
+   cl->host_server->thread_read = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_server_read_client_thread, cl, CREATE_SUSPENDED, NULL);
+   if (!cl->host_server->thread_read)
+     {
+        ERR("Can not launch thread");
+        goto del_handler_peek;
+     }
+
+   svr->clients = eina_list_append(svr->clients, cl);
+   svr->client_count++;
+
+   if (!cl->delete_me)
+     ecore_con_event_client_add(cl);
+
+   ecore_main_win32_handler_del(wh);
+
+   ResumeThread(cl->host_server->thread_read);
+   return ECORE_CALLBACK_DONE;
+
+ del_handler_peek:
+   ecore_main_win32_handler_del(handler_peek);
+ close_event_peek:
+   CloseHandle(cl->host_server->event_peek);
+ del_handler_read:
+   ecore_main_win32_handler_del(handler_read);
+ close_event_read:
+   CloseHandle(cl->host_server->event_read);
+ free_cl:
+   free(cl);
+
+   return ECORE_CALLBACK_CANCEL;
+}
+
+static unsigned int __stdcall
+_ecore_con_local_win32_listening(void *data)
+{
+   Ecore_Con_Server *svr;
+   BOOL res;
+
+   svr = (Ecore_Con_Server *)data;
+
+   while (1)
+     {
+        res = ConnectNamedPipe(svr->pipe, NULL);
+        if (!res)
+          {
+             ERR("Opening the connection to the client failed");
+             CloseHandle(svr->pipe);
+             svr->pipe = NULL;
+          }
+        break;
+     }
+
+   DBG("Client connected");
+
+   printf(" ### %s\n", __FUNCTION__);
+   _endthreadex(0);
+   return 0;
+}
+
+Eina_Bool
+ecore_con_local_listen(Ecore_Con_Server *svr)
+{
+   char buf[256];
+   HANDLE thread_listening;
+   Ecore_Win32_Handler *handler;
+
+   if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
+     {
+        ERR("Your system does not support abstract sockets!");
+        return EINA_FALSE;
+     }
+
+   if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
+     snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", svr->name);
+   else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
+     {
+        const char *computername;
+
+        computername = getenv("CoMPUTERNAME");
+        snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s", computername, svr->name);
+     }
+
+   svr->path = strdup(buf);
+   if (!svr->path)
+     {
+        ERR("Allocation failed");
+        return EINA_FALSE;
+     }
+
+   /*
+    * synchronuous
+    * block mode
+    * wait mode
+    */
+   svr->pipe = CreateNamedPipe(svr->path,
+                               PIPE_ACCESS_DUPLEX,
+                               PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+                               PIPE_UNLIMITED_INSTANCES,
+                               BUFSIZE,
+                               BUFSIZE,
+                               5000,
+                               NULL);
+   if (svr->pipe == INVALID_HANDLE_VALUE)
+     {
+        ERR("Creation of the named pipe failed");
+        goto free_path;
+     }
+
+   /*
+    * We use ConnectNamedPipe() to wait for a client to connect.
+    * As the function is blocking, to let the main loop continuing
+    * its iterations, we call ConnectNamedPipe() in a thread
+    */
+   thread_listening = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_listening, svr, CREATE_SUSPENDED, NULL);
+   if (!thread_listening)
+     {
+        ERR("Creation of the listening thread failed");
+        goto close_pipe;
+     }
+
+   handler = ecore_main_win32_handler_add(thread_listening,
+                                          _ecore_con_local_win32_client_add,
+                                          svr);
+   if (!handler)
+     {
+        ERR("Creation of the client add handler failed");
+        goto del_handler;
+     }
+
+   svr->read_stopped = EINA_TRUE;
+   ResumeThread(thread_listening);
+
+   return EINA_TRUE;
+
+ del_handler:
+   ecore_main_win32_handler_del(handler);
+ close_pipe:
+   CloseHandle(svr->pipe);
+ free_path:
+   free(svr->path);
+   svr->path = NULL;
+
+   return EINA_FALSE;
+}
+
+void
+ecore_con_local_win32_server_del(Ecore_Con_Server *svr)
+{
+   if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
+     return;
+
+   if (((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
+       ((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
+     return;
+
+   svr->read_stop = 1;
+   while (!svr->read_stopped)
+     Sleep(100);
+
+   if (svr->event_peek)
+     CloseHandle(svr->event_peek);
+   svr->event_peek = NULL;
+   if (svr->event_read)
+     CloseHandle(svr->event_read);
+   svr->event_read = NULL;
+   free(svr->path);
+   svr->path = NULL;
+   if (svr->pipe)
+     CloseHandle(svr->pipe);
+   svr->pipe = NULL;
+}
+
+void
+ecore_con_local_win32_client_del(Ecore_Con_Client *cl)
+{
+   if ((cl->host_server->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
+     return;
+
+   if (((cl->host_server->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
+       ((cl->host_server->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
+     return;
+
+   cl->host_server->read_stop = 1;
+   while (!cl->host_server->read_stopped)
+     Sleep(100);
+
+   if (cl->host_server->event_peek)
+     CloseHandle(cl->host_server->event_peek);
+   cl->host_server->event_peek = NULL;
+   if (cl->host_server->event_read)
+     CloseHandle(cl->host_server->event_read);
+   cl->host_server->event_read = NULL;
+   free(cl->host_server->path);
+   cl->host_server->path = NULL;
+   if (cl->host_server->pipe)
+     CloseHandle(cl->host_server->pipe);
+   cl->host_server->pipe = NULL;
+}
+
+Eina_Bool
+ecore_con_local_connect(Ecore_Con_Server *svr,
+                        Eina_Bool (*cb_done)(void *data,
+                                             Ecore_Fd_Handler *fd_handler),
+                        void (*cb_free)(void *data, void *ev))
+{
+   char buf[256];
+   Ecore_Win32_Handler *handler_read;
+   Ecore_Win32_Handler *handler_peek;
+
+   if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
+     {
+        ERR("Your system does not support abstract sockets!");
+        return EINA_FALSE;
+     }
+
+   if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
+     snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", svr->name);
+   else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
+     {
+        const char *computername;
+
+        computername = getenv("COMPUTERNAME");
+        snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s", computername, svr->name);
+     }
+
+   while (1)
+     {
+        svr->pipe = CreateFile(buf,
+                               GENERIC_READ | GENERIC_WRITE,
+                               0,
+                               NULL,
+                               OPEN_EXISTING,
+                               0,
+                               NULL);
+        if (svr->pipe != INVALID_HANDLE_VALUE)
+          break;
+
+        /* if pipe not busy, we exit */
+        if (GetLastError() != ERROR_PIPE_BUSY)
+          {
+             ERR("Connection to a server failed");
+             return EINA_FALSE;
+        }
+
+        /* pipe busy, so we wait for it */
+        if (!WaitNamedPipe(buf, NMPWAIT_WAIT_FOREVER))
+          {
+             ERR("Can not wait for a server");
+             goto close_pipe;
+          }
+     }
+
+   svr->path = strdup(buf);
+   if (!svr->path)
+     {
+        ERR("Allocation failed");
+        goto close_pipe;
+     }
+
+   svr->event_read = CreateEvent(NULL, TRUE, FALSE, NULL);
+   if (!svr->event_read)
+     {
+        ERR("Can not create event read");
+        goto free_path;
+     }
+
+   handler_read = ecore_main_win32_handler_add(svr->event_read,
+                                               _ecore_con_local_win32_client_read_server_handler,
+                                               svr);
+   if (!handler_read)
+     {
+        ERR("Can not create handler read");
+        goto close_event_read;
+     }
+
+   svr->event_peek = CreateEvent(NULL, TRUE, FALSE, NULL);
+   if (!svr->event_peek)
+     {
+        ERR("Can not create event peek");
+        goto del_handler_read;
+     }
+
+   handler_peek = ecore_main_win32_handler_add(svr->event_peek,
+                                               _ecore_con_local_win32_client_peek_server_handler,
+                                               svr);
+   if (!handler_peek)
+     {
+        ERR("Can not create handler peek");
+        goto close_event_peek;
+     }
+
+   svr->thread_read = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_client_read_server_thread, svr, CREATE_SUSPENDED, NULL);
+   if (!svr->thread_read)
+     {
+        ERR("Can not launch thread");
+        goto del_handler_peek;
+     }
+
+   if (!svr->delete_me)
+     {
+        Ecore_Con_Event_Server_Add *e;
+
+        e = calloc(1, sizeof(Ecore_Con_Event_Server_Add));
+        if (e)
+          {
+             svr->event_count++;
+             e->server = svr;
+             ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, e,
+                             cb_free, NULL);
+          }
+     }
+
+   ResumeThread(svr->thread_read);
+
+   return EINA_TRUE;
+
+ del_handler_peek:
+   ecore_main_win32_handler_del(handler_peek);
+ close_event_peek:
+   CloseHandle(svr->event_peek);
+ del_handler_read:
+   ecore_main_win32_handler_del(handler_read);
+ close_event_read:
+   CloseHandle(svr->event_read);
+ free_path:
+   free(svr->path);
+   svr->path = NULL;
+ close_pipe:
+   CloseHandle(svr->pipe);
+
+   return EINA_FALSE;
+}
+
+Eina_Bool
+ecore_con_local_win32_server_flush(Ecore_Con_Server *svr)
+{
+   int num;
+   BOOL res;
+   DWORD written;
+
+   /* This check should never be true */
+   if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
+     return EINA_TRUE;
+
+   if (((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
+       ((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
+     return EINA_FALSE;
+
+   num = svr->write_buf_size - svr->write_buf_offset;
+   if (num <= 0) return EINA_TRUE;
+
+   res = WriteFile(svr->pipe, svr->write_buf + svr->write_buf_offset, num, &written, NULL);
+   if (!res)
+     {
+        char *msg;
+
+        msg = evil_last_error_get();
+        if (msg)
+          {
+             ecore_con_event_server_error(svr, msg);
+             free(msg);
+          }
+        if (!svr->delete_me)
+          ecore_con_event_server_del(svr);
+        svr->dead = EINA_TRUE;
+     }
+
+   svr->write_buf_offset += written;
+   if (svr->write_buf_offset >= svr->write_buf_size)
+     {
+        svr->write_buf_size = 0;
+        svr->write_buf_offset = 0;
+        free(svr->write_buf);
+        svr->write_buf = NULL;
+        svr->want_write = 0;
+     }
+   else if (written < (DWORD)num)
+     svr->want_write = 1;
+
+   return EINA_TRUE;
+}
+
+Eina_Bool
+ecore_con_local_win32_client_flush(Ecore_Con_Client *cl)
+{
+   Ecore_Con_Type type;
+   int num;
+   BOOL res;
+   DWORD written;
+
+   type = cl->host_server->type & ECORE_CON_TYPE;
+
+   /* This check should never be true */
+   if (type == ECORE_CON_LOCAL_ABSTRACT)
+     return EINA_TRUE;
+
+   if ((type != ECORE_CON_LOCAL_USER) &&
+       (type != ECORE_CON_LOCAL_SYSTEM))
+     return EINA_FALSE;
+
+   num = cl->buf_size - cl->buf_offset;
+   if (num <= 0) return EINA_TRUE;
+
+   res = WriteFile(cl->host_server->pipe, cl->buf + cl->buf_offset, num, &written, NULL);
+   if (!res)
+     {
+        char *msg;
+
+        msg = evil_last_error_get();
+        if (msg)
+          {
+             ecore_con_event_client_error(cl, msg);
+             free(msg);
+          }
+        if (!cl->delete_me)
+          ecore_con_event_client_del(cl);
+        cl->dead = EINA_TRUE;
+     }
+
+   cl->buf_offset += written;
+   if (cl->buf_offset >= cl->buf_size)
+     {
+        cl->buf_size = 0;
+        cl->buf_offset = 0;
+        free(cl->buf);
+        cl->buf = NULL;
+        cl->host_server->want_write = 0;
+     }
+   else if (written < (DWORD)num)
+     cl->host_server->want_write = 1;
+
+   return EINA_TRUE;
+}
index 0574341..f484b2d 100644 (file)
@@ -157,6 +157,16 @@ struct _Ecore_Con_Server
    Eina_Bool verify : 1; /* EINA_TRUE if certificates will be verified */
    Eina_Bool reject_excess_clients : 1;
    Eina_Bool delete_me : 1;
+#ifdef _WIN32
+   Eina_Bool want_write : 1;
+   Eina_Bool read_stop : 1;
+   Eina_Bool read_stopped : 1;
+   HANDLE pipe;
+   HANDLE thread_read;
+   HANDLE event_read;
+   HANDLE event_peek;
+   DWORD nbr_bytes;
+#endif
 };
 
 #ifdef HAVE_CURL
@@ -200,9 +210,26 @@ struct _Ecore_Con_Lookup
 
 /* from ecore_con.c */
 void ecore_con_server_infos_del(Ecore_Con_Server *svr, void *info);
+void ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num, Eina_Bool duplicate);
+void ecore_con_event_server_del(Ecore_Con_Server *svr);
 void ecore_con_event_server_error(Ecore_Con_Server *svr, const char *error);
+void ecore_con_event_client_add(Ecore_Con_Client *cl);
+void ecore_con_event_client_data(Ecore_Con_Client *cl, unsigned char *buf, int num, Eina_Bool duplicate);
+void ecore_con_event_client_del(Ecore_Con_Client *cl);
 void ecore_con_event_client_error(Ecore_Con_Client *cl, const char *error);
 
+/* from ecore_local_win32.c */
+#ifdef _WIN32
+Eina_Bool ecore_con_local_listen(Ecore_Con_Server *svr);
+Eina_Bool ecore_con_local_connect(Ecore_Con_Server *svr,
+                            Eina_Bool (*cb_done)(void *data,
+                                                 Ecore_Fd_Handler *fd_handler),
+                            void (*cb_free)(void *data, void *ev));
+Eina_Bool ecore_con_local_win32_server_flush(Ecore_Con_Server *svr);
+Eina_Bool ecore_con_local_win32_client_flush(Ecore_Con_Client *cl);
+void      ecore_con_local_win32_server_del(Ecore_Con_Server *svr);
+void      ecore_con_local_win32_client_del(Ecore_Con_Client *cl);
+#else
 /* from ecore_local.c */
 int ecore_con_local_init(void);
 int ecore_con_local_shutdown(void);
@@ -218,6 +245,8 @@ int ecore_con_local_listen(Ecore_Con_Server *svr,
                               void *data,
                               Ecore_Fd_Handler *fd_handler),
                            void *data);
+#endif
+
 /* from ecore_con_info.c */
 int                 ecore_con_info_init(void);
 int                 ecore_con_info_shutdown(void);