1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #ifdef HAVE_ARPA_INET_H
6 # include <arpa/inet.h>
7 #endif
8 
9 #ifdef HAVE_SYS_SOCKET_H
10 # include <sys/socket.h>
11 #endif
12 
13 #define EFL_NET_SOCKET_SSL_PROTECTED
14 
15 #include "Ecore.h"
16 
17 #include "Efl_Net.h"
18 
19 #include "ecore_private.h"
20 #include "Ecore_Con.h"
21 #include "ecore_con_private.h"
22 
23 #define ECORE_CON_TYPE 0x0f
24 #define ECORE_CON_SSL  0xf0
25 #define ECORE_CON_SUPER_SSL  0xf00
26 
27 /* This file exists solely to provide ABI compatibility */
28 
29 struct _Ecore_Con_Server
30 {
31    ECORE_MAGIC;
32    Eo *dialer;
33    Eo *server;
34    struct {
35       Eina_Future *job;
36       Eina_Binbuf *pending_send; /* until job is fulfilled, no dialer exists,
37                                   * this binbuf allows immediate
38                                   * ecore_con_server_send() in that situation */
39       Eo *clients_ctx;
40       Eina_List *certs;
41       Eina_List *privkeys;
42       Eina_List *crls;
43       Eina_List *cafiles;
44       Eina_Stringshare *verify_name;
45       Eina_Bool verify;
46       Eina_Bool verify_basic;
47       Eina_Bool upgrading;
48       Ecore_Con_Type upgrade_type;
49    } ssl;
50    Eina_List *clients;
51    Eina_List *event_count;
52    const void *data;
53    Eina_Stringshare *name;
54    Eina_Stringshare *ip;
55    size_t pending_write;
56    double start_time;
57    double timeout;
58    Ecore_Con_Type type;
59    int port;
60    Eina_Bool want_mcast;
61    Eina_Bool is_dialer;
62    Eina_Bool connecting;
63    Eina_Bool delete_me;
64 };
65 
66 struct _Ecore_Con_Client
67 {
68    ECORE_MAGIC;
69    Eo *socket;
70    Ecore_Con_Server *svr;
71    Eina_List *event_count;
72    const void *data;
73    Eina_Stringshare *ip;
74    struct {
75       Eina_Future *job;
76       Eo *ctx;
77       Eina_Bool upgrading;
78    } ssl;
79    size_t pending_write;
80    double start_time;
81    int port;
82    Eina_Bool delete_me;
83 };
84 
85 typedef struct _Ecore_Con_Lookup_Ctx {
86    Ecore_Thread *thread;
87    Ecore_Con_Dns_Cb cb;
88    const void *data;
89 } Ecore_Con_Lookup_Ctx;
90 
91 /* allows delete_me to be true */
92 #define ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, ...)                 \
93   do                                                                    \
94     {                                                                   \
95        if (!svr) return __VA_ARGS__;                                    \
96        if (!EINA_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))              \
97          {                                                              \
98             ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__); \
99             return __VA_ARGS__;                                         \
100          }                                                              \
101     }                                                                   \
102   while (0)
103 
104 #define ECORE_CON_SERVER_CHECK_RETURN(svr, ...) \
105   do \
106     { \
107        ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, __VA_ARGS__) ; \
108        EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->delete_me, __VA_ARGS__); \
109     } \
110   while (0)
111 
112 #define ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, ...)                  \
113   do                                                                    \
114     {                                                                   \
115        if (!cl) return __VA_ARGS__;                                     \
116        if (!EINA_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))               \
117          {                                                              \
118             ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, __func__); \
119             return __VA_ARGS__;                                         \
120          }                                                              \
121     }                                                                   \
122   while (0)
123 
124 #define ECORE_CON_CLIENT_CHECK_RETURN(cl, ...) \
125   do \
126     { \
127        ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, __VA_ARGS__) ; \
128        EINA_SAFETY_ON_TRUE_RETURN_VAL(cl->delete_me, __VA_ARGS__); \
129     } \
130   while (0)
131 
132 
133 /* from ecore_con_alloc.c */
134 #define GENERIC_ALLOC_FREE_HEADER(TYPE, Type) \
135   TYPE *Type##_alloc(void); \
136   void Type##_free(TYPE *e);
137 
138 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Add, ecore_con_event_client_add);
139 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Del, ecore_con_event_client_del);
140 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Add, ecore_con_event_server_add);
141 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Del, ecore_con_event_server_del);
142 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Write, ecore_con_event_server_write);
143 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Data, ecore_con_event_server_data);
144 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Error, ecore_con_event_server_error);
145 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Upgrade, ecore_con_event_server_upgrade);
146 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Proxy_Bind, ecore_con_event_proxy_bind);
147 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Write, ecore_con_event_client_write);
148 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Data, ecore_con_event_client_data);
149 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Error, ecore_con_event_client_error);
150 GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Upgrade, ecore_con_event_client_upgrade);
151 #undef GENERIC_ALLOC_FREE_HEADER
152 
153 /* shared */
154 EAPI int ECORE_CON_EVENT_SERVER_DEL = 0;
155 EAPI int ECORE_CON_EVENT_SERVER_ERROR = 0;
156 /* ecore_con_server_add() */
157 EAPI int ECORE_CON_EVENT_CLIENT_ADD = 0;
158 EAPI int ECORE_CON_EVENT_CLIENT_DEL = 0;
159 /* ecore_con_server_connect() */
160 EAPI int ECORE_CON_EVENT_SERVER_ADD = 0;
161 EAPI int ECORE_CON_EVENT_SERVER_DATA = 0;
162 EAPI int ECORE_CON_EVENT_SERVER_WRITE = 0;
163 EAPI int ECORE_CON_EVENT_PROXY_BIND = 0; /* we're not supporting proxy bind, keep only for ABI */
164 EAPI int ECORE_CON_EVENT_SERVER_UPGRADE = 0;
165 /* for each client from ECORE_CON_EVENT_CLIENT_ADD */
166 EAPI int ECORE_CON_EVENT_CLIENT_DATA = 0;
167 EAPI int ECORE_CON_EVENT_CLIENT_WRITE = 0;
168 EAPI int ECORE_CON_EVENT_CLIENT_ERROR = 0;
169 EAPI int ECORE_CON_EVENT_CLIENT_UPGRADE = 0;
170 
171 static Eina_List *_servers = NULL;
172 static Eina_List *_ecore_con_lookups = NULL;
173 static int _ecore_con_event_count = 0;
174 
175 Ecore_Con_Socks *_ecore_con_proxy_once = NULL;
176 Ecore_Con_Socks *_ecore_con_proxy_global = NULL;
177 
178 void
ecore_con_legacy_init(void)179 ecore_con_legacy_init(void)
180 {
181    ECORE_CON_EVENT_CLIENT_ADD = ecore_event_type_new();
182    ECORE_CON_EVENT_CLIENT_DEL = ecore_event_type_new();
183    ECORE_CON_EVENT_SERVER_ADD = ecore_event_type_new();
184    ECORE_CON_EVENT_SERVER_DEL = ecore_event_type_new();
185    ECORE_CON_EVENT_CLIENT_DATA = ecore_event_type_new();
186    ECORE_CON_EVENT_SERVER_DATA = ecore_event_type_new();
187    ECORE_CON_EVENT_CLIENT_WRITE = ecore_event_type_new();
188    ECORE_CON_EVENT_SERVER_WRITE = ecore_event_type_new();
189    ECORE_CON_EVENT_CLIENT_ERROR = ecore_event_type_new();
190    ECORE_CON_EVENT_SERVER_ERROR = ecore_event_type_new();
191    ECORE_CON_EVENT_PROXY_BIND = ecore_event_type_new();
192    ECORE_CON_EVENT_SERVER_UPGRADE = ecore_event_type_new();
193    ECORE_CON_EVENT_CLIENT_UPGRADE = ecore_event_type_new();
194 
195    eina_magic_string_set(ECORE_MAGIC_CON_SERVER, "Ecore_Con_Server");
196    eina_magic_string_set(ECORE_MAGIC_CON_CLIENT, "Ecore_Con_Client");
197    eina_magic_string_set(ECORE_MAGIC_CON_URL, "Ecore_Con_Url");
198 
199    ecore_con_socks_init();
200 }
201 
202 static void _ecore_con_server_free(Ecore_Con_Server *svr);
203 
204 void
ecore_con_legacy_shutdown(void)205 ecore_con_legacy_shutdown(void)
206 {
207    Eina_List *l, *l2;
208    Ecore_Con_Server *svr;
209    Ecore_Con_Lookup_Ctx *lookup_ctx;
210 
211    EINA_LIST_FOREACH_SAFE(_servers, l, l2, svr)
212      {
213         Ecore_Con_Event_Server_Add *ev;
214 
215         if (!svr) continue;
216         svr->delete_me = EINA_TRUE;
217         INF("svr %p is dead", svr);
218         /* some pointer hacks here to prevent double frees if people are being stupid */
219         EINA_LIST_FREE(svr->event_count, ev)
220           ev->server = NULL;
221         _ecore_con_server_free(svr);
222      }
223 
224    EINA_LIST_FREE(_ecore_con_lookups, lookup_ctx)
225      ecore_thread_cancel(lookup_ctx->thread);
226 
227    ecore_event_type_flush(ECORE_CON_EVENT_CLIENT_ADD,
228                           ECORE_CON_EVENT_CLIENT_DEL,
229                           ECORE_CON_EVENT_SERVER_ADD,
230                           ECORE_CON_EVENT_SERVER_DEL,
231                           ECORE_CON_EVENT_CLIENT_DATA,
232                           ECORE_CON_EVENT_SERVER_DATA,
233                           ECORE_CON_EVENT_CLIENT_WRITE,
234                           ECORE_CON_EVENT_SERVER_WRITE,
235                           ECORE_CON_EVENT_CLIENT_ERROR,
236                           ECORE_CON_EVENT_SERVER_ERROR,
237                           ECORE_CON_EVENT_PROXY_BIND,
238                           ECORE_CON_EVENT_SERVER_UPGRADE,
239                           ECORE_CON_EVENT_CLIENT_UPGRADE);
240 
241    ecore_con_socks_shutdown();
242    if (!_ecore_con_event_count) ecore_con_mempool_shutdown();
243    else WRN("%d events still exist, leaking ecore_con mempools", _ecore_con_event_count);
244 }
245 
246 /**
247  * @addtogroup Ecore_Con_Client_Group Ecore Connection Client Functions
248  *
249  * Functions that operate on Ecore connection client objects, these
250  * are announced using ECORE_CON_EVENT_CLIENT_ADD by servers created
251  * with ecore_con_server_add().
252  *
253  * @{
254  */
255 
256 static Efl_Callback_Array_Item *_ecore_con_client_socket_cbs(void);
257 static Efl_Callback_Array_Item *_ecore_con_client_socket_ssl_cbs(void);
258 
259 static void
_ecore_con_client_socket_close(Ecore_Con_Client * cl)260 _ecore_con_client_socket_close(Ecore_Con_Client *cl)
261 {
262    if (!cl->socket) return;
263 
264    if (!efl_io_closer_closed_get(cl->socket))
265      efl_io_closer_close(cl->socket);
266 
267    /* socket may remain alive due other references, we don't own it */
268    efl_event_callback_array_del(cl->socket, _ecore_con_client_socket_cbs(), cl);
269 }
270 
271 static void
_ecore_con_client_free(Ecore_Con_Client * cl)272 _ecore_con_client_free(Ecore_Con_Client *cl)
273 {
274    Ecore_Con_Server *svr = cl->svr;
275 
276    cl->delete_me = EINA_TRUE;
277    cl->svr = NULL;
278 
279    if (svr)
280      svr->clients = eina_list_remove(svr->clients, cl);
281 
282    _ecore_con_client_socket_close(cl);
283 
284    if (cl->socket)
285      {
286         Eo *parent, *inner_socket = efl_io_buffered_stream_inner_io_get(cl->socket);
287 
288         if (efl_isa(inner_socket, EFL_NET_SOCKET_SSL_CLASS))
289           efl_event_callback_array_del(inner_socket, _ecore_con_client_socket_ssl_cbs(), cl);
290 
291         parent = efl_parent_get(cl->socket);
292         if (parent && svr && (parent != svr->server))
293           efl_del(cl->socket); /* we own it */
294         else
295           efl_unref(cl->socket);
296         cl->socket = NULL;
297      }
298 
299    if (cl->ssl.job) eina_future_cancel(cl->ssl.job);
300 
301    if (cl->ssl.ctx)
302      {
303         efl_unref(cl->ssl.ctx);
304         cl->ssl.ctx = NULL;
305      }
306 
307    if (cl->event_count) return;
308 
309    if (svr && (!svr->event_count) && (svr->delete_me))
310      _ecore_con_server_free(svr);
311 
312    cl->data = NULL;
313    eina_stringshare_replace(&cl->ip, NULL);
314 
315    EINA_MAGIC_SET(cl, ECORE_MAGIC_NONE);
316    free(cl);
317 }
318 
319 /* BEGIN: post of Ecore_Event for ecore_con_server_connect() ************/
320 
321 static void
_ecore_con_free_event_client_add(void * data EINA_UNUSED,void * event)322 _ecore_con_free_event_client_add(void *data EINA_UNUSED, void *event)
323 {
324    Ecore_Con_Event_Client_Add *ev = event;
325 
326    if (ev->client)
327      {
328         Ecore_Con_Client *cl = ev->client;
329         cl->event_count = eina_list_remove(cl->event_count, ev);
330         if ((!cl->event_count) && (cl->delete_me))
331           _ecore_con_client_free(cl);
332      }
333    ecore_con_event_client_add_free(ev);
334    _ecore_con_event_count--;
335 }
336 
337 static void
_ecore_con_post_event_client_add(Ecore_Con_Client * cl)338 _ecore_con_post_event_client_add(Ecore_Con_Client *cl)
339 {
340    Ecore_Con_Event_Client_Add *ev = ecore_con_event_client_add_alloc();
341    EINA_SAFETY_ON_NULL_GOTO(ev, error);
342 
343    ev->client = cl;
344    cl->event_count = eina_list_append(cl->event_count, ev);
345 
346    ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, ev, _ecore_con_free_event_client_add, NULL);
347    _ecore_con_event_count++;
348    return;
349 
350  error:
351    _ecore_con_client_free(cl);
352 }
353 
354 static void
_ecore_con_free_event_client_del(void * data EINA_UNUSED,void * event)355 _ecore_con_free_event_client_del(void *data EINA_UNUSED, void *event)
356 {
357    Ecore_Con_Event_Client_Del *ev = event;
358 
359    if (ev->client)
360      {
361         Ecore_Con_Client *cl = ev->client;
362         cl->event_count = eina_list_remove(cl->event_count, ev);
363         if (!cl->event_count)
364           _ecore_con_client_free(cl);
365         else
366           cl->delete_me = EINA_TRUE;
367      }
368    ecore_con_event_client_del_free(ev);
369    _ecore_con_event_count--;
370 }
371 
372 static Eina_Bool
_ecore_con_post_event_client_del(Ecore_Con_Client * cl)373 _ecore_con_post_event_client_del(Ecore_Con_Client *cl)
374 {
375    Ecore_Con_Event_Client_Del *ev = ecore_con_event_client_del_alloc();
376    EINA_SAFETY_ON_NULL_GOTO(ev, error);
377 
378    ev->client = cl;
379    cl->event_count = eina_list_append(cl->event_count, ev);
380 
381    /* legacy compatibility: test suite expects NULL pointer for IP */
382    eina_stringshare_replace(&cl->ip, NULL);
383 
384    ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, ev, _ecore_con_free_event_client_del, NULL);
385    _ecore_con_event_count++;
386    return EINA_TRUE;
387 
388  error:
389    _ecore_con_client_free(cl);
390    return EINA_FALSE;
391 }
392 
393 static void
_ecore_con_free_event_client_data(void * data EINA_UNUSED,void * event)394 _ecore_con_free_event_client_data(void *data EINA_UNUSED, void *event)
395 {
396    Ecore_Con_Event_Client_Data *ev = event;
397 
398    if (ev->client)
399      {
400         Ecore_Con_Client *cl = ev->client;
401         cl->event_count = eina_list_remove(cl->event_count, ev);
402         if ((!cl->event_count) && (cl->delete_me))
403           _ecore_con_client_free(cl);
404      }
405    free(ev->data);
406    ecore_con_event_client_data_free(ev);
407    _ecore_con_event_count--;
408 }
409 
410 static void
_ecore_con_post_event_client_data(Ecore_Con_Client * cl,Eina_Rw_Slice slice)411 _ecore_con_post_event_client_data(Ecore_Con_Client *cl, Eina_Rw_Slice slice)
412 {
413    Ecore_Con_Event_Client_Data *ev = ecore_con_event_client_data_alloc();
414    EINA_SAFETY_ON_NULL_GOTO(ev, error);
415 
416    ev->client = cl;
417    ev->data = slice.mem;
418    ev->size = slice.len;
419    cl->event_count = eina_list_append(cl->event_count, ev);
420 
421    ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, ev, _ecore_con_free_event_client_data, NULL);
422    _ecore_con_event_count++;
423    return;
424 
425  error:
426    free(slice.mem);
427 }
428 
429 static void
_ecore_con_free_event_client_write(void * data EINA_UNUSED,void * event)430 _ecore_con_free_event_client_write(void *data EINA_UNUSED, void *event)
431 {
432    Ecore_Con_Event_Client_Write *ev = event;
433 
434    if (ev->client)
435      {
436         Ecore_Con_Client *cl = ev->client;
437         cl->event_count = eina_list_remove(cl->event_count, ev);
438         if ((!cl->event_count) && (cl->delete_me))
439           _ecore_con_client_free(cl);
440      }
441    ecore_con_event_client_write_free(ev);
442    _ecore_con_event_count--;
443 }
444 
445 static void
_ecore_con_post_event_client_write(Ecore_Con_Client * cl,size_t size)446 _ecore_con_post_event_client_write(Ecore_Con_Client *cl, size_t size)
447 {
448    Ecore_Con_Event_Client_Write *ev = ecore_con_event_client_write_alloc();
449    EINA_SAFETY_ON_NULL_RETURN(ev);
450 
451    ev->client = cl;
452    ev->size = size;
453    cl->event_count = eina_list_append(cl->event_count, ev);
454 
455    ecore_event_add(ECORE_CON_EVENT_CLIENT_WRITE, ev, _ecore_con_free_event_client_write, NULL);
456    _ecore_con_event_count++;
457 }
458 
459 static void
_ecore_con_free_event_client_error(void * data EINA_UNUSED,void * event)460 _ecore_con_free_event_client_error(void *data EINA_UNUSED, void *event)
461 {
462    Ecore_Con_Event_Client_Error *ev = event;
463 
464    if (ev->client)
465      {
466         Ecore_Con_Client *cl = ev->client;
467         cl->event_count = eina_list_remove(cl->event_count, ev);
468         if ((!cl->event_count) && (cl->delete_me))
469           _ecore_con_client_free(cl);
470      }
471    free(ev->error);
472    ecore_con_event_client_error_free(ev);
473    _ecore_con_event_count--;
474 }
475 
476 static Eina_Bool
_ecore_con_post_event_client_error(Ecore_Con_Client * cl,const char * err)477 _ecore_con_post_event_client_error(Ecore_Con_Client *cl, const char *err)
478 {
479    Ecore_Con_Event_Client_Error *ev = ecore_con_event_client_error_alloc();
480    EINA_SAFETY_ON_NULL_GOTO(ev, error);
481 
482    INF("cl=%p error from %s: %s", cl, efl_net_socket_address_remote_get(cl->socket), err);
483 
484    ev->client = cl;
485    ev->error = err ? strdup(err) : NULL;
486    cl->event_count = eina_list_append(cl->event_count, ev);
487 
488    ecore_event_add(ECORE_CON_EVENT_CLIENT_ERROR, ev, _ecore_con_free_event_client_error, NULL);
489    _ecore_con_event_count++;
490    return EINA_TRUE;
491 
492  error:
493    _ecore_con_client_free(cl);
494    return EINA_FALSE;
495 }
496 
497 static void
_ecore_con_free_event_client_upgrade(void * data EINA_UNUSED,void * event)498 _ecore_con_free_event_client_upgrade(void *data EINA_UNUSED, void *event)
499 {
500    Ecore_Con_Event_Client_Upgrade *ev = event;
501 
502    if (ev->client)
503      {
504         Ecore_Con_Client *cl = ev->client;
505         cl->event_count = eina_list_remove(cl->event_count, ev);
506         if ((!cl->event_count) && (cl->delete_me))
507           _ecore_con_client_free(cl);
508      }
509    ecore_con_event_client_upgrade_free(ev);
510    _ecore_con_event_count--;
511 }
512 
513 static void
_ecore_con_post_event_client_upgrade(Ecore_Con_Client * cl)514 _ecore_con_post_event_client_upgrade(Ecore_Con_Client *cl)
515 {
516    Ecore_Con_Event_Client_Upgrade *ev = ecore_con_event_client_upgrade_alloc();
517    EINA_SAFETY_ON_NULL_GOTO(ev, error);
518 
519    ev->client = cl;
520    cl->event_count = eina_list_append(cl->event_count, ev);
521 
522    ecore_event_add(ECORE_CON_EVENT_CLIENT_UPGRADE, ev, _ecore_con_free_event_client_upgrade, NULL);
523    _ecore_con_event_count++;
524    return;
525 
526  error:
527    _ecore_con_client_free(cl);
528 }
529 
530 /* END: post of Ecore_Event for ecore_con_server_add() ******************/
531 
532 static void
_ecore_con_client_socket_progress(void * data,const Efl_Event * event EINA_UNUSED)533 _ecore_con_client_socket_progress(void *data, const Efl_Event *event EINA_UNUSED)
534 {
535    Ecore_Con_Client *cl = data;
536    size_t now = efl_io_buffered_stream_pending_write_get(cl->socket);
537 
538    if (cl->delete_me) return;
539    if (cl->ssl.upgrading) return;
540 
541    if (cl->pending_write == now) return;
542    EINA_SAFETY_ON_TRUE_GOTO(cl->pending_write < now, end); /* forgot to update! */
543 
544    _ecore_con_post_event_client_write(cl, cl->pending_write - now);
545 
546  end:
547    cl->pending_write = now;
548 }
549 
550 static void
_ecore_con_client_socket_slice_changed(void * data,const Efl_Event * event EINA_UNUSED)551 _ecore_con_client_socket_slice_changed(void *data, const Efl_Event *event EINA_UNUSED)
552 {
553    Ecore_Con_Client *cl = data;
554    Eina_Slice ro_slice;
555    Eina_Rw_Slice rw_slice;
556 
557    if (cl->delete_me) return;
558    if (cl->ssl.upgrading) return;
559 
560    ro_slice = efl_io_buffered_stream_slice_get(cl->socket);
561    if (ro_slice.len == 0) return;
562 
563    rw_slice = eina_slice_dup(ro_slice);
564    efl_io_buffered_stream_clear(cl->socket);
565    _ecore_con_post_event_client_data(cl, rw_slice);
566 }
567 
568 static void
_ecore_con_client_socket_read_finished(void * data,const Efl_Event * event EINA_UNUSED)569 _ecore_con_client_socket_read_finished(void *data, const Efl_Event *event EINA_UNUSED)
570 {
571    Ecore_Con_Client *cl = data;
572 
573    DBG("client %p socket %p read finished, queue EOS", cl, cl->socket);
574 
575    if (!efl_io_closer_closed_get(cl->socket))
576      efl_io_buffered_stream_eos_mark(cl->socket);
577 }
578 
579 static void
_ecore_con_client_socket_finished(void * data,const Efl_Event * event EINA_UNUSED)580 _ecore_con_client_socket_finished(void *data, const Efl_Event *event EINA_UNUSED)
581 {
582    Ecore_Con_Client *cl = data;
583 
584    DBG("client %p socket %p finished", cl, cl->socket);
585 
586    _ecore_con_client_socket_close(cl);
587 
588    _ecore_con_post_event_client_del(cl);
589 }
590 
591 static void
_ecore_con_client_socket_error(void * data,const Efl_Event * event)592 _ecore_con_client_socket_error(void *data, const Efl_Event *event)
593 {
594    Ecore_Con_Client *cl = data;
595    Eina_Error *perr = event->info;
596 
597    if (cl->delete_me) return;
598 
599    WRN("error client %s: %s", efl_net_socket_address_remote_get(cl->socket), eina_error_msg_get(*perr));
600 
601    _ecore_con_client_socket_close(cl);
602    _ecore_con_post_event_client_error(cl, eina_error_msg_get(*perr));
603 }
604 
605 EFL_CALLBACKS_ARRAY_DEFINE(_ecore_con_client_socket_cbs,
606                            { EFL_IO_BUFFERED_STREAM_EVENT_PROGRESS, _ecore_con_client_socket_progress },
607                            { EFL_IO_BUFFERED_STREAM_EVENT_SLICE_CHANGED, _ecore_con_client_socket_slice_changed },
608                            { EFL_IO_BUFFERED_STREAM_EVENT_READ_FINISHED, _ecore_con_client_socket_read_finished },
609                            { EFL_IO_BUFFERED_STREAM_EVENT_FINISHED, _ecore_con_client_socket_finished },
610                            { EFL_IO_BUFFERED_STREAM_EVENT_ERROR, _ecore_con_client_socket_error });
611 
612 static Ecore_Con_Client *
ecore_con_client_add(Ecore_Con_Server * svr,Eo * socket)613 ecore_con_client_add(Ecore_Con_Server *svr, Eo *socket)
614 {
615    Ecore_Con_Client *cl;
616    Eo *inner_socket;
617 
618    cl = calloc(1, sizeof(Ecore_Con_Client));
619    EINA_SAFETY_ON_NULL_RETURN_VAL(cl, NULL);
620 
621    cl->socket = efl_ref(socket);
622    cl->svr = svr;
623    cl->start_time = ecore_time_get();
624    cl->port = -1;
625 
626    inner_socket = efl_io_buffered_stream_inner_io_get(socket);
627    if (efl_isa(inner_socket, EFL_NET_SOCKET_TCP_CLASS) ||
628        efl_isa(inner_socket, EFL_NET_SOCKET_SSL_CLASS) ||
629        efl_isa(inner_socket, EFL_NET_SERVER_UDP_CLIENT_CLASS))
630      {
631         const char *addr = efl_net_socket_address_remote_get(inner_socket);
632         if (addr)
633           {
634              const char *p;
635              if (addr[0] != '[') p = strchr(addr, ':');
636              else
637                {
638                   addr++;
639                   p = strchr(addr, ']');
640                }
641              if (p)
642                {
643                   const char *portstr = p;
644                   if (portstr[0] == ']') portstr++;
645                   if (portstr[0] == ':') portstr++; /* not else if! */
646                   cl->ip = eina_stringshare_add_length(addr, p - addr);
647                   cl->port = atoi(portstr);
648                }
649           }
650      }
651    else
652      {
653         /* legacy compatibility */
654         cl->ip = eina_stringshare_add("0.0.0.0");
655         cl->port = -1;
656      }
657 
658    efl_event_callback_array_add(cl->socket, _ecore_con_client_socket_cbs(), cl);
659    if (efl_isa(inner_socket, EFL_NET_SOCKET_SSL_CLASS))
660      efl_event_callback_array_add(inner_socket, _ecore_con_client_socket_ssl_cbs(), cl);
661 
662    ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
663    svr->clients = eina_list_append(svr->clients, cl);
664    return cl;
665 }
666 
667 EAPI int
ecore_con_client_send(Ecore_Con_Client * cl,const void * data,int size)668 ecore_con_client_send(Ecore_Con_Client *cl, const void *data, int size)
669 {
670    Eina_Error err;
671    Eina_Slice slice = { .mem = data, .len = size };
672 
673    ECORE_CON_CLIENT_CHECK_RETURN(cl, 0);
674    EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
675    EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
676 
677    EINA_SAFETY_ON_NULL_RETURN_VAL(cl->socket, 0);
678    err = efl_io_writer_write(cl->socket, &slice, NULL);
679    if (err)
680      {
681         ERR("cl=%p could not send data=%p, size=%d: %s", cl, data, size, eina_error_msg_get(err));
682         return 0;
683      }
684    cl->pending_write = efl_io_buffered_stream_pending_write_get(cl->socket);
685 
686    return slice.len;
687 }
688 
689 EAPI Eina_Bool
ecore_con_client_connected_get(const Ecore_Con_Client * cl)690 ecore_con_client_connected_get(const Ecore_Con_Client *cl)
691 {
692    ECORE_CON_CLIENT_CHECK_RETURN(cl, EINA_FALSE);
693    return !efl_io_closer_closed_get(cl->socket);
694 }
695 
696 EAPI void
ecore_con_client_timeout_set(Ecore_Con_Client * cl,double timeout)697 ecore_con_client_timeout_set(Ecore_Con_Client *cl, double timeout)
698 {
699    ECORE_CON_CLIENT_CHECK_RETURN(cl);
700    efl_io_buffered_stream_timeout_inactivity_set(cl->socket, timeout);
701 }
702 
703 EAPI double
ecore_con_client_timeout_get(const Ecore_Con_Client * cl)704 ecore_con_client_timeout_get(const Ecore_Con_Client *cl)
705 {
706    ECORE_CON_CLIENT_CHECK_RETURN(cl, -1.0);
707    return efl_io_buffered_stream_timeout_inactivity_get(cl->socket);
708 }
709 
710 EAPI void *
ecore_con_client_del(Ecore_Con_Client * cl)711 ecore_con_client_del(Ecore_Con_Client *cl)
712 {
713    const void *data;
714 
715    ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, NULL);
716 
717    data = cl->data;
718 
719    _ecore_con_client_free(cl);
720    return (void *)data;
721 }
722 
723 EAPI void
ecore_con_client_data_set(Ecore_Con_Client * cl,const void * data)724 ecore_con_client_data_set(Ecore_Con_Client *cl,
725                           const void *data)
726 {
727    ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl);
728    cl->data = data;
729 }
730 
731 EAPI void *
ecore_con_client_data_get(Ecore_Con_Client * cl)732 ecore_con_client_data_get(Ecore_Con_Client *cl)
733 {
734    ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, NULL);
735    return (void *)cl->data;
736 }
737 
738 EAPI const char *
ecore_con_client_ip_get(const Ecore_Con_Client * cl)739 ecore_con_client_ip_get(const Ecore_Con_Client *cl)
740 {
741    ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, NULL);
742    return cl->ip;
743 }
744 
745 EAPI int
ecore_con_client_port_get(const Ecore_Con_Client * cl)746 ecore_con_client_port_get(const Ecore_Con_Client *cl)
747 {
748    ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, -1);
749    return cl->port;
750 }
751 
752 EAPI Ecore_Con_Server *
ecore_con_client_server_get(const Ecore_Con_Client * cl)753 ecore_con_client_server_get(const Ecore_Con_Client *cl)
754 {
755    ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, NULL);
756    return cl->svr;
757 }
758 
759 EAPI double
ecore_con_client_uptime_get(const Ecore_Con_Client * cl)760 ecore_con_client_uptime_get(const Ecore_Con_Client *cl)
761 {
762    ECORE_CON_CLIENT_CHECK_RELAXED_RETURN(cl, 0.0);
763    return ecore_time_get() - cl->start_time;
764 }
765 
766 EAPI void
ecore_con_client_flush(Ecore_Con_Client * cl)767 ecore_con_client_flush(Ecore_Con_Client *cl)
768 {
769    ECORE_CON_CLIENT_CHECK_RETURN(cl);
770    Eo *inner_socket;
771 
772    if (!cl->socket) return;
773 
774    efl_io_buffered_stream_flush(cl->socket, EINA_FALSE, EINA_TRUE);
775 
776    inner_socket = efl_io_buffered_stream_inner_io_get(cl->socket);
777 
778    if (!efl_isa(inner_socket, EFL_NET_SOCKET_TCP_CLASS)) return;
779    if (!efl_net_socket_tcp_cork_get(inner_socket)) return;
780 
781    efl_net_socket_tcp_cork_set(inner_socket, EINA_FALSE);
782    efl_net_socket_tcp_cork_set(inner_socket, EINA_TRUE);
783 }
784 
785 EAPI int
ecore_con_client_fd_get(const Ecore_Con_Client * cl)786 ecore_con_client_fd_get(const Ecore_Con_Client *cl)
787 {
788    ECORE_CON_CLIENT_CHECK_RETURN(cl, SOCKET_TO_LOOP_FD(INVALID_SOCKET));
789    if (cl->socket)
790      {
791         Eo *inner_socket = efl_io_buffered_stream_inner_io_get(cl->socket);
792         if (efl_isa(inner_socket, EFL_LOOP_FD_CLASS))
793           {
794              return efl_loop_fd_get(inner_socket);
795           }
796         else
797           {
798              if (efl_isa(inner_socket, EFL_NET_SOCKET_SSL_CLASS))
799                {
800                   Eo* adopted_socket = NULL;
801                   if (efl_net_socket_ssl_adopted_get(inner_socket, &adopted_socket, NULL))
802                     if (efl_isa(adopted_socket, EFL_LOOP_FD_CLASS))
803                       return efl_loop_fd_get(adopted_socket);
804                }
805           }
806      }
807    return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
808 }
809 
810 static void
_ecore_con_client_socket_ssl_ready(void * data,const Efl_Event * event EINA_UNUSED)811 _ecore_con_client_socket_ssl_ready(void *data, const Efl_Event *event EINA_UNUSED)
812 {
813    Ecore_Con_Client *cl = data;
814 
815    cl->ssl.upgrading = EINA_FALSE;
816    INF("cl=%p upgraded to SSL at %s", cl, efl_net_socket_address_remote_get(cl->socket));
817    _ecore_con_post_event_client_upgrade(cl);
818 }
819 
820 static void
_ecore_con_client_socket_ssl_error(void * data,const Efl_Event * event)821 _ecore_con_client_socket_ssl_error(void *data, const Efl_Event *event)
822 {
823    Ecore_Con_Client *cl = data;
824    Eina_Error *perr = event->info;
825 
826    if (cl->delete_me) return;
827 
828    WRN("SSL error client %s: %s", efl_net_socket_address_remote_get(cl->socket), eina_error_msg_get(*perr));
829 
830    _ecore_con_client_socket_close(cl);
831    _ecore_con_post_event_client_error(cl, eina_error_msg_get(*perr));
832 }
833 
834 EFL_CALLBACKS_ARRAY_DEFINE(_ecore_con_client_socket_ssl_cbs,
835                            { EFL_NET_SOCKET_SSL_EVENT_SSL_READY, _ecore_con_client_socket_ssl_ready },
836                            { EFL_NET_SOCKET_SSL_EVENT_SSL_ERROR, _ecore_con_client_socket_ssl_error });
837 
838 static Eina_Value
_ecore_con_client_ssl_upgrade_job(void * data,const Eina_Value v,const Eina_Future * dead EINA_UNUSED)839 _ecore_con_client_ssl_upgrade_job(void *data, const Eina_Value v,
840                                   const Eina_Future *dead EINA_UNUSED)
841 {
842    Ecore_Con_Client *cl = data;
843    Eo *loop = efl_main_loop_get();
844    Eo *inner_socket;
845    Eo *socket;
846    Eo *tcp_socket;
847 
848    //Canceled
849    if (v.type == EINA_VALUE_TYPE_ERROR) return v;
850 
851    tcp_socket = cl->socket;
852    cl->socket = NULL; /* take it, will be wrapped */
853 
854    inner_socket = efl_add(EFL_NET_SOCKET_SSL_CLASS, loop,
855                           efl_net_socket_ssl_adopt(efl_added, tcp_socket, cl->ssl.ctx));
856    EINA_SAFETY_ON_NULL_GOTO(inner_socket, error_inner_socket);
857 
858    /* do not reparent tcp_socket! it's owned by server */
859    efl_unref(tcp_socket); /* inner_socket keeps it */
860 
861    socket = efl_add(EFL_NET_SOCKET_SIMPLE_CLASS, loop,
862                     efl_io_buffered_stream_inner_io_set(efl_added, inner_socket));
863    EINA_SAFETY_ON_NULL_GOTO(socket, error_socket);
864 
865    efl_parent_set(inner_socket, socket);
866 
867    cl->socket = socket;
868    efl_io_closer_close_on_exec_set(socket, EINA_TRUE);
869    efl_io_closer_close_on_invalidate_set(socket, EINA_TRUE);
870    efl_event_callback_array_del(tcp_socket, _ecore_con_client_socket_cbs(), cl);
871    efl_event_callback_array_add(socket, _ecore_con_client_socket_cbs(), cl);
872    efl_event_callback_array_add(inner_socket, _ecore_con_client_socket_ssl_cbs(), cl);
873 
874    DBG("socket=%p upgraded to SSL with inner_socket=%p, ssl_ctx=%p, tcp_socket=%p. Start handshake...",
875        cl->socket,
876        efl_io_buffered_stream_inner_io_get(cl->socket),
877        cl->ssl.ctx,
878        tcp_socket);
879    return v;
880 
881  error_socket:
882    efl_del(inner_socket);
883  error_inner_socket:
884    cl->socket = tcp_socket; /* put it back */
885    if (_ecore_con_post_event_client_error(cl, "Couldn't finish SSL setup"))
886      _ecore_con_post_event_client_del(cl);
887    return v;
888 }
889 
890 static Eo * _ecore_con_server_ssl_ctx_create(const Ecore_Con_Server *svr);
891 
892 static void
_ecore_con_server_job_schedule(Ecore_Con_Server * svr,Eo * loop,Eina_Future_Cb cb)893 _ecore_con_server_job_schedule(Ecore_Con_Server *svr, Eo *loop,
894                                Eina_Future_Cb cb)
895 {
896    eina_future_then(efl_loop_job(loop), cb, svr, &svr->ssl.job);
897 }
898 
899 EAPI Eina_Bool
ecore_con_ssl_client_upgrade(Ecore_Con_Client * cl,Ecore_Con_Type compl_type)900 ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type compl_type)
901 {
902    Ecore_Con_Server *svr;
903    Eo *ssl_ctx;
904    double start;
905 
906    ECORE_CON_CLIENT_CHECK_RETURN(cl, EINA_FALSE);
907    EINA_SAFETY_ON_TRUE_RETURN_VAL((compl_type & ECORE_CON_SSL) == 0, EINA_FALSE);
908    EINA_SAFETY_ON_TRUE_RETURN_VAL(cl->ssl.upgrading, EINA_FALSE);
909    EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(efl_io_buffered_stream_inner_io_get(cl->socket), EFL_NET_SOCKET_TCP_CLASS), EINA_FALSE);
910 
911    svr = cl->svr;
912    EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_isa(efl_net_server_simple_inner_server_get(svr->server), EFL_NET_SERVER_SSL_CLASS), EINA_FALSE); /* cannot upgrade if already SSL server! */
913 
914    start = ecore_time_get();
915    while (efl_io_buffered_stream_pending_write_get(cl->socket) && ((ecore_time_get() - start) <= ecore_animator_frametime_get()))
916      ecore_con_client_flush(cl);
917    if (efl_io_buffered_stream_pending_write_get(cl->socket))
918      {
919         ERR("cl=%p still pending send %zd bytes! Flush client before upgrading to SSL!",
920             cl, efl_io_buffered_stream_pending_write_get(cl->socket));
921         return EINA_FALSE;
922      }
923 
924    if ((!svr->ssl.upgrade_type) || (!svr->ssl.clients_ctx))
925      {
926         svr->ssl.upgrade_type = compl_type;
927         svr->ssl.clients_ctx = _ecore_con_server_ssl_ctx_create(svr);
928         EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.clients_ctx, EINA_FALSE);
929      }
930 
931    if (svr->ssl.upgrade_type == compl_type)
932      ssl_ctx = efl_ref(svr->ssl.clients_ctx);
933    else
934      ssl_ctx = _ecore_con_server_ssl_ctx_create(svr);
935 
936    EINA_SAFETY_ON_NULL_RETURN_VAL(ssl_ctx, EINA_FALSE);
937 
938    cl->ssl.upgrading = EINA_TRUE;
939    cl->ssl.ctx = ssl_ctx;
940 
941    eina_future_then(efl_loop_job(efl_loop_get(cl->socket)),
942                     _ecore_con_client_ssl_upgrade_job, cl, &cl->ssl.job);
943 
944    DBG("cl=%p SSL upgrading from %#x to type=%#x", cl, svr->type, compl_type);
945 
946    return EINA_TRUE;
947 }
948 
949 /**
950  * @}
951  */
952 
953 Eina_Bool
ecore_con_server_check(const Ecore_Con_Server * svr)954 ecore_con_server_check(const Ecore_Con_Server *svr)
955 {
956    ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
957    return EINA_TRUE;
958 }
959 
960 static Ecore_Con_Server *
_ecore_con_server_new(Eina_Bool is_dialer,Ecore_Con_Type type,const char * name,int port,const void * data)961 _ecore_con_server_new(Eina_Bool is_dialer, Ecore_Con_Type type, const char *name, int port, const void *data)
962 {
963    EINA_SAFETY_ON_TRUE_RETURN_VAL(!name || (!name[0]), NULL);
964 
965    Ecore_Con_Server *svr = calloc(1, sizeof(Ecore_Con_Server));
966    EINA_SAFETY_ON_NULL_RETURN_VAL(svr, NULL);
967    svr->start_time = ecore_time_get();
968    svr->name = eina_stringshare_add(name);
969    svr->port = port;
970    svr->data = data;
971    svr->type = type;
972    svr->is_dialer = is_dialer;
973 
974    EINA_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
975    _servers = eina_list_append(_servers, svr);
976    return svr;
977 }
978 
979 static void
_ecore_con_server_dialer_close(Ecore_Con_Server * svr)980 _ecore_con_server_dialer_close(Ecore_Con_Server *svr)
981 {
982    svr->connecting = EINA_FALSE;
983    if (!svr->dialer) return;
984 
985    if (!efl_io_closer_closed_get(svr->dialer))
986      efl_io_closer_close(svr->dialer);
987 }
988 
989 static void
_ecore_con_server_free(Ecore_Con_Server * svr)990 _ecore_con_server_free(Ecore_Con_Server *svr)
991 {
992    const char *str;
993 
994    svr->delete_me = EINA_TRUE;
995    _servers = eina_list_remove(_servers, svr);
996 
997    while (svr->clients)
998      ecore_con_client_del(svr->clients->data);
999 
1000    _ecore_con_server_dialer_close(svr);
1001 
1002    if (svr->ssl.clients_ctx)
1003      {
1004         // This is always created with efl_add_ref
1005         efl_parent_set(svr->ssl.clients_ctx, NULL);
1006         efl_unref(svr->ssl.clients_ctx);
1007         svr->ssl.clients_ctx = NULL;
1008      }
1009 
1010    if (svr->dialer)
1011      {
1012         efl_del(svr->dialer);
1013         svr->dialer = NULL;
1014      }
1015 
1016    if (svr->server)
1017      {
1018         efl_del(svr->server);
1019         svr->server = NULL;
1020      }
1021 
1022    if (svr->ssl.job) eina_future_cancel(svr->ssl.job);
1023 
1024    if (svr->ssl.pending_send)
1025      {
1026         eina_binbuf_free(svr->ssl.pending_send);
1027         svr->ssl.pending_send = NULL;
1028      }
1029 
1030    if (svr->event_count) return;
1031 
1032    EINA_LIST_FREE(svr->ssl.certs, str) eina_stringshare_del(str);
1033    EINA_LIST_FREE(svr->ssl.privkeys, str) eina_stringshare_del(str);
1034    EINA_LIST_FREE(svr->ssl.crls, str) eina_stringshare_del(str);
1035    EINA_LIST_FREE(svr->ssl.cafiles, str) eina_stringshare_del(str);
1036    eina_stringshare_replace(&svr->ssl.verify_name, NULL);
1037 
1038    svr->data = NULL;
1039    eina_stringshare_replace(&svr->name, NULL);
1040    eina_stringshare_replace(&svr->ip, NULL);
1041 
1042    EINA_MAGIC_SET(svr, ECORE_MAGIC_NONE);
1043    free(svr);
1044 }
1045 
1046 /* BEGIN: post of shared Ecore_Event  ***********************************/
1047 
1048 static void
_ecore_con_free_event_server_del(void * data EINA_UNUSED,void * event)1049 _ecore_con_free_event_server_del(void *data EINA_UNUSED, void *event)
1050 {
1051    Ecore_Con_Event_Server_Del *ev = event;
1052 
1053    if (ev->server)
1054      {
1055         Ecore_Con_Server *svr = ev->server;
1056         svr->event_count = eina_list_remove(svr->event_count, ev);
1057         if ((!svr->event_count) && (svr->delete_me))
1058           _ecore_con_server_free(svr);
1059      }
1060    ecore_con_event_server_del_free(ev);
1061    _ecore_con_event_count--;
1062 }
1063 
1064 static Eina_Bool
_ecore_con_post_event_server_del(Ecore_Con_Server * svr)1065 _ecore_con_post_event_server_del(Ecore_Con_Server *svr)
1066 {
1067    Ecore_Con_Event_Server_Del *ev = ecore_con_event_server_del_alloc();
1068    EINA_SAFETY_ON_NULL_GOTO(ev, error);
1069 
1070    if (svr->dialer)
1071      INF("svr=%p disconnected from %s (%s)", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer));
1072    else if (svr->server)
1073      INF("svr=%p stopped serving at %s", svr, efl_net_server_address_get(svr->server));
1074    else
1075      INF("svr=%p name=%s, port=%d %s destroyed before SSL was configured", svr, svr->name, svr->port, svr->is_dialer ? "dialer" : "server");
1076 
1077    if (svr->connecting)
1078      {
1079         DBG("svr=%p was still connecting to %s (%s), ignore ECORE_CON_EVENT_SERVER_DEL", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer));
1080         return EINA_TRUE;
1081      }
1082 
1083    ev->server = svr;
1084    svr->event_count = eina_list_append(svr->event_count, ev);
1085 
1086    ecore_event_add(ECORE_CON_EVENT_SERVER_DEL, ev, _ecore_con_free_event_server_del, NULL);
1087    _ecore_con_event_count++;
1088    return EINA_TRUE;
1089 
1090  error:
1091    _ecore_con_server_free(svr);
1092    return EINA_FALSE;
1093 }
1094 
1095 static void
_ecore_con_free_event_server_error(void * data EINA_UNUSED,void * event)1096 _ecore_con_free_event_server_error(void *data EINA_UNUSED, void *event)
1097 {
1098    Ecore_Con_Event_Server_Error *ev = event;
1099 
1100    if (ev->server)
1101      {
1102         Ecore_Con_Server *svr = ev->server;
1103         svr->event_count = eina_list_remove(svr->event_count, ev);
1104         if ((!svr->event_count) && (svr->delete_me))
1105           _ecore_con_server_free(svr);
1106      }
1107    free(ev->error);
1108    ecore_con_event_server_error_free(ev);
1109    _ecore_con_event_count--;
1110 }
1111 
1112 static Eina_Bool
_ecore_con_post_event_server_error(Ecore_Con_Server * svr,const char * err)1113 _ecore_con_post_event_server_error(Ecore_Con_Server *svr, const char *err)
1114 {
1115    Ecore_Con_Event_Server_Error *ev = ecore_con_event_server_error_alloc();
1116    EINA_SAFETY_ON_NULL_GOTO(ev, error);
1117 
1118    if (svr->dialer)
1119      INF("svr=%p error from %s (%s): %s", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer), err);
1120    else if (svr->server)
1121      INF("svr=%p error at %s: %s", svr, efl_net_server_address_get(svr->server), err);
1122    else
1123      INF("svr=%p name=%s, port=%d %s error before SSL was configured: %s", svr, svr->name, svr->port, svr->is_dialer ? "dialer" : "server", err);
1124 
1125    ev->server = svr;
1126    ev->error = err ? strdup(err) : NULL;
1127    svr->event_count = eina_list_append(svr->event_count, ev);
1128 
1129    ecore_event_add(ECORE_CON_EVENT_SERVER_ERROR, ev, _ecore_con_free_event_server_error, NULL);
1130    _ecore_con_event_count++;
1131    return EINA_TRUE;
1132 
1133  error:
1134    _ecore_con_server_free(svr);
1135    return EINA_FALSE;
1136 }
1137 
1138 /* END: post of shared Ecore_Event  ***********************************/
1139 
1140 
1141 /* BEGIN: post of Ecore_Event for ecore_con_server_connect() ************/
1142 
1143 static void
_ecore_con_free_event_server_add(void * data EINA_UNUSED,void * event)1144 _ecore_con_free_event_server_add(void *data EINA_UNUSED, void *event)
1145 {
1146    Ecore_Con_Event_Server_Add *ev = event;
1147 
1148    if (ev->server)
1149      {
1150         Ecore_Con_Server *svr = ev->server;
1151         svr->event_count = eina_list_remove(svr->event_count, ev);
1152         if ((!svr->event_count) && (svr->delete_me))
1153           _ecore_con_server_free(svr);
1154      }
1155    ecore_con_event_server_add_free(ev);
1156    _ecore_con_event_count--;
1157 }
1158 
1159 static void
_ecore_con_post_event_server_add(Ecore_Con_Server * svr)1160 _ecore_con_post_event_server_add(Ecore_Con_Server *svr)
1161 {
1162    Ecore_Con_Event_Server_Add *ev = ecore_con_event_server_add_alloc();
1163    EINA_SAFETY_ON_NULL_GOTO(ev, error);
1164 
1165    ev->server = svr;
1166    svr->event_count = eina_list_append(svr->event_count, ev);
1167 
1168    ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, ev, _ecore_con_free_event_server_add, NULL);
1169    _ecore_con_event_count++;
1170    return;
1171 
1172  error:
1173    _ecore_con_server_free(svr);
1174 }
1175 
1176 static void
_ecore_con_free_event_server_data(void * data EINA_UNUSED,void * event)1177 _ecore_con_free_event_server_data(void *data EINA_UNUSED, void *event)
1178 {
1179    Ecore_Con_Event_Server_Data *ev = event;
1180 
1181    if (ev->server)
1182      {
1183         Ecore_Con_Server *svr = ev->server;
1184         svr->event_count = eina_list_remove(svr->event_count, ev);
1185         if ((!svr->event_count) && (svr->delete_me))
1186           _ecore_con_server_free(svr);
1187      }
1188    free(ev->data);
1189    ecore_con_event_server_data_free(ev);
1190    _ecore_con_event_count--;
1191 }
1192 
1193 static void
_ecore_con_post_event_server_data(Ecore_Con_Server * svr,Eina_Rw_Slice slice)1194 _ecore_con_post_event_server_data(Ecore_Con_Server *svr, Eina_Rw_Slice slice)
1195 {
1196    Ecore_Con_Event_Server_Data *ev = ecore_con_event_server_data_alloc();
1197    EINA_SAFETY_ON_NULL_GOTO(ev, error);
1198 
1199    ev->server = svr;
1200    ev->data = slice.mem;
1201    ev->size = slice.len;
1202    svr->event_count = eina_list_append(svr->event_count, ev);
1203 
1204    ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, ev, _ecore_con_free_event_server_data, NULL);
1205    _ecore_con_event_count++;
1206    return;
1207 
1208  error:
1209    free(slice.mem);
1210 }
1211 
1212 static void
_ecore_con_free_event_server_write(void * data EINA_UNUSED,void * event)1213 _ecore_con_free_event_server_write(void *data EINA_UNUSED, void *event)
1214 {
1215    Ecore_Con_Event_Server_Write *ev = event;
1216 
1217    if (ev->server)
1218      {
1219         Ecore_Con_Server *svr = ev->server;
1220         svr->event_count = eina_list_remove(svr->event_count, ev);
1221         if ((!svr->event_count) && (svr->delete_me))
1222           _ecore_con_server_free(svr);
1223      }
1224    ecore_con_event_server_write_free(ev);
1225    _ecore_con_event_count--;
1226 }
1227 
1228 static void
_ecore_con_post_event_server_write(Ecore_Con_Server * svr,size_t size)1229 _ecore_con_post_event_server_write(Ecore_Con_Server *svr, size_t size)
1230 {
1231    Ecore_Con_Event_Server_Write *ev = ecore_con_event_server_write_alloc();
1232    EINA_SAFETY_ON_NULL_RETURN(ev);
1233 
1234    ev->server = svr;
1235    ev->size = size;
1236    svr->event_count = eina_list_append(svr->event_count, ev);
1237 
1238    ecore_event_add(ECORE_CON_EVENT_SERVER_WRITE, ev, _ecore_con_free_event_server_write, NULL);
1239    _ecore_con_event_count++;
1240 }
1241 
1242 static void
_ecore_con_free_event_server_upgrade(void * data EINA_UNUSED,void * event)1243 _ecore_con_free_event_server_upgrade(void *data EINA_UNUSED, void *event)
1244 {
1245    Ecore_Con_Event_Server_Upgrade *ev = event;
1246 
1247    if (ev->server)
1248      {
1249         Ecore_Con_Server *svr = ev->server;
1250         svr->event_count = eina_list_remove(svr->event_count, ev);
1251         if ((!svr->event_count) && (svr->delete_me))
1252           _ecore_con_server_free(svr);
1253      }
1254    ecore_con_event_server_upgrade_free(ev);
1255    _ecore_con_event_count--;
1256 }
1257 
1258 static void
_ecore_con_post_event_server_upgrade(Ecore_Con_Server * svr)1259 _ecore_con_post_event_server_upgrade(Ecore_Con_Server *svr)
1260 {
1261    Ecore_Con_Event_Server_Upgrade *ev = ecore_con_event_server_upgrade_alloc();
1262    EINA_SAFETY_ON_NULL_GOTO(ev, error);
1263 
1264    ev->server = svr;
1265    svr->event_count = eina_list_append(svr->event_count, ev);
1266 
1267    ecore_event_add(ECORE_CON_EVENT_SERVER_UPGRADE, ev, _ecore_con_free_event_server_upgrade, NULL);
1268    _ecore_con_event_count++;
1269    return;
1270 
1271  error:
1272    _ecore_con_server_free(svr);
1273 }
1274 
1275 /* END: post of Ecore_Event for ecore_con_server_connect() **************/
1276 
1277 static void
_ecore_con_server_dialer_slice_changed(void * data,const Efl_Event * event EINA_UNUSED)1278 _ecore_con_server_dialer_slice_changed(void *data, const Efl_Event *event EINA_UNUSED)
1279 {
1280    Ecore_Con_Server *svr = data;
1281    Eina_Slice ro_slice;
1282    Eina_Rw_Slice rw_slice;
1283 
1284    if (svr->delete_me) return;
1285    if (svr->ssl.upgrading) return;
1286 
1287    ro_slice = efl_io_buffered_stream_slice_get(svr->dialer);
1288    if (ro_slice.len == 0) return;
1289 
1290    rw_slice = eina_slice_dup(ro_slice);
1291    efl_io_buffered_stream_clear(svr->dialer);
1292    _ecore_con_post_event_server_data(svr, rw_slice);
1293 }
1294 
1295 static void
_ecore_con_server_dialer_progress(void * data,const Efl_Event * event EINA_UNUSED)1296 _ecore_con_server_dialer_progress(void *data, const Efl_Event *event EINA_UNUSED)
1297 {
1298    Ecore_Con_Server *svr = data;
1299    size_t now;
1300 
1301    if (svr->delete_me) return;
1302    if (svr->ssl.upgrading) return;
1303 
1304    now = efl_io_buffered_stream_pending_write_get(svr->dialer);
1305    if (svr->pending_write == now) return;
1306    EINA_SAFETY_ON_TRUE_GOTO(svr->pending_write < now, end); /* forgot to update! */
1307 
1308    _ecore_con_post_event_server_write(svr, svr->pending_write - now);
1309 
1310  end:
1311    svr->pending_write = now;
1312 }
1313 
1314 static void
_ecore_con_server_dialer_read_finished(void * data,const Efl_Event * event EINA_UNUSED)1315 _ecore_con_server_dialer_read_finished(void *data, const Efl_Event *event EINA_UNUSED)
1316 {
1317    Ecore_Con_Server *svr = data;
1318 
1319    if (svr->delete_me) return;
1320 
1321    if (!efl_io_closer_closed_get(svr->dialer))
1322      efl_io_buffered_stream_eos_mark(svr->dialer);
1323 }
1324 
1325 static void
_ecore_con_server_dialer_finished(void * data,const Efl_Event * event EINA_UNUSED)1326 _ecore_con_server_dialer_finished(void *data, const Efl_Event *event EINA_UNUSED)
1327 {
1328    Ecore_Con_Server *svr = data;
1329 
1330    if (svr->delete_me) return;
1331 
1332    _ecore_con_post_event_server_del(svr);
1333 }
1334 
1335 static void
_ecore_con_server_dialer_error(void * data,const Efl_Event * event)1336 _ecore_con_server_dialer_error(void *data, const Efl_Event *event)
1337 {
1338    Ecore_Con_Server *svr = data;
1339    Eina_Error *perr = event->info;
1340    static int nested = EINA_FALSE;
1341 
1342    if (svr->delete_me) return;
1343    if (nested) return;
1344 
1345    nested = EINA_TRUE;
1346 
1347    WRN("error reaching server %s: %s", efl_net_dialer_address_dial_get(svr->dialer), eina_error_msg_get(*perr));
1348 
1349    if (_ecore_con_post_event_server_error(svr, eina_error_msg_get(*perr)))
1350      _ecore_con_server_dialer_close(svr);
1351 
1352    nested = EINA_FALSE;
1353 }
1354 
1355 static void
_ecore_con_server_dialer_resolved(void * data,const Efl_Event * event EINA_UNUSED)1356 _ecore_con_server_dialer_resolved(void *data, const Efl_Event *event EINA_UNUSED)
1357 {
1358    Ecore_Con_Server *svr = data;
1359    Eo *inner_dialer;
1360 
1361    if (svr->delete_me) return;
1362 
1363    inner_dialer = efl_io_buffered_stream_inner_io_get(svr->dialer);
1364    if (efl_isa(inner_dialer, EFL_NET_DIALER_TCP_CLASS) ||
1365        efl_isa(inner_dialer, EFL_NET_DIALER_UDP_CLASS) ||
1366        efl_isa(inner_dialer, EFL_NET_DIALER_SSL_CLASS))
1367      {
1368         const char *p, *ip = efl_net_socket_address_remote_get(svr->dialer);
1369         EINA_SAFETY_ON_NULL_RETURN(ip);
1370 
1371         if (ip[0] != '[') p = strchr(ip, ':');
1372         else
1373           {
1374              ip++;
1375              p = strchr(ip, ']');
1376           }
1377         EINA_SAFETY_ON_NULL_RETURN(p);
1378 
1379         eina_stringshare_del(svr->ip);
1380         svr->ip = eina_stringshare_add_length(ip, p - ip);
1381      }
1382 }
1383 
1384 static void
_ecore_con_server_dialer_connected(void * data,const Efl_Event * event EINA_UNUSED)1385 _ecore_con_server_dialer_connected(void *data, const Efl_Event *event EINA_UNUSED)
1386 {
1387    Ecore_Con_Server *svr = data;
1388 
1389    if (svr->delete_me) return;
1390    if (svr->ssl.upgrading)
1391      {
1392         svr->ssl.upgrading = EINA_FALSE;
1393         INF("svr=%p upgraded to SSL at %s (%s)", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer));
1394         if (svr->ssl.pending_send)
1395           {
1396              Eina_Slice slice = eina_binbuf_slice_get(svr->ssl.pending_send);
1397              ecore_con_server_send(svr, slice.mem, slice.len);
1398              eina_binbuf_free(svr->ssl.pending_send);
1399              svr->ssl.pending_send = NULL;
1400           }
1401         _ecore_con_post_event_server_upgrade(svr);
1402         return;
1403      }
1404 
1405    svr->connecting = EINA_FALSE;
1406    svr->start_time = ecore_time_get();
1407 
1408    INF("svr=%p connected to %s (%s)", svr, efl_net_dialer_address_dial_get(svr->dialer), efl_net_socket_address_remote_get(svr->dialer));
1409 
1410    _ecore_con_post_event_server_add(svr);
1411 }
1412 
1413 EFL_CALLBACKS_ARRAY_DEFINE(_ecore_con_server_dialer_cbs,
1414                            { EFL_IO_BUFFERED_STREAM_EVENT_PROGRESS, _ecore_con_server_dialer_progress },
1415                            { EFL_IO_BUFFERED_STREAM_EVENT_SLICE_CHANGED, _ecore_con_server_dialer_slice_changed },
1416                            { EFL_IO_BUFFERED_STREAM_EVENT_READ_FINISHED, _ecore_con_server_dialer_read_finished },
1417                            { EFL_IO_BUFFERED_STREAM_EVENT_FINISHED, _ecore_con_server_dialer_finished },
1418                            { EFL_IO_BUFFERED_STREAM_EVENT_ERROR, _ecore_con_server_dialer_error },
1419                            { EFL_NET_DIALER_EVENT_DIALER_ERROR, _ecore_con_server_dialer_error },
1420                            { EFL_NET_DIALER_EVENT_DIALER_RESOLVED, _ecore_con_server_dialer_resolved },
1421                            { EFL_NET_DIALER_EVENT_DIALER_CONNECTED, _ecore_con_server_dialer_connected });
1422 
1423 static void
_ecore_con_server_server_client_add(void * data,const Efl_Event * event)1424 _ecore_con_server_server_client_add(void *data, const Efl_Event *event)
1425 {
1426    Ecore_Con_Server *svr = data;
1427    Ecore_Con_Client *cl;
1428    Eo *socket = event->info;
1429 
1430    INF("svr=%p address=%s got client %p (%s) address=%s",
1431        svr, efl_net_server_address_get(svr->server),
1432        socket,
1433        efl_class_name_get(efl_io_buffered_stream_inner_io_get(socket)),
1434        efl_net_socket_address_remote_get(socket));
1435 
1436    cl = ecore_con_client_add(svr, socket);
1437    EINA_SAFETY_ON_NULL_RETURN(cl);
1438 
1439    _ecore_con_post_event_client_add(cl);
1440 }
1441 
1442 static void
_ecore_con_server_server_serving(void * data,const Efl_Event * event EINA_UNUSED)1443 _ecore_con_server_server_serving(void *data, const Efl_Event *event EINA_UNUSED)
1444 {
1445    Ecore_Con_Server *svr = data;
1446    Eo *inner_server;
1447    const char *address = efl_net_server_address_get(svr->server);
1448    const char *p;
1449    char *ip;
1450 
1451    EINA_SAFETY_ON_NULL_RETURN(address);
1452 
1453    INF("svr=%p ready at %s", svr, address);
1454 
1455    if (!svr->want_mcast) return;
1456 
1457    inner_server = efl_net_server_simple_inner_server_get(svr->server);
1458 
1459    if (address[0] != '[') p = strchr(address, ':');
1460    else
1461      {
1462         address++;
1463         p = strchr(address, ']');
1464      }
1465    EINA_SAFETY_ON_NULL_RETURN(p);
1466 
1467    ip = malloc(p - address + 1);
1468    EINA_SAFETY_ON_NULL_RETURN(ip);
1469 
1470    memcpy(ip, address, p - address);
1471    ip[p - address] = '\0';
1472 
1473    DBG("svr=%p join multicast group: %s", svr, ip);
1474    efl_net_server_udp_multicast_join(inner_server, ip);
1475    free(ip);
1476 }
1477 
1478 static void
_ecore_con_server_server_error(void * data,const Efl_Event * event)1479 _ecore_con_server_server_error(void *data, const Efl_Event *event)
1480 {
1481    Ecore_Con_Server *svr = data;
1482    Eina_Error *perr = event->info;
1483 
1484    WRN("svr=%p address=%s error: %s",
1485        svr, efl_net_server_address_get(svr->server),
1486        eina_error_msg_get(*perr));
1487 
1488    _ecore_con_post_event_server_error(svr, eina_error_msg_get(*perr));
1489 }
1490 
1491 EFL_CALLBACKS_ARRAY_DEFINE(_ecore_con_server_server_cbs,
1492                            { EFL_NET_SERVER_EVENT_CLIENT_ADD, _ecore_con_server_server_client_add },
1493                            { EFL_NET_SERVER_EVENT_SERVING, _ecore_con_server_server_serving },
1494                            { EFL_NET_SERVER_EVENT_SERVER_ERROR, _ecore_con_server_server_error });
1495 
1496 /**
1497  * @addtogroup Ecore_Con_Server_Group Ecore Connection Server Functions
1498  *
1499  * Functions that operate on Ecore server objects.
1500  *
1501  * @{
1502  */
1503 
1504 static Eina_Bool
_ecore_con_server_server_set(Ecore_Con_Server * svr,Eo * server)1505 _ecore_con_server_server_set(Ecore_Con_Server *svr, Eo *server)
1506 {
1507    char address[4096] = "";
1508    Eo *inner_server = efl_net_server_simple_inner_server_get(server);
1509    Ecore_Con_Type type = svr->type & ECORE_CON_TYPE;
1510    Eina_Error err;
1511 
1512    svr->server = server;
1513    efl_event_callback_array_add(server, _ecore_con_server_server_cbs(), svr);
1514 
1515    if (efl_isa(inner_server, EFL_NET_SERVER_TCP_CLASS) ||
1516        efl_isa(inner_server, EFL_NET_SERVER_UDP_CLASS) ||
1517        efl_isa(inner_server, EFL_NET_SERVER_SSL_CLASS))
1518      {
1519         if (strchr(svr->name, ':'))
1520           snprintf(address, sizeof(address), "[%s]:%d", svr->name, svr->port);
1521         else
1522           snprintf(address, sizeof(address), "%s:%d", svr->name, svr->port);
1523      }
1524    else if (type == ECORE_CON_LOCAL_ABSTRACT)
1525      snprintf(address, sizeof(address), "abstract:%s", svr->name);
1526    else if ((type == ECORE_CON_LOCAL_USER) ||
1527             (type == ECORE_CON_LOCAL_SYSTEM))
1528      {
1529         char *path = ecore_con_local_path_new(type == ECORE_CON_LOCAL_SYSTEM, svr->name, svr->port);
1530         if (!path)
1531           {
1532              ERR("could not create local path for name='%s', port=%d", svr->name, svr->port);
1533              return EINA_FALSE;
1534           }
1535         else
1536           {
1537              eina_strlcpy(address, path, sizeof(address));
1538              free(path);
1539           }
1540      }
1541 
1542    if (efl_isa(inner_server, EFL_NET_SERVER_FD_CLASS))
1543      {
1544         efl_net_server_fd_reuse_address_set(inner_server, EINA_TRUE);
1545         efl_net_server_fd_reuse_port_set(inner_server, EINA_TRUE);
1546      }
1547    if (efl_isa(inner_server, EFL_NET_SERVER_TCP_CLASS))
1548      {
1549         /* old ecore_con did not map ipv4 to ipv6... */
1550         efl_net_server_ip_ipv6_only_set(inner_server, EINA_TRUE);
1551      }
1552    else if (efl_isa(inner_server, EFL_NET_SERVER_UDP_CLASS))
1553      {
1554         /* old ecore_con did not map ipv4 to ipv6... */
1555         efl_net_server_ip_ipv6_only_set(inner_server, EINA_TRUE);
1556         svr->want_mcast = type == ECORE_CON_REMOTE_MCAST;
1557      }
1558    else if (efl_isa(inner_server, EFL_NET_SERVER_SSL_CLASS))
1559      {
1560         /* old ecore_con did not map ipv4 to ipv6... */
1561         efl_net_server_ip_ipv6_only_set(inner_server, EINA_TRUE);
1562      }
1563 #ifdef EFL_NET_SERVER_UNIX_CLASS
1564    else if (efl_isa(inner_server, EFL_NET_SERVER_UNIX_CLASS))
1565      {
1566         efl_net_server_unix_leading_directories_create_set(inner_server, EINA_TRUE, (type == ECORE_CON_LOCAL_SYSTEM) ? 0755 : 0700);
1567      }
1568 #endif
1569 
1570    if (svr->type & ECORE_CON_SOCKET_ACTIVATE)
1571      {
1572         if (efl_isa(inner_server, EFL_NET_SERVER_FD_CLASS))
1573           efl_net_server_fd_socket_activate(inner_server, address);
1574         else
1575           {
1576              ERR("svr=%p (%s): not able to socket-activate this type!", svr, efl_class_name_get(inner_server));
1577              goto serve;
1578           }
1579 
1580         if (efl_net_server_serving_get(inner_server))
1581           {
1582              DBG("svr=%p (%s) was socket activated as %s",
1583                  svr, efl_class_name_get(inner_server), address);
1584              return EINA_TRUE;
1585           }
1586         else
1587           ERR("svr=%p (%s): not able to socket-activate as %s. Try to serve...", svr, efl_class_name_get(inner_server), address);
1588      }
1589 
1590  serve:
1591    err = efl_net_server_serve(svr->server, address);
1592    if (err)
1593      {
1594         WRN("Could not serve at address=%s using class=%s",
1595             address, efl_class_name_get(inner_server));
1596         return EINA_FALSE;
1597      }
1598 
1599    DBG("svr=%p server=%p (%s) address=%s",
1600        svr, svr->server, efl_class_name_get(inner_server),
1601        efl_net_server_address_get(svr->server));
1602    return EINA_TRUE;
1603 }
1604 
1605 static Eo *
_ecore_con_server_ssl_ctx_create(const Ecore_Con_Server * svr)1606 _ecore_con_server_ssl_ctx_create(const Ecore_Con_Server *svr)
1607 {
1608    Efl_Net_Ssl_Cipher cipher = EFL_NET_SSL_CIPHER_AUTO;
1609    Ecore_Con_Type ssl_type = svr->ssl.upgrade_type & ECORE_CON_SSL;
1610 
1611    if (ssl_type & ECORE_CON_USE_MIXED)
1612      cipher = EFL_NET_SSL_CIPHER_AUTO;
1613    else if (ssl_type & ECORE_CON_USE_TLS)
1614      cipher = EFL_NET_SSL_CIPHER_TLSV1;
1615    else if (ssl_type & ECORE_CON_USE_SSL3)
1616      {
1617         ERR("SSLv3 is unsupported!");
1618         return NULL;
1619      }
1620    else if (ssl_type & ECORE_CON_USE_SSL2)
1621      {
1622         ERR("SSLv2 is unsupported!");
1623         return NULL;
1624      }
1625 
1626    /* legacy compatibility: server never verified peer, only dialer did */
1627 
1628    return efl_add_ref(EFL_NET_SSL_CONTEXT_CLASS, efl_main_loop_get(),
1629                       efl_net_ssl_context_certificates_set(efl_added, eina_list_iterator_new(svr->ssl.certs)),
1630                       efl_net_ssl_context_private_keys_set(efl_added, eina_list_iterator_new(svr->ssl.privkeys)),
1631                       efl_net_ssl_context_certificate_revocation_lists_set(efl_added, eina_list_iterator_new(svr->ssl.crls)),
1632                       efl_net_ssl_context_certificate_authorities_set(efl_added, eina_list_iterator_new(svr->ssl.cafiles)),
1633                       efl_net_ssl_context_default_paths_load_set(efl_added, EINA_FALSE), /* old API didn't load default paths */
1634                       efl_net_ssl_context_setup(efl_added, cipher, EINA_FALSE));
1635 }
1636 
1637 static Eina_Value
_ecore_con_server_server_ssl_job(void * data,const Eina_Value v,const Eina_Future * dead EINA_UNUSED)1638 _ecore_con_server_server_ssl_job(void *data, const Eina_Value v,
1639                                  const Eina_Future *dead EINA_UNUSED)
1640 {
1641    Ecore_Con_Server *svr = data;
1642    Eo *loop = efl_main_loop_get();
1643    Eo *ssl_ctx;
1644    Eo *inner_server;
1645    Eo *server;
1646 
1647    if (v.type == EINA_VALUE_TYPE_ERROR) return v;
1648 
1649    ssl_ctx = _ecore_con_server_ssl_ctx_create(svr);
1650    EINA_SAFETY_ON_NULL_GOTO(ssl_ctx, error_ssl_ctx);
1651 
1652    inner_server = efl_add(EFL_NET_SERVER_SSL_CLASS, loop,
1653                           efl_net_server_ssl_context_set(efl_added, ssl_ctx));
1654    EINA_SAFETY_ON_NULL_GOTO(inner_server, error_inner_server);
1655 
1656    server = efl_add(EFL_NET_SERVER_SIMPLE_CLASS, loop,
1657                     efl_net_server_simple_inner_server_set(efl_added, inner_server));
1658    EINA_SAFETY_ON_NULL_GOTO(server, error_server);
1659 
1660    efl_parent_set(inner_server, server);
1661 
1662    efl_unref(ssl_ctx); /* inner_server keeps it */
1663 
1664    if (!_ecore_con_server_server_set(svr, server))
1665      goto error_serve;
1666 
1667    DBG("server=%p configured with inner_server=%p, ssl_ctx=%p",
1668        svr->server,
1669        efl_net_server_simple_inner_server_get(svr->server),
1670        efl_net_server_ssl_context_get(efl_net_server_simple_inner_server_get(svr->server)));
1671 
1672    return v;
1673 
1674  error_serve:
1675    if (_ecore_con_post_event_server_error(svr, "Couldn't serve using SSL"))
1676      _ecore_con_post_event_server_del(svr);
1677    return v;
1678 
1679  error_server:
1680    efl_del(inner_server);
1681  error_inner_server:
1682    efl_del(ssl_ctx);
1683  error_ssl_ctx:
1684    if (_ecore_con_post_event_server_error(svr, "Couldn't finish SSL setup"))
1685      _ecore_con_post_event_server_del(svr);
1686    return v;
1687 }
1688 
1689 /**
1690  * @example ecore_con_server_example.c
1691  * Shows how to write a simple server using the Ecore_Con library
1692  * using ecore_con_server_add()
1693  */
1694 
1695 EAPI Ecore_Con_Server *
ecore_con_server_add(Ecore_Con_Type compl_type,const char * name,int port,const void * data)1696 ecore_con_server_add(Ecore_Con_Type compl_type,
1697                      const char *name,
1698                      int port,
1699                      const void *data)
1700 {
1701    const Efl_Class *cls = NULL;
1702    Ecore_Con_Server *svr;
1703    Ecore_Con_Type type;
1704    Eo *server;
1705    Eo *loop;
1706 
1707    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
1708 
1709    type = compl_type & ECORE_CON_TYPE;
1710 
1711    /* The allowable port number is an unsigned 16-bit integer for remote connection, so 1-65535, 0 is reserved */
1712    if (((type == ECORE_CON_REMOTE_TCP) || (type == ECORE_CON_REMOTE_NODELAY) || (type == ECORE_CON_REMOTE_CORK) ||
1713         (type == ECORE_CON_REMOTE_UDP) || (type == ECORE_CON_REMOTE_MCAST)) &&
1714        ((port < 0) || (port > 65535)))
1715      {
1716         ERR("Port %i invalid (0 <= port <= 65535)", port);
1717         return NULL;
1718      }
1719 
1720    loop = efl_main_loop_get();
1721    EINA_SAFETY_ON_NULL_RETURN_VAL(loop, NULL);
1722 
1723    svr = _ecore_con_server_new(EINA_FALSE, compl_type, name, port, data);
1724    EINA_SAFETY_ON_NULL_RETURN_VAL(svr, NULL);
1725 
1726    switch (type)
1727      {
1728       case ECORE_CON_LOCAL_USER:
1729       case ECORE_CON_LOCAL_SYSTEM:
1730       case ECORE_CON_LOCAL_ABSTRACT:
1731 #ifdef EFL_NET_SERVER_UNIX_CLASS
1732          cls = EFL_NET_SERVER_UNIX_CLASS;
1733 #elif defined(EFL_NET_SERVER_WINDOWS_CLASS)
1734          cls = EFL_NET_SERVER_WINDOWS_CLASS;
1735 #else
1736          ERR("Your platform doesn't support Efl_Net_Server-compatible local communication");
1737          // TODO: maybe write to a file and use TCP
1738 #endif
1739          break;
1740 
1741       case ECORE_CON_REMOTE_TCP:
1742       case ECORE_CON_REMOTE_NODELAY:
1743       case ECORE_CON_REMOTE_CORK:
1744          cls = EFL_NET_SERVER_TCP_CLASS;
1745          break;
1746 
1747       case ECORE_CON_REMOTE_UDP:
1748       case ECORE_CON_REMOTE_MCAST:
1749          cls = EFL_NET_SERVER_UDP_CLASS;
1750          break;
1751 
1752       default:
1753          ERR("Unsupported type=%#x & %#x = %#x", compl_type, ECORE_CON_TYPE, type);
1754      }
1755 
1756    EINA_SAFETY_ON_NULL_GOTO(cls, error);
1757 
1758    if (compl_type & ECORE_CON_SSL)
1759      {
1760         if (cls != EFL_NET_SERVER_TCP_CLASS)
1761           ERR("SSL can only be used with TCP types, got %s, forcing TCP", efl_class_name_get(cls));
1762 
1763         /* efl_net_ssl_context must be created prior to the object as
1764          * it's immutable once created. However the previous
1765          * Ecore_Con_Server API returned a handle and then configured
1766          * it, like in runtime, but in practice it's only effective
1767          * before the server starts.
1768          *
1769          * Then do not create the SSL server right away, instead do it
1770          * from a job, let the user configure SSL before the job
1771          * finishes.
1772          *
1773          * EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job) will alert users
1774          * trying to configure after the job expires.
1775          *
1776          * We can do that since the documentation says:
1777          *
1778          * > Call this function on a server object before main loop
1779          * > has started to enable verification of certificates
1780          * > against loaded certificates.
1781          */
1782         svr->ssl.upgrade_type = compl_type;
1783         _ecore_con_server_job_schedule(svr, loop, _ecore_con_server_server_ssl_job);
1784         return svr;
1785      }
1786 
1787    server = efl_add(EFL_NET_SERVER_SIMPLE_CLASS, loop,
1788                     efl_net_server_simple_inner_class_set(efl_added, cls));
1789    EINA_SAFETY_ON_NULL_GOTO(server, error);
1790 
1791    if (!_ecore_con_server_server_set(svr, server))
1792      goto error;
1793 
1794    return svr;
1795 
1796  error:
1797    _ecore_con_server_free(svr);
1798    return NULL;
1799 }
1800 
1801 /**
1802  * @brief convert @a socks to proxy URL string and apply using efl_net_dialer_proxy_set().
1803  *
1804  * @param svr the server created by ecore_con_server_connect().
1805  * @param socks the socks handle created by
1806  *        ecore_con_socks4_remote_add() or ecore_con_socks5_remote_add().
1807  *
1808  * @internal
1809  */
1810 static void
_ecore_con_server_proxy_apply(Ecore_Con_Server * svr,const Ecore_Con_Socks * socks)1811 _ecore_con_server_proxy_apply(Ecore_Con_Server *svr, const Ecore_Con_Socks *socks)
1812 {
1813    char str[4096], port[16] = "";
1814    const char *protocol;
1815    const char *user = "";
1816    const char *userpass_sep = "";
1817    const char *pass = "";
1818    const char *auth_sep = "";
1819 
1820    if (socks->version == 4)
1821      {
1822         Ecore_Con_Socks_v4 *v4 = (Ecore_Con_Socks_v4 *)socks;
1823 
1824         if (v4->lookup) protocol = "socks4a";
1825         else protocol = "socks4";
1826 
1827         if (v4->port > 0)
1828           snprintf(port, sizeof(port), ":%d", v4->port);
1829 
1830         if (v4->username)
1831           {
1832              user = v4->username;
1833              auth_sep = "@";
1834           }
1835      }
1836    else if (socks->version == 5)
1837      {
1838         Ecore_Con_Socks_v5 *v5 = (Ecore_Con_Socks_v5 *)socks;
1839 
1840         if (socks->lookup) protocol = "socks5h";
1841         else protocol = "socks5";
1842 
1843         if (v5->port > 0)
1844           snprintf(port, sizeof(port), ":%d", v5->port);
1845 
1846         if (v5->username)
1847           {
1848              user = v5->username;
1849              auth_sep = "@";
1850 
1851              if (v5->password)
1852                {
1853                   pass = v5->password;
1854                   userpass_sep = ":";
1855                }
1856           }
1857      }
1858    else
1859      {
1860         ERR("unsupported socks->version=%d", socks->version);
1861         return;
1862      }
1863 
1864    snprintf(str, sizeof(str),
1865             "%s://%s%s%s%s%s%s",
1866             protocol,
1867             pass, userpass_sep, user, auth_sep,
1868             socks->ip, port);
1869    DBG("using proxy url='%s' for server=%s, port=%d",
1870        str, svr->name, svr->port);
1871 
1872    efl_net_dialer_proxy_set(svr->dialer, str);
1873 
1874    if (socks->bind)
1875      ERR("proxy bind is not supported! Ecore_Con_Socks=%p %s", socks, str);
1876 }
1877 
1878 static Eina_Bool
_ecore_con_server_dialer_set(Ecore_Con_Server * svr,Eo * dialer)1879 _ecore_con_server_dialer_set(Ecore_Con_Server *svr, Eo *dialer)
1880 {
1881    char address[4096] = "";
1882    Eo *inner_dialer = efl_io_buffered_stream_inner_io_get(dialer);
1883    Ecore_Con_Type type = svr->type & ECORE_CON_TYPE;
1884    Eina_Error err;
1885 
1886    svr->dialer = dialer;
1887    efl_io_closer_close_on_exec_set(dialer, EINA_TRUE);
1888    efl_io_closer_close_on_invalidate_set(dialer, EINA_TRUE);
1889    efl_io_buffered_stream_timeout_inactivity_set(dialer, svr->timeout);
1890    efl_event_callback_array_add(dialer, _ecore_con_server_dialer_cbs(), svr);
1891 
1892    if (efl_isa(inner_dialer, EFL_NET_DIALER_TCP_CLASS))
1893      {
1894         efl_net_socket_tcp_no_delay_set(inner_dialer, !!(type & ECORE_CON_REMOTE_NODELAY));
1895         efl_net_socket_tcp_cork_set(inner_dialer, !!(type & ECORE_CON_REMOTE_CORK));
1896      }
1897    else if (efl_isa(inner_dialer, EFL_NET_DIALER_SSL_CLASS))
1898      {
1899         efl_net_dialer_ssl_no_delay_set(inner_dialer, !!(type & ECORE_CON_REMOTE_NODELAY));
1900      }
1901 
1902    if (efl_isa(inner_dialer, EFL_NET_DIALER_TCP_CLASS) ||
1903        efl_isa(inner_dialer, EFL_NET_DIALER_UDP_CLASS) ||
1904        efl_isa(inner_dialer, EFL_NET_DIALER_SSL_CLASS))
1905      {
1906         if (strchr(svr->name, ':'))
1907           snprintf(address, sizeof(address), "[%s]:%d", svr->name, svr->port);
1908         else
1909           snprintf(address, sizeof(address), "%s:%d", svr->name, svr->port);
1910      }
1911    else if (type == ECORE_CON_LOCAL_ABSTRACT)
1912      snprintf(address, sizeof(address), "abstract:%s", svr->name);
1913    else if ((type == ECORE_CON_LOCAL_USER) ||
1914             (type == ECORE_CON_LOCAL_SYSTEM))
1915      {
1916         char *path = ecore_con_local_path_new(type == ECORE_CON_LOCAL_SYSTEM, svr->name, svr->port);
1917 #ifdef EFL_NET_DIALER_UNIX_CLASS
1918         struct stat st;
1919 #endif
1920 
1921         if (!path)
1922           {
1923              ERR("could not create local path for name='%s', port=%d", svr->name, svr->port);
1924              return EINA_FALSE;
1925           }
1926         else
1927           {
1928              eina_strlcpy(address, path, sizeof(address));
1929              free(path);
1930           }
1931 
1932 #ifdef EFL_NET_DIALER_UNIX_CLASS
1933         if ((stat(address, &st) != 0)
1934 #ifdef S_ISSOCK
1935             || (!S_ISSOCK(st.st_mode))
1936 #endif
1937             )
1938           {
1939              DBG("%s is not a socket", address);
1940              return EINA_FALSE;
1941           }
1942 #endif
1943      }
1944 
1945    if ((svr->type & ECORE_CON_NO_PROXY) == ECORE_CON_NO_PROXY)
1946      {
1947         DBG("svr=%p not using any proxy for dialer %p (%s)",
1948             svr, svr->dialer, efl_class_name_get(inner_dialer));
1949         efl_net_dialer_proxy_set(svr->dialer, "");
1950      }
1951    else if (type > ECORE_CON_LOCAL_ABSTRACT)
1952      {
1953         if (_ecore_con_proxy_once)
1954           {
1955              _ecore_con_server_proxy_apply(svr, _ecore_con_proxy_once);
1956              _ecore_con_proxy_once = NULL;
1957           }
1958         else if (_ecore_con_proxy_global)
1959           _ecore_con_server_proxy_apply(svr, _ecore_con_proxy_global);
1960      }
1961 
1962    svr->connecting = EINA_TRUE;
1963 
1964    err = efl_net_dialer_dial(svr->dialer, address);
1965    if (err)
1966      {
1967         WRN("Could not connect to address=%s using class=%s",
1968             address, efl_class_name_get(inner_dialer));
1969         return EINA_FALSE;
1970      }
1971 
1972    DBG("svr=%p dialer=%p (%s) address=%s",
1973        svr, svr->dialer, efl_class_name_get(inner_dialer),
1974        efl_net_dialer_address_dial_get(svr->dialer));
1975    return EINA_TRUE;
1976 }
1977 
1978 static Eina_Value
_ecore_con_server_dialer_ssl_job(void * data,const Eina_Value v,const Eina_Future * dead EINA_UNUSED)1979 _ecore_con_server_dialer_ssl_job(void *data, const Eina_Value v,
1980                                  const Eina_Future *dead EINA_UNUSED)
1981 {
1982    Ecore_Con_Server *svr = data;
1983    Eo *loop = efl_main_loop_get();
1984    Eo *ssl_ctx;
1985    Eo *inner_dialer;
1986    Eo *dialer;
1987    Efl_Net_Ssl_Cipher cipher = EFL_NET_SSL_CIPHER_AUTO;
1988    Efl_Net_Ssl_Verify_Mode verify_mode = EFL_NET_SSL_VERIFY_MODE_NONE; /* was the default */
1989    Ecore_Con_Type ssl_type = svr->ssl.upgrade_type & ECORE_CON_SSL;
1990 
1991    if (ssl_type & ECORE_CON_USE_MIXED)
1992      cipher = EFL_NET_SSL_CIPHER_AUTO;
1993    else if (ssl_type & ECORE_CON_USE_TLS)
1994      cipher = EFL_NET_SSL_CIPHER_TLSV1;
1995    else if (ssl_type & ECORE_CON_USE_SSL3)
1996      {
1997         ERR("SSLv3 is unsupported!");
1998         goto error_ssl_ctx;
1999      }
2000    else if (ssl_type & ECORE_CON_USE_SSL2)
2001      {
2002         ERR("SSLv2 is unsupported!");
2003         goto error_ssl_ctx;
2004      }
2005 
2006    if (svr->ssl.verify)
2007      verify_mode = EFL_NET_SSL_VERIFY_MODE_REQUIRED;
2008 
2009    ssl_ctx = efl_add(EFL_NET_SSL_CONTEXT_CLASS, efl_main_loop_get(),
2010                      efl_net_ssl_context_certificates_set(efl_added, eina_list_iterator_new(svr->ssl.certs)),
2011                      efl_net_ssl_context_private_keys_set(efl_added, eina_list_iterator_new(svr->ssl.privkeys)),
2012                      efl_net_ssl_context_certificate_revocation_lists_set(efl_added, eina_list_iterator_new(svr->ssl.crls)),
2013                      efl_net_ssl_context_certificate_authorities_set(efl_added, eina_list_iterator_new(svr->ssl.cafiles)),
2014                      efl_net_ssl_context_verify_mode_set(efl_added, verify_mode),
2015                      efl_net_ssl_context_hostname_set(efl_added, svr->ssl.verify_name ? svr->ssl.verify_name : svr->name),
2016                      efl_net_ssl_context_hostname_verify_set(efl_added, svr->ssl.verify_basic),
2017                      efl_net_ssl_context_default_paths_load_set(efl_added, EINA_FALSE), /* old API didn't load default paths */
2018                      efl_net_ssl_context_setup(efl_added, cipher, EINA_TRUE));
2019    EINA_SAFETY_ON_NULL_GOTO(ssl_ctx, error_ssl_ctx);
2020 
2021    inner_dialer = efl_add(EFL_NET_DIALER_SSL_CLASS, loop,
2022                           efl_net_dialer_ssl_context_set(efl_added, ssl_ctx));
2023    EINA_SAFETY_ON_NULL_GOTO(inner_dialer, error_inner_dialer);
2024 
2025    dialer = efl_add(EFL_NET_DIALER_SIMPLE_CLASS, loop,
2026                     efl_io_buffered_stream_inner_io_set(efl_added, inner_dialer));
2027    EINA_SAFETY_ON_NULL_GOTO(dialer, error_dialer);
2028 
2029    efl_parent_set(inner_dialer, dialer);
2030    efl_parent_set(ssl_ctx, inner_dialer);
2031 
2032    if (!_ecore_con_server_dialer_set(svr, dialer))
2033      goto error_dial;
2034 
2035    DBG("dialer=%p configured with inner_dialer=%p, ssl_ctx=%p",
2036        svr->dialer,
2037        efl_io_buffered_stream_inner_io_get(svr->dialer),
2038        efl_net_dialer_ssl_context_get(efl_io_buffered_stream_inner_io_get(svr->dialer)));
2039 
2040    if (svr->ssl.pending_send)
2041      {
2042         /* if ecore_con_server_send() was called before the job completed
2043          * then we queued data there, flush to dialer.
2044          * See https://phab.enlightenment.org/T5339
2045          */
2046         Eina_Slice slice = eina_binbuf_slice_get(svr->ssl.pending_send);
2047         ecore_con_server_send(svr, slice.mem, slice.len);
2048         eina_binbuf_free(svr->ssl.pending_send);
2049         svr->ssl.pending_send = NULL;
2050      }
2051 
2052    return v;
2053 
2054  error_dial:
2055    if (_ecore_con_post_event_server_error(svr, "Couldn't dial using SSL"))
2056      _ecore_con_post_event_server_del(svr);
2057    return v;
2058 
2059  error_dialer:
2060    efl_del(inner_dialer);
2061  error_inner_dialer:
2062    efl_del(ssl_ctx);
2063  error_ssl_ctx:
2064    if (_ecore_con_post_event_server_error(svr, "Couldn't finish SSL setup"))
2065      _ecore_con_post_event_server_del(svr);
2066    return v;
2067 }
2068 
2069 static Eina_Value
_ecore_con_server_dialer_ssl_upgrade_job(void * data,const Eina_Value v,const Eina_Future * dead EINA_UNUSED)2070 _ecore_con_server_dialer_ssl_upgrade_job(void *data, const Eina_Value v,
2071                                          const Eina_Future *dead EINA_UNUSED)
2072 {
2073    Ecore_Con_Server *svr = data;
2074    Eo *loop = efl_main_loop_get();
2075    Eo *ssl_ctx;
2076    Eo *inner_dialer;
2077    Eo *dialer;
2078    Eo *tcp_dialer;
2079    Efl_Net_Ssl_Cipher cipher = EFL_NET_SSL_CIPHER_AUTO;
2080    Efl_Net_Ssl_Verify_Mode verify_mode = EFL_NET_SSL_VERIFY_MODE_NONE; /* was the default */
2081    Ecore_Con_Type ssl_type = svr->ssl.upgrade_type & ECORE_CON_SSL;
2082 
2083    //Canceled
2084    if (v.type == EINA_VALUE_TYPE_ERROR) return v;
2085 
2086    if (ssl_type & ECORE_CON_USE_MIXED)
2087      cipher = EFL_NET_SSL_CIPHER_AUTO;
2088    else if (ssl_type & ECORE_CON_USE_TLS)
2089      cipher = EFL_NET_SSL_CIPHER_TLSV1;
2090    else if (ssl_type & ECORE_CON_USE_SSL3)
2091      {
2092         ERR("SSLv3 is unsupported!");
2093         goto error_ssl_ctx;
2094      }
2095    else if (ssl_type & ECORE_CON_USE_SSL2)
2096      {
2097         ERR("SSLv2 is unsupported!");
2098         goto error_ssl_ctx;
2099      }
2100 
2101    if (svr->ssl.verify)
2102      verify_mode = EFL_NET_SSL_VERIFY_MODE_REQUIRED;
2103 
2104    ssl_ctx = efl_add_ref(EFL_NET_SSL_CONTEXT_CLASS, efl_main_loop_get(),
2105                          efl_net_ssl_context_certificates_set(efl_added, eina_list_iterator_new(svr->ssl.certs)),
2106                          efl_net_ssl_context_private_keys_set(efl_added, eina_list_iterator_new(svr->ssl.privkeys)),
2107                          efl_net_ssl_context_certificate_revocation_lists_set(efl_added, eina_list_iterator_new(svr->ssl.crls)),
2108                          efl_net_ssl_context_certificate_authorities_set(efl_added, eina_list_iterator_new(svr->ssl.cafiles)),
2109                          efl_net_ssl_context_verify_mode_set(efl_added, verify_mode),
2110                          efl_net_ssl_context_hostname_set(efl_added, svr->ssl.verify_name ? svr->ssl.verify_name : svr->name),
2111                          efl_net_ssl_context_hostname_verify_set(efl_added, svr->ssl.verify_basic),
2112                          efl_net_ssl_context_default_paths_load_set(efl_added, EINA_FALSE), /* old API didn't load default paths */
2113                          efl_net_ssl_context_setup(efl_added, cipher, EINA_TRUE));
2114    EINA_SAFETY_ON_NULL_GOTO(ssl_ctx, error_ssl_ctx);
2115 
2116    tcp_dialer = svr->dialer;
2117    svr->dialer = NULL; /* take it, will be wrapped */
2118 
2119    inner_dialer = efl_add(EFL_NET_DIALER_SSL_CLASS, loop,
2120                           efl_net_socket_ssl_adopt(efl_added, tcp_dialer, ssl_ctx));
2121    EINA_SAFETY_ON_NULL_GOTO(inner_dialer, error_inner_dialer);
2122 
2123    efl_parent_set(tcp_dialer, inner_dialer);
2124 
2125    dialer = efl_add(EFL_NET_DIALER_SIMPLE_CLASS, loop,
2126                     efl_io_buffered_stream_inner_io_set(efl_added, inner_dialer));
2127    EINA_SAFETY_ON_NULL_GOTO(dialer, error_dialer);
2128 
2129    efl_parent_set(inner_dialer, dialer);
2130 
2131    efl_unref(ssl_ctx); /* inner_dialer keeps it */
2132 
2133    svr->dialer = dialer;
2134    efl_io_closer_close_on_exec_set(dialer, EINA_TRUE);
2135    efl_io_closer_close_on_invalidate_set(dialer, EINA_TRUE);
2136    efl_event_callback_array_del(tcp_dialer, _ecore_con_server_dialer_cbs(), svr);
2137    efl_event_callback_array_add(dialer, _ecore_con_server_dialer_cbs(), svr);
2138 
2139    DBG("dialer=%p upgraded to SSL with inner_dialer=%p, ssl_ctx=%p, tcp_dialer=%p. Start handshake...",
2140        svr->dialer,
2141        efl_io_buffered_stream_inner_io_get(svr->dialer),
2142        efl_net_dialer_ssl_context_get(efl_io_buffered_stream_inner_io_get(svr->dialer)),
2143        tcp_dialer);
2144    return v;
2145 
2146  error_dialer:
2147    efl_del(inner_dialer);
2148  error_inner_dialer:
2149    svr->dialer = tcp_dialer; /* put it back */
2150    efl_del(ssl_ctx);
2151  error_ssl_ctx:
2152    if (_ecore_con_post_event_server_error(svr, "Couldn't finish SSL setup"))
2153      _ecore_con_post_event_server_del(svr);
2154    return v;
2155 }
2156 
2157 /**
2158  * @example ecore_con_client_example.c
2159  *
2160  * Shows how to write a simple client (dialer that connects to the
2161  * example server using ecore_con_server_connect().
2162  */
2163 
2164 EAPI Ecore_Con_Server *
ecore_con_server_connect(Ecore_Con_Type compl_type,const char * name,int port,const void * data)2165 ecore_con_server_connect(Ecore_Con_Type compl_type,
2166                          const char *name,
2167                          int port,
2168                          const void *data)
2169 {
2170    const Efl_Class *cls = NULL;
2171    Ecore_Con_Server *svr;
2172    Ecore_Con_Type type;
2173    Eo *dialer;
2174    Eo *loop;
2175 
2176    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
2177 
2178    type = compl_type & ECORE_CON_TYPE;
2179 
2180    loop = efl_main_loop_get();
2181    EINA_SAFETY_ON_NULL_RETURN_VAL(loop, NULL);
2182 
2183    svr = _ecore_con_server_new(EINA_TRUE, compl_type, name, port, data);
2184    EINA_SAFETY_ON_NULL_RETURN_VAL(svr, NULL);
2185 
2186    switch (type)
2187      {
2188       case ECORE_CON_LOCAL_USER:
2189       case ECORE_CON_LOCAL_SYSTEM:
2190       case ECORE_CON_LOCAL_ABSTRACT:
2191 #ifdef EFL_NET_DIALER_UNIX_CLASS
2192          cls = EFL_NET_DIALER_UNIX_CLASS;
2193 #elif defined(EFL_NET_DIALER_WINDOWS_CLASS)
2194          cls = EFL_NET_DIALER_WINDOWS_CLASS;
2195 #else
2196          ERR("Your platform doesn't support Efl_Net_Dialer-compatible local communication");
2197          // TODO: maybe write to a file and use TCP
2198 #endif
2199          break;
2200 
2201       case ECORE_CON_REMOTE_TCP:
2202       case ECORE_CON_REMOTE_NODELAY:
2203       case ECORE_CON_REMOTE_CORK:
2204          cls = EFL_NET_DIALER_TCP_CLASS;
2205          break;
2206 
2207       case ECORE_CON_REMOTE_UDP:
2208       case ECORE_CON_REMOTE_BROADCAST:
2209          cls = EFL_NET_DIALER_UDP_CLASS;
2210          break;
2211 
2212       default:
2213          ERR("Unsupported type=%#x & %#x = %#x", compl_type, ECORE_CON_TYPE, type);
2214      }
2215    EINA_SAFETY_ON_NULL_GOTO(cls, error);
2216 
2217    if (compl_type & ECORE_CON_SSL)
2218      {
2219         if (cls != EFL_NET_DIALER_TCP_CLASS)
2220           ERR("SSL can only be used with TCP types, got %s, forcing TCP", efl_class_name_get(cls));
2221 
2222         /* efl_net_ssl_context must be created prior to the object as
2223          * it's immutable once created. However the previous
2224          * Ecore_Con_Server API returned a handle and then configured
2225          * it, like in runtime, but in practice it's only effective
2226          * before the connection happens.
2227          *
2228          * Then do not create the SSL dialer right away, instead do it
2229          * from a job, let the user configure SSL before the job
2230          * finishes.
2231          *
2232          * EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job) will alert users
2233          * trying to configure after the job expires.
2234          *
2235          * We can do that since the documentation says:
2236          *
2237          * > Call this function on a server object before main loop
2238          * > has started to enable verification of certificates
2239          * > against loaded certificates.
2240          */
2241         _ecore_con_server_job_schedule(svr, loop, _ecore_con_server_dialer_ssl_job);
2242         return svr;
2243      }
2244 
2245    dialer = efl_add(EFL_NET_DIALER_SIMPLE_CLASS, loop,
2246                     efl_net_dialer_simple_inner_class_set(efl_added, cls));
2247    EINA_SAFETY_ON_NULL_GOTO(dialer, error);
2248 
2249    if (!_ecore_con_server_dialer_set(svr, dialer))
2250      goto error;
2251 
2252    return svr;
2253 
2254  error:
2255    _ecore_con_server_free(svr);
2256    return NULL;
2257 }
2258 
2259 EAPI const char *
ecore_con_server_name_get(const Ecore_Con_Server * svr)2260 ecore_con_server_name_get(const Ecore_Con_Server *svr)
2261 {
2262    ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
2263    return svr->name;
2264 }
2265 
2266 EAPI void
ecore_con_server_client_limit_set(Ecore_Con_Server * svr,int client_limit,char reject_excess_clients)2267 ecore_con_server_client_limit_set(Ecore_Con_Server *svr,
2268                                   int client_limit,
2269                                   char reject_excess_clients)
2270 {
2271    ECORE_CON_SERVER_CHECK_RETURN(svr);
2272    if (!svr->server) return;
2273    efl_net_server_clients_limit_set(svr->server, client_limit, reject_excess_clients);
2274 }
2275 
2276 EAPI const Eina_List *
ecore_con_server_clients_get(const Ecore_Con_Server * svr)2277 ecore_con_server_clients_get(const Ecore_Con_Server *svr)
2278 {
2279    ECORE_CON_SERVER_CHECK_RETURN(svr, NULL);
2280    return svr->clients;
2281 }
2282 
2283 EAPI void
ecore_con_server_timeout_set(Ecore_Con_Server * svr,double timeout)2284 ecore_con_server_timeout_set(Ecore_Con_Server *svr, double timeout)
2285 {
2286    ECORE_CON_SERVER_CHECK_RETURN(svr);
2287 
2288    svr->timeout = timeout; /* used for new clients */
2289 
2290    if (!svr->dialer) return;
2291    efl_io_buffered_stream_timeout_inactivity_set(svr->dialer, timeout);
2292 }
2293 
2294 EAPI double
ecore_con_server_timeout_get(const Ecore_Con_Server * svr)2295 ecore_con_server_timeout_get(const Ecore_Con_Server *svr)
2296 {
2297    ECORE_CON_SERVER_CHECK_RETURN(svr, -1.0);
2298    return svr->timeout;
2299 }
2300 
2301 EAPI void *
ecore_con_server_del(Ecore_Con_Server * svr)2302 ecore_con_server_del(Ecore_Con_Server *svr)
2303 {
2304    const void *data;
2305 
2306    ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
2307 
2308    data = svr->data;
2309 
2310    _ecore_con_server_free(svr);
2311    return (void *)data;
2312 }
2313 
2314 EAPI void *
ecore_con_server_data_get(Ecore_Con_Server * svr)2315 ecore_con_server_data_get(Ecore_Con_Server *svr)
2316 {
2317    ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
2318    return (void *)svr->data;
2319 }
2320 
2321 EAPI void *
ecore_con_server_data_set(Ecore_Con_Server * svr,void * data)2322 ecore_con_server_data_set(Ecore_Con_Server *svr,
2323                           void *data)
2324 {
2325    const void *old;
2326 
2327    ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
2328    old = svr->data;
2329    svr->data = data;
2330    return (void *)old;
2331 }
2332 
2333 EAPI Eina_Bool
ecore_con_server_connected_get(const Ecore_Con_Server * svr)2334 ecore_con_server_connected_get(const Ecore_Con_Server *svr)
2335 {
2336    ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
2337    if (svr->is_dialer)
2338      {
2339         if (svr->dialer)
2340           return efl_net_dialer_connected_get(svr->dialer);
2341         return EINA_FALSE; /* still setting up SSL */
2342      }
2343    return EINA_TRUE;
2344 }
2345 
2346 EAPI int
ecore_con_server_port_get(const Ecore_Con_Server * svr)2347 ecore_con_server_port_get(const Ecore_Con_Server *svr)
2348 {
2349    ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, -1);
2350    return svr->port;
2351 }
2352 
2353 EAPI int
ecore_con_server_send(Ecore_Con_Server * svr,const void * data,int size)2354 ecore_con_server_send(Ecore_Con_Server *svr, const void *data, int size)
2355 {
2356    Eina_Error err;
2357    Eina_Slice slice = { .mem = data, .len = size };
2358 
2359    ECORE_CON_SERVER_CHECK_RETURN(svr, 0);
2360    EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
2361    EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
2362 
2363    /* while upgrading or no dialer (due SSL dialer being created on
2364     * the next mainloop iteration from a job as described from
2365     * ecore_con_server_connect()), queue pending data and send as soon
2366     * as the dialer is assigned.
2367     *
2368     * This allows immediate usage of ecore_con_server_send() after
2369     * ecore_con_server_connect() as the old API did and needed by
2370     * https://phab.enlightenment.org/T5339
2371     */
2372    if ((svr->ssl.upgrading) || (!svr->dialer))
2373      {
2374         Eina_Bool r;
2375         if (!svr->ssl.pending_send)
2376           {
2377              svr->ssl.pending_send = eina_binbuf_new();
2378              EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.pending_send, 0);
2379           }
2380         r = eina_binbuf_append_length(svr->ssl.pending_send, data, size);
2381         EINA_SAFETY_ON_FALSE_RETURN_VAL(r, 0);
2382         return size;
2383      }
2384 
2385    err = efl_io_writer_write(svr->dialer, &slice, NULL);
2386    if (err)
2387      {
2388         ERR("svr=%p could not send data=%p, size=%d: %s",
2389             svr, data, size, eina_error_msg_get(err));
2390         return 0;
2391      }
2392    svr->pending_write = efl_io_buffered_stream_pending_write_get(svr->dialer);
2393 
2394    return slice.len;
2395 }
2396 
2397 EAPI const char *
ecore_con_server_ip_get(const Ecore_Con_Server * svr)2398 ecore_con_server_ip_get(const Ecore_Con_Server *svr)
2399 {
2400    ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, NULL);
2401    return svr->ip;
2402 }
2403 
2404 EAPI double
ecore_con_server_uptime_get(const Ecore_Con_Server * svr)2405 ecore_con_server_uptime_get(const Ecore_Con_Server *svr)
2406 {
2407    ECORE_CON_SERVER_CHECK_RELAXED_RETURN(svr, 0.0);
2408    return ecore_time_get() - svr->start_time;
2409 }
2410 
2411 EAPI void
ecore_con_server_flush(Ecore_Con_Server * svr)2412 ecore_con_server_flush(Ecore_Con_Server *svr)
2413 {
2414    ECORE_CON_SERVER_CHECK_RETURN(svr);
2415    Eo *inner_dialer;
2416 
2417    if (!svr->dialer) return;
2418 
2419    while (!efl_io_closer_closed_get(svr->dialer) &&
2420           !efl_net_dialer_connected_get(svr->dialer))
2421      ecore_main_loop_iterate();
2422 
2423    efl_io_buffered_stream_flush(svr->dialer, EINA_FALSE, EINA_TRUE);
2424 
2425    inner_dialer = efl_io_buffered_stream_inner_io_get(svr->dialer);
2426 
2427    if (!efl_isa(inner_dialer, EFL_NET_SOCKET_TCP_CLASS)) return;
2428    if (!efl_net_socket_tcp_cork_get(inner_dialer)) return;
2429 
2430    efl_net_socket_tcp_cork_set(inner_dialer, EINA_FALSE);
2431    efl_net_socket_tcp_cork_set(inner_dialer, EINA_TRUE);
2432 }
2433 
2434 EAPI int
ecore_con_server_fd_get(const Ecore_Con_Server * svr)2435 ecore_con_server_fd_get(const Ecore_Con_Server *svr)
2436 {
2437    ECORE_CON_SERVER_CHECK_RETURN(svr, SOCKET_TO_LOOP_FD(INVALID_SOCKET));
2438    if (svr->dialer)
2439      {
2440         Eo *inner_dialer = efl_io_buffered_stream_inner_io_get(svr->dialer);
2441         if (efl_isa(inner_dialer, EFL_LOOP_FD_CLASS))
2442           {
2443              return efl_loop_fd_get(inner_dialer);
2444           }
2445         else
2446           {
2447              if (efl_isa(inner_dialer, EFL_NET_DIALER_SSL_CLASS))
2448                {
2449                   Eo* adopted_dialer = NULL;
2450                   if (efl_net_socket_ssl_adopted_get(inner_dialer, &adopted_dialer, NULL))
2451                     if (efl_isa(adopted_dialer, EFL_LOOP_FD_CLASS))
2452                       return efl_loop_fd_get(adopted_dialer);
2453                }
2454           }
2455         return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
2456      }
2457    if (svr->server)
2458      {
2459         Eo *inner_server = efl_net_server_simple_inner_server_get(svr->server);
2460         if (efl_isa(inner_server, EFL_LOOP_FD_CLASS))
2461           return efl_loop_fd_get(inner_server);
2462         return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
2463      }
2464    return SOCKET_TO_LOOP_FD(INVALID_SOCKET);
2465 }
2466 
2467 EAPI Eina_Bool
ecore_con_ssl_server_cert_add(Ecore_Con_Server * svr,const char * cert)2468 ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr, const char *cert)
2469 {
2470    ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
2471    EINA_SAFETY_ON_NULL_RETURN_VAL(cert, EINA_FALSE);
2472 
2473    if (!svr->server) /* SSL adds a job to allow setup */
2474      EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.job, EINA_FALSE);
2475    else
2476      EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.clients_ctx != NULL, EINA_FALSE);
2477 
2478    svr->ssl.certs = eina_list_append(svr->ssl.certs, eina_stringshare_add(cert));
2479    return EINA_TRUE;
2480 }
2481 
2482 EAPI Eina_Bool
ecore_con_ssl_server_privkey_add(Ecore_Con_Server * svr,const char * privkey)2483 ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr, const char *privkey)
2484 {
2485    ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
2486    EINA_SAFETY_ON_NULL_RETURN_VAL(privkey, EINA_FALSE);
2487 
2488    if (!svr->server) /* SSL adds a job to allow setup */
2489      EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.job, EINA_FALSE);
2490    else
2491      EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.clients_ctx != NULL, EINA_FALSE);
2492 
2493    svr->ssl.privkeys = eina_list_append(svr->ssl.privkeys, eina_stringshare_add(privkey));
2494    return EINA_TRUE;
2495 }
2496 
2497 EAPI Eina_Bool
ecore_con_ssl_server_crl_add(Ecore_Con_Server * svr,const char * crl)2498 ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr, const char *crl)
2499 {
2500    ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
2501    EINA_SAFETY_ON_NULL_RETURN_VAL(crl, EINA_FALSE);
2502 
2503    if (!svr->server) /* SSL adds a job to allow setup */
2504      EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.job, EINA_FALSE);
2505    else
2506      EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.clients_ctx != NULL, EINA_FALSE);
2507 
2508    svr->ssl.crls = eina_list_append(svr->ssl.crls, eina_stringshare_add(crl));
2509    return EINA_TRUE;
2510 }
2511 
2512 EAPI Eina_Bool
ecore_con_ssl_server_cafile_add(Ecore_Con_Server * svr,const char * cafile)2513 ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr, const char *cafile)
2514 {
2515    ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
2516    EINA_SAFETY_ON_NULL_RETURN_VAL(cafile, EINA_FALSE);
2517 
2518    if (!svr->server) /* SSL adds a job to allow setup */
2519      EINA_SAFETY_ON_NULL_RETURN_VAL(svr->ssl.job, EINA_FALSE);
2520    else
2521      EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.clients_ctx != NULL, EINA_FALSE);
2522 
2523    svr->ssl.cafiles = eina_list_append(svr->ssl.cafiles, eina_stringshare_add(cafile));
2524    return EINA_TRUE;
2525 }
2526 
2527 EAPI void
ecore_con_ssl_server_verify(Ecore_Con_Server * svr)2528 ecore_con_ssl_server_verify(Ecore_Con_Server *svr)
2529 {
2530    ECORE_CON_SERVER_CHECK_RETURN(svr);
2531 
2532    if (!svr->server) /* SSL adds a job to allow setup */
2533      EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job);
2534    else
2535      EINA_SAFETY_ON_TRUE_RETURN(svr->ssl.clients_ctx != NULL);
2536 
2537    if (!svr->is_dialer)
2538      {
2539         /* legacy compatible + print a warning */
2540         WRN("svr=%p created with ecore_con_server_add()", svr);
2541         return;
2542      }
2543 
2544    svr->ssl.verify = EINA_TRUE;
2545 }
2546 
2547 EAPI void
ecore_con_ssl_server_verify_basic(Ecore_Con_Server * svr)2548 ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr)
2549 {
2550    ECORE_CON_SERVER_CHECK_RETURN(svr);
2551    EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job);
2552 
2553    if (!svr->server) /* SSL adds a job to allow setup */
2554      EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job);
2555    else
2556      EINA_SAFETY_ON_TRUE_RETURN(svr->ssl.clients_ctx != NULL);
2557 
2558    if (!svr->is_dialer)
2559      {
2560         /* legacy compatible + print a warning */
2561         WRN("svr=%p created with ecore_con_server_add()", svr);
2562         return;
2563      }
2564 
2565    svr->ssl.verify_basic = EINA_TRUE;
2566 }
2567 
2568 EAPI void
ecore_con_ssl_server_verify_name_set(Ecore_Con_Server * svr,const char * name)2569 ecore_con_ssl_server_verify_name_set(Ecore_Con_Server *svr, const char *name)
2570 {
2571    ECORE_CON_SERVER_CHECK_RETURN(svr);
2572    EINA_SAFETY_ON_NULL_RETURN(name);
2573 
2574    if (!svr->server) /* SSL adds a job to allow setup */
2575      EINA_SAFETY_ON_NULL_RETURN(svr->ssl.job);
2576    else
2577      EINA_SAFETY_ON_TRUE_RETURN(svr->ssl.clients_ctx != NULL);
2578 
2579    eina_stringshare_replace(&svr->ssl.verify_name, name);
2580 }
2581 
2582 EAPI const char *
ecore_con_ssl_server_verify_name_get(Ecore_Con_Server * svr)2583 ecore_con_ssl_server_verify_name_get(Ecore_Con_Server *svr)
2584 {
2585    ECORE_CON_SERVER_CHECK_RETURN(svr, NULL);
2586    return svr->ssl.verify_name ? svr->ssl.verify_name : svr->name;
2587 }
2588 
2589 EAPI Eina_Bool
ecore_con_ssl_server_upgrade(Ecore_Con_Server * svr,Ecore_Con_Type compl_type)2590 ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type compl_type)
2591 {
2592    double start;
2593 
2594    ECORE_CON_SERVER_CHECK_RETURN(svr, EINA_FALSE);
2595    EINA_SAFETY_ON_NULL_RETURN_VAL(svr->dialer, EINA_FALSE);
2596    EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->server != NULL, EINA_FALSE);
2597    EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->ssl.upgrading, EINA_FALSE);
2598    EINA_SAFETY_ON_TRUE_RETURN_VAL((compl_type & ECORE_CON_SSL) == 0, EINA_FALSE);
2599    EINA_SAFETY_ON_FALSE_RETURN_VAL(efl_isa(efl_io_buffered_stream_inner_io_get(svr->dialer), EFL_NET_DIALER_TCP_CLASS), EINA_FALSE);
2600 
2601    start = ecore_time_get();
2602    while (efl_io_buffered_stream_pending_write_get(svr->dialer) && ((ecore_time_get() - start) <= ecore_animator_frametime_get()))
2603      ecore_con_server_flush(svr);
2604    if (efl_io_buffered_stream_pending_write_get(svr->dialer))
2605      {
2606         ERR("svr=%p still pending send %zd bytes! Flush server before upgrading to SSL!",
2607             svr, efl_io_buffered_stream_pending_write_get(svr->dialer));
2608         return EINA_FALSE;
2609      }
2610 
2611    svr->ssl.upgrading = EINA_TRUE;
2612    svr->ssl.upgrade_type = compl_type;
2613 
2614    _ecore_con_server_job_schedule(svr, efl_loop_get(svr->dialer),
2615                                   _ecore_con_server_dialer_ssl_upgrade_job);
2616 
2617    DBG("svr=%p SSL upgrading from %#x to type=%#x", svr, svr->type, compl_type);
2618 
2619    return EINA_TRUE;
2620 }
2621 
2622 /**
2623  * @}
2624  */
2625 
2626 static void
_ecore_con_lookup_done_cb(void * data,const char * host,const char * port EINA_UNUSED,const struct addrinfo * hints EINA_UNUSED,struct addrinfo * result,int gai_error)2627 _ecore_con_lookup_done_cb(void *data, const char *host, const char *port EINA_UNUSED, const struct addrinfo *hints EINA_UNUSED, struct addrinfo *result, int gai_error)
2628 {
2629    Ecore_Con_Lookup_Ctx *ctx = data;
2630 
2631    ctx->thread = NULL;
2632 
2633    if (gai_error)
2634      WRN("Failed to lookup host='%s': %s", host, gai_strerror(gai_error));
2635    else if (result)
2636      {
2637         char ip[INET6_ADDRSTRLEN];
2638         const void *mem;
2639 
2640         if (result->ai_family == AF_INET)
2641           {
2642              const struct sockaddr_in *a = (const struct sockaddr_in *)result->ai_addr;
2643              mem = &a->sin_addr;
2644           }
2645         else if (result->ai_family == AF_INET6)
2646           {
2647              const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)result->ai_addr;
2648              mem = &a->sin6_addr;
2649           }
2650         else
2651           {
2652              ERR("unexpected result->ai_family=%d", result->ai_family);
2653              goto end;
2654           }
2655 
2656         if (!inet_ntop(result->ai_family, mem, ip, sizeof(ip)))
2657           {
2658              ERR("could not convert IP to string: %s", eina_error_msg_get(errno));
2659              goto end;
2660           }
2661         ctx->cb(result->ai_canonname, ip, result->ai_addr, result->ai_addrlen, (void *)ctx->data);
2662      }
2663 
2664  end:
2665    freeaddrinfo(result);
2666    _ecore_con_lookups = eina_list_remove(_ecore_con_lookups, ctx);
2667    free(ctx);
2668 }
2669 
2670 /*
2671  * NOTE: this function has numerous problems:
2672  *  - not able to specify family (IPv4 or IPv6 or both).
2673  *  - callback reports a single result
2674  *  - doesn't return a handle to cancel (likely to access memory after free)
2675  *  - doesn't report errors
2676  */
2677 EAPI Eina_Bool
ecore_con_lookup(const char * name,Ecore_Con_Dns_Cb done_cb,const void * data)2678 ecore_con_lookup(const char *name, Ecore_Con_Dns_Cb done_cb, const void *data)
2679 {
2680    Ecore_Con_Lookup_Ctx *ctx;
2681    struct addrinfo hints = {
2682      .ai_family = AF_UNSPEC,
2683      .ai_flags = AI_ADDRCONFIG | AI_V4MAPPED | AI_CANONNAME,
2684    };
2685 
2686    EINA_SAFETY_ON_TRUE_RETURN_VAL(!name || (!name[0]), EINA_FALSE);
2687    EINA_SAFETY_ON_NULL_RETURN_VAL(done_cb, EINA_FALSE);
2688 
2689    ctx = malloc(sizeof(Ecore_Con_Lookup_Ctx));
2690    EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, EINA_FALSE);
2691    ctx->cb = done_cb;
2692    ctx->data = data;
2693 
2694    ctx->thread = efl_net_ip_resolve_async_new(name, "0", &hints, _ecore_con_lookup_done_cb, ctx);
2695    EINA_SAFETY_ON_NULL_GOTO(ctx->thread, error);
2696 
2697    _ecore_con_lookups = eina_list_append(_ecore_con_lookups, ctx);
2698    return EINA_TRUE;
2699 
2700  error:
2701    free(ctx);
2702    return EINA_FALSE;
2703 }
2704