Tizen 2.1 base
[framework/uifw/ecore.git] / src / lib / ecore_con / ecore_con_local_win32.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <process.h>
6
7 #include <Evil.h>
8 #include <Ecore.h>
9
10 #include "Ecore_Con.h"
11 #include "ecore_con_private.h"
12
13 #define BUFSIZE 512
14
15
16 static int _ecore_con_local_init_count = 0;
17
18 int
19 ecore_con_local_init(void)
20 {
21    if (++_ecore_con_local_init_count != 1)
22      return _ecore_con_local_init_count;
23
24    return _ecore_con_local_init_count;
25 }
26
27 int
28 ecore_con_local_shutdown(void)
29 {
30    if (--_ecore_con_local_init_count != 0)
31      return _ecore_con_local_init_count;
32
33    return _ecore_con_local_init_count;
34 }
35
36
37 static Eina_Bool
38 _ecore_con_local_win32_server_read_client_handler(void *data, Ecore_Win32_Handler *wh)
39 {
40   Ecore_Con_Client *cl;
41   void *buf;
42   DWORD n;
43   Eina_Bool broken_pipe = EINA_FALSE;
44
45   cl = (Ecore_Con_Client *)data;
46
47   if (!ResetEvent(cl->host_server->event_read))
48     return ECORE_CALLBACK_RENEW;
49
50   buf = malloc(cl->host_server->nbr_bytes);
51   if (!buf)
52     return ECORE_CALLBACK_RENEW;
53
54   if (ReadFile(cl->host_server->pipe, buf, cl->host_server->nbr_bytes, &n, NULL))
55     {
56        if (!cl->delete_me)
57          ecore_con_event_client_data(cl, buf, cl->host_server->nbr_bytes, EINA_FALSE);
58        cl->host_server->want_write = 1;
59     }
60   else
61     {
62       if (GetLastError() == ERROR_BROKEN_PIPE)
63         broken_pipe = EINA_TRUE;
64     }
65
66   if (broken_pipe)
67     {
68 #if 0
69        char *msg;
70
71        msg = evil_last_error_get();
72        if (msg)
73          {
74             ecore_con_event_client_error(cl, msg);
75             free(msg);
76          }
77 #endif
78        _ecore_con_client_kill(cl);
79        return ECORE_CALLBACK_CANCEL;
80     }
81
82   if (cl->host_server->want_write)
83     ecore_con_local_win32_client_flush(cl);
84
85    ecore_main_win32_handler_del(wh);
86
87   return ECORE_CALLBACK_DONE;
88 }
89
90 static Eina_Bool
91 _ecore_con_local_win32_server_peek_client_handler(void *data, Ecore_Win32_Handler *wh)
92 {
93    Ecore_Con_Client *cl;
94 #if 0
95    char *msg;
96 #endif
97
98    cl = (Ecore_Con_Client *)data;
99
100    if (!ResetEvent(cl->host_server->event_peek))
101      return ECORE_CALLBACK_RENEW;
102
103 #if 0
104    msg = evil_last_error_get();
105    if (msg)
106      {
107         ecore_con_event_server_error(cl->host_server, msg);
108         free(msg);
109      }
110 #endif
111    _ecore_con_server_kill(cl->host_server);
112    return ECORE_CALLBACK_CANCEL;
113
114    ecore_main_win32_handler_del(wh);
115
116    return ECORE_CALLBACK_DONE;
117 }
118
119 static Eina_Bool
120 _ecore_con_local_win32_client_peek_server_handler(void *data, Ecore_Win32_Handler *wh)
121 {
122    Ecore_Con_Server *svr;
123 #if 0
124    char *msg;
125 #endif
126
127    svr = (Ecore_Con_Server *)data;
128
129    if (!ResetEvent(svr->event_peek))
130      return ECORE_CALLBACK_RENEW;
131 #if 0
132    msg = evil_last_error_get();
133    if (msg)
134      {
135         ecore_con_event_server_error(svr, msg);
136         free(msg);
137      }
138 #endif
139    _ecore_con_server_kill(svr);
140    return ECORE_CALLBACK_CANCEL;
141
142    ecore_main_win32_handler_del(wh);
143
144    return ECORE_CALLBACK_DONE;
145 }
146
147 static Eina_Bool
148 _ecore_con_local_win32_client_read_server_handler(void *data, Ecore_Win32_Handler *wh)
149 {
150   Ecore_Con_Server *svr;
151   void *buf;
152   DWORD n;
153   Eina_Bool broken_pipe = EINA_FALSE;
154
155   svr = (Ecore_Con_Server *)data;
156
157   if (!ResetEvent(svr->event_read))
158     return ECORE_CALLBACK_RENEW;
159
160   buf = malloc(svr->nbr_bytes);
161   if (!buf)
162     return ECORE_CALLBACK_RENEW;
163
164   if (ReadFile(svr->pipe, buf, svr->nbr_bytes, &n, NULL))
165     {
166        if (!svr->delete_me)
167          ecore_con_event_server_data(svr, buf, svr->nbr_bytes, EINA_FALSE);
168        svr->want_write = 1;
169     }
170   else
171     {
172       if (GetLastError() == ERROR_BROKEN_PIPE)
173         broken_pipe = EINA_TRUE;
174     }
175
176   if (broken_pipe)
177     {
178 #if 0
179        char *msg;
180
181        msg = evil_last_error_get();
182        if (msg)
183          {
184             ecore_con_event_server_error(svr, msg);
185             free(msg);
186          }
187 #endif
188        _ecore_con_server_kill(svr);
189        return ECORE_CALLBACK_CANCEL;
190     }
191
192   if (svr->want_write)
193     ecore_con_local_win32_server_flush(svr);
194
195    ecore_main_win32_handler_del(wh);
196
197   return ECORE_CALLBACK_DONE;
198 }
199
200 /* thread to read data sent by the server to the client */
201 static unsigned int __stdcall
202 _ecore_con_local_win32_client_read_server_thread(void *data)
203 {
204    Ecore_Con_Server *svr;
205    DWORD nbr_bytes = 0;
206
207    svr = (Ecore_Con_Server *)data;
208
209    svr->read_stopped = EINA_FALSE;
210
211    while (!svr->read_stop)
212      {
213         if (PeekNamedPipe(svr->pipe, NULL, 0, NULL, &nbr_bytes, NULL))
214           {
215              if (nbr_bytes <= 0)
216                continue;
217
218              svr->nbr_bytes = nbr_bytes;
219              if (!SetEvent(svr->event_read))
220                continue;
221           }
222         else
223           {
224              if (GetLastError() == ERROR_BROKEN_PIPE)
225                {
226                   if (!SetEvent(svr->event_peek))
227                     continue;
228                   break;
229                }
230           }
231      }
232
233    printf(" ### %s\n", __FUNCTION__);
234    svr->read_stopped = EINA_TRUE;
235    _endthreadex(0);
236    return 0;
237 }
238
239 /* thread to read data sent by the client to the server */
240 static unsigned int __stdcall
241 _ecore_con_local_win32_server_read_client_thread(void *data)
242 {
243    Ecore_Con_Client *cl;
244    DWORD nbr_bytes = 0;
245
246    cl = (Ecore_Con_Client *)data;
247
248    cl->host_server->read_stopped = EINA_FALSE;
249
250    while (!cl->host_server->read_stop)
251      {
252         if (PeekNamedPipe(cl->host_server->pipe, NULL, 0, NULL, &nbr_bytes, NULL))
253           {
254              if (nbr_bytes <= 0)
255                continue;
256
257              cl->host_server->nbr_bytes = nbr_bytes;
258              if (!SetEvent(cl->host_server->event_read))
259                continue;
260           }
261         else
262           {
263              if (GetLastError() == ERROR_BROKEN_PIPE)
264                {
265                   if (!SetEvent(cl->host_server->event_peek))
266                     continue;
267                   break;
268                }
269           }
270      }
271
272    printf(" ### %s\n", __FUNCTION__);
273    cl->host_server->read_stopped = EINA_TRUE;
274    _endthreadex(0);
275    return 0;
276 }
277
278 static Eina_Bool
279 _ecore_con_local_win32_client_add(void *data, Ecore_Win32_Handler *wh)
280 {
281    Ecore_Con_Client *cl = NULL;
282    Ecore_Con_Server *svr;
283    Ecore_Win32_Handler *handler_read;
284    Ecore_Win32_Handler *handler_peek;
285
286    svr = (Ecore_Con_Server *)data;
287
288    if (!svr->pipe)
289      return ECORE_CALLBACK_CANCEL;
290
291    if (svr->delete_me)
292      return ECORE_CALLBACK_CANCEL;
293
294    if ((svr->client_limit >= 0) && (!svr->reject_excess_clients) &&
295        (svr->client_count >= (unsigned int)svr->client_limit))
296      return ECORE_CALLBACK_CANCEL;
297
298    cl = calloc(1, sizeof(Ecore_Con_Client));
299    if (!cl)
300      {
301         ERR("allocation failed");
302         return ECORE_CALLBACK_CANCEL;
303      }
304
305    cl->host_server = svr;
306    ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
307
308    cl->host_server->event_read = CreateEvent(NULL, TRUE, FALSE, NULL);
309    if (!cl->host_server->event_read)
310      {
311         ERR("Can not create event read");
312         goto free_cl;
313      }
314
315    handler_read = ecore_main_win32_handler_add(cl->host_server->event_read,
316                                                _ecore_con_local_win32_server_read_client_handler,
317                                                cl);
318    if (!handler_read)
319      {
320         ERR("Can not create handler read");
321         goto close_event_read;
322      }
323
324    cl->host_server->event_peek = CreateEvent(NULL, TRUE, FALSE, NULL);
325    if (!cl->host_server->event_peek)
326      {
327         ERR("Can not create event peek");
328         goto del_handler_read;
329      }
330
331    handler_peek = ecore_main_win32_handler_add(cl->host_server->event_peek,
332                                                _ecore_con_local_win32_server_peek_client_handler,
333                                                cl);
334    if (!handler_peek)
335      {
336         ERR("Can not create handler peek");
337         goto close_event_peek;
338      }
339
340    cl->host_server->read_stopped = EINA_TRUE;
341    cl->host_server->thread_read = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_server_read_client_thread, cl, CREATE_SUSPENDED, NULL);
342    if (!cl->host_server->thread_read)
343      {
344         ERR("Can not launch thread");
345         goto del_handler_peek;
346      }
347
348    svr->clients = eina_list_append(svr->clients, cl);
349    svr->client_count++;
350
351    if (!cl->delete_me)
352      ecore_con_event_client_add(cl);
353
354    ecore_main_win32_handler_del(wh);
355
356    ResumeThread(cl->host_server->thread_read);
357    return ECORE_CALLBACK_DONE;
358
359  del_handler_peek:
360    ecore_main_win32_handler_del(handler_peek);
361  close_event_peek:
362    CloseHandle(cl->host_server->event_peek);
363  del_handler_read:
364    ecore_main_win32_handler_del(handler_read);
365  close_event_read:
366    CloseHandle(cl->host_server->event_read);
367  free_cl:
368    free(cl);
369
370    return ECORE_CALLBACK_CANCEL;
371 }
372
373 static unsigned int __stdcall
374 _ecore_con_local_win32_listening(void *data)
375 {
376    Ecore_Con_Server *svr;
377    BOOL res;
378
379    svr = (Ecore_Con_Server *)data;
380
381    while (1)
382      {
383         res = ConnectNamedPipe(svr->pipe, NULL);
384         if (!res)
385           {
386              ERR("Opening the connection to the client failed");
387              CloseHandle(svr->pipe);
388              svr->pipe = NULL;
389           }
390         break;
391      }
392
393    DBG("Client connected");
394
395    printf(" ### %s\n", __FUNCTION__);
396    _endthreadex(0);
397    return 0;
398 }
399
400 Eina_Bool
401 ecore_con_local_listen(Ecore_Con_Server *svr)
402 {
403    char buf[256];
404    HANDLE thread_listening;
405    Ecore_Win32_Handler *handler;
406
407    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
408      {
409         ERR("Your system does not support abstract sockets!");
410         return EINA_FALSE;
411      }
412
413    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
414      snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", svr->name);
415    else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
416      {
417         const char *computername;
418
419         computername = getenv("CoMPUTERNAME");
420         snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s", computername, svr->name);
421      }
422
423    svr->path = strdup(buf);
424    if (!svr->path)
425      {
426         ERR("Allocation failed");
427         return EINA_FALSE;
428      }
429
430    /*
431     * synchronuous
432     * block mode
433     * wait mode
434     */
435    svr->pipe = CreateNamedPipe(svr->path,
436                                PIPE_ACCESS_DUPLEX,
437                                PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
438                                PIPE_UNLIMITED_INSTANCES,
439                                BUFSIZE,
440                                BUFSIZE,
441                                5000,
442                                NULL);
443    if (svr->pipe == INVALID_HANDLE_VALUE)
444      {
445         ERR("Creation of the named pipe failed");
446         goto free_path;
447      }
448
449    /*
450     * We use ConnectNamedPipe() to wait for a client to connect.
451     * As the function is blocking, to let the main loop continuing
452     * its iterations, we call ConnectNamedPipe() in a thread
453     */
454    thread_listening = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_listening, svr, CREATE_SUSPENDED, NULL);
455    if (!thread_listening)
456      {
457         ERR("Creation of the listening thread failed");
458         goto close_pipe;
459      }
460
461    handler = ecore_main_win32_handler_add(thread_listening,
462                                           _ecore_con_local_win32_client_add,
463                                           svr);
464    if (!handler)
465      {
466         ERR("Creation of the client add handler failed");
467         goto del_handler;
468      }
469
470    svr->read_stopped = EINA_TRUE;
471    ResumeThread(thread_listening);
472
473    return EINA_TRUE;
474
475  del_handler:
476    ecore_main_win32_handler_del(handler);
477  close_pipe:
478    CloseHandle(svr->pipe);
479  free_path:
480    free(svr->path);
481    svr->path = NULL;
482
483    return EINA_FALSE;
484 }
485
486 void
487 ecore_con_local_win32_server_del(Ecore_Con_Server *svr)
488 {
489    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
490      return;
491
492    if (((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
493        ((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
494      return;
495
496    svr->read_stop = 1;
497    while (!svr->read_stopped)
498      Sleep(100);
499
500    if (svr->event_peek)
501      CloseHandle(svr->event_peek);
502    svr->event_peek = NULL;
503    if (svr->event_read)
504      CloseHandle(svr->event_read);
505    svr->event_read = NULL;
506    free(svr->path);
507    svr->path = NULL;
508    if (svr->pipe)
509      CloseHandle(svr->pipe);
510    svr->pipe = NULL;
511 }
512
513 void
514 ecore_con_local_win32_client_del(Ecore_Con_Client *cl)
515 {
516    if ((cl->host_server->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
517      return;
518
519    if (((cl->host_server->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
520        ((cl->host_server->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
521      return;
522
523    cl->host_server->read_stop = 1;
524    while (!cl->host_server->read_stopped)
525      Sleep(100);
526
527    if (cl->host_server->event_peek)
528      CloseHandle(cl->host_server->event_peek);
529    cl->host_server->event_peek = NULL;
530    if (cl->host_server->event_read)
531      CloseHandle(cl->host_server->event_read);
532    cl->host_server->event_read = NULL;
533    free(cl->host_server->path);
534    cl->host_server->path = NULL;
535    if (cl->host_server->pipe)
536      CloseHandle(cl->host_server->pipe);
537    cl->host_server->pipe = NULL;
538 }
539
540 Eina_Bool
541 ecore_con_local_connect(Ecore_Con_Server *svr,
542                         Eina_Bool (*cb_done)(void *data,
543                                              Ecore_Fd_Handler *fd_handler))
544 {
545    char buf[256];
546    Ecore_Win32_Handler *handler_read;
547    Ecore_Win32_Handler *handler_peek;
548
549    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
550      {
551         ERR("Your system does not support abstract sockets!");
552         return EINA_FALSE;
553      }
554
555    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
556      snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", svr->name);
557    else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
558      {
559         const char *computername;
560
561         computername = getenv("COMPUTERNAME");
562         snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s", computername, svr->name);
563      }
564
565    while (1)
566      {
567         svr->pipe = CreateFile(buf,
568                                GENERIC_READ | GENERIC_WRITE,
569                                0,
570                                NULL,
571                                OPEN_EXISTING,
572                                0,
573                                NULL);
574         if (svr->pipe != INVALID_HANDLE_VALUE)
575           break;
576
577         /* if pipe not busy, we exit */
578         if (GetLastError() != ERROR_PIPE_BUSY)
579           {
580              ERR("Connection to a server failed");
581              return EINA_FALSE;
582         }
583
584         /* pipe busy, so we wait for it */
585         if (!WaitNamedPipe(buf, NMPWAIT_WAIT_FOREVER))
586           {
587              ERR("Can not wait for a server");
588              goto close_pipe;
589           }
590      }
591
592    svr->path = strdup(buf);
593    if (!svr->path)
594      {
595         ERR("Allocation failed");
596         goto close_pipe;
597      }
598
599    svr->event_read = CreateEvent(NULL, TRUE, FALSE, NULL);
600    if (!svr->event_read)
601      {
602         ERR("Can not create event read");
603         goto free_path;
604      }
605
606    handler_read = ecore_main_win32_handler_add(svr->event_read,
607                                                _ecore_con_local_win32_client_read_server_handler,
608                                                svr);
609    if (!handler_read)
610      {
611         ERR("Can not create handler read");
612         goto close_event_read;
613      }
614
615    svr->event_peek = CreateEvent(NULL, TRUE, FALSE, NULL);
616    if (!svr->event_peek)
617      {
618         ERR("Can not create event peek");
619         goto del_handler_read;
620      }
621
622    handler_peek = ecore_main_win32_handler_add(svr->event_peek,
623                                                _ecore_con_local_win32_client_peek_server_handler,
624                                                svr);
625    if (!handler_peek)
626      {
627         ERR("Can not create handler peek");
628         goto close_event_peek;
629      }
630
631    svr->thread_read = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_client_read_server_thread, svr, CREATE_SUSPENDED, NULL);
632    if (!svr->thread_read)
633      {
634         ERR("Can not launch thread");
635         goto del_handler_peek;
636      }
637
638    if (!svr->delete_me) ecore_con_event_server_add(svr);
639
640    ResumeThread(svr->thread_read);
641
642    return EINA_TRUE;
643
644  del_handler_peek:
645    ecore_main_win32_handler_del(handler_peek);
646  close_event_peek:
647    CloseHandle(svr->event_peek);
648  del_handler_read:
649    ecore_main_win32_handler_del(handler_read);
650  close_event_read:
651    CloseHandle(svr->event_read);
652  free_path:
653    free(svr->path);
654    svr->path = NULL;
655  close_pipe:
656    CloseHandle(svr->pipe);
657
658    return EINA_FALSE;
659 }
660
661 Eina_Bool
662 ecore_con_local_win32_server_flush(Ecore_Con_Server *svr)
663 {
664    int num;
665    BOOL res;
666    DWORD written;
667
668    /* This check should never be true */
669    if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
670      return EINA_TRUE;
671
672    if (((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
673        ((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
674      return EINA_FALSE;
675
676    num = eina_binbuf_length_get(svr->buf) - svr->write_buf_offset;
677    if (num <= 0) return EINA_TRUE;
678
679    res = WriteFile(svr->pipe, eina_binbuf_string_get(svr->buf) + svr->write_buf_offset, num, &written, NULL);
680    if (!res)
681      {
682         char *msg;
683
684         msg = evil_last_error_get();
685         if (msg)
686           {
687              ecore_con_event_server_error(svr, msg);
688              free(msg);
689           }
690         _ecore_con_server_kill(svr);
691      }
692
693    svr->write_buf_offset += written;
694    if (svr->write_buf_offset >= eina_binbuf_length_get(svr->buf))
695      {
696         svr->write_buf_offset = 0;
697         eina_binbuf_free(svr->buf);
698         svr->buf = NULL;
699         svr->want_write = 0;
700      }
701    else if (written < (DWORD)num)
702      svr->want_write = 1;
703
704    return EINA_TRUE;
705 }
706
707 Eina_Bool
708 ecore_con_local_win32_client_flush(Ecore_Con_Client *cl)
709 {
710    Ecore_Con_Type type;
711    int num;
712    BOOL res;
713    DWORD written;
714
715    type = cl->host_server->type & ECORE_CON_TYPE;
716
717    /* This check should never be true */
718    if (type == ECORE_CON_LOCAL_ABSTRACT)
719      return EINA_TRUE;
720
721    if ((type != ECORE_CON_LOCAL_USER) &&
722        (type != ECORE_CON_LOCAL_SYSTEM))
723      return EINA_FALSE;
724
725    num = eina_binbuf_length_get(cl->buf) - cl->buf_offset;
726    if (num <= 0) return EINA_TRUE;
727
728    res = WriteFile(cl->host_server->pipe, eina_binbuf_string_get(cl->buf) + cl->buf_offset, num, &written, NULL);
729    if (!res)
730      {
731         char *msg;
732
733         msg = evil_last_error_get();
734         if (msg)
735           {
736              ecore_con_event_client_error(cl, msg);
737              free(msg);
738           }
739         _ecore_con_client_kill(cl);
740      }
741
742    cl->buf_offset += written;
743    if (cl->buf_offset >= eina_binbuf_length_get(cl->buf))
744      {
745         cl->buf_offset = 0;
746         eina_binbuf_free(cl->buf);
747         cl->buf = NULL;
748         cl->host_server->want_write = 0;
749      }
750    else if (written < (DWORD)num)
751      cl->host_server->want_write = 1;
752
753    return EINA_TRUE;
754 }