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