aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore_con
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore_con')
-rw-r--r--libraries/ecore/src/lib/ecore_con/Ecore_Con.h1801
-rw-r--r--libraries/ecore/src/lib/ecore_con/Makefile.am45
-rw-r--r--libraries/ecore/src/lib/ecore_con/Makefile.in909
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con.c2600
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_alloc.c99
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_ares.c628
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_info.c450
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_local.c317
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_local_win32.c769
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_private.h321
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c1777
-rw-r--r--libraries/ecore/src/lib/ecore_con/ecore_con_url.c1572
12 files changed, 11288 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_con/Ecore_Con.h b/libraries/ecore/src/lib/ecore_con/Ecore_Con.h
new file mode 100644
index 0000000..e3b68c4
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/Ecore_Con.h
@@ -0,0 +1,1801 @@
1#ifndef _ECORE_CON_H
2#define _ECORE_CON_H
3
4#include <time.h>
5#include <libgen.h>
6#ifdef _WIN32
7# include <ws2tcpip.h>
8#else
9# include <netdb.h>
10#endif
11#include <Eina.h>
12
13#ifdef EAPI
14# undef EAPI
15#endif
16
17#ifdef _WIN32
18# ifdef EFL_ECORE_CON_BUILD
19# ifdef DLL_EXPORT
20# define EAPI __declspec(dllexport)
21# else
22# define EAPI
23# endif
24# else
25# define EAPI __declspec(dllimport)
26# endif
27#else
28# ifdef __GNUC__
29# if __GNUC__ >= 4
30# define EAPI __attribute__ ((visibility("default")))
31# else
32# define EAPI
33# endif
34# else
35# define EAPI
36# endif
37#endif
38
39/**
40 * @defgroup Ecore_Con_Group Ecore_Con - Connection functions
41 *
42 * The Ecore Connection Library ( @c Ecore_Con ) provides simple mechanisms
43 * for communications between programs using reliable sockets. It saves
44 * the programmer from having to worry about file descriptors and waiting
45 * for incoming connections.
46 *
47 * There are two main objects in the @c Ecore_Con library: the @c
48 * Ecore_Con_Server and the @c Ecore_Con_Client.
49 *
50 * The @c Ecore_Con_Server represents a server that can be connected to.
51 * It is used regardless of whether the program is acting as a server or
52 * client itself.
53 *
54 * To create a listening server call @c ecore_con_server_add(), optionally using
55 * an ECORE_CON_USE_* encryption type OR'ed with the type for encryption.
56 *
57 * To connect to a server, call @c ecore_con_server_connect(). Data can
58 * then be sent to the server using the @c ecore_con_server_send().
59 *
60 * Functions are described in the following groupings:
61 * @li @ref Ecore_Con_Lib_Group
62 * @li @ref Ecore_Con_Server_Group
63 * @li @ref Ecore_Con_Client_Group
64 * @li @ref Ecore_Con_Url_Group
65 *
66 * Events are described in @ref Ecore_Con_Events_Group.
67 */
68
69
70/**
71 * @defgroup Ecore_Con_Events_Group Events
72 *
73 * @li ECORE_CON_CLIENT_ADD: Whenever a client connection is made to an
74 * @c Ecore_Con_Server, an event of this type is emitted, allowing the
75 * retrieval of the client's ip with @ref ecore_con_client_ip_get and
76 * associating data with the client using ecore_con_client_data_set.
77 * @li ECORE_CON_EVENT_CLIENT_DEL: Whenever a client connection to an
78 * @c Ecore_Con_Server, an event of this type is emitted. The contents of
79 * the data with this event are variable, but if the client object in the data
80 * is non-null, it must be freed with @ref ecore_con_client_del.
81 * @li ECORE_CON_EVENT_SERVER_ADD: Whenever a server object is created
82 * with @ref ecore_con_server_connect, an event of this type is emitted,
83 * allowing for data to be serialized and sent to the server using
84 * @ref ecore_con_server_send. At this point, the http handshake has
85 * occurred.
86 * @li ECORE_CON_EVENT_SERVER_DEL: Whenever a server object is destroyed,
87 * usually by the server connection being refused or dropped, an event of this
88 * type is emitted. The contents of the data with this event are variable,
89 * but if the server object in the data is non-null, it must be freed
90 * with @ref ecore_con_server_del.
91 * @li ECORE_CON_EVENT_CLIENT_DATA: Whenever a client connects to your server
92 * object and sends data, an event of this type is emitted. The data will contain both
93 * the size and contents of the message sent by the client. It should be noted that
94 * data within this object is transient, so it must be duplicated in order to be
95 * retained. This event will continue to occur until the client has stopped sending its
96 * message, so a good option for storing this data is an Eina_Strbuf. Once the message has
97 * been received in full, the client object must be freed with ecore_con_client_free.
98 * @li ECORE_CON_EVENT_SERVER_DATA: Whenever your server object connects to its destination
99 * and receives data, an event of this type is emitted. The data will contain both
100 * the size and contents of the message sent by the server. It should be noted that
101 * data within this object is transient, so it must be duplicated in order to be
102 * retained. This event will continue to occur until the server has stopped sending its
103 * message, so a good option for storing this data is an Eina_Strbuf. Once the message has
104 * been received in full, the server object must be freed with ecore_con_server_free.
105 *
106 */
107
108/**
109 * @defgroup Ecore_Con_Buffer Buffering
110 *
111 * As Ecore_Con works on an event driven design, as data arrives, events will
112 * be produced containing the data that arrived. It is up to the user of
113 * Ecore_Con to either parse as they go, append to a file to later parse the
114 * whole file in one go, or append to memory to parse or handle leter.
115 *
116 * To help with this Eina has some handy API's. The Eina_Binbuf and
117 * Eina_Strbuf APIs, abstract dynamic buffer management and make it trivial
118 * to handle buffers at runtime, without having to manage them. Eina_Binbuf
119 * makes it possible to create, expand, reset and slice a blob of memory -
120 * all via API. No system calls, no pointer manipulations and no size
121 * calculation.
122 *
123 * Additional functions include adding content at specified byte positions in
124 * the buffer, escaping the inputs, find and replace strings. This provides
125 * extreme flexibility to play around, with a dynamic blob of memory.
126 *
127 * It is good to free it (using eina_binbuf_free()) after using it.
128 *
129 * Eina_Binbuf compliments Ecore_Con use cases, where dynamic sizes of data
130 * arrive from the network (think http download in chunks). Using
131 * Eina_Binbuf provides enough flexibility to handle data as it arrives and
132 * to defer its processing until desired, without having to think about
133 * where to store the temporary data and how to manage its size.
134 *
135 * An example of how to use these with Ecore_Con follows.
136 *
137 * @code
138 * #include <Eina.h>
139 * #include <Ecore.h>
140 * #include <Ecore_Con.h>
141 *
142 * static Eina_Bool
143 * data_callback(void *data, int type, void *event)
144 * {
145 * Ecore_Con_Event_Url_Data *url_data = event;
146 * if ( url_data->size > 0)
147 * {
148 * // append data as it arrives - don't worry where or how it gets stored.
149 * // Also don't worry about size, expanding, reallocing etc.
150 * // just keep appending - size is automatically handled.
151 *
152 * eina_binbuf_append_length(data, url_data->data, url_data->size);
153 *
154 * fprintf(stderr, "Appended %d \n", url_data->size);
155 * }
156 * return EINA_TRUE;
157 * }
158 *
159 *
160 *
161 * static Eina_Bool
162 * completion_callback(void *data, int type, void *event)
163 * {
164 * Ecore_Con_Event_Url_Complete *url_complete = event;
165 * printf("download completed with status code: %d\n", url_complete->status);
166 *
167 * // get the data back from Eina_Binbuf
168 * char *ptr = eina_binbuf_string_get(data);
169 * size_t size = eina_binbuf_length_get(data);
170 *
171 * // process data as required (write to file)
172 * fprintf(stderr, "Size of data = %d bytes\n", size);
173 * int fd = open("./elm.png", O_CREAT);
174 * write(fd, ptr, size);
175 * close(fd);
176 *
177 * // free it when done.
178 * eina_binbuf_free(data);
179 *
180 * ecore_main_loop_quit();
181 *
182 * return EINA_TRUE;
183 * }
184 *
185 *
186 * int
187 * main(int argc, char **argv)
188 * {
189 *
190 * const char *url = "http://www.enlightenment.org/p/index/d/logo.png";
191 *
192 * ecore_init();
193 * ecore_con_init();
194 * ecore_con_url_init();
195 *
196 *
197 * // This is single additional line to manage dynamic network data.
198 * Eina_Binbuf *data = eina_binbuf_new();
199 * Ecore_Con_Url *url_con = ecore_con_url_new(url);
200 *
201 * ecore_event_handler_add(ECORE_CON_EVENT_URL_COMPLETE,
202 * completion_callback,
203 * data);
204 * ecore_event_handler_add(ECORE_CON_EVENT_URL_DATA,
205 * data_callback,
206 * data);
207 * ecore_con_url_get(url_con);
208 *
209 * ecore_main_loop_begin();
210 * return 0;
211 * }
212 * @endcode
213 */
214
215#ifdef __cplusplus
216extern "C" {
217#endif
218#define ECORE_CON_USE_SSL ECORE_CON_USE_SSL2
219#define ECORE_CON_REMOTE_SYSTEM ECORE_CON_REMOTE_TCP
220
221
222/**
223 * @typedef Ecore_Con_Server
224 * A connection handle to a server
225 * @ingroup Ecore_Con_Server_Group
226 */
227typedef struct _Ecore_Con_Server Ecore_Con_Server;
228
229/**
230 * @typedef Ecore_Con_Client
231 * A connection handle to a client
232 * @ingroup Ecore_Con_Client_Group
233 */
234typedef struct _Ecore_Con_Client Ecore_Con_Client;
235
236/**
237 * @typedef Ecore_Con_Url
238 * A handle to an http upload/download object
239 * @ingroup Ecore_Con_Url_Group
240 */
241typedef struct _Ecore_Con_Url Ecore_Con_Url;
242
243
244/**
245 * @addtogroup Ecore_Con_Events_Group Events
246 * @{
247 */
248
249/**
250 * @typedef Ecore_Con_Event_Client_Add
251 * Used as the @p data param for the corresponding event
252 */
253typedef struct _Ecore_Con_Event_Client_Add Ecore_Con_Event_Client_Add;
254
255/**
256 * @typedef Ecore_Con_Event_Client_Upgrade
257 * Used as the @p data param for the corresponding event
258 * @since 1.1
259 */
260typedef struct _Ecore_Con_Event_Client_Upgrade Ecore_Con_Event_Client_Upgrade;
261
262/**
263 * @typedef Ecore_Con_Event_Client_Del
264 * Used as the @p data param for the corresponding event
265 */
266typedef struct _Ecore_Con_Event_Client_Del Ecore_Con_Event_Client_Del;
267
268/**
269 * @typedef Ecore_Con_Event_Client_Error
270 * Used as the @p data param for the corresponding event
271 * @since 1.1
272 */
273typedef struct _Ecore_Con_Event_Client_Error Ecore_Con_Event_Client_Error;
274
275/**
276 * @typedef Ecore_Con_Event_Server_Add
277 * Used as the @p data param for the corresponding event
278 */
279typedef struct _Ecore_Con_Event_Server_Add Ecore_Con_Event_Server_Add;
280
281/**
282 * @typedef Ecore_Con_Event_Server_Upgrade
283 * Used as the @p data param for the corresponding event
284 * @since 1.1
285 */
286typedef struct _Ecore_Con_Event_Server_Upgrade Ecore_Con_Event_Server_Upgrade;
287
288/**
289 * @typedef Ecore_Con_Event_Server_Del
290 * Used as the @p data param for the corresponding event
291 */
292typedef struct _Ecore_Con_Event_Server_Del Ecore_Con_Event_Server_Del;
293
294/**
295 * @typedef Ecore_Con_Event_Server_Error
296 * Used as the @p data param for the corresponding event
297 * @since 1.1
298 */
299typedef struct _Ecore_Con_Event_Server_Error Ecore_Con_Event_Server_Error;
300
301/**
302 * @typedef Ecore_Con_Event_Client_Data
303 * Used as the @p data param for the corresponding event
304 */
305typedef struct _Ecore_Con_Event_Client_Data Ecore_Con_Event_Client_Data;
306
307/**
308 * @typedef Ecore_Con_Event_Server_Data
309 * Used as the @p data param for the corresponding event
310 */
311typedef struct _Ecore_Con_Event_Server_Data Ecore_Con_Event_Server_Data;
312
313/**
314 * @typedef Ecore_Con_Event_Client_Write
315 * Used as the @p data param for the corresponding event
316 * @since 1.1
317 */
318typedef struct _Ecore_Con_Event_Client_Write Ecore_Con_Event_Client_Write;
319
320/**
321 * @typedef Ecore_Con_Event_Server_Write
322 * Used as the @p data param for the corresponding event
323 * @since 1.1
324 */
325typedef struct _Ecore_Con_Event_Server_Write Ecore_Con_Event_Server_Write;
326
327/**
328 * @typedef Ecore_Con_Event_Url_Data
329 * Used as the @p data param for the corresponding event
330 * @ingroup Ecore_Con_Url_Group
331 */
332typedef struct _Ecore_Con_Event_Url_Data Ecore_Con_Event_Url_Data;
333
334/**
335 * @typedef Ecore_Con_Event_Url_Complete
336 * Used as the @p data param for the corresponding event
337 * @ingroup Ecore_Con_Url_Group
338 */
339typedef struct _Ecore_Con_Event_Url_Complete Ecore_Con_Event_Url_Complete;
340
341/**
342 * @typedef Ecore_Con_Event_Url_Progress
343 * Used as the @p data param for the corresponding event
344 * @ingroup Ecore_Con_Url_Group
345 */
346typedef struct _Ecore_Con_Event_Url_Progress Ecore_Con_Event_Url_Progress;
347
348/**
349 * @struct _Ecore_Con_Event_Client_Add
350 * Used as the @p data param for the @ref ECORE_CON_EVENT_CLIENT_ADD event
351 */
352struct _Ecore_Con_Event_Client_Add
353{
354 Ecore_Con_Client *client; /** the client that connected */
355};
356
357/**
358 * @struct _Ecore_Con_Event_Client_Upgrade
359 * Used as the @p data param for the @ref ECORE_CON_EVENT_CLIENT_UPGRADE event
360 * @since 1.1
361 */
362struct _Ecore_Con_Event_Client_Upgrade
363{
364 Ecore_Con_Client *client; /** the client that completed handshake */
365};
366
367/**
368 * @struct _Ecore_Con_Event_Client_Del
369 * Used as the @p data param for the @ref ECORE_CON_EVENT_CLIENT_DEL event
370 */
371struct _Ecore_Con_Event_Client_Del
372{
373 Ecore_Con_Client *client; /** the client that was lost */
374};
375
376/**
377 * @struct _Ecore_Con_Event_Client_Error
378 * Used as the @p data param for the @ref ECORE_CON_EVENT_CLIENT_ERROR event
379 */
380struct _Ecore_Con_Event_Client_Error
381{
382 Ecore_Con_Client *client; /** the client for which an error occurred */
383 char *error; /**< the error string describing what happened */
384};
385
386/**
387 * @struct _Ecore_Con_Event_Server_Add
388 * Used as the @p data param for the @ref ECORE_CON_EVENT_SERVER_ADD event
389 */
390struct _Ecore_Con_Event_Server_Add
391{
392 Ecore_Con_Server *server; /** the server that was connected to */
393};
394
395/**
396 * @struct _Ecore_Con_Event_Server_Upgrade
397 * Used as the @p data param for the @ref ECORE_CON_EVENT_SERVER_UPGRADE event
398 * @since 1.1
399 */
400struct _Ecore_Con_Event_Server_Upgrade
401{
402 Ecore_Con_Server *server; /** the server that was connected to */
403};
404
405/**
406 * @struct _Ecore_Con_Event_Server_Del
407 * Used as the @p data param for the @ref ECORE_CON_EVENT_SERVER_DEL event
408 */
409struct _Ecore_Con_Event_Server_Del
410{
411 Ecore_Con_Server *server; /** the client that was lost */
412};
413
414/**
415 * @struct _Ecore_Con_Event_Server_Error
416 * Used as the @p data param for the @ref ECORE_CON_EVENT_SERVER_ERROR event
417 */
418struct _Ecore_Con_Event_Server_Error
419{
420 Ecore_Con_Server *server; /** the server for which an error occurred */
421 char *error; /**< the error string describing what happened */
422};
423
424/**
425 * @struct _Ecore_Con_Event_Client_Data
426 * Used as the @p data param for the @ref ECORE_CON_EVENT_CLIENT_DATA event
427 */
428struct _Ecore_Con_Event_Client_Data
429{
430 Ecore_Con_Client *client; /**< the client that connected */
431 void *data; /**< the data that the client sent */
432 int size; /**< the length of the data sent */
433};
434
435/**
436 * @struct _Ecore_Con_Event_Server_Data
437 * Used as the @p data param for the @ref ECORE_CON_EVENT_SERVER_DATA event
438 */
439struct _Ecore_Con_Event_Server_Data
440{
441 Ecore_Con_Server *server; /**< the server that was connected to */
442 void *data; /**< the data that the server sent */
443 int size; /**< the length of the data sent */
444};
445
446/**
447 * @struct _Ecore_Con_Event_Client_Write
448 * Used as the @p data param for the @ref ECORE_CON_EVENT_CLIENT_WRITE event
449 */
450struct _Ecore_Con_Event_Client_Write
451{
452 Ecore_Con_Client *client; /**< the client that connected */
453 int size; /**< the length of the data sent */
454};
455
456/**
457 * @struct _Ecore_Con_Event_Server_Write
458 * Used as the @p data param for the @ref ECORE_CON_EVENT_SERVER_WRITE event
459 */
460struct _Ecore_Con_Event_Server_Write
461{
462 Ecore_Con_Server *server; /**< the server that was connected to */
463 int size; /**< the length of the data sent */
464};
465
466/**
467 * @struct _Ecore_Con_Event_Url_Data
468 * Used as the @p data param for the @ref ECORE_CON_EVENT_URL_DATA event
469 * @ingroup Ecore_Con_Url_Group
470 */
471struct _Ecore_Con_Event_Url_Data
472{
473 Ecore_Con_Url *url_con; /**< a pointer to the connection object */
474 int size; /**< the size of the current received data (in bytes) */
475 unsigned char data[1]; /**< the data received on this event */
476};
477
478/**
479 * @struct _Ecore_Con_Event_Url_Complete
480 * Used as the @p data param for the @ref ECORE_CON_EVENT_URL_COMPLETE event
481 * @ingroup Ecore_Con_Url_Group
482 */
483struct _Ecore_Con_Event_Url_Complete
484{
485 Ecore_Con_Url *url_con; /**< a pointer to the connection object */
486 int status; /**< HTTP status code of the operation (200, 404, 401, etc.) */
487};
488
489/**
490 * @struct _Ecore_Con_Event_Url_Progress
491 * Used as the @p data param for the @ref ECORE_CON_EVENT_URL_PROGRESS event
492 * @ingroup Ecore_Con_Url_Group
493 */
494struct _Ecore_Con_Event_Url_Progress
495{
496 Ecore_Con_Url *url_con; /**< a pointer to the connection object */
497 struct
498 {
499 double total; /**< total size of the downloading data (in bytes) */
500 double now; /**< current size of the downloading data (in bytes) */
501 } down; /**< download info */
502 struct
503 {
504 double total; /**< total size of the uploading data (in bytes) */
505 double now; /**< current size of the uploading data (in bytes) */
506 } up; /**< upload info */
507};
508
509/** A client has connected to the server */
510EAPI extern int ECORE_CON_EVENT_CLIENT_ADD;
511/** A client has disconnected from the server */
512EAPI extern int ECORE_CON_EVENT_CLIENT_DEL;
513/** A client experienced an error
514 * @since 1.1
515 */
516EAPI extern int ECORE_CON_EVENT_CLIENT_ERROR;
517/** A client connection has been upgraded to SSL
518 * @since 1.1
519 */
520EAPI extern int ECORE_CON_EVENT_CLIENT_UPGRADE;
521/** A server was created */
522EAPI extern int ECORE_CON_EVENT_SERVER_ADD;
523/** A server connection was lost */
524EAPI extern int ECORE_CON_EVENT_SERVER_DEL;
525/** A server experienced an error
526 * @since 1.1
527 */
528EAPI extern int ECORE_CON_EVENT_SERVER_ERROR;
529/** A server connection has been upgraded to SSL
530 * @since 1.1
531 */
532EAPI extern int ECORE_CON_EVENT_SERVER_UPGRADE;
533/** A server connection has sent data to its client
534 * @since 1.1
535 */
536EAPI extern int ECORE_CON_EVENT_CLIENT_WRITE;
537/** A server connection object has sent data
538 * @since 1.1
539 */
540EAPI extern int ECORE_CON_EVENT_SERVER_WRITE;
541/** A client connected to the server has sent data */
542EAPI extern int ECORE_CON_EVENT_CLIENT_DATA;
543/** A server connection object has data */
544EAPI extern int ECORE_CON_EVENT_SERVER_DATA;
545/** A URL object has data */
546EAPI extern int ECORE_CON_EVENT_URL_DATA;
547/** A URL object has completed its transfer to and from the server and can be reused */
548EAPI extern int ECORE_CON_EVENT_URL_COMPLETE;
549/** A URL object has made progress in its transfer */
550EAPI extern int ECORE_CON_EVENT_URL_PROGRESS;
551
552/**
553 * @}
554 */
555
556/**
557 * @defgroup Ecore_Con_Lib_Group Ecore Connection Library Functions
558 *
559 * Utility functions that set up and shut down the Ecore Connection
560 * library.
561 *
562 * There's also ecore_con_lookup() that can be used to make simple asynchronous
563 * DNS lookups.
564 *
565 * A simple example of how to use these functions:
566 * @li @ref ecore_con_lookup_example_c
567 *
568 * @{
569 */
570
571/**
572 * @typedef Ecore_Con_Dns_Cb
573 * A callback type for use with @ref ecore_con_lookup.
574 */
575typedef void (*Ecore_Con_Dns_Cb)(const char *canonname,
576 const char *ip,
577 struct sockaddr *addr,
578 int addrlen,
579 void *data);
580
581/**
582 * @typedef Ecore_Con_Type
583 * @enum _Ecore_Con_Type
584 * Types for an ecore_con client/server object. A correct way to set this type is
585 * with an ECORE_CON_$TYPE, optionally OR'ed with an ECORE_CON_$USE if encryption is desired,
586 * and LOAD_CERT if the previously loaded certificate should be used.
587 * @code
588 * ECORE_CON_REMOTE_TCP | ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT
589 * @endcode
590 * @ingroup Ecore_Con_Server_Group
591 */
592typedef enum _Ecore_Con_Type
593{
594 /** Socket in ~/.ecore */
595 ECORE_CON_LOCAL_USER = 0,
596 /** Socket in /tmp */
597 ECORE_CON_LOCAL_SYSTEM = 1,
598 /** Abstract socket */
599 ECORE_CON_LOCAL_ABSTRACT = 2,
600 /** Remote server using TCP */
601 ECORE_CON_REMOTE_TCP = 3,
602 /** Remote multicast server */
603 ECORE_CON_REMOTE_MCAST = 4,
604 /** Remote server using UDP */
605 ECORE_CON_REMOTE_UDP = 5,
606 /** Remote broadcast using UDP */
607 ECORE_CON_REMOTE_BROADCAST = 6,
608 ECORE_CON_REMOTE_NODELAY = 7,
609 /** Use SSL2: UNSUPPORTED. **/
610 ECORE_CON_USE_SSL2 = (1 << 4),
611 /** Use SSL3 */
612 ECORE_CON_USE_SSL3 = (1 << 5),
613 /** Use TLS */
614 ECORE_CON_USE_TLS = (1 << 6),
615 /** Use both TLS and SSL3 */
616 ECORE_CON_USE_MIXED = ECORE_CON_USE_SSL3 | ECORE_CON_USE_TLS,
617 /** Attempt to use the loaded certificate */
618 ECORE_CON_LOAD_CERT = (1 << 7)
619} Ecore_Con_Type;
620
621/**
622 * Initialises the Ecore_Con library.
623 * @return Number of times the library has been initialised without being
624 * shut down.
625 *
626 * @note This function already calls ecore_init() internally, so you don't need
627 * to call it explicitly.
628 */
629EAPI int ecore_con_init(void);
630
631/**
632 * Shuts down the Ecore_Con library.
633 * @return Number of times the library has been initialised without being
634 * shut down.
635 * @note This function already calls ecore_shutdown() internally, so you don't
636 * need to call it explicitly unless you called ecore_init() explicitly too.
637 */
638EAPI int ecore_con_shutdown(void);
639
640/**
641 * Do an asynchronous DNS lookup.
642 *
643 * @param name IP address or server name to translate.
644 * @param done_cb Callback to notify when done.
645 * @param data User data to be given to done_cb.
646 * @return EINA_TRUE if the request did not fail to be set up, EINA_FALSE if it
647 * failed.
648 *
649 * This function performs a DNS lookup on the hostname specified by @p name,
650 * then calls @p done_cb with the result and the @p data given as parameter.
651 * The result will be given to the @p done_cb as follows:
652 * @li @c canonname - the canonical name of the address
653 * @li @c ip - the resolved ip address
654 * @li @c addr - a pointer to the socket address
655 * @li @c addrlen - the length of the socket address, in bytes
656 * @li @c data - the data pointer given as parameter to ecore_con_lookup()
657 */
658EAPI Eina_Bool ecore_con_lookup(const char *name,
659 Ecore_Con_Dns_Cb done_cb,
660 const void *data);
661
662/**
663 * @}
664 */
665
666/**
667 * @defgroup Ecore_Con_SSL_Group Ecore Connection SSL Functions
668 *
669 * @{
670 */
671EAPI int ecore_con_ssl_available_get(void);
672EAPI Eina_Bool ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr, const char *cert);
673EAPI Eina_Bool ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr, const char *key_file);
674EAPI Eina_Bool ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr, const char *crl_file);
675EAPI Eina_Bool ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr, const char *ca_file);
676EAPI void ecore_con_ssl_server_verify(Ecore_Con_Server *svr);
677EAPI void ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr);
678EAPI Eina_Bool ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type compl_type);
679EAPI Eina_Bool ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type compl_type);
680
681/**
682 * @}
683 */
684
685/**
686 * @defgroup Ecore_Con_Server_Group Ecore Connection Server Functions
687 *
688 * This group of functions is applied to an @ref Ecore_Con_Server object. It
689 * doesn't mean that they should be used in the server application, but on the
690 * server object. In fact, most of them should be used in the client
691 * application, when retrieving information or sending data.
692 *
693 * Setting up a server is very simple: you just need to start it with
694 * ecore_con_server_add() and setup some callbacks to the events
695 * #ECORE_CON_EVENT_CLIENT_ADD, #ECORE_CON_EVENT_CLIENT_DEL and
696 * #ECORE_CON_EVENT_CLIENT_DATA, that will be called when a client is
697 * communicating with the server:
698 *
699 * @code
700 * if (!(svr = ecore_con_server_add(ECORE_CON_REMOTE_TCP, "127.0.0.1", 8080, NULL)))
701 * exit(1);
702 *
703 * ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, _add_cb, NULL);
704 * ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, _del_cb, NULL);
705 * ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, _data_cb, NULL);
706 *
707 * ecore_main_loop_begin();
708 * @endcode
709 *
710 * The function ecore_con_server_connect() can be used to write a client that
711 * connects to a server. The resulting code will be very similar to the server
712 * code:
713 *
714 * @code
715 * if (!(svr = ecore_con_server_connect(ECORE_CON_REMOTE_TCP, "127.0.0.1", 8080, NULL)))
716 * exit(1);
717 *
718 * ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, _add_cb, NULL);
719 * ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, _del_cb, NULL);
720 * ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, _data_cb, NULL);
721 *
722 * ecore_main_loop_begin();
723 * @endcode
724 *
725 * After these two pieces of code are executed, respectively, in the server and
726 * client code, the server will be up and running and the client will try to
727 * connect to it. The connection, with its subsequent messages being sent from
728 * server to client and client to server, can be represented in the following
729 * sequence diagram:
730 *
731 * @htmlonly
732 * <img src="ecore_con-client-server.png" style="max-width: 400px"/>
733 * <a href="ecore_con-client-server.png">Full size</a>
734 * @endhtmlonly
735 *
736 * @image rtf ecore_con-client-server.png
737 * @image latex ecore_con-client-server.eps width=\textwidth
738 *
739 * Please notice the important difference between these two codes: the first is
740 * used for writing a @b server, while the second should be used for writing a
741 * @b client.
742 *
743 * A reference for the @c client functions can be found at @ref
744 * Ecore_Con_Client_Group.
745 *
746 * Examples of usage for this API can be found here:
747 * @li @ref ecore_con_server_simple_example_c
748 * @li @ref ecore_con_client_simple_example_c
749 *
750 * @{
751 */
752
753/**
754 * Creates a server to listen for connections.
755 *
756 * @param type The connection type.
757 * @param name Name to associate with the socket. It is used when
758 * generating the socket name of a Unix socket, or for
759 * determining what host to listen on for TCP sockets.
760 * @c NULL will not be accepted.
761 * @param port Number to identify socket. When a Unix socket is used,
762 * it becomes part of the socket name. When a TCP socket
763 * is used, it is used as the TCP port.
764 * @param data Data to associate with the created Ecore_Con_Server
765 * object.
766 * @return A new Ecore_Con_Server.
767 *
768 * The socket on which the server listens depends on the connection
769 * type:
770 * @li If @a type is @c ECORE_CON_LOCAL_USER, the server will listen on
771 * the Unix socket "~/.ecore/[name]/[port]".
772 * @li If @a type is @c ECORE_CON_LOCAL_SYSTEM, the server will listen
773 * on Unix socket "/tmp/.ecore_service|[name]|[port]".
774 * @li If @a type is @c ECORE_CON_REMOTE_TCP, the server will listen
775 * on TCP port @c port.
776 *
777 * More information about the @p type can be found at @ref _Ecore_Con_Type.
778 *
779 * The @p data parameter can be fetched later using ecore_con_server_data_get()
780 * or changed with ecore_con_server_data_set().
781 */
782EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type,
783 const char *name, int port,
784 const void *data);
785
786/**
787 * Creates a connection to the specified server and returns an associated object.
788 *
789 * @param type The connection type.
790 * @param name Name used when determining what socket to connect to.
791 * It is used to generate the socket name when the socket
792 * is a Unix socket. It is used as the hostname when
793 * connecting with a TCP socket.
794 * @param port Number to identify the socket to connect to. Used when
795 * generating the socket name for a Unix socket, or as the
796 * TCP port when connecting to a TCP socket.
797 * @param data Data to associate with the created Ecore_Con_Server
798 * object.
799 * @return A new Ecore_Con_Server.
800 *
801 * The socket to which the connection is made depends on the connection type:
802 * @li If @a type is @c ECORE_CON_LOCAL_USER, the function will
803 * connect to the server at the Unix socket
804 * "~/.ecore/[name]/[port]".
805 * @li If @a type is @c ECORE_CON_LOCAL_SYSTEM, the function will
806 * connect to the server at the Unix socket
807 * "/tmp/.ecore_service|[name]|[port]".
808 * @li If @a type is @c ECORE_CON_REMOTE_TCP, the function will
809 * connect to the server at the TCP port "[name]:[port]".
810 *
811 * More information about the @p type can be found at @ref _Ecore_Con_Type.
812 *
813 * This function won't block. It will either succeed, or fail due to invalid
814 * parameters, failed memory allocation, etc., returning @c NULL on that case.
815 *
816 * However, even if this call returns a valid @ref Ecore_Con_Server, the
817 * connection will only be successfully completed if an event of type
818 * #ECORE_CON_EVENT_SERVER_ADD is received. If it fails to complete, an
819 * #ECORE_CON_EVENT_SERVER_DEL will be received.
820 *
821 * The @p data parameter can be fetched later using ecore_con_server_data_get()
822 * or changed with ecore_con_server_data_set().
823 */
824EAPI Ecore_Con_Server *ecore_con_server_connect(Ecore_Con_Type type,
825 const char *name, int port,
826 const void *data);
827/**
828 * Closes the connection and frees the given server.
829 *
830 * @param svr The given server.
831 * @return Data associated with the server when it was created.
832 *
833 * All the clients connected to this server will be disconnected.
834 *
835 * @see ecore_con_server_add, ecore_con_server_connect
836 */
837EAPI void * ecore_con_server_del(Ecore_Con_Server *svr);
838
839/**
840 * Retrieves the data associated with the given server.
841 *
842 * @param svr The given server.
843 * @return The associated data.
844 *
845 * @see ecore_con_server_data_set()
846 */
847EAPI void * ecore_con_server_data_get(Ecore_Con_Server *svr);
848/**
849 * Sets the data associated with the given server.
850 *
851 * @param svr The given server.
852 * @param data The data to associate with @p svr
853 * @return The previously associated data, if any.
854 *
855 * @see ecore_con_server_data_get()
856 */
857EAPI void * ecore_con_server_data_set(Ecore_Con_Server *svr,
858 void *data);
859/**
860 * Retrieves whether the given server is currently connected.
861 *
862 * @param svr The given server.
863 * @return #EINA_TRUE if the server is connected. #EINA_FALSE otherwise.
864 */
865EAPI Eina_Bool ecore_con_server_connected_get(Ecore_Con_Server *svr);
866/**
867 * Retrieves the current list of clients.
868 *
869 * @param svr The given server.
870 * @return The list of clients on this server.
871 *
872 * Each node in the returned list points to an @ref Ecore_Con_Client. This list
873 * cannot be modified or freed. It can also change if new clients are connected
874 * or disconnected, and will become invalid when the server is deleted/freed.
875 */
876EAPI const Eina_List * ecore_con_server_clients_get(Ecore_Con_Server *svr);
877
878/**
879 * Retrieves the name of server.
880 *
881 * @param svr The given server.
882 * @return The name of the server.
883 *
884 * The name returned is the name used to connect on this server.
885 */
886EAPI const char * ecore_con_server_name_get(Ecore_Con_Server *svr);
887
888/**
889 * Retrieves the server port in use.
890 *
891 * @param svr The given server.
892 * @return The server port in use.
893 *
894 * The port where the server is listening for connections.
895 */
896EAPI int ecore_con_server_port_get(Ecore_Con_Server *svr);
897/**
898 * @brief Check how long a server has been connected
899 *
900 * @param svr The server to check
901 * @return The total time, in seconds, that the server has been
902 * connected/running
903 *
904 * This function is used to find out the time that has been elapsed since
905 * ecore_con_server_add() succeeded.
906 */
907EAPI double ecore_con_server_uptime_get(Ecore_Con_Server *svr);
908/**
909 * Sends the given data to the given server.
910 *
911 * @param svr The given server.
912 * @param data The given data.
913 * @param size Length of the data, in bytes, to send.
914 * @return The number of bytes sent. @c 0 will be returned if there is an
915 * error.
916 *
917 * This function will send the given data to the server as soon as the program
918 * is back to the main loop. Thus, this function returns immediately
919 * (non-blocking). If the data needs to be sent @b now, call
920 * ecore_con_server_flush() after this one.
921 *
922 * @see ecore_con_client_send()
923 * @see ecore_con_server_flush()
924 */
925EAPI int ecore_con_server_send(Ecore_Con_Server *svr,
926 const void *data,
927 int size);
928/**
929 * Sets a limit on the number of clients that can be handled concurrently
930 * by the given server, and a policy on what to do if excess clients try to
931 * connect.
932 *
933 * @param svr The given server.
934 * @param client_limit The maximum number of clients to handle
935 * concurrently. -1 means unlimited (default). 0
936 * effectively disables the server.
937 * @param reject_excess_clients Set to 1 to automatically disconnect
938 * excess clients as soon as they connect if you are
939 * already handling client_limit clients. Set to 0
940 * (default) to just hold off on the "accept()"
941 * system call until the number of active clients
942 * drops. This causes the kernel to queue up to 4096
943 * connections (or your kernel's limit, whichever is
944 * lower).
945 *
946 * Beware that if you set this once ecore is already running, you may
947 * already have pending CLIENT_ADD events in your event queue. Those
948 * clients have already connected and will not be affected by this call.
949 * Only clients subsequently trying to connect will be affected.
950 */
951EAPI void ecore_con_server_client_limit_set(Ecore_Con_Server *svr,
952 int client_limit,
953 char reject_excess_clients);
954/**
955 * Gets the IP address of a server that has been connected to.
956 *
957 * @param svr The given server.
958 * @return A pointer to an internal string that contains the IP address of
959 * the connected server in the form "XXX.YYY.ZZZ.AAA" IP notation.
960 * This string should not be modified or trusted to stay valid after
961 * deletion for the @p svr object. If no IP is known NULL is returned.
962 */
963EAPI const char * ecore_con_server_ip_get(Ecore_Con_Server *svr);
964/**
965 * Flushes all pending data to the given server.
966 *
967 * @param svr The given server.
968 *
969 * This function will block until all data is sent to the server.
970 *
971 * @see ecore_con_server_send()
972 * @see ecore_con_client_flush()
973 */
974EAPI void ecore_con_server_flush(Ecore_Con_Server *svr);
975/**
976 * Set the default time after which an inactive client will be disconnected
977 *
978 * @param svr The server object
979 * @param timeout The timeout, in seconds, to disconnect after
980 *
981 * This function is used by the server to set the default idle timeout on
982 * clients. If the any of the clients becomes idle for a time higher than this
983 * value, it will be disconnected. A value of < 1 disables the idle timeout.
984 *
985 * This timeout is not affected by the one set by
986 * ecore_con_client_timeout_set(). A client will be disconnected whenever the
987 * client or the server timeout is reached. That means, the lower timeout value
988 * will be used for that client if ecore_con_client_timeout_set() is used on it.
989 *
990 * @see ecore_con_server_timeout_get()
991 * @see ecore_con_client_timeout_set()
992 */
993EAPI void ecore_con_server_timeout_set(Ecore_Con_Server *svr, double timeout);
994/**
995 * Get the default time after which an inactive client will be disconnected
996 *
997 * @param svr The server object
998 * @return The timeout, in seconds, to disconnect after
999 *
1000 * This function is used to get the idle timeout for clients. A value of < 1
1001 * means the idle timeout is disabled.
1002 *
1003 * @see ecore_con_server_timeout_set()
1004 * @see ecore_con_client_timeout_get()
1005 */
1006EAPI double ecore_con_server_timeout_get(Ecore_Con_Server *svr);
1007
1008/**
1009 * Get the fd that the server is connected to
1010 *
1011 * @param svr The server object
1012 * @return The fd, or -1 on failure
1013 *
1014 * This function returns the fd which is used by the underlying server connection.
1015 * It should not be tampered with unless you REALLY know what you are doing.
1016 * @note This function is only valid for servers created with ecore_con_server_connect()
1017 * @warning Seriously. Don't use this unless you know what you are doing.
1018 * @since 1.1
1019 */
1020EAPI int ecore_con_server_fd_get(Ecore_Con_Server *svr);
1021
1022/**
1023 * Get the fd that the client is connected to
1024 *
1025 * @param cl The client object
1026 * @return The fd, or -1 on failure
1027 *
1028 * This function returns the fd which is used by the underlying client connection.
1029 * It should not be tampered with unless you REALLY know what you are doing.
1030 * @since 1.1
1031 */
1032EAPI int ecore_con_client_fd_get(Ecore_Con_Client *cl);
1033/**
1034 * @}
1035 */
1036
1037/**
1038 * @defgroup Ecore_Con_Client_Group Ecore Connection Client Functions
1039 *
1040 * Functions to communicate with and/or set options on a client.
1041 *
1042 * This set of functions, as explained in @ref Ecore_Con_Server_Group, is used
1043 * to send data to a client, or to set options and get information about this
1044 * client. Most of them should be used on the server, applied on the client
1045 * object.
1046 *
1047 * If you need to implement a client, the way to connect to a server is
1048 * described in @ref Ecore_Con_Server_Group.
1049 *
1050 * An example of usage of these functions can be found at:
1051 * @li @ref ecore_con_client_simple_example_c
1052 *
1053 * @{
1054 */
1055
1056/**
1057 * Sends the given data to the given client.
1058 *
1059 * @param cl The given client.
1060 * @param data The given data.
1061 * @param size Length of the data, in bytes, to send.
1062 * @return The number of bytes sent. @c 0 will be returned if there is an
1063 * error.
1064 *
1065 * This function will send the given data to the client as soon as the program
1066 * is back to the main loop. Thus, this function returns immediately
1067 * (non-blocking). If the data needs to be sent @b now, call
1068 * ecore_con_client_flush() after this one.
1069 *
1070 * @see ecore_con_server_send()
1071 * @see ecore_con_client_flush()
1072 */
1073EAPI int ecore_con_client_send(Ecore_Con_Client *cl,
1074 const void *data,
1075 int size);
1076/**
1077 * Retrieves the server representing the socket the client has
1078 * connected to.
1079 *
1080 * @param cl The given client.
1081 * @return The server that the client connected to.
1082 */
1083EAPI Ecore_Con_Server *ecore_con_client_server_get(Ecore_Con_Client *cl);
1084/**
1085 * Closes the connection and frees memory allocated to the given client.
1086 *
1087 * @param cl The given client.
1088 * @return Data associated with the client.
1089 */
1090EAPI void * ecore_con_client_del(Ecore_Con_Client *cl);
1091/**
1092 * Sets the data associated with the given client to @p data.
1093 *
1094 * @param cl The given client.
1095 * @param data What to set the data to.
1096 */
1097EAPI void ecore_con_client_data_set(Ecore_Con_Client *cl,
1098 const void *data);
1099/**
1100 * Retrieves the data associated with the given client.
1101 *
1102 * @param cl The given client.
1103 * @return The data associated with @p cl.
1104 */
1105EAPI void * ecore_con_client_data_get(Ecore_Con_Client *cl);
1106
1107/**
1108 * Gets the IP address of a client that has connected.
1109 *
1110 * @param cl The given client.
1111 * @return A pointer to an internal string that contains the IP address of
1112 * the connected client in the form "XXX.YYY.ZZZ.AAA" IP notation.
1113 *
1114 * The returned string should not be modified, freed or trusted to stay valid
1115 * after deletion for the @p cl object. If no IP is known NULL is returned.
1116 */
1117EAPI const char * ecore_con_client_ip_get(Ecore_Con_Client *cl);
1118/**
1119 * Flushes all pending data to the given client.
1120 *
1121 * @param cl The given client.
1122 *
1123 * This function will block until all data is sent to the server.
1124 *
1125 * @see ecore_con_client_send()
1126 * @see ecore_con_server_flush()
1127 */
1128EAPI void ecore_con_client_flush(Ecore_Con_Client *cl);
1129/**
1130 * @brief Check how long a client has been connected
1131 *
1132 * @param cl The client to check
1133 * @return The total time, in seconds, that the client has been connected to
1134 * the server
1135 *
1136 * This function is used to find out how long a client has been connected for.
1137 */
1138EAPI double ecore_con_client_uptime_get(Ecore_Con_Client *cl);
1139/**
1140 * Get the default time after which the client will be disconnected when
1141 * inactive
1142 *
1143 * @param cl The client object
1144 * @return The timeout, in seconds, to disconnect after
1145 *
1146 * This function is used to get the idle timeout for a client. A value of < 1
1147 * means the idle timeout is disabled.
1148 *
1149 * @see ecore_con_client_timeout_set()
1150 */
1151EAPI double ecore_con_client_timeout_get(Ecore_Con_Client *cl);
1152/**
1153 * Set the time after which the client will be disconnected when inactive
1154 *
1155 * @param cl The client object
1156 * @param timeout The timeout, in seconds, to disconnect after
1157 *
1158 * This function is used by the server to set the idle timeout on a specific
1159 * client. If the client becomes idle for a time higher than this value, it will
1160 * be disconnected. A value of < 1 disables the idle timeout.
1161 *
1162 * This timeout is not affected by the one set by
1163 * ecore_con_server_timeout_set(). A client will be disconnected whenever the
1164 * client or the server timeout is reached. That means, the lower timeout value
1165 * will be used for that client if ecore_con_server_timeout_set() is used on the
1166 * server.
1167 *
1168 * @see ecore_con_client_timeout_get()
1169 * @see ecore_con_server_timeout_set()
1170 */
1171EAPI void ecore_con_client_timeout_set(Ecore_Con_Client *cl, double timeout);
1172/**
1173 * Returns whether the client is still connected
1174 *
1175 * @param cl The given client.
1176 * @return #EINA_TRUE if connected, else EINA_FALSE
1177 */
1178EAPI Eina_Bool ecore_con_client_connected_get(Ecore_Con_Client *cl);
1179/**
1180 * @brief Return the port that the client has connected to
1181 *
1182 * @param cl The client
1183 * @return The port that @p cl has connected to, or -1 on error
1184 * Use this function to return the port on which a given client has connected.
1185 */
1186EAPI int ecore_con_client_port_get(Ecore_Con_Client *cl);
1187
1188/**
1189 * @}
1190 */
1191
1192/**
1193 * @defgroup Ecore_Con_Url_Group Ecore URL Connection Functions
1194 *
1195 * Utility functions that set up, use and shut down the Ecore URL
1196 * Connection library.
1197 *
1198 * These functions are a shortcut to make it easy to perform http requests
1199 * (POST, GET, etc).
1200 *
1201 * Brief usage:
1202 * 1. Create an Ecore_Con_Url object with ecore_con_url_new(url);
1203 * 2. Register to receive the #ECORE_CON_EVENT_URL_COMPLETE event
1204 * (and optionally the #ECORE_CON_EVENT_URL_DATA and
1205 * #ECORE_CON_EVENT_URL_PROGRESS event to receive
1206 * the response, e.g. for HTTP/FTP downloads)
1207 * 3. Perform the operation with ecore_con_url_get(...);
1208 *
1209 * Note that it is good to reuse @ref Ecore_Con_Url objects wherever possible,
1210 * but bear in mind that each one can only perform one operation at a time. You
1211 * need to wait for the #ECORE_CON_EVENT_URL_COMPLETE event before re-using or
1212 * destroying the object.
1213 *
1214 * If it's necessary to change the @ref Ecore_Con_Url object url, use
1215 * ecore_con_url_url_set().
1216 *
1217 * Simple Usage 1 (HTTP GET):
1218 * @code
1219 * ecore_con_url_url_set(url_con, "http://www.google.com");
1220 * ecore_con_url_get(url_con);
1221 * @endcode
1222 *
1223 * Simple usage 2 (HTTP POST):
1224 * @code
1225 * ecore_con_url_url_set(url_con, "http://www.example.com/post_handler.cgi");
1226 * ecore_con_url_post(url_con, data, data_length, "multipart/form-data");
1227 * @endcode
1228 *
1229 * Simple Usage 3 (FTP download):
1230 * @code
1231 * fd = creat(filename, 0644)
1232 * ecore_con_url_url_set(url_con, "ftp://ftp.example.com/pub/myfile");
1233 * ecore_con_url_fd_set(url_con, fd);
1234 * ecore_con_url_get(url_con);
1235 * @endcode
1236 *
1237 * Simple Usage 4 (FTP upload as ftp://ftp.example.com/file):
1238 * @code
1239 * ecore_con_url_url_set(url_con, "ftp://ftp.example.com");
1240 * ecore_con_url_ftp_upload(url_con, "/tmp/file", "user", "pass", NULL);
1241 * @endcode
1242 *
1243 * Simple Usage 5 (FTP upload as ftp://ftp.example.com/dir/file):
1244 * @code
1245 * ecore_con_url_url_set(url_con, "ftp://ftp.example.com");
1246 * ecore_con_url_ftp_upload(url_con, "/tmp/file", "user", "pass","dir");
1247 * @endcode
1248 *
1249 * These are complete examples for the API:
1250 * @li @ref ecore_con_url_download_example.c "Downloading a file"
1251 * @li @ref ecore_con_url_headers_example.c "Setting many options for the
1252 * connection"
1253 *
1254 * @{
1255 */
1256
1257/**
1258 * @typedef Ecore_Con_Url_Time
1259 * @enum _Ecore_Con_Url_Time
1260 * The type of condition to use when making an HTTP request dependent on time,
1261 * so that headers such as "If-Modified-Since" are used.
1262 */
1263typedef enum _Ecore_Con_Url_Time
1264{
1265 /**
1266 * Do not place time restrictions on the HTTP requests.
1267 */
1268 ECORE_CON_URL_TIME_NONE = 0,
1269 /**
1270 * Add the "If-Modified-Since" HTTP header, so that the request is performed
1271 * by the server only if the target has been modified since the time value
1272 * passed to it in the request.
1273 */
1274 ECORE_CON_URL_TIME_IFMODSINCE,
1275 /**
1276 * Add the "If-Unmodified-Since" HTTP header, so that the request is
1277 * performed by the server only if the target has NOT been modified since
1278 * the time value passed to it in the request.
1279 */
1280 ECORE_CON_URL_TIME_IFUNMODSINCE
1281} Ecore_Con_Url_Time;
1282
1283/**
1284 * Initialises the Ecore_Con_Url library.
1285 * @return Number of times the library has been initialised without being
1286 * shut down.
1287 *
1288 * @note This function doesn't call ecore_con_init(). You still need to call it
1289 * explicitly before calling this one.
1290 */
1291EAPI int ecore_con_url_init(void);
1292
1293/**
1294 * Shuts down the Ecore_Con_Url library.
1295 * @return Number of calls that still uses Ecore_Con_Url
1296 *
1297 * @note This function doesn't call ecore_con_shutdown(). You still need to call
1298 * it explicitly after calling this one.
1299 */
1300EAPI int ecore_con_url_shutdown(void);
1301
1302/**
1303 * Enable or disable HTTP 1.1 pipelining.
1304 * @param enable EINA_TRUE will turn it on, EINA_FALSE will disable it.
1305 *
1306 * Pipelining allows to send one request after another one, without having to
1307 * wait for the reply of the first request. The respective replies are received
1308 * in the order that the requests were sent.
1309 *
1310 * Enabling this feature will be valid for all requests done using @c
1311 * ecore_con_url.
1312 *
1313 * See http://en.wikipedia.org/wiki/HTTP_pipelining for more info.
1314 *
1315 * @see ecore_con_url_pipeline_get()
1316 */
1317EAPI void ecore_con_url_pipeline_set(Eina_Bool enable);
1318/**
1319 * Is HTTP 1.1 pipelining enable ?
1320 * @return EINA_TRUE if it is enable.
1321 *
1322 * @see ecore_con_url_pipeline_set()
1323 */
1324EAPI Eina_Bool ecore_con_url_pipeline_get(void);
1325
1326/**
1327 * Creates and initializes a new Ecore_Con_Url connection object.
1328 *
1329 * @param url URL that will receive requests. Can be changed using
1330 * ecore_con_url_url_set.
1331 *
1332 * @return NULL on error, a new Ecore_Con_Url on success.
1333 *
1334 * Creates and initializes a new Ecore_Con_Url connection object that can be
1335 * used for sending requests.
1336 *
1337 * @see ecore_con_url_custom_new()
1338 * @see ecore_con_url_url_set()
1339 */
1340EAPI Ecore_Con_Url * ecore_con_url_new(const char *url);
1341/**
1342 * Creates a custom connection object.
1343 *
1344 * @param url URL that will receive requests
1345 * @param custom_request Custom request (e.g. GET, POST, HEAD, PUT, etc)
1346 *
1347 * @return NULL on error, a new Ecore_Con_Url on success.
1348 *
1349 * Creates and initializes a new Ecore_Con_Url for a custom request (e.g. HEAD,
1350 * SUBSCRIBE and other obscure HTTP requests). This object should be used like
1351 * one created with ecore_con_url_new().
1352 *
1353 * @see ecore_con_url_new()
1354 * @see ecore_con_url_url_set()
1355 */
1356EAPI Ecore_Con_Url * ecore_con_url_custom_new(const char *url,
1357 const char *custom_request);
1358/**
1359 * Destroys a Ecore_Con_Url connection object.
1360 *
1361 * @param url_con Connection object to free.
1362 *
1363 * @see ecore_con_url_new()
1364 */
1365EAPI void ecore_con_url_free(Ecore_Con_Url *url_con);
1366/**
1367 * Sets the URL to send the request to.
1368 *
1369 * @param url_con Connection object through which the request will be sent.
1370 * @param url URL that will receive the request
1371 *
1372 * @return EINA_TRUE on success, EINA_FALSE on error.
1373 *
1374 */
1375EAPI Eina_Bool ecore_con_url_url_set(Ecore_Con_Url *url_con,
1376 const char *url);
1377/**
1378 * Gets the URL to send the request to.
1379 *
1380 * @param url_con Connection object through which the request will be sent.
1381 * @return URL that will receive the request, NULL on failure. URL is stringshared.
1382 * @since 1.1
1383 */
1384EAPI const char *ecore_con_url_url_get(Ecore_Con_Url *url_con);
1385/**
1386 * Associates data with a connection object.
1387 *
1388 * @param url_con Connection object to associate data.
1389 * @param data Data to be set.
1390 *
1391 * Associates data with a connection object, which can be retrieved later with
1392 * ecore_con_url_data_get()).
1393 *
1394 * @see ecore_con_url_data_get()
1395 */
1396EAPI void ecore_con_url_data_set(Ecore_Con_Url *url_con,
1397 void *data);
1398/**
1399 * Retrieves data associated with a Ecore_Con_Url connection object.
1400 *
1401 * @param url_con Connection object to retrieve data from.
1402 *
1403 * @return Data associated with the given object.
1404 *
1405 * Retrieves data associated with a Ecore_Con_Url connection object (previously
1406 * set with ecore_con_url_data_set()).
1407 *
1408 * @see ecore_con_url_data_set()
1409 */
1410EAPI void * ecore_con_url_data_get(Ecore_Con_Url *url_con);
1411/**
1412 * Adds an additional header to the request connection object.
1413 *
1414 * @param url_con Connection object
1415 * @param key Header key
1416 * @param value Header value
1417 *
1418 * Adds an additional header (User-Agent, Content-Type, etc.) to the request
1419 * connection object. This addition will be valid for only one
1420 * ecore_con_url_get() or ecore_con_url_post() call.
1421 *
1422 * Some functions like ecore_con_url_time() also add headers to the request.
1423 *
1424 * @see ecore_con_url_get()
1425 * @see ecore_con_url_post()
1426 * @see ecore_con_url_additional_headers_clear()
1427 */
1428EAPI void ecore_con_url_additional_header_add(Ecore_Con_Url *url_con,
1429 const char *key,
1430 const char *value);
1431/**
1432 * Cleans additional headers.
1433 *
1434 * @param url_con Connection object to clean additional headers.
1435 *
1436 * Cleans additional headers associated with a connection object (previously
1437 * added with ecore_con_url_additional_header_add()).
1438 *
1439 * @see ecore_con_url_additional_header_add()
1440 * @see ecore_con_url_get()
1441 * @see ecore_con_url_post()
1442 */
1443EAPI void ecore_con_url_additional_headers_clear(Ecore_Con_Url *url_con);
1444/**
1445 * Retrieves headers from last request sent.
1446 *
1447 * @param url_con Connection object to retrieve response headers from.
1448 *
1449 * Retrieves a list containing the response headers. This function should be
1450 * used after an ECORE_CON_EVENT_URL_COMPLETE event (headers should normally be
1451 * ready at that time).
1452 *
1453 * @return List of response headers. This list must not be modified by the user.
1454 */
1455EAPI const Eina_List * ecore_con_url_response_headers_get(Ecore_Con_Url *url_con);
1456/**
1457 * Setup a file for receiving response data.
1458 *
1459 * @param url_con Connection object to set file
1460 * @param fd File descriptor associated with the file. A negative value will
1461 * unset any previously set fd.
1462 *
1463 * Sets up a file to have response data written into. Note that
1464 * ECORE_CON_EVENT_URL_DATA events will not be emitted if a file has been set to
1465 * receive the response data.
1466 *
1467 * This call can be used to easily setup a file where the downloaded data will
1468 * be saved.
1469 */
1470EAPI void ecore_con_url_fd_set(Ecore_Con_Url *url_con, int fd);
1471/**
1472 * Retrieves the number of bytes received.
1473 *
1474 * Retrieves the number of bytes received on the last request of the given
1475 * connection object.
1476 *
1477 * @param url_con Connection object which the request was sent on.
1478 *
1479 * @return Number of bytes received on request.
1480 *
1481 * @see ecore_con_url_get()
1482 * @see ecore_con_url_post()
1483 */
1484EAPI int ecore_con_url_received_bytes_get(Ecore_Con_Url *url_con);
1485/**
1486 * Sets url_con to use http auth, with given username and password, "safely" or not.
1487 *
1488 * @param url_con Connection object to perform a request on, previously created
1489 * with ecore_con_url_new() or ecore_con_url_custom_new().
1490 * @param username Username to use in authentication
1491 * @param password Password to use in authentication
1492 * @param safe Whether to use "safer" methods (eg, NOT http basic auth)
1493 *
1494 * @return #EINA_TRUE on success, #EINA_FALSE on error.
1495 *
1496 * ATTENTION: requires libcurl >= 7.19.1 to work, otherwise will always return 0.
1497 */
1498EAPI Eina_Bool ecore_con_url_httpauth_set(Ecore_Con_Url *url_con,
1499 const char *username,
1500 const char *password,
1501 Eina_Bool safe);
1502/**
1503 * Sends a request.
1504 *
1505 * @param url_con Connection object to perform a request on, previously created
1506 * with ecore_con_url_new() or ecore_con_url_custom_new().
1507 * @param data Payload (data sent on the request)
1508 * @param length Payload length. If @c -1, rely on automatic length
1509 * calculation via @c strlen() on @p data.
1510 * @param content_type Content type of the payload (e.g. text/xml)
1511 *
1512 * @return #EINA_TRUE on success, #EINA_FALSE on error.
1513 *
1514 * @see ecore_con_url_custom_new()
1515 * @see ecore_con_url_additional_headers_clear()
1516 * @see ecore_con_url_additional_header_add()
1517 * @see ecore_con_url_data_set()
1518 * @see ecore_con_url_data_get()
1519 * @see ecore_con_url_response_headers_get()
1520 * @see ecore_con_url_time()
1521 * @see ecore_con_url_get()
1522 * @see ecore_con_url_post()
1523 *
1524 * @deprecated Use ecore_con_url_post() instead of this.
1525 */
1526EINA_DEPRECATED EAPI Eina_Bool ecore_con_url_send(Ecore_Con_Url *url_con,
1527 const void *data, long length,
1528 const char *content_type);
1529/**
1530 * Sends a get request.
1531 *
1532 * @param url_con Connection object to perform a request on, previously created
1533 *
1534 * @return #EINA_TRUE on success, #EINA_FALSE on error.
1535 *
1536 * The request is performed immediately, but you need to setup event handlers
1537 * for #ECORE_CON_EVENT_URL_DATA, #ECORE_CON_EVENT_URL_COMPLETE or
1538 * #ECORE_CON_EVENT_URL_PROGRESS to get more information about its result.
1539 *
1540 * @see ecore_con_url_custom_new()
1541 * @see ecore_con_url_additional_headers_clear()
1542 * @see ecore_con_url_additional_header_add()
1543 * @see ecore_con_url_data_set()
1544 * @see ecore_con_url_data_get()
1545 * @see ecore_con_url_response_headers_get()
1546 * @see ecore_con_url_time()
1547 * @see ecore_con_url_post()
1548 */
1549EAPI Eina_Bool ecore_con_url_get(Ecore_Con_Url *url_con);
1550/**
1551 * Sends a post request.
1552 *
1553 * @param url_con Connection object to perform a request on, previously created
1554 * with ecore_con_url_new() or ecore_con_url_custom_new().
1555 * @param data Payload (data sent on the request). Can be @c NULL.
1556 * @param length Payload length. If @c -1, rely on automatic length
1557 * calculation via @c strlen() on @p data.
1558 * @param content_type Content type of the payload (e.g. text/xml). Can be @c
1559 * NULL.
1560 *
1561 * @return #EINA_TRUE on success, #EINA_FALSE on error.
1562 *
1563 * The request starts immediately, but you need to setup event handlers
1564 * for #ECORE_CON_EVENT_URL_DATA, #ECORE_CON_EVENT_URL_COMPLETE or
1565 * #ECORE_CON_EVENT_URL_PROGRESS to get more information about its result.
1566 *
1567 * This call won't block your main loop.
1568 *
1569 * @see ecore_con_url_custom_new()
1570 * @see ecore_con_url_additional_headers_clear()
1571 * @see ecore_con_url_additional_header_add()
1572 * @see ecore_con_url_data_set()
1573 * @see ecore_con_url_data_get()
1574 * @see ecore_con_url_response_headers_get()
1575 * @see ecore_con_url_time()
1576 * @see ecore_con_url_get()
1577 */
1578EAPI Eina_Bool ecore_con_url_post(Ecore_Con_Url *url_con,
1579 const void *data, long length,
1580 const char *content_type);
1581/**
1582 * Sets whether HTTP requests should be conditional, dependent on
1583 * modification time.
1584 *
1585 * @param url_con Ecore_Con_Url to act upon.
1586 * @param condition Condition to use for HTTP requests.
1587 * @param timestamp Time since 1 Jan 1970 to use in the condition.
1588 *
1589 * This function may set the header "If-Modified-Since" or
1590 * "If-Unmodified-Since", depending on the value of @p time_condition, with the
1591 * value @p timestamp.
1592 *
1593 * @sa ecore_con_url_get()
1594 * @sa ecore_con_url_post()
1595 */
1596EAPI void ecore_con_url_time(Ecore_Con_Url *url_con,
1597 Ecore_Con_Url_Time time_condition,
1598 double timestamp);
1599
1600/**
1601 * @brief Uploads a file to an ftp site.
1602 * @param url_con The Ecore_Con_Url object to send with
1603 * @param filename The path to the file to send
1604 * @param user The username to log in with
1605 * @param pass The password to log in with
1606 * @param upload_dir The directory to which the file should be uploaded
1607 * @return #EINA_TRUE on success, else #EINA_FALSE.
1608 * Upload @p filename to an ftp server set in @p url_con using @p user
1609 * and @p pass to directory @p upload_dir
1610 */
1611EAPI Eina_Bool ecore_con_url_ftp_upload(Ecore_Con_Url *url_con,
1612 const char *filename,
1613 const char *user,
1614 const char *pass,
1615 const char *upload_dir);
1616/**
1617 * Toggle libcurl's verbose output.
1618 *
1619 * @param url_con Ecore_Con_Url instance which will be acted upon.
1620 * @param verbose Whether or not to enable libcurl's verbose output.
1621 *
1622 * If @p verbose is @c EINA_TRUE, libcurl will output a lot of verbose
1623 * information about its operations, which is useful for
1624 * debugging. The verbose information will be sent to stderr.
1625 */
1626EAPI void ecore_con_url_verbose_set(Ecore_Con_Url *url_con,
1627 Eina_Bool verbose);
1628/**
1629 * Enable or disable EPSV extension
1630 * @return FIXME: To be more documented.
1631 */
1632EAPI void ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con,
1633 Eina_Bool use_epsv);
1634
1635/**
1636 * Enables the cookie engine for subsequent HTTP requests.
1637 *
1638 * @param url_con Ecore_Con_Url instance which will be acted upon.
1639 *
1640 * After this function is called, cookies set by the server in HTTP responses
1641 * will be parsed and stored, as well as sent back to the server in new HTTP
1642 * requests.
1643 *
1644 * @note Even though this function is called @c ecore_con_url_cookies_init(),
1645 * there is no symmetrical shutdown operation.
1646 */
1647EAPI void ecore_con_url_cookies_init(Ecore_Con_Url *url_con);
1648/**
1649 * Controls whether session cookies from previous sessions shall be loaded.
1650 *
1651 * @param url_con Ecore_Con_Url instance which will be acted upon.
1652 * @param ignore If @c EINA_TRUE, ignore session cookies when loading cookies
1653 * from files. If @c EINA_FALSE, all cookies will be loaded.
1654 *
1655 * Session cookies are cookies with no expire date set, which usually means
1656 * they are removed after the current session is closed.
1657 *
1658 * By default, when Ecore_Con_Url loads cookies from a file, all cookies are
1659 * loaded, including session cookies, which, most of the time, were supposed
1660 * to be loaded and valid only for that session.
1661 *
1662 * If @p ignore is set to @c EINA_TRUE, when Ecore_Con_Url loads cookies from
1663 * the files passed to @c ecore_con_url_cookies_file_add(), session cookies
1664 * will not be loaded.
1665 *
1666 * @see ecore_con_url_cookies_file_add()
1667 */
1668EAPI void ecore_con_url_cookies_ignore_old_session_set(Ecore_Con_Url *url_con,
1669 Eina_Bool ignore);
1670/**
1671 * Clears currently loaded cookies.
1672 * @param url_con Ecore_Con_Url instance which will be acted upon.
1673 *
1674 * The cleared cookies are removed and will not be sent in subsequent HTTP
1675 * requests, nor will they be written to the cookiejar file set via
1676 * @c ecore_con_url_cookies_jar_file_set().
1677 *
1678 * @note This function will initialize the cookie engine if it has not been
1679 * initialized yet.
1680 * @note The cookie files set by ecore_con_url_cookies_file_add() aren't loaded
1681 * immediately, just when the request is started. Thus, if you ask to
1682 * clear the cookies, but has a file already set by that function, the
1683 * cookies will then be loaded and you will have old cookies set. In order
1684 * to don't have any old cookie set, you need to don't call
1685 * ecore_con_url_cookies_file_add() ever on the @p url_con handler, and
1686 * call this function to clear any cookie set by a previous request on
1687 * this handler.
1688 *
1689 * @see ecore_con_url_cookies_session_clear()
1690 * @see ecore_con_url_cookies_ignore_old_session_set()
1691 */
1692EAPI void ecore_con_url_cookies_clear(Ecore_Con_Url *url_con);
1693/**
1694 * Clears currently loaded session cookies.
1695 *
1696 * @param url_con Ecore_Con_Url instance which will be acted upon.
1697 *
1698 * Session cookies are cookies with no expire date set, which usually means
1699 * they are removed after the current session is closed.
1700 *
1701 * The cleared cookies are removed and will not be sent in subsequent HTTP
1702 * requests, nor will they be written to the cookiejar file set via
1703 * @c ecore_con_url_cookies_jar_file_set().
1704 *
1705 * @note This function will initialize the cookie engine if it has not been
1706 * initialized yet.
1707 * @note The cookie files set by ecore_con_url_cookies_file_add() aren't loaded
1708 * immediately, just when the request is started. Thus, if you ask to
1709 * clear the session cookies, but has a file already set by that function,
1710 * the session cookies will then be loaded and you will have old cookies
1711 * set. In order to don't have any old session cookie set, you need to
1712 * don't call ecore_con_url_cookies_file_add() ever on the @p url_con
1713 * handler, and call this function to clear any session cookie set by a
1714 * previous request on this handler. An easier way to don't use old
1715 * session cookies is by using the function
1716 * ecore_con_url_cookies_ignore_old_session_set().
1717 *
1718 * @see ecore_con_url_cookies_clear()
1719 * @see ecore_con_url_cookies_ignore_old_session_set()
1720 */
1721EAPI void ecore_con_url_cookies_session_clear(Ecore_Con_Url *url_con);
1722/**
1723 * Adds a file to the list of files from which to load cookies.
1724 *
1725 * @param url_con Ecore_Con_Url instance which will be acted upon.
1726 * @param file_name Name of the file that will be added to the list.
1727 *
1728 * Files must contain cookies defined according to two possible formats:
1729 *
1730 * @li HTTP-style header ("Set-Cookie: ...").
1731 * @li <a href="http://www.cookiecentral.com/faq/#3.5">Netscape/Mozilla cookie data format.</a>
1732 *
1733 * Cookies will only be @b read from this file. If you want to save cookies to a
1734 * file, use ecore_con_url_cookies_jar_file_set(). Also notice that this
1735 * function supports the both types of cookie file cited above, while
1736 * ecore_con_url_cookies_jar_file_set() will save only in the Netscape/Mozilla's
1737 * format.
1738 *
1739 * Please notice that the file will not be read immediately, but rather added
1740 * to a list of files that will be loaded and parsed at a later time.
1741 *
1742 * @note This function will initialize the cookie engine if it has not been
1743 * initialized yet.
1744 *
1745 * @see ecore_con_url_cookies_ignore_old_session_set()
1746 * @see ecore_con_url_cookies_jar_file_set()
1747 */
1748EAPI void ecore_con_url_cookies_file_add(Ecore_Con_Url *url_con,
1749 const char * const file_name);
1750/**
1751 * Sets the name of the file to which all current cookies will be written when
1752 * either cookies are flushed or Ecore_Con is shut down.
1753 *
1754 * @param url_con Ecore_Con_Url instance which will be acted upon.
1755 * @param cookiejar_file File to which the cookies will be written.
1756 *
1757 * @return @c EINA_TRUE is the file name has been set successfully,
1758 * @c EINA_FALSE otherwise.
1759 *
1760 * Cookies are written following Netscape/Mozilla's data format, also known as
1761 * cookie-jar.
1762 *
1763 * Cookies will only be @b saved to this file. If you need to read cookies from
1764 * a file, use ecore_con_url_cookies_file_add() instead.
1765 *
1766 * @note This function will initialize the cookie engine if it has not been
1767 * initialized yet.
1768 *
1769 * @see ecore_con_url_cookies_jar_write()
1770 */
1771EAPI Eina_Bool ecore_con_url_cookies_jar_file_set(Ecore_Con_Url *url_con,
1772 const char * const cookiejar_file);
1773/**
1774 * Writes all current cookies to the cookie jar immediately.
1775 *
1776 * @param url_con Ecore_Con_Url instance which will be acted upon.
1777 *
1778 * A cookie-jar file must have been previously set by
1779 * @c ecore_con_url_jar_file_set, otherwise nothing will be done.
1780 *
1781 * @note This function will initialize the cookie engine if it has not been
1782 * initialized yet.
1783 *
1784 * @see ecore_con_url_cookies_jar_file_set()
1785 */
1786EAPI void ecore_con_url_cookies_jar_write(Ecore_Con_Url *url_con);
1787
1788EAPI void ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con,
1789 Eina_Bool verify);
1790EAPI int ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con,
1791 const char *ca_path);
1792
1793/**
1794 * @}
1795 */
1796
1797#ifdef __cplusplus
1798}
1799#endif
1800
1801#endif
diff --git a/libraries/ecore/src/lib/ecore_con/Makefile.am b/libraries/ecore/src/lib/ecore_con/Makefile.am
new file mode 100644
index 0000000..300586d
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/Makefile.am
@@ -0,0 +1,45 @@
1MAINTAINERCLEANFILES = Makefile.in
2
3AM_CPPFLAGS = \
4-I$(top_builddir)/src/lib/ecore \
5-I$(top_builddir)/src/lib/ecore_con \
6-I$(top_srcdir)/src/lib/ecore \
7-I$(top_srcdir)/src/lib/ecore_con \
8@EFL_ECORE_CON_BUILD@ \
9@SSL_CFLAGS@ \
10@CURL_CFLAGS@ \
11@EINA_CFLAGS@ \
12@TLS_CFLAGS@ \
13@CARES_CFLAGS@ \
14@WIN32_CPPFLAGS@
15
16lib_LTLIBRARIES = libecore_con.la
17includes_HEADERS = Ecore_Con.h
18includesdir = $(includedir)/ecore-@VMAJ@
19
20libecore_con_la_SOURCES = \
21ecore_con.c \
22ecore_con_ssl.c \
23ecore_con_url.c \
24ecore_con_alloc.c
25
26if ECORE_HAVE_WIN32
27libecore_con_la_SOURCES += ecore_con_local_win32.c
28else
29libecore_con_la_SOURCES += ecore_con_local.c
30endif
31
32if HAVE_CARES
33libecore_con_la_SOURCES += ecore_con_ares.c
34else
35libecore_con_la_SOURCES += ecore_con_info.c
36endif
37
38libecore_con_la_CFLAGS = @WIN32_CFLAGS@
39libecore_con_la_LIBADD = \
40$(top_builddir)/src/lib/ecore/libecore.la \
41@SSL_LIBS@ @CURL_LIBS@ @EINA_LIBS@ @TLS_LIBS@ @CARES_LIBS@ @WIN32_LIBS@
42
43libecore_con_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@
44
45EXTRA_DIST = ecore_con_private.h
diff --git a/libraries/ecore/src/lib/ecore_con/Makefile.in b/libraries/ecore/src/lib/ecore_con/Makefile.in
new file mode 100644
index 0000000..5940a83
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/Makefile.in
@@ -0,0 +1,909 @@
1# Makefile.in generated by automake 1.11.1 from Makefile.am.
2# @configure_input@
3
4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
6# Inc.
7# This Makefile.in is free software; the Free Software Foundation
8# gives unlimited permission to copy and/or distribute it,
9# with or without modifications, as long as this notice is preserved.
10
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
13# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14# PARTICULAR PURPOSE.
15
16@SET_MAKE@
17
18
19VPATH = @srcdir@
20pkgdatadir = $(datadir)/@PACKAGE@
21pkgincludedir = $(includedir)/@PACKAGE@
22pkglibdir = $(libdir)/@PACKAGE@
23pkglibexecdir = $(libexecdir)/@PACKAGE@
24am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
25install_sh_DATA = $(install_sh) -c -m 644
26install_sh_PROGRAM = $(install_sh) -c
27install_sh_SCRIPT = $(install_sh) -c
28INSTALL_HEADER = $(INSTALL_DATA)
29transform = $(program_transform_name)
30NORMAL_INSTALL = :
31PRE_INSTALL = :
32POST_INSTALL = :
33NORMAL_UNINSTALL = :
34PRE_UNINSTALL = :
35POST_UNINSTALL = :
36build_triplet = @build@
37host_triplet = @host@
38@ECORE_HAVE_WIN32_TRUE@am__append_1 = ecore_con_local_win32.c
39@ECORE_HAVE_WIN32_FALSE@am__append_2 = ecore_con_local.c
40@HAVE_CARES_TRUE@am__append_3 = ecore_con_ares.c
41@HAVE_CARES_FALSE@am__append_4 = ecore_con_info.c
42subdir = src/lib/ecore_con
43DIST_COMMON = $(includes_HEADERS) $(srcdir)/Makefile.am \
44 $(srcdir)/Makefile.in
45ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
46am__aclocal_m4_deps = $(top_srcdir)/m4/ac_attribute.m4 \
47 $(top_srcdir)/m4/ac_path_generic.m4 \
48 $(top_srcdir)/m4/check_x_extension.m4 \
49 $(top_srcdir)/m4/ecore_check_module.m4 \
50 $(top_srcdir)/m4/ecore_check_options.m4 \
51 $(top_srcdir)/m4/efl_compiler_flag.m4 \
52 $(top_srcdir)/m4/efl_doxygen.m4 \
53 $(top_srcdir)/m4/efl_examples.m4 \
54 $(top_srcdir)/m4/efl_path_max.m4 $(top_srcdir)/m4/efl_tests.m4 \
55 $(top_srcdir)/m4/efl_threads.m4 $(top_srcdir)/m4/gettext.m4 \
56 $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
57 $(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lib-ld.m4 \
58 $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
59 $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
60 $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
61 $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
62 $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
63 $(top_srcdir)/configure.ac
64am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
65 $(ACLOCAL_M4)
66mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
67CONFIG_HEADER = $(top_builddir)/config.h
68CONFIG_CLEAN_FILES =
69CONFIG_CLEAN_VPATH_FILES =
70am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
71am__vpath_adj = case $$p in \
72 $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
73 *) f=$$p;; \
74 esac;
75am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
76am__install_max = 40
77am__nobase_strip_setup = \
78 srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
79am__nobase_strip = \
80 for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
81am__nobase_list = $(am__nobase_strip_setup); \
82 for p in $$list; do echo "$$p $$p"; done | \
83 sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
84 $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
85 if (++n[$$2] == $(am__install_max)) \
86 { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
87 END { for (dir in files) print dir, files[dir] }'
88am__base_list = \
89 sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
90 sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
91am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includesdir)"
92LTLIBRARIES = $(lib_LTLIBRARIES)
93libecore_con_la_DEPENDENCIES = \
94 $(top_builddir)/src/lib/ecore/libecore.la
95am__libecore_con_la_SOURCES_DIST = ecore_con.c ecore_con_ssl.c \
96 ecore_con_url.c ecore_con_alloc.c ecore_con_local_win32.c \
97 ecore_con_local.c ecore_con_ares.c ecore_con_info.c
98@ECORE_HAVE_WIN32_TRUE@am__objects_1 = libecore_con_la-ecore_con_local_win32.lo
99@ECORE_HAVE_WIN32_FALSE@am__objects_2 = \
100@ECORE_HAVE_WIN32_FALSE@ libecore_con_la-ecore_con_local.lo
101@HAVE_CARES_TRUE@am__objects_3 = libecore_con_la-ecore_con_ares.lo
102@HAVE_CARES_FALSE@am__objects_4 = libecore_con_la-ecore_con_info.lo
103am_libecore_con_la_OBJECTS = libecore_con_la-ecore_con.lo \
104 libecore_con_la-ecore_con_ssl.lo \
105 libecore_con_la-ecore_con_url.lo \
106 libecore_con_la-ecore_con_alloc.lo $(am__objects_1) \
107 $(am__objects_2) $(am__objects_3) $(am__objects_4)
108libecore_con_la_OBJECTS = $(am_libecore_con_la_OBJECTS)
109AM_V_lt = $(am__v_lt_$(V))
110am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
111am__v_lt_0 = --silent
112libecore_con_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
113 $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
114 $(libecore_con_la_CFLAGS) $(CFLAGS) $(libecore_con_la_LDFLAGS) \
115 $(LDFLAGS) -o $@
116DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
117depcomp = $(SHELL) $(top_srcdir)/depcomp
118am__depfiles_maybe = depfiles
119am__mv = mv -f
120COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
121 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
122LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
123 $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
124 $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
125 $(AM_CFLAGS) $(CFLAGS)
126AM_V_CC = $(am__v_CC_$(V))
127am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
128am__v_CC_0 = @echo " CC " $@;
129AM_V_at = $(am__v_at_$(V))
130am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
131am__v_at_0 = @
132CCLD = $(CC)
133LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
134 $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
135 $(AM_LDFLAGS) $(LDFLAGS) -o $@
136AM_V_CCLD = $(am__v_CCLD_$(V))
137am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
138am__v_CCLD_0 = @echo " CCLD " $@;
139AM_V_GEN = $(am__v_GEN_$(V))
140am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
141am__v_GEN_0 = @echo " GEN " $@;
142SOURCES = $(libecore_con_la_SOURCES)
143DIST_SOURCES = $(am__libecore_con_la_SOURCES_DIST)
144HEADERS = $(includes_HEADERS)
145ETAGS = etags
146CTAGS = ctags
147DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
148ACLOCAL = @ACLOCAL@
149ALLOCA = @ALLOCA@
150AMTAR = @AMTAR@
151AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
152AR = @AR@
153AS = @AS@
154AUTOCONF = @AUTOCONF@
155AUTOHEADER = @AUTOHEADER@
156AUTOMAKE = @AUTOMAKE@
157AWK = @AWK@
158CARES_CFLAGS = @CARES_CFLAGS@
159CARES_LIBS = @CARES_LIBS@
160CC = @CC@
161CCDEPMODE = @CCDEPMODE@
162CFLAGS = @CFLAGS@
163CHECK_CFLAGS = @CHECK_CFLAGS@
164CHECK_LIBS = @CHECK_LIBS@
165CPP = @CPP@
166CPPFLAGS = @CPPFLAGS@
167CURL_CFLAGS = @CURL_CFLAGS@
168CURL_LIBS = @CURL_LIBS@
169CXX = @CXX@
170CXXCPP = @CXXCPP@
171CXXDEPMODE = @CXXDEPMODE@
172CXXFLAGS = @CXXFLAGS@
173CYGPATH_W = @CYGPATH_W@
174DEFS = @DEFS@
175DEPDIR = @DEPDIR@
176DIRECTFB_CFLAGS = @DIRECTFB_CFLAGS@
177DIRECTFB_LIBS = @DIRECTFB_LIBS@
178DLLTOOL = @DLLTOOL@
179DSYMUTIL = @DSYMUTIL@
180DUMPBIN = @DUMPBIN@
181ECHO_C = @ECHO_C@
182ECHO_N = @ECHO_N@
183ECHO_T = @ECHO_T@
184ECORE_XCB_CFLAGS = @ECORE_XCB_CFLAGS@
185ECORE_XCB_LIBS = @ECORE_XCB_LIBS@
186EFL_ECORE_BUILD = @EFL_ECORE_BUILD@
187EFL_ECORE_CON_BUILD = @EFL_ECORE_CON_BUILD@
188EFL_ECORE_EVAS_BUILD = @EFL_ECORE_EVAS_BUILD@
189EFL_ECORE_FILE_BUILD = @EFL_ECORE_FILE_BUILD@
190EFL_ECORE_IMF_BUILD = @EFL_ECORE_IMF_BUILD@
191EFL_ECORE_IMF_EVAS_BUILD = @EFL_ECORE_IMF_EVAS_BUILD@
192EFL_ECORE_INPUT_BUILD = @EFL_ECORE_INPUT_BUILD@
193EFL_ECORE_INPUT_EVAS_BUILD = @EFL_ECORE_INPUT_EVAS_BUILD@
194EFL_ECORE_IPC_BUILD = @EFL_ECORE_IPC_BUILD@
195EFL_ECORE_PSL1GHT_BUILD = @EFL_ECORE_PSL1GHT_BUILD@
196EFL_ECORE_SDL_BUILD = @EFL_ECORE_SDL_BUILD@
197EFL_ECORE_WIN32_BUILD = @EFL_ECORE_WIN32_BUILD@
198EFL_ECORE_WINCE_BUILD = @EFL_ECORE_WINCE_BUILD@
199EFL_PTHREAD_CFLAGS = @EFL_PTHREAD_CFLAGS@
200EFL_PTHREAD_LIBS = @EFL_PTHREAD_LIBS@
201EGREP = @EGREP@
202EINA_CFLAGS = @EINA_CFLAGS@
203EINA_LIBS = @EINA_LIBS@
204ESCAPE_CFLAGS = @ESCAPE_CFLAGS@
205ESCAPE_LIBS = @ESCAPE_LIBS@
206EVAS_CFLAGS = @EVAS_CFLAGS@
207EVAS_LIBS = @EVAS_LIBS@
208EVIL_CFLAGS = @EVIL_CFLAGS@
209EVIL_LIBS = @EVIL_LIBS@
210EXEEXT = @EXEEXT@
211FGREP = @FGREP@
212GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
213GLIB_CFLAGS = @GLIB_CFLAGS@
214GLIB_LIBS = @GLIB_LIBS@
215GMSGFMT = @GMSGFMT@
216GMSGFMT_015 = @GMSGFMT_015@
217GREP = @GREP@
218INSTALL = @INSTALL@
219INSTALL_DATA = @INSTALL_DATA@
220INSTALL_PROGRAM = @INSTALL_PROGRAM@
221INSTALL_SCRIPT = @INSTALL_SCRIPT@
222INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
223INTLLIBS = @INTLLIBS@
224INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
225KEYSYMDEFS = @KEYSYMDEFS@
226LD = @LD@
227LDFLAGS = @LDFLAGS@
228LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
229LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
230LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
231LIBICONV = @LIBICONV@
232LIBINTL = @LIBINTL@
233LIBOBJS = @LIBOBJS@
234LIBS = @LIBS@
235LIBTOOL = @LIBTOOL@
236LIPO = @LIPO@
237LN_S = @LN_S@
238LTLIBICONV = @LTLIBICONV@
239LTLIBINTL = @LTLIBINTL@
240LTLIBOBJS = @LTLIBOBJS@
241MAKEINFO = @MAKEINFO@
242MKDIR_P = @MKDIR_P@
243MSGFMT = @MSGFMT@
244MSGFMT_015 = @MSGFMT_015@
245MSGMERGE = @MSGMERGE@
246NM = @NM@
247NMEDIT = @NMEDIT@
248OBJC = @OBJC@
249OBJCDEPMODE = @OBJCDEPMODE@
250OBJCFLAGS = @OBJCFLAGS@
251OBJDUMP = @OBJDUMP@
252OBJEXT = @OBJEXT@
253OTOOL = @OTOOL@
254OTOOL64 = @OTOOL64@
255PACKAGE = @PACKAGE@
256PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
257PACKAGE_NAME = @PACKAGE_NAME@
258PACKAGE_STRING = @PACKAGE_STRING@
259PACKAGE_TARNAME = @PACKAGE_TARNAME@
260PACKAGE_URL = @PACKAGE_URL@
261PACKAGE_VERSION = @PACKAGE_VERSION@
262PATH_SEPARATOR = @PATH_SEPARATOR@
263PIXMAN_CFLAGS = @PIXMAN_CFLAGS@
264PIXMAN_LIBS = @PIXMAN_LIBS@
265PKG_CONFIG = @PKG_CONFIG@
266PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
267PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
268POSUB = @POSUB@
269RANLIB = @RANLIB@
270SDL_CFLAGS = @SDL_CFLAGS@
271SDL_CONFIG = @SDL_CONFIG@
272SDL_LIBS = @SDL_LIBS@
273SED = @SED@
274SET_MAKE = @SET_MAKE@
275SHELL = @SHELL@
276SSL_CFLAGS = @SSL_CFLAGS@
277SSL_LIBS = @SSL_LIBS@
278STRIP = @STRIP@
279TLS2_CFLAGS = @TLS2_CFLAGS@
280TLS2_LIBS = @TLS2_LIBS@
281TLS_CFLAGS = @TLS_CFLAGS@
282TLS_LIBS = @TLS_LIBS@
283TSLIB_CFLAGS = @TSLIB_CFLAGS@
284TSLIB_LIBS = @TSLIB_LIBS@
285USE_NLS = @USE_NLS@
286VERSION = @VERSION@
287VMAJ = @VMAJ@
288WIN32_CFLAGS = @WIN32_CFLAGS@
289WIN32_CPPFLAGS = @WIN32_CPPFLAGS@
290WIN32_LIBS = @WIN32_LIBS@
291XCB_COMPOSITE_CFLAGS = @XCB_COMPOSITE_CFLAGS@
292XCB_COMPOSITE_LIBS = @XCB_COMPOSITE_LIBS@
293XCB_CURSOR_CFLAGS = @XCB_CURSOR_CFLAGS@
294XCB_CURSOR_LIBS = @XCB_CURSOR_LIBS@
295XCB_DAMAGE_CFLAGS = @XCB_DAMAGE_CFLAGS@
296XCB_DAMAGE_LIBS = @XCB_DAMAGE_LIBS@
297XCB_DPMS_CFLAGS = @XCB_DPMS_CFLAGS@
298XCB_DPMS_LIBS = @XCB_DPMS_LIBS@
299XCB_RANDR_CFLAGS = @XCB_RANDR_CFLAGS@
300XCB_RANDR_LIBS = @XCB_RANDR_LIBS@
301XCB_RENDER_CFLAGS = @XCB_RENDER_CFLAGS@
302XCB_RENDER_LIBS = @XCB_RENDER_LIBS@
303XCB_SCREENSAVER_CFLAGS = @XCB_SCREENSAVER_CFLAGS@
304XCB_SCREENSAVER_LIBS = @XCB_SCREENSAVER_LIBS@
305XCB_SHAPE_CFLAGS = @XCB_SHAPE_CFLAGS@
306XCB_SHAPE_LIBS = @XCB_SHAPE_LIBS@
307XCB_SYNC_CFLAGS = @XCB_SYNC_CFLAGS@
308XCB_SYNC_LIBS = @XCB_SYNC_LIBS@
309XCB_X11_CFLAGS = @XCB_X11_CFLAGS@
310XCB_X11_LIBS = @XCB_X11_LIBS@
311XCB_XFIXES_CFLAGS = @XCB_XFIXES_CFLAGS@
312XCB_XFIXES_LIBS = @XCB_XFIXES_LIBS@
313XCB_XGESTURE_CFLAGS = @XCB_XGESTURE_CFLAGS@
314XCB_XGESTURE_LIBS = @XCB_XGESTURE_LIBS@
315XCB_XINERAMA_CFLAGS = @XCB_XINERAMA_CFLAGS@
316XCB_XINERAMA_LIBS = @XCB_XINERAMA_LIBS@
317XCB_XINPUT_CFLAGS = @XCB_XINPUT_CFLAGS@
318XCB_XINPUT_LIBS = @XCB_XINPUT_LIBS@
319XCB_XPRINT_CFLAGS = @XCB_XPRINT_CFLAGS@
320XCB_XPRINT_LIBS = @XCB_XPRINT_LIBS@
321XCB_XTEST_CFLAGS = @XCB_XTEST_CFLAGS@
322XCB_XTEST_LIBS = @XCB_XTEST_LIBS@
323XCOMPOSITE_CFLAGS = @XCOMPOSITE_CFLAGS@
324XCOMPOSITE_LIBS = @XCOMPOSITE_LIBS@
325XDAMAGE_CFLAGS = @XDAMAGE_CFLAGS@
326XDAMAGE_LIBS = @XDAMAGE_LIBS@
327XDPMS_CFLAGS = @XDPMS_CFLAGS@
328XDPMS_LIBS = @XDPMS_LIBS@
329XFIXES_CFLAGS = @XFIXES_CFLAGS@
330XFIXES_LIBS = @XFIXES_LIBS@
331XGESTURE_CFLAGS = @XGESTURE_CFLAGS@
332XGESTURE_LIBS = @XGESTURE_LIBS@
333XGETTEXT = @XGETTEXT@
334XGETTEXT_015 = @XGETTEXT_015@
335XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
336XI2_CFLAGS = @XI2_CFLAGS@
337XI2_LIBS = @XI2_LIBS@
338XINERAMA_CFLAGS = @XINERAMA_CFLAGS@
339XINERAMA_LIBS = @XINERAMA_LIBS@
340XKB_CFLAGS = @XKB_CFLAGS@
341XKB_LIBS = @XKB_LIBS@
342XMKMF = @XMKMF@
343XPRINT_CFLAGS = @XPRINT_CFLAGS@
344XPRINT_LIBS = @XPRINT_LIBS@
345XRANDR_CFLAGS = @XRANDR_CFLAGS@
346XRANDR_LIBS = @XRANDR_LIBS@
347XRENDER_CFLAGS = @XRENDER_CFLAGS@
348XRENDER_LIBS = @XRENDER_LIBS@
349XSS_CFLAGS = @XSS_CFLAGS@
350XSS_LIBS = @XSS_LIBS@
351XTEST_CFLAGS = @XTEST_CFLAGS@
352XTEST_LIBS = @XTEST_LIBS@
353X_CFLAGS = @X_CFLAGS@
354X_EXTRA_LIBS = @X_EXTRA_LIBS@
355X_LIBS = @X_LIBS@
356X_PRE_LIBS = @X_PRE_LIBS@
357Xcursor_cflags = @Xcursor_cflags@
358Xcursor_libs = @Xcursor_libs@
359abs_builddir = @abs_builddir@
360abs_srcdir = @abs_srcdir@
361abs_top_builddir = @abs_top_builddir@
362abs_top_srcdir = @abs_top_srcdir@
363ac_ct_CC = @ac_ct_CC@
364ac_ct_CXX = @ac_ct_CXX@
365ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
366ac_ct_OBJC = @ac_ct_OBJC@
367am__include = @am__include@
368am__leading_dot = @am__leading_dot@
369am__quote = @am__quote@
370am__tar = @am__tar@
371am__untar = @am__untar@
372bindir = @bindir@
373build = @build@
374build_alias = @build_alias@
375build_cpu = @build_cpu@
376build_os = @build_os@
377build_vendor = @build_vendor@
378builddir = @builddir@
379cocoa_ldflags = @cocoa_ldflags@
380datadir = @datadir@
381datarootdir = @datarootdir@
382dlopen_libs = @dlopen_libs@
383docdir = @docdir@
384dvidir = @dvidir@
385ecore_cocoa_cflags = @ecore_cocoa_cflags@
386ecore_cocoa_libs = @ecore_cocoa_libs@
387ecore_con_cflags = @ecore_con_cflags@
388ecore_con_libs = @ecore_con_libs@
389ecore_directfb_cflags = @ecore_directfb_cflags@
390ecore_directfb_libs = @ecore_directfb_libs@
391ecore_evas_cflags = @ecore_evas_cflags@
392ecore_evas_libs = @ecore_evas_libs@
393ecore_fb_cflags = @ecore_fb_cflags@
394ecore_fb_libs = @ecore_fb_libs@
395ecore_file_cflags = @ecore_file_cflags@
396ecore_file_libs = @ecore_file_libs@
397ecore_imf_cflags = @ecore_imf_cflags@
398ecore_imf_evas_cflags = @ecore_imf_evas_cflags@
399ecore_imf_evas_libs = @ecore_imf_evas_libs@
400ecore_imf_libs = @ecore_imf_libs@
401ecore_imf_xim_cflags = @ecore_imf_xim_cflags@
402ecore_imf_xim_libs = @ecore_imf_xim_libs@
403ecore_input_cflags = @ecore_input_cflags@
404ecore_input_evas_cflags = @ecore_input_evas_cflags@
405ecore_input_evas_libs = @ecore_input_evas_libs@
406ecore_input_libs = @ecore_input_libs@
407ecore_ipc_cflags = @ecore_ipc_cflags@
408ecore_ipc_libs = @ecore_ipc_libs@
409ecore_psl1ght_cflags = @ecore_psl1ght_cflags@
410ecore_psl1ght_libs = @ecore_psl1ght_libs@
411ecore_sdl_cflags = @ecore_sdl_cflags@
412ecore_sdl_libs = @ecore_sdl_libs@
413ecore_win32_cflags = @ecore_win32_cflags@
414ecore_win32_libs = @ecore_win32_libs@
415ecore_wince_cflags = @ecore_wince_cflags@
416ecore_wince_libs = @ecore_wince_libs@
417ecore_x_cflags = @ecore_x_cflags@
418ecore_x_libs = @ecore_x_libs@
419ecore_x_libs_private = @ecore_x_libs_private@
420efl_doxygen = @efl_doxygen@
421efl_have_doxygen = @efl_have_doxygen@
422exec_prefix = @exec_prefix@
423have_ecore_x_xcb_define = @have_ecore_x_xcb_define@
424host = @host@
425host_alias = @host_alias@
426host_cpu = @host_cpu@
427host_os = @host_os@
428host_vendor = @host_vendor@
429htmldir = @htmldir@
430includedir = @includedir@
431infodir = @infodir@
432install_sh = @install_sh@
433libdir = @libdir@
434libexecdir = @libexecdir@
435localedir = @localedir@
436localstatedir = @localstatedir@
437lt_ECHO = @lt_ECHO@
438lt_enable_auto_import = @lt_enable_auto_import@
439mandir = @mandir@
440mkdir_p = @mkdir_p@
441oldincludedir = @oldincludedir@
442pdfdir = @pdfdir@
443pkgconfig_requires_private = @pkgconfig_requires_private@
444prefix = @prefix@
445program_transform_name = @program_transform_name@
446psdir = @psdir@
447release_info = @release_info@
448requirements_ecore = @requirements_ecore@
449requirements_ecore_cocoa = @requirements_ecore_cocoa@
450requirements_ecore_con = @requirements_ecore_con@
451requirements_ecore_directfb = @requirements_ecore_directfb@
452requirements_ecore_evas = @requirements_ecore_evas@
453requirements_ecore_fb = @requirements_ecore_fb@
454requirements_ecore_file = @requirements_ecore_file@
455requirements_ecore_imf = @requirements_ecore_imf@
456requirements_ecore_imf_evas = @requirements_ecore_imf_evas@
457requirements_ecore_imf_xim = @requirements_ecore_imf_xim@
458requirements_ecore_input = @requirements_ecore_input@
459requirements_ecore_input_evas = @requirements_ecore_input_evas@
460requirements_ecore_ipc = @requirements_ecore_ipc@
461requirements_ecore_psl1ght = @requirements_ecore_psl1ght@
462requirements_ecore_sdl = @requirements_ecore_sdl@
463requirements_ecore_win32 = @requirements_ecore_win32@
464requirements_ecore_wince = @requirements_ecore_wince@
465requirements_ecore_x = @requirements_ecore_x@
466rt_libs = @rt_libs@
467sbindir = @sbindir@
468sharedstatedir = @sharedstatedir@
469srcdir = @srcdir@
470sysconfdir = @sysconfdir@
471target_alias = @target_alias@
472top_build_prefix = @top_build_prefix@
473top_builddir = @top_builddir@
474top_srcdir = @top_srcdir@
475version_info = @version_info@
476x_cflags = @x_cflags@
477x_includes = @x_includes@
478x_libs = @x_libs@
479MAINTAINERCLEANFILES = Makefile.in
480AM_CPPFLAGS = \
481-I$(top_builddir)/src/lib/ecore \
482-I$(top_builddir)/src/lib/ecore_con \
483-I$(top_srcdir)/src/lib/ecore \
484-I$(top_srcdir)/src/lib/ecore_con \
485@EFL_ECORE_CON_BUILD@ \
486@SSL_CFLAGS@ \
487@CURL_CFLAGS@ \
488@EINA_CFLAGS@ \
489@TLS_CFLAGS@ \
490@CARES_CFLAGS@ \
491@WIN32_CPPFLAGS@
492
493lib_LTLIBRARIES = libecore_con.la
494includes_HEADERS = Ecore_Con.h
495includesdir = $(includedir)/ecore-@VMAJ@
496libecore_con_la_SOURCES = ecore_con.c ecore_con_ssl.c ecore_con_url.c \
497 ecore_con_alloc.c $(am__append_1) $(am__append_2) \
498 $(am__append_3) $(am__append_4)
499libecore_con_la_CFLAGS = @WIN32_CFLAGS@
500libecore_con_la_LIBADD = \
501$(top_builddir)/src/lib/ecore/libecore.la \
502@SSL_LIBS@ @CURL_LIBS@ @EINA_LIBS@ @TLS_LIBS@ @CARES_LIBS@ @WIN32_LIBS@
503
504libecore_con_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ @release_info@
505EXTRA_DIST = ecore_con_private.h
506all: all-am
507
508.SUFFIXES:
509.SUFFIXES: .c .lo .o .obj
510$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
511 @for dep in $?; do \
512 case '$(am__configure_deps)' in \
513 *$$dep*) \
514 ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
515 && { if test -f $@; then exit 0; else break; fi; }; \
516 exit 1;; \
517 esac; \
518 done; \
519 echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lib/ecore_con/Makefile'; \
520 $(am__cd) $(top_srcdir) && \
521 $(AUTOMAKE) --gnu src/lib/ecore_con/Makefile
522.PRECIOUS: Makefile
523Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
524 @case '$?' in \
525 *config.status*) \
526 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
527 *) \
528 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
529 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
530 esac;
531
532$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
533 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
534
535$(top_srcdir)/configure: $(am__configure_deps)
536 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
537$(ACLOCAL_M4): $(am__aclocal_m4_deps)
538 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
539$(am__aclocal_m4_deps):
540install-libLTLIBRARIES: $(lib_LTLIBRARIES)
541 @$(NORMAL_INSTALL)
542 test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
543 @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
544 list2=; for p in $$list; do \
545 if test -f $$p; then \
546 list2="$$list2 $$p"; \
547 else :; fi; \
548 done; \
549 test -z "$$list2" || { \
550 echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
551 $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
552 }
553
554uninstall-libLTLIBRARIES:
555 @$(NORMAL_UNINSTALL)
556 @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
557 for p in $$list; do \
558 $(am__strip_dir) \
559 echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
560 $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
561 done
562
563clean-libLTLIBRARIES:
564 -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
565 @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
566 dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
567 test "$$dir" != "$$p" || dir=.; \
568 echo "rm -f \"$${dir}/so_locations\""; \
569 rm -f "$${dir}/so_locations"; \
570 done
571libecore_con.la: $(libecore_con_la_OBJECTS) $(libecore_con_la_DEPENDENCIES)
572 $(AM_V_CCLD)$(libecore_con_la_LINK) -rpath $(libdir) $(libecore_con_la_OBJECTS) $(libecore_con_la_LIBADD) $(LIBS)
573
574mostlyclean-compile:
575 -rm -f *.$(OBJEXT)
576
577distclean-compile:
578 -rm -f *.tab.c
579
580@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libecore_con_la-ecore_con.Plo@am__quote@
581@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libecore_con_la-ecore_con_alloc.Plo@am__quote@
582@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libecore_con_la-ecore_con_ares.Plo@am__quote@
583@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libecore_con_la-ecore_con_info.Plo@am__quote@
584@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libecore_con_la-ecore_con_local.Plo@am__quote@
585@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libecore_con_la-ecore_con_local_win32.Plo@am__quote@
586@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libecore_con_la-ecore_con_ssl.Plo@am__quote@
587@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libecore_con_la-ecore_con_url.Plo@am__quote@
588
589.c.o:
590@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
591@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
592@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
593@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
594@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
595@am__fastdepCC_FALSE@ $(COMPILE) -c $<
596
597.c.obj:
598@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
599@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
600@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
601@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
602@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
603@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
604
605.c.lo:
606@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
607@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
608@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
609@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
610@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
611@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
612
613libecore_con_la-ecore_con.lo: ecore_con.c
614@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -MT libecore_con_la-ecore_con.lo -MD -MP -MF $(DEPDIR)/libecore_con_la-ecore_con.Tpo -c -o libecore_con_la-ecore_con.lo `test -f 'ecore_con.c' || echo '$(srcdir)/'`ecore_con.c
615@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libecore_con_la-ecore_con.Tpo $(DEPDIR)/libecore_con_la-ecore_con.Plo
616@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
617@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ecore_con.c' object='libecore_con_la-ecore_con.lo' libtool=yes @AMDEPBACKSLASH@
618@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
619@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -c -o libecore_con_la-ecore_con.lo `test -f 'ecore_con.c' || echo '$(srcdir)/'`ecore_con.c
620
621libecore_con_la-ecore_con_ssl.lo: ecore_con_ssl.c
622@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -MT libecore_con_la-ecore_con_ssl.lo -MD -MP -MF $(DEPDIR)/libecore_con_la-ecore_con_ssl.Tpo -c -o libecore_con_la-ecore_con_ssl.lo `test -f 'ecore_con_ssl.c' || echo '$(srcdir)/'`ecore_con_ssl.c
623@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libecore_con_la-ecore_con_ssl.Tpo $(DEPDIR)/libecore_con_la-ecore_con_ssl.Plo
624@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
625@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ecore_con_ssl.c' object='libecore_con_la-ecore_con_ssl.lo' libtool=yes @AMDEPBACKSLASH@
626@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
627@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -c -o libecore_con_la-ecore_con_ssl.lo `test -f 'ecore_con_ssl.c' || echo '$(srcdir)/'`ecore_con_ssl.c
628
629libecore_con_la-ecore_con_url.lo: ecore_con_url.c
630@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -MT libecore_con_la-ecore_con_url.lo -MD -MP -MF $(DEPDIR)/libecore_con_la-ecore_con_url.Tpo -c -o libecore_con_la-ecore_con_url.lo `test -f 'ecore_con_url.c' || echo '$(srcdir)/'`ecore_con_url.c
631@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libecore_con_la-ecore_con_url.Tpo $(DEPDIR)/libecore_con_la-ecore_con_url.Plo
632@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
633@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ecore_con_url.c' object='libecore_con_la-ecore_con_url.lo' libtool=yes @AMDEPBACKSLASH@
634@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
635@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -c -o libecore_con_la-ecore_con_url.lo `test -f 'ecore_con_url.c' || echo '$(srcdir)/'`ecore_con_url.c
636
637libecore_con_la-ecore_con_alloc.lo: ecore_con_alloc.c
638@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -MT libecore_con_la-ecore_con_alloc.lo -MD -MP -MF $(DEPDIR)/libecore_con_la-ecore_con_alloc.Tpo -c -o libecore_con_la-ecore_con_alloc.lo `test -f 'ecore_con_alloc.c' || echo '$(srcdir)/'`ecore_con_alloc.c
639@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libecore_con_la-ecore_con_alloc.Tpo $(DEPDIR)/libecore_con_la-ecore_con_alloc.Plo
640@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
641@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ecore_con_alloc.c' object='libecore_con_la-ecore_con_alloc.lo' libtool=yes @AMDEPBACKSLASH@
642@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
643@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -c -o libecore_con_la-ecore_con_alloc.lo `test -f 'ecore_con_alloc.c' || echo '$(srcdir)/'`ecore_con_alloc.c
644
645libecore_con_la-ecore_con_local_win32.lo: ecore_con_local_win32.c
646@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -MT libecore_con_la-ecore_con_local_win32.lo -MD -MP -MF $(DEPDIR)/libecore_con_la-ecore_con_local_win32.Tpo -c -o libecore_con_la-ecore_con_local_win32.lo `test -f 'ecore_con_local_win32.c' || echo '$(srcdir)/'`ecore_con_local_win32.c
647@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libecore_con_la-ecore_con_local_win32.Tpo $(DEPDIR)/libecore_con_la-ecore_con_local_win32.Plo
648@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
649@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ecore_con_local_win32.c' object='libecore_con_la-ecore_con_local_win32.lo' libtool=yes @AMDEPBACKSLASH@
650@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
651@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -c -o libecore_con_la-ecore_con_local_win32.lo `test -f 'ecore_con_local_win32.c' || echo '$(srcdir)/'`ecore_con_local_win32.c
652
653libecore_con_la-ecore_con_local.lo: ecore_con_local.c
654@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -MT libecore_con_la-ecore_con_local.lo -MD -MP -MF $(DEPDIR)/libecore_con_la-ecore_con_local.Tpo -c -o libecore_con_la-ecore_con_local.lo `test -f 'ecore_con_local.c' || echo '$(srcdir)/'`ecore_con_local.c
655@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libecore_con_la-ecore_con_local.Tpo $(DEPDIR)/libecore_con_la-ecore_con_local.Plo
656@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
657@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ecore_con_local.c' object='libecore_con_la-ecore_con_local.lo' libtool=yes @AMDEPBACKSLASH@
658@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
659@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -c -o libecore_con_la-ecore_con_local.lo `test -f 'ecore_con_local.c' || echo '$(srcdir)/'`ecore_con_local.c
660
661libecore_con_la-ecore_con_ares.lo: ecore_con_ares.c
662@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -MT libecore_con_la-ecore_con_ares.lo -MD -MP -MF $(DEPDIR)/libecore_con_la-ecore_con_ares.Tpo -c -o libecore_con_la-ecore_con_ares.lo `test -f 'ecore_con_ares.c' || echo '$(srcdir)/'`ecore_con_ares.c
663@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libecore_con_la-ecore_con_ares.Tpo $(DEPDIR)/libecore_con_la-ecore_con_ares.Plo
664@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
665@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ecore_con_ares.c' object='libecore_con_la-ecore_con_ares.lo' libtool=yes @AMDEPBACKSLASH@
666@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
667@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -c -o libecore_con_la-ecore_con_ares.lo `test -f 'ecore_con_ares.c' || echo '$(srcdir)/'`ecore_con_ares.c
668
669libecore_con_la-ecore_con_info.lo: ecore_con_info.c
670@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -MT libecore_con_la-ecore_con_info.lo -MD -MP -MF $(DEPDIR)/libecore_con_la-ecore_con_info.Tpo -c -o libecore_con_la-ecore_con_info.lo `test -f 'ecore_con_info.c' || echo '$(srcdir)/'`ecore_con_info.c
671@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libecore_con_la-ecore_con_info.Tpo $(DEPDIR)/libecore_con_la-ecore_con_info.Plo
672@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
673@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ecore_con_info.c' object='libecore_con_la-ecore_con_info.lo' libtool=yes @AMDEPBACKSLASH@
674@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
675@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libecore_con_la_CFLAGS) $(CFLAGS) -c -o libecore_con_la-ecore_con_info.lo `test -f 'ecore_con_info.c' || echo '$(srcdir)/'`ecore_con_info.c
676
677mostlyclean-libtool:
678 -rm -f *.lo
679
680clean-libtool:
681 -rm -rf .libs _libs
682install-includesHEADERS: $(includes_HEADERS)
683 @$(NORMAL_INSTALL)
684 test -z "$(includesdir)" || $(MKDIR_P) "$(DESTDIR)$(includesdir)"
685 @list='$(includes_HEADERS)'; test -n "$(includesdir)" || list=; \
686 for p in $$list; do \
687 if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
688 echo "$$d$$p"; \
689 done | $(am__base_list) | \
690 while read files; do \
691 echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includesdir)'"; \
692 $(INSTALL_HEADER) $$files "$(DESTDIR)$(includesdir)" || exit $$?; \
693 done
694
695uninstall-includesHEADERS:
696 @$(NORMAL_UNINSTALL)
697 @list='$(includes_HEADERS)'; test -n "$(includesdir)" || list=; \
698 files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
699 test -n "$$files" || exit 0; \
700 echo " ( cd '$(DESTDIR)$(includesdir)' && rm -f" $$files ")"; \
701 cd "$(DESTDIR)$(includesdir)" && rm -f $$files
702
703ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
704 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
705 unique=`for i in $$list; do \
706 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
707 done | \
708 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
709 END { if (nonempty) { for (i in files) print i; }; }'`; \
710 mkid -fID $$unique
711tags: TAGS
712
713TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
714 $(TAGS_FILES) $(LISP)
715 set x; \
716 here=`pwd`; \
717 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
718 unique=`for i in $$list; do \
719 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
720 done | \
721 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
722 END { if (nonempty) { for (i in files) print i; }; }'`; \
723 shift; \
724 if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
725 test -n "$$unique" || unique=$$empty_fix; \
726 if test $$# -gt 0; then \
727 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
728 "$$@" $$unique; \
729 else \
730 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
731 $$unique; \
732 fi; \
733 fi
734ctags: CTAGS
735CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
736 $(TAGS_FILES) $(LISP)
737 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
738 unique=`for i in $$list; do \
739 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
740 done | \
741 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
742 END { if (nonempty) { for (i in files) print i; }; }'`; \
743 test -z "$(CTAGS_ARGS)$$unique" \
744 || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
745 $$unique
746
747GTAGS:
748 here=`$(am__cd) $(top_builddir) && pwd` \
749 && $(am__cd) $(top_srcdir) \
750 && gtags -i $(GTAGS_ARGS) "$$here"
751
752distclean-tags:
753 -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
754
755distdir: $(DISTFILES)
756 @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
757 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
758 list='$(DISTFILES)'; \
759 dist_files=`for file in $$list; do echo $$file; done | \
760 sed -e "s|^$$srcdirstrip/||;t" \
761 -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
762 case $$dist_files in \
763 */*) $(MKDIR_P) `echo "$$dist_files" | \
764 sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
765 sort -u` ;; \
766 esac; \
767 for file in $$dist_files; do \
768 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
769 if test -d $$d/$$file; then \
770 dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
771 if test -d "$(distdir)/$$file"; then \
772 find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
773 fi; \
774 if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
775 cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
776 find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
777 fi; \
778 cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
779 else \
780 test -f "$(distdir)/$$file" \
781 || cp -p $$d/$$file "$(distdir)/$$file" \
782 || exit 1; \
783 fi; \
784 done
785check-am: all-am
786check: check-am
787all-am: Makefile $(LTLIBRARIES) $(HEADERS)
788installdirs:
789 for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includesdir)"; do \
790 test -z "$$dir" || $(MKDIR_P) "$$dir"; \
791 done
792install: install-am
793install-exec: install-exec-am
794install-data: install-data-am
795uninstall: uninstall-am
796
797install-am: all-am
798 @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
799
800installcheck: installcheck-am
801install-strip:
802 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
803 install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
804 `test -z '$(STRIP)' || \
805 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
806mostlyclean-generic:
807
808clean-generic:
809
810distclean-generic:
811 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
812 -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
813
814maintainer-clean-generic:
815 @echo "This command is intended for maintainers to use"
816 @echo "it deletes files that may require special tools to rebuild."
817 -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
818clean: clean-am
819
820clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
821 mostlyclean-am
822
823distclean: distclean-am
824 -rm -rf ./$(DEPDIR)
825 -rm -f Makefile
826distclean-am: clean-am distclean-compile distclean-generic \
827 distclean-tags
828
829dvi: dvi-am
830
831dvi-am:
832
833html: html-am
834
835html-am:
836
837info: info-am
838
839info-am:
840
841install-data-am: install-includesHEADERS
842
843install-dvi: install-dvi-am
844
845install-dvi-am:
846
847install-exec-am: install-libLTLIBRARIES
848
849install-html: install-html-am
850
851install-html-am:
852
853install-info: install-info-am
854
855install-info-am:
856
857install-man:
858
859install-pdf: install-pdf-am
860
861install-pdf-am:
862
863install-ps: install-ps-am
864
865install-ps-am:
866
867installcheck-am:
868
869maintainer-clean: maintainer-clean-am
870 -rm -rf ./$(DEPDIR)
871 -rm -f Makefile
872maintainer-clean-am: distclean-am maintainer-clean-generic
873
874mostlyclean: mostlyclean-am
875
876mostlyclean-am: mostlyclean-compile mostlyclean-generic \
877 mostlyclean-libtool
878
879pdf: pdf-am
880
881pdf-am:
882
883ps: ps-am
884
885ps-am:
886
887uninstall-am: uninstall-includesHEADERS uninstall-libLTLIBRARIES
888
889.MAKE: install-am install-strip
890
891.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
892 clean-libLTLIBRARIES clean-libtool ctags distclean \
893 distclean-compile distclean-generic distclean-libtool \
894 distclean-tags distdir dvi dvi-am html html-am info info-am \
895 install install-am install-data install-data-am install-dvi \
896 install-dvi-am install-exec install-exec-am install-html \
897 install-html-am install-includesHEADERS install-info \
898 install-info-am install-libLTLIBRARIES install-man install-pdf \
899 install-pdf-am install-ps install-ps-am install-strip \
900 installcheck installcheck-am installdirs maintainer-clean \
901 maintainer-clean-generic mostlyclean mostlyclean-compile \
902 mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
903 tags uninstall uninstall-am uninstall-includesHEADERS \
904 uninstall-libLTLIBRARIES
905
906
907# Tell versions [3.59,3.63) of GNU make to not export all variables.
908# Otherwise a system limit (for SysV at least) may be exceeded.
909.NOEXPORT:
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con.c b/libraries/ecore/src/lib/ecore_con/ecore_con.c
new file mode 100644
index 0000000..7bd0358
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con.c
@@ -0,0 +1,2600 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <string.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <errno.h>
10#include <unistd.h>
11#include <fcntl.h>
12
13#ifdef HAVE_NETINET_TCP_H
14# include <netinet/tcp.h>
15#endif
16
17#ifdef HAVE_NETINET_IN_H
18# include <netinet/in.h>
19#endif
20
21#ifdef HAVE_ARPA_INET_H
22# include <arpa/inet.h>
23#endif
24
25#ifdef HAVE_SYS_SOCKET_H
26# include <sys/socket.h>
27#endif
28
29#ifdef HAVE_SYS_UN_H
30# include <sys/un.h>
31#endif
32
33#ifdef HAVE_WS2TCPIP_H
34# include <ws2tcpip.h>
35#endif
36
37#ifdef HAVE_EVIL
38# include <Evil.h>
39#endif
40
41#include "Ecore.h"
42#include "ecore_private.h"
43#include "Ecore_Con.h"
44#include "ecore_con_private.h"
45
46static Eina_Bool _ecore_con_client_timer(Ecore_Con_Client *cl);
47static void _ecore_con_cl_timer_update(Ecore_Con_Client *cl);
48
49static Eina_Bool _ecore_con_server_timer(Ecore_Con_Server *svr);
50static void _ecore_con_server_timer_update(Ecore_Con_Server *svr);
51
52static void _ecore_con_cb_tcp_connect(void *data,
53 Ecore_Con_Info *info);
54static void _ecore_con_cb_udp_connect(void *data,
55 Ecore_Con_Info *info);
56static void _ecore_con_cb_tcp_listen(void *data,
57 Ecore_Con_Info *info);
58static void _ecore_con_cb_udp_listen(void *data,
59 Ecore_Con_Info *info);
60
61static void _ecore_con_server_free(Ecore_Con_Server *svr);
62static void _ecore_con_client_free(Ecore_Con_Client *cl);
63
64static void _ecore_con_cl_read(Ecore_Con_Server *svr);
65static Eina_Bool _ecore_con_svr_tcp_handler(void *data,
66 Ecore_Fd_Handler *fd_handler);
67static Eina_Bool _ecore_con_cl_handler(void *data,
68 Ecore_Fd_Handler *fd_handler);
69static Eina_Bool _ecore_con_cl_udp_handler(void *data,
70 Ecore_Fd_Handler *fd_handler);
71static Eina_Bool _ecore_con_svr_udp_handler(void *data,
72 Ecore_Fd_Handler *fd_handler);
73
74static void _ecore_con_svr_cl_read(Ecore_Con_Client *cl);
75static Eina_Bool _ecore_con_svr_cl_handler(void *data,
76 Ecore_Fd_Handler *fd_handler);
77
78static void _ecore_con_server_flush(Ecore_Con_Server *svr);
79static void _ecore_con_client_flush(Ecore_Con_Client *cl);
80
81static void _ecore_con_event_client_add_free(Ecore_Con_Server *svr,
82 void *ev);
83static void _ecore_con_event_client_del_free(Ecore_Con_Server *svr,
84 void *ev);
85static void _ecore_con_event_client_data_free(Ecore_Con_Server *svr,
86 void *ev);
87static void _ecore_con_event_server_add_free(void *data,
88 void *ev);
89static void _ecore_con_event_server_del_free(void *data,
90 void *ev);
91static void _ecore_con_event_server_data_free(void *data,
92 void *ev);
93static void _ecore_con_event_server_error_free(void *data,
94 Ecore_Con_Event_Server_Error *e);
95static void _ecore_con_event_client_error_free(Ecore_Con_Server *svr,
96 Ecore_Con_Event_Client_Error *e);
97static void _ecore_con_event_server_write_free(void *data,
98 Ecore_Con_Event_Server_Write *e);
99static void _ecore_con_event_client_write_free(Ecore_Con_Server *svr,
100 Ecore_Con_Event_Client_Write *e);
101
102static void _ecore_con_lookup_done(void *data,
103 Ecore_Con_Info *infos);
104
105static const char * _ecore_con_pretty_ip(struct sockaddr *client_addr);
106
107EAPI int ECORE_CON_EVENT_CLIENT_ADD = 0;
108EAPI int ECORE_CON_EVENT_CLIENT_DEL = 0;
109EAPI int ECORE_CON_EVENT_SERVER_ADD = 0;
110EAPI int ECORE_CON_EVENT_SERVER_DEL = 0;
111EAPI int ECORE_CON_EVENT_CLIENT_DATA = 0;
112EAPI int ECORE_CON_EVENT_SERVER_DATA = 0;
113EAPI int ECORE_CON_EVENT_CLIENT_WRITE = 0;
114EAPI int ECORE_CON_EVENT_SERVER_WRITE = 0;
115EAPI int ECORE_CON_EVENT_CLIENT_ERROR = 0;
116EAPI int ECORE_CON_EVENT_SERVER_ERROR = 0;
117
118static Eina_List *servers = NULL;
119static int _ecore_con_init_count = 0;
120static int _ecore_con_event_count = 0;
121int _ecore_con_log_dom = -1;
122
123EAPI int
124ecore_con_init(void)
125{
126 if (++_ecore_con_init_count != 1)
127 return _ecore_con_init_count;
128
129#ifdef HAVE_EVIL
130 if (!evil_init())
131 return --_ecore_con_init_count;
132
133#endif
134
135 if (!ecore_init())
136 return --_ecore_con_init_count;
137
138 _ecore_con_log_dom = eina_log_domain_register
139 ("ecore_con", ECORE_CON_DEFAULT_LOG_COLOR);
140 if (_ecore_con_log_dom < 0)
141 {
142 EINA_LOG_ERR("Impossible to create a log domain for Ecore Con.");
143 ecore_shutdown();
144 return --_ecore_con_init_count;
145 }
146
147 ecore_con_mempool_init();
148
149 ECORE_CON_EVENT_CLIENT_ADD = ecore_event_type_new();
150 ECORE_CON_EVENT_CLIENT_DEL = ecore_event_type_new();
151 ECORE_CON_EVENT_SERVER_ADD = ecore_event_type_new();
152 ECORE_CON_EVENT_SERVER_DEL = ecore_event_type_new();
153 ECORE_CON_EVENT_CLIENT_DATA = ecore_event_type_new();
154 ECORE_CON_EVENT_SERVER_DATA = ecore_event_type_new();
155 ECORE_CON_EVENT_CLIENT_WRITE = ecore_event_type_new();
156 ECORE_CON_EVENT_SERVER_WRITE = ecore_event_type_new();
157 ECORE_CON_EVENT_CLIENT_ERROR = ecore_event_type_new();
158 ECORE_CON_EVENT_SERVER_ERROR = ecore_event_type_new();
159
160
161 eina_magic_string_set(ECORE_MAGIC_CON_SERVER, "Ecore_Con_Server");
162 eina_magic_string_set(ECORE_MAGIC_CON_CLIENT, "Ecore_Con_Server");
163 eina_magic_string_set(ECORE_MAGIC_CON_URL, "Ecore_Con_Url");
164
165 /* TODO Remember return value, if it fails, use gethostbyname() */
166 ecore_con_ssl_init();
167 ecore_con_info_init();
168
169 return _ecore_con_init_count;
170}
171
172EAPI int
173ecore_con_shutdown(void)
174{
175 Eina_List *l, *l2;
176 Ecore_Con_Server *svr;
177
178 if (--_ecore_con_init_count != 0)
179 return _ecore_con_init_count;
180
181 EINA_LIST_FOREACH_SAFE(servers, l, l2, svr)
182 {
183 Ecore_Con_Event_Server_Add *ev;
184
185 svr->delete_me = svr->dead = EINA_TRUE;
186 /* some pointer hacks here to prevent double frees if people are being stupid */
187 EINA_LIST_FREE(svr->event_count, ev)
188 ev->server = NULL;
189 _ecore_con_server_free(svr);
190 }
191
192 if (!_ecore_con_event_count) ecore_con_mempool_shutdown();
193
194 ecore_con_info_shutdown();
195 ecore_con_ssl_shutdown();
196 eina_log_domain_unregister(_ecore_con_log_dom);
197 _ecore_con_log_dom = -1;
198 ecore_shutdown();
199#ifdef HAVE_EVIL
200 evil_shutdown();
201#endif
202
203 return _ecore_con_init_count;
204}
205
206EAPI Eina_Bool
207ecore_con_lookup(const char *name,
208 Ecore_Con_Dns_Cb done_cb,
209 const void *data)
210{
211 Ecore_Con_Server *svr;
212 Ecore_Con_Lookup *lk;
213 struct addrinfo hints;
214
215 if (!name || !done_cb)
216 return EINA_FALSE;
217
218 svr = calloc(1, sizeof(Ecore_Con_Server));
219 if (!svr)
220 return EINA_FALSE;
221
222 lk = malloc(sizeof (Ecore_Con_Lookup));
223 if (!lk)
224 {
225 free(svr);
226 return EINA_FALSE;
227 }
228
229 lk->done_cb = done_cb;
230 lk->data = data;
231
232 svr->name = strdup(name);
233 if (!svr->name)
234 goto on_error;
235
236 svr->type = ECORE_CON_REMOTE_TCP;
237 svr->port = 1025;
238 svr->data = lk;
239 svr->created = EINA_TRUE;
240 svr->reject_excess_clients = EINA_FALSE;
241 svr->client_limit = -1;
242 svr->clients = NULL;
243 svr->ppid = getpid();
244
245 memset(&hints, 0, sizeof(struct addrinfo));
246 hints.ai_family = AF_UNSPEC;
247 hints.ai_socktype = SOCK_STREAM;
248 hints.ai_flags = AI_CANONNAME;
249 hints.ai_protocol = IPPROTO_TCP;
250 hints.ai_canonname = NULL;
251 hints.ai_next = NULL;
252 hints.ai_addr = NULL;
253
254 if (ecore_con_info_get(svr, _ecore_con_lookup_done, svr,
255 &hints))
256 return EINA_TRUE;
257
258 free(svr->name);
259on_error:
260 free(lk);
261 free(svr);
262 return EINA_FALSE;
263}
264
265/**
266 * @addtogroup Ecore_Con_Server_Group Ecore Connection Server Functions
267 *
268 * Functions that operate on Ecore server objects.
269 *
270 * @{
271 */
272
273/**
274 * @example ecore_con_server_example.c
275 * Shows how to write a simple server using the Ecore_Con library.
276 */
277
278EAPI Ecore_Con_Server *
279ecore_con_server_add(Ecore_Con_Type compl_type,
280 const char *name,
281 int port,
282 const void *data)
283{
284 Ecore_Con_Server *svr;
285 Ecore_Con_Type type;
286
287 if (port < 0 || !name)
288 return NULL; /* local user socket: FILE: ~/.ecore/[name]/[port] */
289
290 /* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */
291 /* remote system socket: TCP/IP: [name]:[port] */
292 svr = calloc(1, sizeof(Ecore_Con_Server));
293 if (!svr)
294 return NULL;
295
296 svr->name = strdup(name);
297 if (!svr->name)
298 goto error;
299
300 svr->type = compl_type;
301 svr->port = port;
302 svr->data = (void *)data;
303 svr->created = EINA_TRUE;
304 if (compl_type & ECORE_CON_LOAD_CERT)
305 svr->use_cert = EINA_TRUE;
306 svr->reject_excess_clients = EINA_FALSE;
307 svr->client_limit = -1;
308 svr->clients = NULL;
309 svr->ppid = getpid();
310 if (ecore_con_ssl_server_prepare(svr, compl_type & ECORE_CON_SSL))
311 goto error;
312
313 type = compl_type & ECORE_CON_TYPE;
314
315 if ((type == ECORE_CON_LOCAL_USER) ||
316 (type == ECORE_CON_LOCAL_SYSTEM) ||
317 (type == ECORE_CON_LOCAL_ABSTRACT))
318 /* Local */
319#ifdef _WIN32
320 if (!ecore_con_local_listen(svr))
321 goto error;
322#else
323 if (!ecore_con_local_listen(svr, _ecore_con_svr_tcp_handler, svr))
324 goto error;
325#endif
326
327 if ((type == ECORE_CON_REMOTE_TCP) ||
328 (type == ECORE_CON_REMOTE_NODELAY))
329 {
330 /* TCP */
331 if (!ecore_con_info_tcp_listen(svr, _ecore_con_cb_tcp_listen,
332 svr))
333 goto error;
334 }
335 else if ((type == ECORE_CON_REMOTE_MCAST) ||
336 (type == ECORE_CON_REMOTE_UDP))
337 /* UDP and MCAST */
338 if (!ecore_con_info_udp_listen(svr, _ecore_con_cb_udp_listen,
339 svr))
340 goto error;
341
342 servers = eina_list_append(servers, svr);
343 ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
344
345 return svr;
346
347error:
348 if (svr->name)
349 free(svr->name);
350
351 if (svr->path)
352 free(svr->path);
353
354
355 if (svr->fd_handler)
356 ecore_main_fd_handler_del(svr->fd_handler);
357
358 if (svr->fd > 0)
359 close(svr->fd);
360
361 if (svr->buf)
362 eina_binbuf_free(svr->buf);
363
364 if (svr->ip)
365 eina_stringshare_del(svr->ip);
366
367 ecore_con_ssl_server_shutdown(svr);
368 free(svr);
369 return NULL;
370}
371
372EAPI Ecore_Con_Server *
373ecore_con_server_connect(Ecore_Con_Type compl_type,
374 const char *name,
375 int port,
376 const void *data)
377{
378 Ecore_Con_Server *svr;
379 Ecore_Con_Type type;
380
381 if ((!name) || (!name[0]))
382 return NULL;
383 /* local user socket: FILE: ~/.ecore/[name]/[port] */
384 /* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */
385 /* remote system socket: TCP/IP: [name]:[port] */
386 svr = calloc(1, sizeof(Ecore_Con_Server));
387 if (!svr)
388 return NULL;
389
390 svr->name = strdup(name);
391 if (!svr->name)
392 goto error;
393
394 svr->type = compl_type;
395 svr->port = port;
396 svr->data = (void *)data;
397 svr->created = EINA_FALSE;
398 svr->use_cert = (compl_type & ECORE_CON_LOAD_CERT);
399 svr->reject_excess_clients = EINA_FALSE;
400 svr->clients = NULL;
401 svr->client_limit = -1;
402 if (ecore_con_ssl_server_prepare(svr, compl_type & ECORE_CON_SSL))
403 goto error;
404
405 type = compl_type & ECORE_CON_TYPE;
406
407 if (((type == ECORE_CON_REMOTE_TCP) ||
408 (type == ECORE_CON_REMOTE_NODELAY) ||
409 (type == ECORE_CON_REMOTE_UDP) ||
410 (type == ECORE_CON_REMOTE_BROADCAST)) &&
411 (port < 0))
412 goto error;
413
414 if ((type == ECORE_CON_LOCAL_USER) ||
415 (type == ECORE_CON_LOCAL_SYSTEM) ||
416 (type == ECORE_CON_LOCAL_ABSTRACT))
417 /* Local */
418#ifdef _WIN32
419 if (!ecore_con_local_connect(svr, _ecore_con_cl_handler))
420 goto error;
421#else
422 if (!ecore_con_local_connect(svr, _ecore_con_cl_handler, svr))
423 goto error;
424#endif
425
426 if ((type == ECORE_CON_REMOTE_TCP) ||
427 (type == ECORE_CON_REMOTE_NODELAY))
428 {
429 /* TCP */
430 if (!ecore_con_info_tcp_connect(svr, _ecore_con_cb_tcp_connect,
431 svr))
432 goto error;
433 }
434 else if ((type == ECORE_CON_REMOTE_UDP) ||
435 (type == ECORE_CON_REMOTE_BROADCAST))
436 /* UDP and MCAST */
437 if (!ecore_con_info_udp_connect(svr, _ecore_con_cb_udp_connect,
438 svr))
439 goto error;
440
441 servers = eina_list_append(servers, svr);
442 ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
443
444 return svr;
445
446error:
447 if (svr->name)
448 free(svr->name);
449
450 if (svr->path)
451 free(svr->path);
452
453 if (svr->fd_handler)
454 ecore_main_fd_handler_del(svr->fd_handler);
455
456 if (svr->fd > 0)
457 close(svr->fd);
458
459 ecore_con_ssl_server_shutdown(svr);
460 free(svr);
461 return NULL;
462}
463
464EAPI void
465ecore_con_server_timeout_set(Ecore_Con_Server *svr,
466 double timeout)
467{
468 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
469 {
470 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_timeout_set");
471 return;
472 }
473
474 if (svr->created)
475 svr->client_disconnect_time = timeout;
476 else
477 svr->disconnect_time = timeout;
478}
479
480EAPI double
481ecore_con_server_timeout_get(Ecore_Con_Server *svr)
482{
483 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
484 {
485 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_timeout_get");
486 return 0;
487 }
488
489 return svr->created ? svr->client_disconnect_time : svr->disconnect_time;
490}
491
492EAPI void *
493ecore_con_server_del(Ecore_Con_Server *svr)
494{
495 void *data;
496
497 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
498 {
499 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_del");
500 return NULL;
501 }
502
503 if (svr->delete_me)
504 return NULL;
505
506 data = svr->data;
507 svr->delete_me = EINA_TRUE;
508 if (svr->event_count)
509 {
510 if (svr->fd_handler)
511 {
512 ecore_main_fd_handler_del(svr->fd_handler);
513 svr->fd_handler = NULL;
514 }
515 }
516 else
517 _ecore_con_server_free(svr);
518
519 return data;
520}
521
522EAPI void *
523ecore_con_server_data_get(Ecore_Con_Server *svr)
524{
525 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
526 {
527 ECORE_MAGIC_FAIL(svr,
528 ECORE_MAGIC_CON_SERVER,
529 "ecore_con_server_data_get");
530 return NULL;
531 }
532
533 return svr->data;
534}
535
536EAPI void *
537ecore_con_server_data_set(Ecore_Con_Server *svr,
538 void *data)
539{
540 void *ret = NULL;
541
542 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
543 {
544 ECORE_MAGIC_FAIL(svr,
545 ECORE_MAGIC_CON_SERVER,
546 "ecore_con_server_data_get");
547 return NULL;
548 }
549
550 ret = svr->data;
551 svr->data = data;
552 return ret;
553}
554
555EAPI Eina_Bool
556ecore_con_server_connected_get(Ecore_Con_Server *svr)
557{
558 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
559 {
560 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER,
561 "ecore_con_server_connected_get");
562 return EINA_FALSE;
563 }
564
565 if (svr->connecting)
566 return EINA_FALSE;
567
568 return EINA_TRUE;
569}
570
571EAPI const Eina_List *
572ecore_con_server_clients_get(Ecore_Con_Server *svr)
573{
574 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
575 {
576 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER,
577 "ecore_con_server_clients_get");
578 return NULL;
579 }
580
581 return svr->clients;
582}
583
584EAPI const char *
585ecore_con_server_name_get(Ecore_Con_Server *svr)
586{
587 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
588 {
589 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER,
590 "ecore_con_server_name_get");
591 return NULL;
592 }
593
594 return svr->name;
595}
596
597EAPI int
598ecore_con_server_port_get(Ecore_Con_Server *svr)
599{
600 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
601 {
602 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER,
603 "ecore_con_server_port_get");
604 return -1;
605 }
606 return svr->port;
607}
608
609EAPI int
610ecore_con_server_send(Ecore_Con_Server *svr,
611 const void *data,
612 int size)
613{
614 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
615 {
616 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_send");
617 return 0;
618 }
619
620 EINA_SAFETY_ON_TRUE_RETURN_VAL(svr->dead, 0);
621
622 EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
623
624 EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
625
626 if (svr->fd_handler)
627 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
628
629 if (!svr->buf)
630 {
631 svr->buf = eina_binbuf_new();
632 EINA_SAFETY_ON_NULL_RETURN_VAL(svr->buf, 0);
633 }
634 eina_binbuf_append_length(svr->buf, data, size);
635
636 return size;
637}
638
639EAPI void
640ecore_con_server_client_limit_set(Ecore_Con_Server *svr,
641 int client_limit,
642 char reject_excess_clients)
643{
644 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
645 {
646 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER,
647 "ecore_con_server_client_limit_set");
648 return;
649 }
650
651 svr->client_limit = client_limit;
652 svr->reject_excess_clients = reject_excess_clients;
653}
654
655EAPI const char *
656ecore_con_server_ip_get(Ecore_Con_Server *svr)
657{
658 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
659 {
660 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_ip_get");
661 return NULL;
662 }
663
664 return svr->ip;
665}
666
667EAPI double
668ecore_con_server_uptime_get(Ecore_Con_Server *svr)
669{
670 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
671 {
672 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_uptime_get");
673 return -1;
674 }
675
676 return ecore_time_get() - svr->start_time;
677}
678
679EAPI void
680ecore_con_server_flush(Ecore_Con_Server *svr)
681{
682 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
683 {
684 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_server_flush");
685 return;
686 }
687
688 _ecore_con_server_flush(svr);
689}
690
691/**
692 * @}
693 */
694
695/**
696 * @addtogroup Ecore_Con_Client_Group Ecore Connection Client Functions
697 *
698 * Functions that operate on Ecore connection client objects.
699 *
700 * @{
701 */
702
703/**
704 * @example ecore_con_client_example.c
705 * Shows how to write a simple client that connects to the example server.
706 */
707
708EAPI int
709ecore_con_client_send(Ecore_Con_Client *cl,
710 const void *data,
711 int size)
712{
713 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
714 {
715 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_send");
716 return 0;
717 }
718
719 EINA_SAFETY_ON_TRUE_RETURN_VAL(cl->dead, 0);
720
721 EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
722
723 EINA_SAFETY_ON_TRUE_RETURN_VAL(size < 1, 0);
724
725 if (cl->fd_handler)
726 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
727
728 if (cl->host_server && ((cl->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP))
729 sendto(cl->host_server->fd, data, size, 0, (struct sockaddr *)cl->client_addr,
730 cl->client_addr_len);
731 else if (!cl->buf)
732 {
733 cl->buf = eina_binbuf_new();
734 EINA_SAFETY_ON_NULL_RETURN_VAL(cl->buf, 0);
735 }
736 eina_binbuf_append_length(cl->buf, data, size);
737
738 return size;
739}
740
741EAPI Ecore_Con_Server *
742ecore_con_client_server_get(Ecore_Con_Client *cl)
743{
744 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
745 {
746 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT,
747 "ecore_con_client_server_get");
748 return NULL;
749 }
750
751 return cl->host_server;
752}
753
754EAPI Eina_Bool
755ecore_con_client_connected_get(Ecore_Con_Client *cl)
756{
757 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
758 {
759 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT,
760 "ecore_con_client_connected_get");
761 return EINA_FALSE;
762 }
763
764 return !cl->dead;
765}
766
767EAPI void
768ecore_con_client_timeout_set(Ecore_Con_Client *cl,
769 double timeout)
770{
771 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
772 {
773 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT,
774 "ecore_con_client_timeout_set");
775 return;
776 }
777
778 cl->disconnect_time = timeout;
779
780 _ecore_con_cl_timer_update(cl);
781}
782
783EAPI double
784ecore_con_client_timeout_get(Ecore_Con_Client *cl)
785{
786 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
787 {
788 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_timeout_get");
789 return 0;
790 }
791
792 return cl->disconnect_time;
793}
794
795EAPI void *
796ecore_con_client_del(Ecore_Con_Client *cl)
797{
798 void *data = NULL;
799
800 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
801 {
802 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_del");
803 return NULL;
804 }
805
806 data = cl->data;
807 cl->delete_me = EINA_TRUE;
808 if (cl->event_count)
809 {
810 if (cl->fd_handler)
811 {
812 ecore_main_fd_handler_del(cl->fd_handler);
813 cl->fd_handler = NULL;
814 }
815 }
816 else
817 {
818 if (cl->host_server)
819 {
820 cl->host_server->clients = eina_list_remove(cl->host_server->clients, cl);
821 --cl->host_server->client_count;
822 }
823
824 _ecore_con_client_free(cl);
825 }
826
827 return data;
828}
829
830EAPI void
831ecore_con_client_data_set(Ecore_Con_Client *cl,
832 const void *data)
833{
834 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
835 {
836 ECORE_MAGIC_FAIL(cl,
837 ECORE_MAGIC_CON_CLIENT,
838 "ecore_con_client_data_set");
839 return;
840 }
841
842 cl->data = (void *)data;
843}
844
845EAPI void *
846ecore_con_client_data_get(Ecore_Con_Client *cl)
847{
848 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
849 {
850 ECORE_MAGIC_FAIL(cl,
851 ECORE_MAGIC_CON_CLIENT,
852 "ecore_con_client_data_get");
853 return NULL;
854 }
855
856 return cl->data;
857}
858
859EAPI const char *
860ecore_con_client_ip_get(Ecore_Con_Client *cl)
861{
862 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
863 {
864 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_ip_get");
865 return NULL;
866 }
867 if (!cl->ip)
868 cl->ip = _ecore_con_pretty_ip(cl->client_addr);
869
870 return cl->ip;
871}
872
873EAPI int
874ecore_con_client_port_get(Ecore_Con_Client *cl)
875{
876 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
877 {
878 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_port_get");
879 return -1;
880 }
881 if (cl->client_addr->sa_family == AF_INET)
882 return ((struct sockaddr_in*)cl->client_addr)->sin_port;
883#ifdef HAVE_IPV6
884 return ((struct sockaddr_in6*)cl->client_addr)->sin6_port;
885#else
886 return -1;
887#endif
888}
889
890EAPI double
891ecore_con_client_uptime_get(Ecore_Con_Client *cl)
892{
893 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
894 {
895 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_uptime_get");
896 return -1;
897 }
898
899 return ecore_time_get() - cl->start_time;
900}
901
902EAPI void
903ecore_con_client_flush(Ecore_Con_Client *cl)
904{
905 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
906 {
907 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_flush");
908 return;
909 }
910
911 _ecore_con_client_flush(cl);
912}
913
914EAPI int
915ecore_con_server_fd_get(Ecore_Con_Server *svr)
916{
917 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
918 {
919 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__);
920 return -1;
921 }
922 if (svr->created) return -1;
923 return ecore_main_fd_handler_fd_get(svr->fd_handler);
924}
925
926EAPI int
927ecore_con_client_fd_get(Ecore_Con_Client *cl)
928{
929 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
930 {
931 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, __func__);
932 return -1;
933 }
934 return ecore_main_fd_handler_fd_get(cl->fd_handler);
935}
936
937/**
938 * @}
939 */
940
941void
942ecore_con_event_server_add(Ecore_Con_Server *svr)
943{
944 /* we got our server! */
945 Ecore_Con_Event_Server_Add *e;
946 int ev = ECORE_CON_EVENT_SERVER_ADD;
947
948 e = ecore_con_event_server_add_alloc();
949 EINA_SAFETY_ON_NULL_RETURN(e);
950
951 svr->event_count = eina_list_append(svr->event_count, e);
952 _ecore_con_server_timer_update(svr);
953 e->server = svr;
954 if (svr->upgrade) ev = ECORE_CON_EVENT_SERVER_UPGRADE;
955 ecore_event_add(ev, e,
956 _ecore_con_event_server_add_free, NULL);
957 _ecore_con_event_count++;
958}
959
960void
961ecore_con_event_server_del(Ecore_Con_Server *svr)
962{
963 Ecore_Con_Event_Server_Del *e;
964
965 e = ecore_con_event_server_del_alloc();
966 EINA_SAFETY_ON_NULL_RETURN(e);
967
968 svr->event_count = eina_list_append(svr->event_count, e);
969 _ecore_con_server_timer_update(svr);
970 e->server = svr;
971 ecore_event_add(ECORE_CON_EVENT_SERVER_DEL, e,
972 _ecore_con_event_server_del_free, NULL);
973 _ecore_con_event_count++;
974}
975
976void
977ecore_con_event_server_write(Ecore_Con_Server *svr, int num)
978{
979 Ecore_Con_Event_Server_Write *e;
980
981 e = ecore_con_event_server_write_alloc();
982 EINA_SAFETY_ON_NULL_RETURN(e);
983
984 svr->event_count = eina_list_append(svr->event_count, e);
985 e->server = svr;
986 e->size = num;
987 ecore_event_add(ECORE_CON_EVENT_SERVER_WRITE, e,
988 (Ecore_End_Cb)_ecore_con_event_server_write_free, NULL);
989 _ecore_con_event_count++;
990}
991
992void
993ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num, Eina_Bool duplicate)
994{
995 Ecore_Con_Event_Server_Data *e;
996
997 e = ecore_con_event_server_data_alloc();
998 EINA_SAFETY_ON_NULL_RETURN(e);
999
1000 svr->event_count = eina_list_append(svr->event_count, e);
1001 _ecore_con_server_timer_update(svr);
1002 e->server = svr;
1003 if (duplicate)
1004 {
1005 e->data = malloc(num);
1006 if (!e->data)
1007 {
1008 ERR("server data allocation failure !");
1009 _ecore_con_event_server_data_free(NULL, e);
1010 return;
1011 }
1012 memcpy(e->data, buf, num);
1013 }
1014 else
1015 e->data = buf;
1016 e->size = num;
1017 ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e,
1018 _ecore_con_event_server_data_free, NULL);
1019 _ecore_con_event_count++;
1020}
1021
1022void
1023ecore_con_event_client_add(Ecore_Con_Client *cl)
1024{
1025 Ecore_Con_Event_Client_Add *e;
1026 int ev = ECORE_CON_EVENT_CLIENT_ADD;
1027
1028 e = ecore_con_event_client_add_alloc();
1029 EINA_SAFETY_ON_NULL_RETURN(e);
1030
1031 cl->event_count = eina_list_append(cl->event_count, e);
1032 cl->host_server->event_count = eina_list_append(cl->host_server->event_count, e);
1033 _ecore_con_cl_timer_update(cl);
1034 e->client = cl;
1035 if (cl->upgrade) ev = ECORE_CON_EVENT_CLIENT_UPGRADE;
1036 ecore_event_add(ev, e,
1037 (Ecore_End_Cb)_ecore_con_event_client_add_free, cl->host_server);
1038 _ecore_con_event_count++;
1039}
1040
1041void
1042ecore_con_event_client_del(Ecore_Con_Client *cl)
1043{
1044 Ecore_Con_Event_Client_Del *e;
1045
1046 if (!cl) return;
1047 e = ecore_con_event_client_del_alloc();
1048 EINA_SAFETY_ON_NULL_RETURN(e);
1049 cl->event_count = eina_list_append(cl->event_count, e);
1050
1051 cl->host_server->event_count = eina_list_append(cl->host_server->event_count, e);
1052 _ecore_con_cl_timer_update(cl);
1053 e->client = cl;
1054 ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e,
1055 (Ecore_End_Cb)_ecore_con_event_client_del_free, cl->host_server);
1056 _ecore_con_event_count++;
1057}
1058
1059void
1060ecore_con_event_client_write(Ecore_Con_Client *cl, int num)
1061{
1062 Ecore_Con_Event_Client_Write *e;
1063
1064 e = ecore_con_event_client_write_alloc();
1065 EINA_SAFETY_ON_NULL_RETURN(e);
1066
1067 cl->event_count = eina_list_append(cl->event_count, e);
1068 cl->host_server->event_count = eina_list_append(cl->host_server->event_count, e);
1069 e->client = cl;
1070 e->size = num;
1071 ecore_event_add(ECORE_CON_EVENT_CLIENT_WRITE, e,
1072 (Ecore_End_Cb)_ecore_con_event_client_write_free, cl->host_server);
1073 _ecore_con_event_count++;
1074}
1075
1076void
1077ecore_con_event_client_data(Ecore_Con_Client *cl, unsigned char *buf, int num, Eina_Bool duplicate)
1078{
1079 Ecore_Con_Event_Client_Data *e;
1080
1081 e = ecore_con_event_client_data_alloc();
1082 EINA_SAFETY_ON_NULL_RETURN(e);
1083
1084 cl->event_count = eina_list_append(cl->event_count, e);
1085 cl->host_server->event_count = eina_list_append(cl->host_server->event_count, e);
1086 _ecore_con_cl_timer_update(cl);
1087 e->client = cl;
1088 if (duplicate)
1089 {
1090 e->data = malloc(num);
1091 if (!e->data)
1092 {
1093 ERR("client data allocation failure !");
1094 _ecore_con_event_client_data_free(cl->host_server, e);
1095 return;
1096 }
1097 memcpy(e->data, buf, num);
1098 }
1099 else
1100 e->data = buf;
1101 e->size = num;
1102 ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e,
1103 (Ecore_End_Cb)_ecore_con_event_client_data_free, cl->host_server);
1104 _ecore_con_event_count++;
1105}
1106
1107
1108void
1109ecore_con_server_infos_del(Ecore_Con_Server *svr, void *info)
1110{
1111 svr->infos = eina_list_remove(svr->infos, info);
1112}
1113
1114void
1115ecore_con_event_server_error(Ecore_Con_Server *svr, const char *error)
1116{
1117 Ecore_Con_Event_Server_Error *e;
1118
1119 e = ecore_con_event_server_error_alloc();
1120 EINA_SAFETY_ON_NULL_RETURN(e);
1121
1122 e->server = svr;
1123 e->error = strdup(error);
1124 ERR("%s", error);
1125 svr->event_count = eina_list_append(svr->event_count, e);
1126 ecore_event_add(ECORE_CON_EVENT_SERVER_ERROR, e, (Ecore_End_Cb)_ecore_con_event_server_error_free, NULL);
1127 _ecore_con_event_count++;
1128}
1129
1130void
1131ecore_con_event_client_error(Ecore_Con_Client *cl, const char *error)
1132{
1133 Ecore_Con_Event_Client_Error *e;
1134
1135 e = ecore_con_event_client_error_alloc();
1136 EINA_SAFETY_ON_NULL_RETURN(e);
1137
1138 e->client = cl;
1139 e->error = strdup(error);
1140 ERR("%s", error);
1141 cl->event_count = eina_list_append(cl->event_count, e);
1142 cl->host_server->event_count = eina_list_append(cl->host_server->event_count, e);
1143 ecore_event_add(ECORE_CON_EVENT_CLIENT_ERROR, e, (Ecore_End_Cb)_ecore_con_event_client_error_free, cl->host_server);
1144 _ecore_con_event_count++;
1145}
1146
1147static void
1148_ecore_con_server_free(Ecore_Con_Server *svr)
1149{
1150 Ecore_Con_Client *cl;
1151 double t_start, t;
1152
1153 if (svr->event_count) return;
1154
1155 while (svr->infos)
1156 {
1157 ecore_con_info_data_clear(svr->infos->data);
1158 svr->infos = eina_list_remove_list(svr->infos, svr->infos);
1159 }
1160 if ((!svr->buf) && svr->delete_me && (!svr->dead) && (!svr->event_count))
1161 {
1162 /* this is a catch-all for cases when a server is not properly killed. */
1163 svr->dead = EINA_TRUE;
1164 ecore_con_event_server_del(svr);
1165 return;
1166 }
1167
1168 t_start = ecore_time_get();
1169 while (svr->buf && (!svr->dead))
1170 {
1171 _ecore_con_server_flush(svr);
1172 t = ecore_time_get();
1173 if ((t - t_start) > 0.5)
1174 {
1175 WRN("ECORE_CON: EEK - stuck in _ecore_con_server_free() trying\n"
1176 " to flush data out from the server, and have been for\n"
1177 " %1.1f seconds. This is taking too long. Aborting flush.",
1178 (t - t_start));
1179 break;
1180 }
1181 }
1182
1183#ifdef _WIN32
1184 ecore_con_local_win32_server_del(svr);
1185#endif
1186 if (svr->event_count) return;
1187 ECORE_MAGIC_SET(svr, ECORE_MAGIC_NONE);
1188
1189 if (svr->buf)
1190 eina_binbuf_free(svr->buf);
1191
1192 EINA_LIST_FREE(svr->clients, cl)
1193 {
1194 Ecore_Con_Event_Server_Add *ev;
1195
1196 /* some pointer hacks here to prevent double frees if people are being stupid */
1197 EINA_LIST_FREE(cl->event_count, ev)
1198 ev->server = NULL;
1199 cl->delete_me = cl->dead = EINA_TRUE;
1200 _ecore_con_client_free(cl);
1201 }
1202 if ((svr->created) && (svr->path) && (svr->ppid == getpid()))
1203 unlink(svr->path);
1204
1205 ecore_con_ssl_server_shutdown(svr);
1206 free(svr->name);
1207
1208 free(svr->path);
1209
1210 eina_stringshare_del(svr->ip);
1211
1212 if (svr->fd_handler)
1213 ecore_main_fd_handler_del(svr->fd_handler);
1214
1215 if (svr->fd > 0)
1216 close(svr->fd);
1217
1218 if (svr->until_deletion)
1219 ecore_timer_del(svr->until_deletion);
1220
1221 servers = eina_list_remove(servers, svr);
1222 svr->data = NULL;
1223 free(svr);
1224}
1225
1226static void
1227_ecore_con_client_free(Ecore_Con_Client *cl)
1228{
1229 double t_start, t;
1230
1231 if (cl->event_count) return;
1232
1233 if (cl->delete_me && (!cl->dead) && (!cl->event_count))
1234 {
1235 /* this is a catch-all for cases when a client is not properly killed. */
1236 cl->dead = EINA_TRUE;
1237 ecore_con_event_client_del(cl);
1238 return;
1239 }
1240
1241
1242 t_start = ecore_time_get();
1243 while ((cl->buf) && (!cl->dead))
1244 {
1245 _ecore_con_client_flush(cl);
1246 t = ecore_time_get();
1247 if ((t - t_start) > 0.5)
1248 {
1249 WRN("EEK - stuck in _ecore_con_client_free() trying\n"
1250 " to flush data out from the client, and have been for\n"
1251 " %1.1f seconds. This is taking too long. Aborting flush.",
1252 (t - t_start));
1253 break;
1254 }
1255 }
1256
1257#ifdef _WIN32
1258 ecore_con_local_win32_client_del(cl);
1259#endif
1260
1261 if (cl->event_count) return;
1262 ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE);
1263
1264 free(cl->buf);
1265
1266 if (cl->host_server->type & ECORE_CON_SSL)
1267 ecore_con_ssl_client_shutdown(cl);
1268
1269 if (cl->fd_handler)
1270 ecore_main_fd_handler_del(cl->fd_handler);
1271
1272 if (cl->fd > 0)
1273 close(cl->fd);
1274
1275 free(cl->client_addr);
1276 cl->client_addr = NULL;
1277
1278 if (cl->until_deletion)
1279 ecore_timer_del(cl->until_deletion);
1280
1281 eina_stringshare_del(cl->ip);
1282 cl->data = NULL;
1283 free(cl);
1284 return;
1285}
1286
1287static void
1288_ecore_con_server_kill(Ecore_Con_Server *svr)
1289{
1290 if (!svr->delete_me)
1291 ecore_con_event_server_del(svr);
1292
1293 svr->dead = EINA_TRUE;
1294 if (svr->fd_handler)
1295 ecore_main_fd_handler_del(svr->fd_handler);
1296
1297 svr->fd_handler = NULL;
1298}
1299
1300static Eina_Bool
1301_ecore_con_server_timer(Ecore_Con_Server *svr)
1302{
1303 ecore_con_server_del(svr);
1304
1305 svr->until_deletion = NULL;
1306 return ECORE_CALLBACK_CANCEL;
1307}
1308
1309static void
1310_ecore_con_server_timer_update(Ecore_Con_Server *svr)
1311{
1312 if (svr->disconnect_time)
1313 {
1314 if (svr->disconnect_time > 0)
1315 {
1316 if (svr->until_deletion)
1317 ecore_timer_interval_set(svr->until_deletion, svr->disconnect_time);
1318 else
1319 svr->until_deletion = ecore_timer_add(svr->disconnect_time, (Ecore_Task_Cb)_ecore_con_server_timer, svr);
1320 }
1321 else if (svr->until_deletion)
1322 {
1323 ecore_timer_del(svr->until_deletion);
1324 svr->until_deletion = NULL;
1325 }
1326 }
1327 else
1328 {
1329 if (svr->until_deletion)
1330 {
1331 ecore_timer_del(svr->until_deletion);
1332 svr->until_deletion = NULL;
1333 }
1334 }
1335}
1336
1337static Eina_Bool
1338_ecore_con_client_timer(Ecore_Con_Client *cl)
1339{
1340 ecore_con_client_del(cl);
1341
1342 cl->until_deletion = NULL;
1343 return ECORE_CALLBACK_CANCEL;
1344}
1345
1346static void
1347_ecore_con_cl_timer_update(Ecore_Con_Client *cl)
1348{
1349 if (cl->disconnect_time)
1350 {
1351 if (cl->disconnect_time > 0)
1352 {
1353 if (cl->until_deletion)
1354 ecore_timer_interval_set(cl->until_deletion, cl->disconnect_time);
1355 else
1356 cl->until_deletion = ecore_timer_add(cl->disconnect_time, (Ecore_Task_Cb)_ecore_con_client_timer, cl);
1357 }
1358 else if (cl->until_deletion)
1359 {
1360 ecore_timer_del(cl->until_deletion);
1361 cl->until_deletion = NULL;
1362 }
1363 }
1364 else
1365 {
1366 if (cl->host_server->client_disconnect_time > 0)
1367 {
1368 if (cl->until_deletion)
1369 ecore_timer_interval_set(cl->until_deletion, cl->host_server->client_disconnect_time);
1370 else
1371 cl->until_deletion = ecore_timer_add(cl->host_server->client_disconnect_time, (Ecore_Task_Cb)_ecore_con_client_timer, cl);
1372 }
1373 else if (cl->until_deletion)
1374 {
1375 ecore_timer_del(cl->until_deletion);
1376 cl->until_deletion = NULL;
1377 }
1378 }
1379}
1380
1381static void
1382_ecore_con_cb_tcp_listen(void *data,
1383 Ecore_Con_Info *net_info)
1384{
1385 Ecore_Con_Server *svr;
1386 struct linger lin;
1387
1388 svr = data;
1389
1390 if (!net_info) /* error message has already been handled */
1391 goto error;
1392
1393 svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
1394 net_info->info.ai_protocol);
1395 if (svr->fd < 0)
1396 {
1397 ecore_con_event_server_error(svr, strerror(errno));
1398 goto error;
1399 }
1400
1401 if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
1402 {
1403 ecore_con_event_server_error(svr, strerror(errno));
1404 goto error;
1405 }
1406
1407 if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
1408 {
1409 ecore_con_event_server_error(svr, strerror(errno));
1410 goto error;
1411 }
1412
1413 lin.l_onoff = 1;
1414 lin.l_linger = 0;
1415 if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
1416 sizeof(struct linger)) < 0)
1417 {
1418 ecore_con_event_server_error(svr, strerror(errno));
1419 goto error;
1420 }
1421
1422 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
1423 {
1424#ifdef HAVE_NETINET_TCP_H
1425 int flag = 1;
1426
1427 if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
1428 sizeof(int)) < 0)
1429#endif
1430 {
1431 ecore_con_event_server_error(svr, strerror(errno));
1432 goto error;
1433 }
1434 }
1435
1436 if (bind(svr->fd, net_info->info.ai_addr,
1437 net_info->info.ai_addrlen) < 0)
1438 {
1439 ecore_con_event_server_error(svr, strerror(errno));
1440 goto error;
1441 }
1442 if (listen(svr->fd, 4096) < 0)
1443 {
1444 ecore_con_event_server_error(svr, strerror(errno));
1445 goto error;
1446 }
1447
1448 svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
1449 _ecore_con_svr_tcp_handler, svr, NULL, NULL);
1450 if (!svr->fd_handler)
1451 {
1452 ecore_con_event_server_error(svr, "Memory allocation failure");
1453 goto error;
1454 }
1455
1456 return;
1457
1458error:
1459 ecore_con_ssl_server_shutdown(svr);
1460 _ecore_con_server_kill(svr);
1461}
1462
1463static void
1464_ecore_con_cb_udp_listen(void *data,
1465 Ecore_Con_Info *net_info)
1466{
1467 Ecore_Con_Server *svr;
1468 Ecore_Con_Type type;
1469 struct ip_mreq mreq;
1470#ifdef HAVE_IPV6
1471 struct ipv6_mreq mreq6;
1472#endif
1473 const int on = 1;
1474
1475 svr = data;
1476 type = svr->type;
1477 type &= ECORE_CON_TYPE;
1478
1479 if (!net_info) /* error message has already been handled */
1480 goto error;
1481
1482 svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
1483 net_info->info.ai_protocol);
1484 if (svr->fd < 0)
1485 {
1486 ecore_con_event_server_error(svr, strerror(errno));
1487 goto error;
1488 }
1489
1490 if (type == ECORE_CON_REMOTE_MCAST)
1491 {
1492 if (net_info->info.ai_family == AF_INET)
1493 {
1494 if (!inet_pton(net_info->info.ai_family, net_info->ip,
1495 &mreq.imr_multiaddr))
1496 {
1497 ecore_con_event_server_error(svr, strerror(errno));
1498 goto error;
1499 }
1500
1501 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
1502 if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1503 (const void *)&mreq, sizeof(mreq)) != 0)
1504 {
1505 ecore_con_event_server_error(svr, strerror(errno));
1506 goto error;
1507 }
1508 }
1509#ifdef HAVE_IPV6
1510 else if (net_info->info.ai_family == AF_INET6)
1511 {
1512 if (!inet_pton(net_info->info.ai_family, net_info->ip,
1513 &mreq6.ipv6mr_multiaddr))
1514 {
1515 ecore_con_event_server_error(svr, strerror(errno));
1516 goto error;
1517 }
1518 mreq6.ipv6mr_interface = htonl(INADDR_ANY);
1519 if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
1520 (const void *)&mreq6, sizeof(mreq6)) != 0)
1521 {
1522 ecore_con_event_server_error(svr, strerror(errno));
1523 goto error;
1524 }
1525 }
1526#endif
1527 }
1528
1529 if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) != 0)
1530 {
1531 ecore_con_event_server_error(svr, strerror(errno));
1532 goto error;
1533 }
1534
1535 if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
1536 {
1537 ecore_con_event_server_error(svr, strerror(errno));
1538 goto error;
1539 }
1540
1541 if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
1542 {
1543 ecore_con_event_server_error(svr, strerror(errno));
1544 goto error;
1545 }
1546
1547 if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
1548 {
1549 ecore_con_event_server_error(svr, strerror(errno));
1550 goto error;
1551 }
1552
1553 svr->fd_handler =
1554 ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
1555 _ecore_con_svr_udp_handler, svr, NULL, NULL);
1556 if (!svr->fd_handler)
1557 {
1558 ecore_con_event_server_error(svr, "Memory allocation failure");
1559 goto error;
1560 }
1561
1562 svr->ip = eina_stringshare_add(net_info->ip);
1563
1564 return;
1565
1566error:
1567 ecore_con_ssl_server_shutdown(svr);
1568 _ecore_con_server_kill(svr);
1569}
1570
1571static void
1572_ecore_con_cb_tcp_connect(void *data,
1573 Ecore_Con_Info *net_info)
1574{
1575 Ecore_Con_Server *svr;
1576 int res;
1577 int curstate = 0;
1578
1579 svr = data;
1580
1581 if (!net_info) /* error message has already been handled */
1582 goto error;
1583
1584 svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
1585 net_info->info.ai_protocol);
1586 if (svr->fd < 0)
1587 {
1588 ecore_con_event_server_error(svr, strerror(errno));
1589 goto error;
1590 }
1591
1592 if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
1593 {
1594 ecore_con_event_server_error(svr, strerror(errno));
1595 goto error;
1596 }
1597
1598 if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
1599 {
1600 ecore_con_event_server_error(svr, strerror(errno));
1601 goto error;
1602 }
1603
1604 if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)) < 0)
1605 {
1606 ecore_con_event_server_error(svr, strerror(errno));
1607 goto error;
1608 }
1609
1610 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_NODELAY)
1611 {
1612#ifdef HAVE_NETINET_TCP_H
1613 int flag = 1;
1614
1615 if (setsockopt(svr->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)) < 0)
1616#endif
1617 {
1618 ecore_con_event_server_error(svr, strerror(errno));
1619 goto error;
1620 }
1621 }
1622
1623 res = connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen);
1624#ifdef _WIN32
1625 if (res == SOCKET_ERROR)
1626 {
1627 if (WSAGetLastError() != WSAEINPROGRESS)
1628 goto error; /* FIXME: strerror on windows? */
1629
1630#else
1631 if (res < 0)
1632 {
1633 if (errno != EINPROGRESS)
1634 {
1635 ecore_con_event_server_error(svr, strerror(errno));
1636 goto error;
1637 }
1638
1639#endif
1640 svr->connecting = EINA_TRUE;
1641 svr->fd_handler =
1642 ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
1643 _ecore_con_cl_handler, svr, NULL, NULL);
1644 }
1645 else
1646 svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
1647 _ecore_con_cl_handler, svr, NULL, NULL);
1648
1649 if (svr->type & ECORE_CON_SSL)
1650 {
1651 svr->handshaking = EINA_TRUE;
1652 svr->ssl_state = ECORE_CON_SSL_STATE_INIT;
1653 DBG("beginning ssl handshake");
1654 if (ecore_con_ssl_server_init(svr))
1655 goto error;
1656 }
1657
1658 if (!svr->fd_handler)
1659 {
1660 ecore_con_event_server_error(svr, "Memory allocation failure");
1661 goto error;
1662 }
1663
1664 svr->ip = eina_stringshare_add(net_info->ip);
1665
1666 return;
1667
1668error:
1669 ecore_con_ssl_server_shutdown(svr);
1670 _ecore_con_server_kill(svr);
1671}
1672
1673static void
1674_ecore_con_cb_udp_connect(void *data,
1675 Ecore_Con_Info *net_info)
1676{
1677 Ecore_Con_Server *svr;
1678 int curstate = 0;
1679 int broadcast = 1;
1680 svr = data;
1681
1682 if (!net_info) /* error message has already been handled */
1683 goto error;
1684
1685 svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype,
1686 net_info->info.ai_protocol);
1687 if (svr->fd < 0)
1688 {
1689 ecore_con_event_server_error(svr, strerror(errno));
1690 goto error;
1691 }
1692
1693 if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
1694 {
1695 ecore_con_event_server_error(svr, strerror(errno));
1696 goto error;
1697 }
1698
1699 if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
1700 {
1701 ecore_con_event_server_error(svr, strerror(errno));
1702 goto error;
1703 }
1704
1705 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_BROADCAST)
1706 {
1707 if (setsockopt(svr->fd, SOL_SOCKET, SO_BROADCAST,
1708 (const void *)&broadcast,
1709 sizeof(broadcast)) < 0)
1710 {
1711 ecore_con_event_server_error(svr, strerror(errno));
1712 goto error;
1713 }
1714 }
1715 else if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR,
1716 (const void *)&curstate, sizeof(curstate)) < 0)
1717 {
1718 ecore_con_event_server_error(svr, strerror(errno));
1719 goto error;
1720 }
1721
1722 if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
1723 {
1724 ecore_con_event_server_error(svr, strerror(errno));
1725 goto error;
1726 }
1727
1728 svr->fd_handler = ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
1729 _ecore_con_cl_udp_handler, svr, NULL, NULL);
1730
1731 if (!svr->fd_handler)
1732 {
1733 ecore_con_event_server_error(svr, "Memory allocation failure");
1734 goto error;
1735 }
1736
1737 svr->ip = eina_stringshare_add(net_info->ip);
1738
1739 return;
1740
1741error:
1742 ecore_con_ssl_server_shutdown(svr);
1743 _ecore_con_server_kill(svr);
1744}
1745
1746static Ecore_Con_State
1747svr_try_connect_plain(Ecore_Con_Server *svr)
1748{
1749 int res;
1750 int so_err = 0;
1751 socklen_t size = sizeof(int);
1752
1753 res = getsockopt(svr->fd, SOL_SOCKET, SO_ERROR, (void *)&so_err, &size);
1754#ifdef _WIN32
1755 if (res == SOCKET_ERROR)
1756 so_err = WSAGetLastError();
1757
1758 if ((so_err == WSAEINPROGRESS) && !svr->dead)
1759 return ECORE_CON_INPROGRESS;
1760
1761#else
1762 if (res < 0)
1763 so_err = errno;
1764
1765 if ((so_err == EINPROGRESS) && !svr->dead)
1766 return ECORE_CON_INPROGRESS;
1767
1768#endif
1769
1770 if (so_err)
1771 {
1772 /* we lost our server! */
1773 ecore_con_event_server_error(svr, strerror(errno));
1774 ERR("Connection lost: %s", strerror(so_err));
1775 _ecore_con_server_kill(svr);
1776 return ECORE_CON_DISCONNECTED;
1777 }
1778
1779 if ((!svr->delete_me) && (!svr->handshaking) && svr->connecting)
1780 {
1781 svr->connecting = EINA_FALSE;
1782 svr->start_time = ecore_time_get();
1783 ecore_con_event_server_add(svr);
1784 }
1785
1786 if (svr->fd_handler && (!svr->buf))
1787 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
1788
1789 if (!svr->dead)
1790 return ECORE_CON_CONNECTED;
1791 else
1792 return ECORE_CON_DISCONNECTED;
1793}
1794
1795static const char *
1796_ecore_con_pretty_ip(struct sockaddr *client_addr)
1797{
1798#ifndef HAVE_IPV6
1799 char ipbuf[INET_ADDRSTRLEN + 1];
1800#else
1801 char ipbuf[INET6_ADDRSTRLEN + 1];
1802#endif
1803 int family = client_addr->sa_family;
1804 void *src;
1805
1806 switch(family)
1807 {
1808 case AF_INET:
1809 src = &(((struct sockaddr_in *)client_addr)->sin_addr);
1810 break;
1811#ifdef HAVE_IPV6
1812 case AF_INET6:
1813 src = &(((struct sockaddr_in6 *)client_addr)->sin6_addr);
1814
1815 if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src))
1816 {
1817 family = AF_INET;
1818 src = (char*)src + 12;
1819 }
1820 break;
1821#endif
1822 default:
1823 return eina_stringshare_add("0.0.0.0");
1824 }
1825
1826 if (!inet_ntop(family, src, ipbuf, sizeof(ipbuf)))
1827 return eina_stringshare_add("0.0.0.0");
1828
1829 ipbuf[sizeof(ipbuf) - 1] = 0;
1830 return eina_stringshare_add(ipbuf);
1831}
1832
1833static Eina_Bool
1834_ecore_con_svr_tcp_handler(void *data,
1835 Ecore_Fd_Handler *fd_handler __UNUSED__)
1836{
1837 Ecore_Con_Server *svr;
1838 Ecore_Con_Client *cl = NULL;
1839 unsigned char client_addr[256];
1840 unsigned int client_addr_len;
1841
1842 svr = data;
1843 if (svr->dead)
1844 return ECORE_CALLBACK_RENEW;
1845
1846 if (svr->delete_me)
1847 return ECORE_CALLBACK_RENEW;
1848
1849 if ((svr->client_limit >= 0) && (!svr->reject_excess_clients) &&
1850 (svr->client_count >= (unsigned int)svr->client_limit))
1851 return ECORE_CALLBACK_RENEW;
1852
1853 /* a new client */
1854
1855 cl = calloc(1, sizeof(Ecore_Con_Client));
1856 if (!cl)
1857 {
1858 ecore_con_event_server_error(svr, "Memory allocation failure when attempting to add a new client");
1859 return ECORE_CALLBACK_RENEW;
1860 }
1861 cl->host_server = svr;
1862
1863 client_addr_len = sizeof(client_addr);
1864 memset(&client_addr, 0, client_addr_len);
1865 cl->fd = accept(svr->fd, (struct sockaddr *)&client_addr, (socklen_t *)&client_addr_len);
1866 if (cl->fd < 0)
1867 {
1868 ecore_con_event_server_error(svr, strerror(errno));
1869 goto free_cl;
1870 }
1871
1872 if ((svr->client_limit >= 0) && (svr->reject_excess_clients) &&
1873 (svr->client_count >= (unsigned int)svr->client_limit))
1874 {
1875 ecore_con_event_server_error(svr, "Maximum client limit reached");
1876 goto close_fd;
1877 }
1878
1879 if (fcntl(cl->fd, F_SETFL, O_NONBLOCK) < 0)
1880 {
1881 ecore_con_event_server_error(svr, strerror(errno));
1882 goto close_fd;
1883 }
1884 if (fcntl(cl->fd, F_SETFD, FD_CLOEXEC) < 0)
1885 {
1886 ecore_con_event_server_error(svr, strerror(errno));
1887 goto close_fd;
1888 }
1889 cl->fd_handler = ecore_main_fd_handler_add(cl->fd, ECORE_FD_READ,
1890 _ecore_con_svr_cl_handler, cl, NULL, NULL);
1891 if (!cl->fd_handler)
1892 goto close_fd;
1893
1894 ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
1895
1896 if ((!svr->upgrade) && (svr->type & ECORE_CON_SSL))
1897 {
1898 cl->handshaking = EINA_TRUE;
1899 cl->ssl_state = ECORE_CON_SSL_STATE_INIT;
1900 if (ecore_con_ssl_client_init(cl))
1901 goto del_handler;
1902 }
1903
1904 cl->client_addr = malloc(client_addr_len);
1905 if (!cl->client_addr)
1906 {
1907 ecore_con_event_server_error(svr, "Memory allocation failure when attempting to add a new client");
1908 goto del_handler;
1909 }
1910 cl->client_addr_len = client_addr_len;
1911 memcpy(cl->client_addr, &client_addr, client_addr_len);
1912
1913 svr->clients = eina_list_append(svr->clients, cl);
1914 svr->client_count++;
1915
1916 if ((!cl->delete_me) && (!cl->handshaking))
1917 ecore_con_event_client_add(cl);
1918
1919 return ECORE_CALLBACK_RENEW;
1920
1921 del_handler:
1922 ecore_main_fd_handler_del(cl->fd_handler);
1923 close_fd:
1924 close(cl->fd);
1925 free_cl:
1926 free(cl);
1927
1928 return ECORE_CALLBACK_RENEW;
1929}
1930
1931static void
1932_ecore_con_cl_read(Ecore_Con_Server *svr)
1933{
1934 DBG("svr=%p", svr);
1935 int num = 0;
1936 Eina_Bool lost_server = EINA_TRUE;
1937 unsigned char buf[READBUFSIZ];
1938
1939 /* only possible with non-ssl connections */
1940 if (svr->connecting && (svr_try_connect_plain(svr) != ECORE_CON_CONNECTED))
1941 return;
1942
1943 if (svr->handshaking)
1944 {
1945 DBG("Continuing ssl handshake");
1946 if (!ecore_con_ssl_server_init(svr))
1947 lost_server = EINA_FALSE;
1948 _ecore_con_server_timer_update(svr);
1949 }
1950
1951 if (!(svr->type & ECORE_CON_SSL))
1952 {
1953 num = read(svr->fd, buf, sizeof(buf));
1954 /* 0 is not a valid return value for a tcp socket */
1955 if ((num > 0) || ((num < 0) && (errno == EAGAIN)))
1956 lost_server = EINA_FALSE;
1957 else if (num < 0)
1958 ecore_con_event_server_error(svr, strerror(errno));
1959 }
1960 else
1961 {
1962 num = ecore_con_ssl_server_read(svr, buf, sizeof(buf));
1963 /* this is not an actual 0 return, 0 here just means non-fatal error such as EAGAIN */
1964 if (num >= 0)
1965 lost_server = EINA_FALSE;
1966 }
1967
1968 if ((!svr->delete_me) && (num > 0))
1969 ecore_con_event_server_data(svr, buf, num, EINA_TRUE);
1970
1971 if (lost_server)
1972 _ecore_con_server_kill(svr);
1973}
1974
1975static Eina_Bool
1976_ecore_con_cl_handler(void *data,
1977 Ecore_Fd_Handler *fd_handler)
1978{
1979 Ecore_Con_Server *svr;
1980 Eina_Bool want_read, want_write;
1981
1982 svr = data;
1983 if (svr->dead)
1984 return ECORE_CALLBACK_RENEW;
1985
1986 if (svr->delete_me)
1987 return ECORE_CALLBACK_RENEW;
1988
1989 want_read = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ);
1990 want_write = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE);
1991
1992 if (svr->handshaking && (want_read || want_write))
1993 {
1994 DBG("Continuing ssl handshake: preparing to %s...", want_read ? "read" : "write");
1995#ifdef ISCOMFITOR
1996 if (want_read)
1997 {
1998 char buf[READBUFSIZ];
1999 ssize_t len;
2000 len = recv(svr->fd, buf, sizeof(buf), MSG_DONTWAIT | MSG_PEEK);
2001 DBG("%zu bytes in buffer", len);
2002 }
2003#endif
2004 if (ecore_con_ssl_server_init(svr))
2005 {
2006 ERR("ssl handshaking failed!");
2007 svr->handshaking = EINA_FALSE;
2008
2009 }
2010 else if (!svr->ssl_state)
2011 {
2012 svr->connecting = EINA_FALSE;
2013 svr->start_time = ecore_time_get();
2014 ecore_con_event_server_add(svr);
2015 }
2016 }
2017 else if (want_read)
2018 _ecore_con_cl_read(svr);
2019 else if (want_write) /* only possible with non-ssl connections */
2020 {
2021 if (svr->connecting && (!svr_try_connect_plain(svr)))
2022 return ECORE_CALLBACK_RENEW;
2023
2024 _ecore_con_server_flush(svr);
2025 }
2026
2027 return ECORE_CALLBACK_RENEW;
2028}
2029
2030static Eina_Bool
2031_ecore_con_cl_udp_handler(void *data,
2032 Ecore_Fd_Handler *fd_handler)
2033{
2034 unsigned char buf[READBUFSIZ];
2035 int num;
2036 Ecore_Con_Server *svr;
2037 Eina_Bool want_read, want_write;
2038
2039 want_read = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ);
2040 want_write = ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE);
2041
2042 svr = data;
2043 if (svr->dead || svr->delete_me || ((!want_read) && (!want_write)))
2044 return ECORE_CALLBACK_RENEW;
2045
2046 if (want_write)
2047 {
2048 _ecore_con_server_flush(svr);
2049 return ECORE_CALLBACK_RENEW;
2050 }
2051
2052 num = read(svr->fd, buf, READBUFSIZ);
2053
2054 if ((!svr->delete_me) && (num > 0))
2055 ecore_con_event_server_data(svr, buf, num, EINA_TRUE);
2056
2057 if (num < 0 && (errno != EAGAIN) && (errno != EINTR))
2058 {
2059 ecore_con_event_server_error(svr, strerror(errno));
2060 _ecore_con_server_kill(svr);
2061 }
2062
2063 return ECORE_CALLBACK_RENEW;
2064}
2065
2066static Eina_Bool
2067_ecore_con_svr_udp_handler(void *data,
2068 Ecore_Fd_Handler *fd_handler)
2069{
2070 unsigned char buf[READBUFSIZ];
2071 unsigned char client_addr[256];
2072 socklen_t client_addr_len = sizeof(client_addr);
2073 int num;
2074 Ecore_Con_Server *svr;
2075 Ecore_Con_Client *cl = NULL;
2076
2077 svr = data;
2078
2079 if (svr->delete_me || svr->dead)
2080 return ECORE_CALLBACK_RENEW;
2081
2082 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
2083 {
2084 _ecore_con_client_flush(cl);
2085 return ECORE_CALLBACK_RENEW;
2086 }
2087
2088 if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
2089 return ECORE_CALLBACK_RENEW;
2090
2091#ifdef _WIN32
2092 num = fcntl(svr->fd, F_SETFL, O_NONBLOCK);
2093 if (num >= 0)
2094 num = recvfrom(svr->fd, (char *)buf, sizeof(buf), 0,
2095 (struct sockaddr *)&client_addr,
2096 &client_addr_len);
2097
2098#else
2099 num = recvfrom(svr->fd, buf, sizeof(buf), MSG_DONTWAIT,
2100 (struct sockaddr *)&client_addr,
2101 &client_addr_len);
2102#endif
2103
2104 if (num < 0 && (errno != EAGAIN) && (errno != EINTR))
2105 {
2106 ecore_con_event_server_error(svr, strerror(errno));
2107 if (!svr->delete_me)
2108 ecore_con_event_client_del(NULL);
2109
2110 svr->dead = EINA_TRUE;
2111 svr->fd_handler = NULL;
2112 return ECORE_CALLBACK_CANCEL;
2113 }
2114
2115
2116/* Create a new client for use in the client data event */
2117 cl = calloc(1, sizeof(Ecore_Con_Client));
2118 EINA_SAFETY_ON_NULL_RETURN_VAL(cl, ECORE_CALLBACK_RENEW);
2119
2120 cl->host_server = svr;
2121 cl->client_addr = malloc(client_addr_len);
2122 if (!cl->client_addr)
2123 {
2124 free(cl);
2125 return ECORE_CALLBACK_RENEW;
2126 }
2127 cl->client_addr_len = client_addr_len;
2128
2129 memcpy(cl->client_addr, &client_addr, client_addr_len);
2130 ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
2131 svr->clients = eina_list_append(svr->clients, cl);
2132 svr->client_count++;
2133
2134 ecore_con_event_client_add(cl);
2135 ecore_con_event_client_data(cl, buf, num, EINA_TRUE);
2136
2137 return ECORE_CALLBACK_RENEW;
2138}
2139
2140static void
2141_ecore_con_svr_cl_read(Ecore_Con_Client *cl)
2142{
2143 int num = 0;
2144 Eina_Bool lost_client = EINA_TRUE;
2145 unsigned char buf[READBUFSIZ];
2146
2147 DBG("cl=%p", cl);
2148
2149 if (cl->handshaking)
2150 {
2151 /* add an extra handshake attempt just before read, even though
2152 * read also attempts to handshake, to try to finish sooner
2153 */
2154 if (ecore_con_ssl_client_init(cl))
2155 lost_client = EINA_FALSE;
2156
2157 _ecore_con_cl_timer_update(cl);
2158 }
2159
2160 if (!(cl->host_server->type & ECORE_CON_SSL) || (!cl->upgrade))
2161 {
2162 num = read(cl->fd, buf, sizeof(buf));
2163 /* 0 is not a valid return value for a tcp socket */
2164 if ((num > 0) || ((num < 0) && ((errno == EAGAIN) || (errno == EINTR))))
2165 lost_client = EINA_FALSE;
2166 else if (num < 0)
2167 ecore_con_event_client_error(cl, strerror(errno));
2168 }
2169 else
2170 {
2171 num = ecore_con_ssl_client_read(cl, buf, sizeof(buf));
2172 /* this is not an actual 0 return, 0 here just means non-fatal error such as EAGAIN */
2173 if (num >= 0)
2174 lost_client = EINA_FALSE;
2175 }
2176
2177 if ((!cl->delete_me) && (num > 0))
2178 ecore_con_event_client_data(cl, buf, num, EINA_TRUE);
2179
2180 if (lost_client)
2181 {
2182 if (!cl->delete_me)
2183 ecore_con_event_client_del(cl);
2184 INF("Lost client %s", (cl->ip) ? cl->ip : "");
2185 cl->dead = EINA_TRUE;
2186 if (cl->fd_handler)
2187 ecore_main_fd_handler_del(cl->fd_handler);
2188
2189 cl->fd_handler = NULL;
2190 return;
2191 }
2192}
2193
2194static Eina_Bool
2195_ecore_con_svr_cl_handler(void *data,
2196 Ecore_Fd_Handler *fd_handler)
2197{
2198 Ecore_Con_Client *cl;
2199
2200 cl = data;
2201 if (cl->dead)
2202 return ECORE_CALLBACK_RENEW;
2203
2204 if (cl->delete_me)
2205 return ECORE_CALLBACK_RENEW;
2206
2207 if (cl->handshaking && ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ | ECORE_FD_WRITE))
2208 {
2209 if (ecore_con_ssl_client_init(cl))
2210 {
2211 ERR("ssl handshaking failed!");
2212 cl->handshaking = EINA_FALSE;
2213 cl->dead = EINA_TRUE;
2214 INF("Lost client %s", (cl->ip) ? cl->ip : "");
2215 ecore_con_event_client_del(cl);
2216 }
2217 else if (!cl->ssl_state)
2218 ecore_con_event_client_add(cl);
2219 }
2220 else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
2221 _ecore_con_svr_cl_read(cl);
2222
2223 else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
2224 _ecore_con_client_flush(cl);
2225
2226 return ECORE_CALLBACK_RENEW;
2227}
2228
2229static void
2230_ecore_con_server_flush(Ecore_Con_Server *svr)
2231{
2232 int count, num;
2233
2234#ifdef _WIN32
2235 if (ecore_con_local_win32_server_flush(svr))
2236 return;
2237#endif
2238
2239 if ((!svr->buf) && svr->fd_handler)
2240 {
2241 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
2242 return;
2243 }
2244
2245 num = eina_binbuf_length_get(svr->buf) - svr->write_buf_offset;
2246
2247 /* check whether we need to write anything at all.
2248 * we must not write zero bytes with SSL_write() since it
2249 * causes undefined behaviour
2250 */
2251 /* we thank Tommy[D] for needing to check negative buffer sizes
2252 * here because his system is amazing.
2253 */
2254 if (num <= 0) return;
2255
2256 if (svr->handshaking)
2257 {
2258 DBG("Continuing ssl handshake");
2259 if (ecore_con_ssl_server_init(svr))
2260 _ecore_con_server_kill(svr);
2261 _ecore_con_server_timer_update(svr);
2262 return;
2263 }
2264
2265 if (!(svr->type & ECORE_CON_SSL))
2266 count = write(svr->fd, eina_binbuf_string_get(svr->buf) + svr->write_buf_offset, num);
2267 else
2268 count = ecore_con_ssl_server_write(svr, eina_binbuf_string_get(svr->buf) + svr->write_buf_offset, num);
2269
2270 if (count < 0)
2271 {
2272 if ((errno != EAGAIN) && (errno != EINTR))
2273 {
2274 ecore_con_event_server_error(svr, strerror(errno));
2275 _ecore_con_server_kill(svr);
2276 }
2277 return;
2278 }
2279
2280 if (count) ecore_con_event_server_write(svr, count);
2281 svr->write_buf_offset += count;
2282 if (svr->write_buf_offset >= eina_binbuf_length_get(svr->buf))
2283 {
2284 svr->write_buf_offset = 0;
2285 eina_binbuf_free(svr->buf);
2286 svr->buf = NULL;
2287 if (svr->fd_handler)
2288 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
2289 }
2290 else if ((count < num) && svr->fd_handler)
2291 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
2292}
2293
2294static void
2295_ecore_con_client_flush(Ecore_Con_Client *cl)
2296{
2297 int num, count = 0;
2298
2299#ifdef _WIN32
2300 if (ecore_con_local_win32_client_flush(cl))
2301 return;
2302#endif
2303
2304 if (!cl->buf && cl->fd_handler)
2305 {
2306 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
2307 return;
2308 }
2309
2310 if (cl->handshaking)
2311 {
2312 if (ecore_con_ssl_client_init(cl))
2313 count = -1;
2314
2315 _ecore_con_cl_timer_update(cl);
2316 }
2317
2318 if (!count)
2319 {
2320 num = eina_binbuf_length_get(cl->buf) - cl->buf_offset;
2321 if (num <= 0) return;
2322 if (!(cl->host_server->type & ECORE_CON_SSL) || (!cl->upgrade))
2323 count = write(cl->fd, eina_binbuf_string_get(cl->buf) + cl->buf_offset, num);
2324 else
2325 count = ecore_con_ssl_client_write(cl, eina_binbuf_string_get(cl->buf) + cl->buf_offset, num);
2326 }
2327
2328 if (count < 0)
2329 {
2330 if ((errno != EAGAIN) && (errno != EINTR) && (!cl->delete_me))
2331 {
2332 ecore_con_event_client_error(cl, strerror(errno));
2333 ecore_con_event_client_del(cl);
2334 cl->dead = EINA_TRUE;
2335 INF("Lost client %s", (cl->ip) ? cl->ip : "");
2336 if (cl->fd_handler)
2337 ecore_main_fd_handler_del(cl->fd_handler);
2338
2339 cl->fd_handler = NULL;
2340 }
2341
2342 return;
2343 }
2344
2345 if (count) ecore_con_event_client_write(cl, count);
2346 cl->buf_offset += count;
2347 if (cl->buf_offset >= eina_binbuf_length_get(cl->buf))
2348 {
2349 cl->buf_offset = 0;
2350 eina_binbuf_free(cl->buf);
2351 cl->buf = NULL;
2352 if (cl->fd_handler)
2353 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
2354 }
2355 else if ((count < num) && cl->fd_handler)
2356 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
2357}
2358
2359static void
2360_ecore_con_event_client_add_free(Ecore_Con_Server *svr,
2361 void *ev)
2362{
2363 Ecore_Con_Event_Client_Add *e;
2364
2365 e = ev;
2366 if (e->client)
2367 {
2368 e->client->event_count = eina_list_remove(e->client->event_count, e);
2369 if (e->client->host_server)
2370 {
2371 e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, ev);
2372 if ((!svr->event_count) && (svr->delete_me))
2373 _ecore_con_server_free(svr);
2374 }
2375 if ((!e->client->event_count) && (e->client->delete_me))
2376 ecore_con_client_del(e->client);
2377 }
2378
2379 ecore_con_event_client_add_free(e);
2380 _ecore_con_event_count--;
2381 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2382 ecore_con_mempool_shutdown();
2383}
2384
2385static void
2386_ecore_con_event_client_del_free(Ecore_Con_Server *svr,
2387 void *ev)
2388{
2389 Ecore_Con_Event_Client_Del *e;
2390
2391 e = ev;
2392 if (e->client)
2393 {
2394 e->client->event_count = eina_list_remove(e->client->event_count, e);
2395 if (e->client->host_server)
2396 {
2397 e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, ev);
2398 if ((!svr->event_count) && (svr->delete_me))
2399 _ecore_con_server_free(svr);
2400 }
2401 if ((!e->client->event_count) && (e->client->delete_me))
2402 ecore_con_client_del(e->client);
2403 }
2404 ecore_con_event_client_del_free(e);
2405 _ecore_con_event_count--;
2406 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2407 ecore_con_mempool_shutdown();
2408}
2409
2410static void
2411_ecore_con_event_client_write_free(Ecore_Con_Server *svr,
2412 Ecore_Con_Event_Client_Write *e)
2413{
2414 if (e->client)
2415 {
2416 e->client->event_count = eina_list_remove(e->client->event_count, e);
2417 if (e->client->host_server)
2418 {
2419 e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, e);
2420 if ((!svr->event_count) && (svr->delete_me))
2421 _ecore_con_server_free(svr);
2422 }
2423 if (((!e->client->event_count) && (e->client->delete_me)) ||
2424 ((e->client->host_server &&
2425 ((e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP ||
2426 (e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_MCAST))))
2427 ecore_con_client_del(e->client);
2428 }
2429 ecore_con_event_client_write_free(e);
2430 _ecore_con_event_count--;
2431 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2432 ecore_con_mempool_shutdown();
2433}
2434
2435static void
2436_ecore_con_event_client_data_free(Ecore_Con_Server *svr,
2437 void *ev)
2438{
2439 Ecore_Con_Event_Client_Data *e;
2440
2441 e = ev;
2442 if (e->client)
2443 {
2444 e->client->event_count = eina_list_remove(e->client->event_count, e);
2445 if (e->client->host_server)
2446 {
2447 e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, ev);
2448 }
2449 if ((!svr->event_count) && (svr->delete_me))
2450 _ecore_con_server_free(svr);
2451 if (((!e->client->event_count) && (e->client->delete_me)) ||
2452 ((e->client->host_server &&
2453 ((e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_UDP ||
2454 (e->client->host_server->type & ECORE_CON_TYPE) == ECORE_CON_REMOTE_MCAST))))
2455 ecore_con_client_del(e->client);
2456 }
2457 free(e->data);
2458 ecore_con_event_client_data_free(e);
2459 _ecore_con_event_count--;
2460 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2461 ecore_con_mempool_shutdown();
2462}
2463
2464static void
2465_ecore_con_event_server_add_free(void *data __UNUSED__,
2466 void *ev)
2467{
2468 Ecore_Con_Event_Server_Add *e;
2469
2470 e = ev;
2471 if (e->server)
2472 {
2473 e->server->event_count = eina_list_remove(e->server->event_count, ev);
2474 if ((!e->server->event_count) && (e->server->delete_me))
2475 _ecore_con_server_free(e->server);
2476 }
2477 ecore_con_event_server_add_free(e);
2478 _ecore_con_event_count--;
2479 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2480 ecore_con_mempool_shutdown();
2481}
2482
2483static void
2484_ecore_con_event_server_del_free(void *data __UNUSED__,
2485 void *ev)
2486{
2487 Ecore_Con_Event_Server_Del *e;
2488
2489 e = ev;
2490 if (e->server)
2491 {
2492 e->server->event_count = eina_list_remove(e->server->event_count, ev);
2493 if ((!e->server->event_count) && (e->server->delete_me))
2494 _ecore_con_server_free(e->server);
2495 }
2496 ecore_con_event_server_del_free(e);
2497 _ecore_con_event_count--;
2498 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2499 ecore_con_mempool_shutdown();
2500}
2501
2502static void
2503_ecore_con_event_server_write_free(void *data __UNUSED__,
2504 Ecore_Con_Event_Server_Write *e)
2505{
2506 if (e->server)
2507 {
2508 e->server->event_count = eina_list_remove(e->server->event_count, e);
2509 if ((!e->server->event_count) && (e->server->delete_me))
2510 _ecore_con_server_free(e->server);
2511 }
2512
2513 ecore_con_event_server_write_free(e);
2514 _ecore_con_event_count--;
2515 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2516 ecore_con_mempool_shutdown();
2517}
2518
2519static void
2520_ecore_con_event_server_data_free(void *data __UNUSED__,
2521 void *ev)
2522{
2523 Ecore_Con_Event_Server_Data *e;
2524
2525 e = ev;
2526 if (e->server)
2527 {
2528 e->server->event_count = eina_list_remove(e->server->event_count, ev);
2529 if ((!e->server->event_count) && (e->server->delete_me))
2530 _ecore_con_server_free(e->server);
2531 }
2532
2533 free(e->data);
2534 ecore_con_event_server_data_free(e);
2535 _ecore_con_event_count--;
2536 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2537 ecore_con_mempool_shutdown();
2538}
2539
2540
2541static void
2542_ecore_con_event_server_error_free(void *data __UNUSED__, Ecore_Con_Event_Server_Error *e)
2543{
2544 if (e->server)
2545 {
2546 e->server->event_count = eina_list_remove(e->server->event_count, e);
2547 if ((!e->server->event_count) && (e->server->delete_me))
2548 _ecore_con_server_free(e->server);
2549 }
2550 free(e->error);
2551 ecore_con_event_server_error_free(e);
2552 _ecore_con_event_count--;
2553 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2554 ecore_con_mempool_shutdown();
2555}
2556
2557static void
2558_ecore_con_event_client_error_free(Ecore_Con_Server *svr, Ecore_Con_Event_Client_Error *e)
2559{
2560 if (e->client)
2561 {
2562 e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, e);
2563 if ((!e->client->event_count) && (e->client->delete_me))
2564 _ecore_con_client_free(e->client);
2565 if (e->client->host_server)
2566 {
2567 e->client->host_server->event_count = eina_list_remove(e->client->host_server->event_count, e);
2568 if ((!svr->event_count) && (svr->delete_me))
2569 _ecore_con_server_free(svr);
2570 }
2571 }
2572 free(e->error);
2573 ecore_con_event_client_error_free(e);
2574 _ecore_con_event_count--;
2575 if ((!_ecore_con_event_count) && (!_ecore_con_init_count))
2576 ecore_con_mempool_shutdown();
2577}
2578
2579static void
2580_ecore_con_lookup_done(void *data,
2581 Ecore_Con_Info *infos)
2582{
2583 Ecore_Con_Server *svr;
2584 Ecore_Con_Lookup *lk;
2585
2586 svr = data;
2587 lk = svr->data;
2588
2589 if (infos)
2590 lk->done_cb(infos->info.ai_canonname, infos->ip,
2591 infos->info.ai_addr, infos->info.ai_addrlen,
2592 (void *)lk->data);
2593 else
2594 lk->done_cb(NULL, NULL, NULL, 0, (void *)lk->data);
2595
2596 free(svr->name);
2597 free(lk);
2598 free(svr);
2599}
2600
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_alloc.c b/libraries/ecore/src/lib/ecore_con/ecore_con_alloc.c
new file mode 100644
index 0000000..206948b
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_alloc.c
@@ -0,0 +1,99 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include "Ecore.h"
6#include "ecore_private.h"
7#include "Ecore_Con.h"
8#include "ecore_con_private.h"
9
10typedef struct _Ecore_Con_Mempool Ecore_Con_Mempool;
11struct _Ecore_Con_Mempool
12{
13 const char *name;
14 Eina_Mempool *mp;
15 size_t size;
16};
17
18#define GENERIC_ALLOC_FREE(TYPE, Type) \
19 Ecore_Con_Mempool Type##_mp = { #TYPE, NULL, sizeof (TYPE) }; \
20 \
21 TYPE * \
22 Type##_alloc(void) \
23 { \
24 return eina_mempool_malloc(Type##_mp.mp, sizeof (TYPE)); \
25 } \
26 \
27 void \
28 Type##_free(TYPE *e) \
29 { \
30 eina_mempool_free(Type##_mp.mp, e); \
31 }
32
33GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Add, ecore_con_event_client_add);
34GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Del, ecore_con_event_client_del);
35GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Write, ecore_con_event_client_write);
36GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Data, ecore_con_event_client_data);
37GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Error, ecore_con_event_server_error);
38GENERIC_ALLOC_FREE(Ecore_Con_Event_Client_Error, ecore_con_event_client_error);
39GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Add, ecore_con_event_server_add);
40GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Del, ecore_con_event_server_del);
41GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Write, ecore_con_event_server_write);
42GENERIC_ALLOC_FREE(Ecore_Con_Event_Server_Data, ecore_con_event_server_data);
43
44static Ecore_Con_Mempool *mempool_array[] = {
45 &ecore_con_event_client_add_mp,
46 &ecore_con_event_client_del_mp,
47 &ecore_con_event_client_write_mp,
48 &ecore_con_event_client_data_mp,
49 &ecore_con_event_server_error_mp,
50 &ecore_con_event_client_error_mp,
51 &ecore_con_event_server_add_mp,
52 &ecore_con_event_server_del_mp,
53 &ecore_con_event_server_write_mp,
54 &ecore_con_event_server_data_mp
55};
56
57void
58ecore_con_mempool_init(void)
59{
60 const char *choice;
61 unsigned int i;
62
63 choice = getenv("EINA_MEMPOOL");
64 if (!choice || !choice[0])
65 choice = "chained_mempool";
66
67 for (i = 0; i < sizeof (mempool_array) / sizeof (mempool_array[0]); ++i)
68 {
69 retry:
70 mempool_array[i]->mp = eina_mempool_add(choice, mempool_array[i]->name, NULL, mempool_array[i]->size, 64);
71 if (!mempool_array[i]->mp)
72 {
73 if (strcmp(choice, "pass_through") != 0)
74 {
75 ERR("Falling back to pass through ! Previously tried '%s' mempool.", choice);
76 choice = "pass_through";
77 goto retry;
78 }
79 else
80 {
81 ERR("Impossible to allocate mempool '%s' !", choice);
82 return ;
83 }
84 }
85 }
86}
87
88void
89ecore_con_mempool_shutdown(void)
90{
91 unsigned int i;
92
93 for (i = 0; i < sizeof (mempool_array) / sizeof (mempool_array[0]); ++i)
94 {
95 eina_mempool_del(mempool_array[i]->mp);
96 mempool_array[i]->mp = NULL;
97 }
98}
99
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_ares.c b/libraries/ecore/src/lib/ecore_con/ecore_con_ares.c
new file mode 100644
index 0000000..dd5a212
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_ares.c
@@ -0,0 +1,628 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5/*
6 * This version of ecore_con_info use c-ares to provide asynchronous dns lookup.
7 *
8 * Note: It doesn't fork nor does it use libc getaddrinfo.
9 * http://c-ares.haxx.se/docs.html
10 */
11
12#include <string.h>
13#include <sys/types.h>
14
15#ifdef HAVE_NETINET_IN_H
16# include <netinet/in.h>
17#endif
18
19#ifdef HAVE_ARPA_INET_H
20# include <arpa/inet.h>
21#endif
22
23#include <ares.h>
24
25#include "Ecore.h"
26#include "Ecore_Con.h"
27#include "ecore_con_private.h"
28
29typedef struct _Ecore_Con_FD Ecore_Con_FD;
30typedef struct _Ecore_Con_CAres Ecore_Con_CAres;
31
32struct _Ecore_Con_FD
33{
34 Ecore_Fd_Handler *handler;
35 Ecore_Timer *timer;
36 int fd;
37};
38
39struct _Ecore_Con_CAres
40{
41 Ecore_Con_Server *svr;
42 Ecore_Con_Info_Cb done_cb;
43 void *data;
44 struct addrinfo hints;
45 Ecore_Con_Info *result;
46
47 union {
48 struct in_addr v4;
49#ifdef HAVE_IPV6
50 struct in6_addr v6;
51#endif
52 } addr;
53
54 Eina_Bool byaddr : 1;
55 Eina_Bool isv6 : 1;
56};
57
58static ares_channel info_channel;
59static int info_init = 0;
60static Eina_List *info_fds = NULL;
61
62static void _ecore_con_info_ares_nameinfo(Ecore_Con_CAres *arg,
63 int status,
64 int timeouts,
65 char *node,
66 char *service);
67static void _ecore_con_info_ares_host_cb(Ecore_Con_CAres *arg,
68 int status,
69 int timeouts,
70 struct hostent *hostent);
71static Eina_Bool _ecore_con_info_cares_fd_cb(Ecore_Con_FD *ecf,
72 Ecore_Fd_Handler *fd_handler);
73static Eina_Bool _ecore_con_info_cares_timeout_cb(void *data);
74
75static void
76_ecore_con_info_cares_state_cb(void *data,
77 ares_socket_t fd,
78 int readable,
79 int writable);
80static int
81_ecore_con_info_fds_search(const Ecore_Con_FD *fd1,
82 const Ecore_Con_FD *fd2);
83
84int
85ecore_con_info_init(void)
86{
87 struct ares_options opts;
88
89 if (!info_init)
90 {
91 if (ares_library_init(ARES_LIB_INIT_ALL))
92 return 0;
93
94 opts.lookups = "fb"; /* hosts file then dns */
95 opts.sock_state_cb = _ecore_con_info_cares_state_cb;
96
97 if (ares_init_options(&info_channel, &opts,
98 ARES_OPT_LOOKUPS | ARES_OPT_SOCK_STATE_CB) != ARES_SUCCESS)
99 {
100 ares_library_cleanup();
101 return 0;
102 }
103 }
104
105 info_init++;
106 return info_init;
107}
108
109int
110ecore_con_info_shutdown(void)
111{
112 info_init--;
113 if (info_init == 0)
114 {
115 /* Cancel all ongoing request */
116 ares_cancel(info_channel);
117 ares_destroy(info_channel);
118
119 /* Shutdown ares */
120 ares_library_cleanup();
121 }
122
123 return info_init;
124}
125
126int
127ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
128 Ecore_Con_Info_Cb done_cb,
129 void *data)
130{
131 struct addrinfo hints;
132
133 memset(&hints, 0, sizeof(struct addrinfo));
134#ifdef HAVE_IPV6
135 hints.ai_family = AF_INET6;
136#else
137 hints.ai_family = AF_INET;
138#endif
139 hints.ai_socktype = SOCK_STREAM;
140 hints.ai_flags = AI_CANONNAME;
141 hints.ai_protocol = IPPROTO_TCP;
142 hints.ai_canonname = NULL;
143 hints.ai_next = NULL;
144 hints.ai_addr = NULL;
145
146 return ecore_con_info_get(svr, done_cb, data, &hints);
147}
148
149int
150ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
151 Ecore_Con_Info_Cb done_cb,
152 void *data)
153{
154 struct addrinfo hints;
155
156 memset(&hints, 0, sizeof(struct addrinfo));
157#ifdef HAVE_IPV6
158 hints.ai_family = AF_INET6;
159#else
160 hints.ai_family = AF_INET;
161#endif
162 hints.ai_socktype = SOCK_STREAM;
163 hints.ai_flags = AI_PASSIVE;
164 hints.ai_protocol = IPPROTO_TCP;
165 hints.ai_canonname = NULL;
166 hints.ai_next = NULL;
167 hints.ai_addr = NULL;
168
169 return ecore_con_info_get(svr, done_cb, data, &hints);
170}
171
172int
173ecore_con_info_udp_connect(Ecore_Con_Server *svr,
174 Ecore_Con_Info_Cb done_cb,
175 void *data)
176{
177 struct addrinfo hints;
178
179 memset(&hints, 0, sizeof(struct addrinfo));
180#ifdef HAVE_IPV6
181 hints.ai_family = AF_INET6;
182#else
183 hints.ai_family = AF_INET;
184#endif
185 hints.ai_socktype = SOCK_DGRAM;
186 hints.ai_flags = AI_CANONNAME;
187 hints.ai_protocol = IPPROTO_UDP;
188 hints.ai_canonname = NULL;
189 hints.ai_next = NULL;
190 hints.ai_addr = NULL;
191
192 return ecore_con_info_get(svr, done_cb, data, &hints);
193}
194
195int
196ecore_con_info_udp_listen(Ecore_Con_Server *svr,
197 Ecore_Con_Info_Cb done_cb,
198 void *data)
199{
200 struct addrinfo hints;
201
202 memset(&hints, 0, sizeof(struct addrinfo));
203#ifdef HAVE_IPV6
204 hints.ai_family = AF_INET6;
205#else
206 hints.ai_family = AF_INET;
207#endif
208 hints.ai_socktype = SOCK_DGRAM;
209 hints.ai_flags = AI_PASSIVE;
210 hints.ai_protocol = IPPROTO_UDP;
211 hints.ai_canonname = NULL;
212 hints.ai_next = NULL;
213 hints.ai_addr = NULL;
214
215 return ecore_con_info_get(svr, done_cb, data, &hints);
216}
217
218int
219ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
220 Ecore_Con_Info_Cb done_cb,
221 void *data)
222{
223 struct addrinfo hints;
224
225 memset(&hints, 0, sizeof(struct addrinfo));
226#ifdef HAVE_IPV6
227 hints.ai_family = AF_INET6;
228#else
229 hints.ai_family = AF_INET;
230#endif
231 hints.ai_socktype = SOCK_DGRAM;
232 hints.ai_flags = 0;
233 hints.ai_protocol = IPPROTO_UDP;
234 hints.ai_canonname = NULL;
235 hints.ai_next = NULL;
236 hints.ai_addr = NULL;
237
238 return ecore_con_info_get(svr, done_cb, data, &hints);
239}
240
241static Eina_Bool
242_ecore_con_info_ares_getnameinfo(Ecore_Con_CAres *arg,
243 int addrtype,
244 const char *name,
245 struct sockaddr *addr,
246 int addrlen)
247{
248 int length = 0;
249
250 if (name)
251 length = strlen(name) + 1;
252 else
253 length = 1;
254
255 arg->result = malloc(sizeof(Ecore_Con_Info) + length);
256 if (!arg->result)
257 return EINA_FALSE;
258
259 /* FIXME: What to do when hint is not set ? */
260 arg->result->info.ai_flags = arg->hints.ai_flags;
261 arg->result->info.ai_socktype = arg->hints.ai_socktype;
262 arg->result->info.ai_protocol = arg->hints.ai_protocol;
263
264 arg->result->info.ai_family = addrtype;
265 arg->result->info.ai_addrlen = addrlen;
266 arg->result->info.ai_addr = addr;
267 arg->result->info.ai_canonname = (char *)(arg->result + 1);
268
269 if (!name)
270 *arg->result->info.ai_canonname = '\0';
271 else
272 strcpy(arg->result->info.ai_canonname, name);
273
274 arg->result->info.ai_next = NULL;
275
276 ares_getnameinfo(
277 info_channel, addr, addrlen,
278 ARES_NI_NUMERICSERV | ARES_NI_NUMERICHOST |
279 ARES_NI_LOOKUPSERVICE | ARES_NI_LOOKUPHOST,
280 (ares_nameinfo_callback)_ecore_con_info_ares_nameinfo, arg);
281
282 return EINA_TRUE;
283}
284
285EAPI int
286ecore_con_info_get(Ecore_Con_Server *svr,
287 Ecore_Con_Info_Cb done_cb,
288 void *data,
289 struct addrinfo *hints)
290{
291 Ecore_Con_CAres *cares;
292#ifdef HAVE_IPV6
293 int ai_family = AF_INET6;
294#else
295 int ai_family = AF_INET;
296#endif
297
298 cares = calloc(1, sizeof(Ecore_Con_CAres));
299 if (!cares)
300 return 0;
301
302 cares->svr = svr;
303 cares->done_cb = done_cb;
304 cares->data = data;
305
306 if (hints)
307 {
308 ai_family = hints->ai_family;
309 memcpy(&cares->hints, hints, sizeof(struct addrinfo));
310 }
311
312 if (inet_pton(AF_INET, svr->name, &cares->addr.v4) == 1)
313 {
314 cares->byaddr = EINA_TRUE;
315 cares->isv6 = EINA_FALSE;
316 ares_gethostbyaddr(info_channel, &cares->addr.v4,
317 sizeof(cares->addr.v4),
318 AF_INET,
319 (ares_host_callback)_ecore_con_info_ares_host_cb,
320 cares);
321 }
322#ifdef HAVE_IPV6
323 else if (inet_pton(AF_INET6, svr->name, &cares->addr.v6) == 1)
324 {
325 cares->byaddr = EINA_TRUE;
326 cares->isv6 = EINA_TRUE;
327 ares_gethostbyaddr(info_channel, &cares->addr.v6,
328 sizeof(cares->addr.v6),
329 AF_INET6,
330 (ares_host_callback)_ecore_con_info_ares_host_cb,
331 cares);
332 }
333#endif
334 else
335 {
336 cares->byaddr = EINA_FALSE;
337 ares_gethostbyname(info_channel, svr->name, ai_family,
338 (ares_host_callback)_ecore_con_info_ares_host_cb,
339 cares);
340 }
341
342 svr->infos = eina_list_append(svr->infos, cares);
343 return 1;
344}
345
346void
347ecore_con_info_data_clear(void *info)
348{
349 Ecore_Con_CAres *cares = info;
350 if (cares) cares->data = NULL;
351}
352
353static Eina_Bool
354_ecore_con_info_cares_timeout_cb(void *data __UNUSED__)
355{
356 ares_process_fd(info_channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
357 return ECORE_CALLBACK_RENEW;
358}
359
360static Eina_Bool
361_ecore_con_info_cares_fd_cb(Ecore_Con_FD *ecf,
362 Ecore_Fd_Handler *fd_handler)
363{
364 ares_socket_t read_fd, write_fd;
365
366 read_fd = write_fd = ARES_SOCKET_BAD;
367
368 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
369 read_fd = ecf->fd;
370 if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
371 write_fd = ecf->fd;
372
373 ares_process_fd(info_channel, read_fd, write_fd);
374
375 return ECORE_CALLBACK_RENEW;
376}
377
378static int
379_ecore_con_info_fds_search(const Ecore_Con_FD *fd1,
380 const Ecore_Con_FD *fd2)
381{
382 return fd1->fd - fd2->fd;
383}
384
385static void
386_ecore_con_info_cares_state_cb(void *data __UNUSED__,
387 ares_socket_t fd,
388 int readable,
389 int writable)
390{
391 int flags = 0;
392 Ecore_Con_FD *search = NULL, *ecf = NULL;
393
394 search = eina_list_search_unsorted(info_fds,
395 (Eina_Compare_Cb)_ecore_con_info_fds_search, &ecf);
396
397 if (!(readable | writable))
398 {
399 ares_process_fd(info_channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
400 if (search)
401 {
402 info_fds = eina_list_remove(info_fds, search);
403 ecore_timer_del(search->timer);
404 ecore_main_fd_handler_del(search->handler);
405 free(search);
406 }
407 return;
408 }
409
410 if (!search)
411 {
412 search = malloc(sizeof(Ecore_Con_FD));
413 EINA_SAFETY_ON_NULL_RETURN(search);
414
415 search->fd = fd;
416 search->handler = ecore_main_fd_handler_add(fd, ECORE_FD_WRITE | ECORE_FD_READ,
417 (Ecore_Fd_Cb)_ecore_con_info_cares_fd_cb, search, NULL, NULL);
418 /* c-ares default timeout is 5 seconds */
419 search->timer = ecore_timer_add(5, _ecore_con_info_cares_timeout_cb, NULL);
420 info_fds = eina_list_append(info_fds, search);
421 }
422
423 if (readable) flags |= ECORE_FD_READ;
424 if (writable) flags |= ECORE_FD_WRITE;
425 ecore_main_fd_handler_active_set(search->handler, flags);
426}
427
428static void
429_ecore_con_info_ares_host_cb(Ecore_Con_CAres *arg,
430 int status,
431 int timeouts __UNUSED__,
432 struct hostent *hostent)
433{
434 struct sockaddr *addr;
435 int addrlen;
436
437 /* Found something ? */
438 switch (status)
439 {
440 case ARES_SUCCESS:
441 if (!hostent->h_addr_list[0])
442 {
443 ERR("No IP found");
444 goto on_error;
445 }
446
447 switch (hostent->h_addrtype)
448 {
449 case AF_INET:
450 {
451 struct sockaddr_in *addri;
452
453 addrlen = sizeof(struct sockaddr_in);
454 addri = malloc(addrlen);
455
456 if (!addri)
457 goto on_mem_error;
458
459 addri->sin_family = AF_INET;
460 addri->sin_port = htons(arg->svr->port);
461
462 memcpy(&addri->sin_addr.s_addr,
463 hostent->h_addr_list[0], sizeof(struct in_addr));
464
465 addr = (struct sockaddr *)addri;
466 break;
467 }
468#ifdef HAVE_IPV6
469 case AF_INET6:
470 {
471 struct sockaddr_in6 *addri6;
472
473 addrlen = sizeof(struct sockaddr_in6);
474 addri6 = malloc(addrlen);
475
476 if (!addri6)
477 goto on_mem_error;
478
479 addri6->sin6_family = AF_INET6;
480 addri6->sin6_port = htons(arg->svr->port);
481 addri6->sin6_flowinfo = 0;
482 addri6->sin6_scope_id = 0;
483
484 memcpy(&addri6->sin6_addr.s6_addr,
485 hostent->h_addr_list[0], sizeof(struct in6_addr));
486
487 addr = (struct sockaddr *)addri6;
488 break;
489 }
490#endif
491 default:
492 ERR("Unknown addrtype %i", hostent->h_addrtype);
493 goto on_error;
494 }
495
496 if (!_ecore_con_info_ares_getnameinfo(arg, hostent->h_addrtype,
497 hostent->h_name,
498 addr, addrlen))
499 goto on_error;
500
501 break;
502
503 case ARES_ENOTFOUND: /* address notfound */
504 if (arg->byaddr)
505 {
506#ifdef HAVE_IPV6
507 /* This happen when host doesn't have a reverse. */
508 if (arg->isv6)
509 {
510 struct sockaddr_in6 *addri6;
511
512 addrlen = sizeof(struct sockaddr_in6);
513 addri6 = malloc(addrlen);
514
515 if (!addri6)
516 goto on_mem_error;
517
518 addri6->sin6_family = AF_INET6;
519 addri6->sin6_port = htons(arg->svr->port);
520 addri6->sin6_flowinfo = 0;
521 addri6->sin6_scope_id = 0;
522
523 memcpy(&addri6->sin6_addr.s6_addr,
524 &arg->addr.v6, sizeof(struct in6_addr));
525
526 addr = (struct sockaddr *)addri6;
527 }
528 else
529#endif
530 {
531 struct sockaddr_in *addri;
532
533 addrlen = sizeof(struct sockaddr_in);
534 addri = malloc(addrlen);
535
536 if (!addri)
537 goto on_mem_error;
538
539 addri->sin_family = AF_INET;
540 addri->sin_port = htons(arg->svr->port);
541
542 memcpy(&addri->sin_addr.s_addr,
543 &arg->addr.v4, sizeof(struct in_addr));
544
545 addr = (struct sockaddr *)addri;
546 }
547
548 if (!_ecore_con_info_ares_getnameinfo(arg,
549#ifdef HAVE_IPV6
550 arg->isv6 ? AF_INET6 :
551#endif
552 AF_INET,
553 NULL, addr,
554 addrlen))
555 goto on_error;
556
557 break;
558 }
559
560 case ARES_ENOTIMP: /* unknown family */
561 case ARES_EBADNAME: /* not a valid internet address */
562 case ARES_ENOMEM: /* not enough memory */
563 case ARES_EDESTRUCTION: /* request canceled, shuting down */
564 case ARES_ENODATA: /* no data returned */
565 case ARES_ECONNREFUSED: /* connection refused */
566 case ARES_ETIMEOUT: /* connection timed out */
567 ecore_con_event_server_error(arg->svr, ares_strerror(status));
568 goto on_error;
569
570 default:
571 ERR("Unknown status returned by c-ares: %i assuming error", status);
572 ecore_con_event_server_error(arg->svr, ares_strerror(status));
573 goto on_error;
574 }
575
576 return;
577
578on_mem_error:
579 ERR("Not enough memory");
580
581on_error:
582 if (arg->data)
583 {
584 ecore_con_server_infos_del(arg->data, arg);
585 arg->done_cb(arg->data, NULL);
586 }
587 free(arg);
588}
589
590static void
591_ecore_con_info_ares_nameinfo(Ecore_Con_CAres *arg,
592 int status,
593 int timeouts __UNUSED__,
594 char *node,
595 char *service)
596{
597 switch (status)
598 {
599 case ARES_SUCCESS:
600 if (node)
601 strcpy(arg->result->ip, node);
602 else
603 *arg->result->ip = '\0';
604
605 if (service)
606 strcpy(arg->result->service, service);
607 else
608 *arg->result->service = '\0';
609
610 if (arg->data) arg->done_cb(arg->data, arg->result);
611 break;
612
613 case ARES_ENOTIMP:
614 case ARES_ENOTFOUND:
615 case ARES_ENOMEM:
616 case ARES_EDESTRUCTION:
617 case ARES_EBADFLAGS:
618 ecore_con_event_server_error(arg->svr, ares_strerror(status));
619 if (arg->data) arg->done_cb(arg->data, NULL);
620 break;
621 }
622
623 free(arg->result->info.ai_addr);
624 free(arg->result);
625 if (arg->data) ecore_con_server_infos_del(arg->data, arg);
626 free(arg);
627}
628
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_info.c b/libraries/ecore/src/lib/ecore_con/ecore_con_info.c
new file mode 100644
index 0000000..4ece6b0
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_info.c
@@ -0,0 +1,450 @@
1/*
2 * getaddrinfo with callback
3 *
4 * man getaddrinfo
5 *
6 */
7
8#ifdef HAVE_CONFIG_H
9# include <config.h>
10#endif
11
12#ifdef HAVE_ALLOCA_H
13# include <alloca.h>
14#elif defined __GNUC__
15# define alloca __builtin_alloca
16#elif defined _AIX
17# define alloca __alloca
18#elif defined _MSC_VER
19# include <malloc.h>
20# define alloca _alloca
21#else
22# include <stddef.h>
23# ifdef __cplusplus
24extern "C"
25# endif
26void *alloca(size_t);
27#endif
28
29#include <string.h>
30#include <sys/types.h>
31#include <unistd.h>
32#include <ctype.h>
33#ifdef __OpenBSD__
34# include <sys/types.h>
35#endif
36
37#ifdef HAVE_NETINET_IN_H
38# include <netinet/in.h>
39#endif
40
41#ifdef HAVE_ARPA_INET_H
42# include <arpa/inet.h>
43#endif
44
45#ifdef HAVE_ARPA_NAMESER_H
46# include <arpa/nameser.h>
47#endif
48
49#ifdef HAVE_SYS_SOCKET_H
50# include <sys/socket.h>
51#endif
52
53#ifdef HAVE_NETDB_H
54# include <netdb.h>
55#endif
56
57#include <errno.h>
58
59#include "Ecore.h"
60#include "ecore_private.h"
61#include "ecore_con_private.h"
62
63typedef struct _CB_Data CB_Data;
64
65struct _CB_Data
66{
67 EINA_INLIST;
68 Ecore_Con_Info_Cb cb_done;
69 void *data;
70 Ecore_Fd_Handler *fdh;
71 pid_t pid;
72 Ecore_Event_Handler *handler;
73 int fd2;
74};
75
76static void _ecore_con_info_readdata(CB_Data *cbdata);
77static void _ecore_con_info_slave_free(CB_Data *cbdata);
78static Eina_Bool _ecore_con_info_data_handler(void *data,
79 Ecore_Fd_Handler *fd_handler);
80static Eina_Bool _ecore_con_info_exit_handler(void *data,
81 int type __UNUSED__,
82 void *event);
83
84static int info_init = 0;
85static CB_Data *info_slaves = NULL;
86
87int
88ecore_con_info_init(void)
89{
90 info_init++;
91 return info_init;
92}
93
94int
95ecore_con_info_shutdown(void)
96{
97 info_init--;
98 if (info_init == 0)
99 while (info_slaves) _ecore_con_info_slave_free(info_slaves);
100
101 return info_init;
102}
103
104int
105ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
106 Ecore_Con_Info_Cb done_cb,
107 void *data)
108{
109 struct addrinfo hints;
110
111 memset(&hints, 0, sizeof(struct addrinfo));
112 hints.ai_family = AF_UNSPEC;
113 hints.ai_socktype = SOCK_STREAM;
114 hints.ai_flags = AI_CANONNAME;
115 hints.ai_protocol = IPPROTO_TCP;
116 hints.ai_canonname = NULL;
117 hints.ai_next = NULL;
118 hints.ai_addr = NULL;
119
120 return ecore_con_info_get(svr, done_cb, data, &hints);
121}
122
123int
124ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
125 Ecore_Con_Info_Cb done_cb,
126 void *data)
127{
128 struct addrinfo hints;
129
130 memset(&hints, 0, sizeof(struct addrinfo));
131 hints.ai_family = AF_UNSPEC;
132 hints.ai_socktype = SOCK_STREAM;
133 hints.ai_flags = AI_PASSIVE;
134 hints.ai_protocol = IPPROTO_TCP;
135 hints.ai_canonname = NULL;
136 hints.ai_next = NULL;
137 hints.ai_addr = NULL;
138
139 return ecore_con_info_get(svr, done_cb, data, &hints);
140}
141
142int
143ecore_con_info_udp_connect(Ecore_Con_Server *svr,
144 Ecore_Con_Info_Cb done_cb,
145 void *data)
146{
147 struct addrinfo hints;
148
149 memset(&hints, 0, sizeof(struct addrinfo));
150 hints.ai_family = AF_UNSPEC;
151 hints.ai_socktype = SOCK_DGRAM;
152 hints.ai_flags = AI_CANONNAME;
153 hints.ai_protocol = IPPROTO_UDP;
154 hints.ai_canonname = NULL;
155 hints.ai_next = NULL;
156 hints.ai_addr = NULL;
157
158 return ecore_con_info_get(svr, done_cb, data, &hints);
159}
160
161int
162ecore_con_info_udp_listen(Ecore_Con_Server *svr,
163 Ecore_Con_Info_Cb done_cb,
164 void *data)
165{
166 struct addrinfo hints;
167
168 memset(&hints, 0, sizeof(struct addrinfo));
169 hints.ai_family = AF_UNSPEC;
170 hints.ai_socktype = SOCK_DGRAM;
171 hints.ai_flags = AI_PASSIVE;
172 hints.ai_protocol = IPPROTO_UDP;
173 hints.ai_canonname = NULL;
174 hints.ai_next = NULL;
175 hints.ai_addr = NULL;
176
177 return ecore_con_info_get(svr, done_cb, data, &hints);
178}
179
180int
181ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
182 Ecore_Con_Info_Cb done_cb,
183 void *data)
184{
185 struct addrinfo hints;
186
187 memset(&hints, 0, sizeof(struct addrinfo));
188 hints.ai_family = AF_UNSPEC;
189 hints.ai_socktype = SOCK_DGRAM;
190 hints.ai_flags = 0;
191 hints.ai_protocol = IPPROTO_UDP;
192 hints.ai_canonname = NULL;
193 hints.ai_next = NULL;
194 hints.ai_addr = NULL;
195
196 return ecore_con_info_get(svr, done_cb, data, &hints);
197}
198
199EAPI int
200ecore_con_info_get(Ecore_Con_Server *svr,
201 Ecore_Con_Info_Cb done_cb,
202 void *data,
203 struct addrinfo *hints)
204{
205 CB_Data *cbdata;
206 int fd[2];
207
208 if (pipe(fd) < 0)
209 {
210 ecore_con_event_server_error(svr, strerror(errno));
211 return 0;
212 }
213
214 cbdata = calloc(1, sizeof(CB_Data));
215 if (!cbdata)
216 {
217 close(fd[0]);
218 close(fd[1]);
219 return 0;
220 }
221
222 cbdata->cb_done = done_cb;
223 cbdata->data = data;
224 cbdata->fd2 = fd[1];
225 if (!(cbdata->fdh = ecore_main_fd_handler_add(fd[0], ECORE_FD_READ,
226 _ecore_con_info_data_handler,
227 cbdata,
228 NULL, NULL)))
229 {
230 ecore_con_event_server_error(svr, "Memory allocation failure");
231 free(cbdata);
232 close(fd[0]);
233 close(fd[1]);
234 return 0;
235 }
236
237 if ((cbdata->pid = fork()) == 0)
238 {
239 Ecore_Con_Info *container;
240 struct addrinfo *result = NULL;
241 char service[NI_MAXSERV] = {0};
242 char hbuf[NI_MAXHOST] = {0};
243 char sbuf[NI_MAXSERV] = {0};
244 unsigned char *tosend = NULL;
245 int tosend_len;
246 int canonname_len = 0;
247 int err;
248
249 eina_convert_itoa(svr->port, service);
250 /* CHILD */
251 if (!getaddrinfo(svr->name, service, hints, &result) && result)
252 {
253 if (result->ai_canonname)
254 canonname_len = strlen(result->ai_canonname) + 1;
255
256 tosend_len = sizeof(Ecore_Con_Info) + result->ai_addrlen +
257 canonname_len;
258
259 tosend = alloca(tosend_len);
260 memset(tosend, 0, tosend_len);
261
262 container = (Ecore_Con_Info *)tosend;
263 container->size = tosend_len;
264
265 memcpy(&container->info,
266 result,
267 sizeof(struct addrinfo));
268 memcpy(tosend + sizeof(Ecore_Con_Info),
269 result->ai_addr,
270 result->ai_addrlen);
271 if (result->ai_canonname) /* FIXME: else... */
272 memcpy(tosend + sizeof(Ecore_Con_Info) + result->ai_addrlen,
273 result->ai_canonname,
274 canonname_len);
275
276 if (!getnameinfo(result->ai_addr, result->ai_addrlen,
277 hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
278 NI_NUMERICHOST | NI_NUMERICSERV))
279 {
280 memcpy(container->ip, hbuf, sizeof(container->ip));
281 memcpy(container->service, sbuf, sizeof(container->service));
282 }
283
284 err = write(fd[1], tosend, tosend_len);
285 }
286
287 if (result)
288 freeaddrinfo(result);
289
290 err = write(fd[1], "", 1);
291 close(fd[1]);
292#if defined(__USE_ISOC99) && !defined(__UCLIBC__)
293 _Exit(0);
294#else
295 _exit(0);
296#endif
297 }
298
299 /* PARENT */
300 cbdata->handler =
301 ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_con_info_exit_handler,
302 cbdata);
303 close(fd[1]);
304 if (!cbdata->handler)
305 {
306 ecore_main_fd_handler_del(cbdata->fdh);
307 free(cbdata);
308 close(fd[0]);
309 return 0;
310 }
311
312 info_slaves = (CB_Data *)eina_inlist_append(EINA_INLIST_GET(
313 info_slaves),
314 EINA_INLIST_GET(cbdata));
315 svr->infos = eina_list_append(svr->infos, cbdata);
316 return 1;
317}
318
319void
320ecore_con_info_data_clear(void *info)
321{
322 CB_Data *cbdata = info;
323 cbdata->data = NULL;
324}
325
326static void
327_ecore_con_info_readdata(CB_Data *cbdata)
328{
329 Ecore_Con_Info container;
330 Ecore_Con_Info *recv_info;
331 unsigned char *torecv;
332 int torecv_len;
333
334 ssize_t size;
335
336 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container,
337 sizeof(Ecore_Con_Info));
338 if (size == sizeof(Ecore_Con_Info))
339 {
340 torecv_len = container.size;
341 torecv = malloc(torecv_len);
342
343 memcpy(torecv, &container, sizeof(Ecore_Con_Info));
344
345 size = read(ecore_main_fd_handler_fd_get(cbdata->fdh),
346 torecv + sizeof(Ecore_Con_Info),
347 torecv_len - sizeof(Ecore_Con_Info));
348 if ((size > 0) &&
349 ((size_t)size == torecv_len - sizeof(Ecore_Con_Info)))
350 {
351 recv_info = (Ecore_Con_Info *)torecv;
352
353 recv_info->info.ai_addr =
354 (struct sockaddr *)(torecv + sizeof(Ecore_Con_Info));
355 if ((size_t)torecv_len !=
356 (sizeof(Ecore_Con_Info) + recv_info->info.ai_addrlen))
357 recv_info->info.ai_canonname = (char *)
358 (torecv + sizeof(Ecore_Con_Info) + recv_info->info.ai_addrlen);
359 else
360 recv_info->info.ai_canonname = NULL;
361
362 recv_info->info.ai_next = NULL;
363
364 if (cbdata->data)
365 {
366 cbdata->cb_done(cbdata->data, recv_info);
367 ecore_con_server_infos_del(cbdata->data, cbdata);
368 }
369
370 free(torecv);
371 }
372 else
373 {
374 if (cbdata->data)
375 {
376 cbdata->cb_done(cbdata->data, NULL);
377 ecore_con_server_infos_del(cbdata->data, cbdata);
378 }
379 }
380 }
381 else
382 {
383 if (cbdata->data)
384 {
385 ecore_con_event_server_error(cbdata->data, strerror(errno));
386 cbdata->cb_done(cbdata->data, NULL);
387 ecore_con_server_infos_del(cbdata->data, cbdata);
388 }
389 }
390
391 cbdata->cb_done = NULL;
392}
393
394static void
395_ecore_con_info_slave_free(CB_Data *cbdata)
396{
397 info_slaves = (CB_Data *)eina_inlist_remove(EINA_INLIST_GET(info_slaves),
398 EINA_INLIST_GET(cbdata));
399 ecore_main_fd_handler_del(cbdata->fdh);
400 ecore_event_handler_del(cbdata->handler);
401 close(ecore_main_fd_handler_fd_get(cbdata->fdh));
402 if (cbdata->data) ecore_con_server_infos_del(cbdata->data, cbdata);
403 free(cbdata);
404}
405
406static Eina_Bool
407_ecore_con_info_data_handler(void *data,
408 Ecore_Fd_Handler *fd_handler)
409{
410 CB_Data *cbdata;
411
412 cbdata = data;
413 if (cbdata->cb_done)
414 {
415 if (ecore_main_fd_handler_active_get(fd_handler,
416 ECORE_FD_READ))
417 _ecore_con_info_readdata(cbdata);
418 else
419 {
420 if (cbdata->data)
421 {
422 cbdata->cb_done(cbdata->data, NULL);
423 cbdata->cb_done = NULL;
424 ecore_con_server_infos_del(cbdata->data, cbdata);
425 }
426 }
427 }
428
429 _ecore_con_info_slave_free(cbdata);
430 return ECORE_CALLBACK_CANCEL;
431}
432
433static Eina_Bool
434_ecore_con_info_exit_handler(void *data,
435 int type __UNUSED__,
436 void *event)
437{
438 CB_Data *cbdata;
439 Ecore_Exe_Event_Del *ev;
440
441 ev = event;
442 cbdata = data;
443 if (cbdata->pid != ev->pid)
444 return ECORE_CALLBACK_RENEW;
445
446 return ECORE_CALLBACK_CANCEL; /* FIXME: Woot ??? */
447 _ecore_con_info_slave_free(cbdata);
448 return ECORE_CALLBACK_CANCEL;
449}
450
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_local.c b/libraries/ecore/src/lib/ecore_con/ecore_con_local.c
new file mode 100644
index 0000000..f02cc1f
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_local.c
@@ -0,0 +1,317 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <string.h>
7#include <unistd.h>
8#include <time.h>
9#include <fcntl.h>
10#include <sys/stat.h>
11
12#ifdef HAVE_SYS_SOCKET_H
13# include <sys/socket.h>
14#endif
15
16#ifdef HAVE_SYS_UN_H
17# include <sys/un.h>
18#endif
19
20#ifdef HAVE_WS2TCPIP_H
21# include <ws2tcpip.h>
22#endif
23
24#include <Ecore.h>
25#include <ecore_private.h>
26
27#include "Ecore_Con.h"
28#include "ecore_con_private.h"
29
30#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + \
31 (size_t)(((struct sockaddr_un *)NULL)-> \
32 sun_path))
33#define LENGTH_OF_ABSTRACT_SOCKADDR_UN(s, path) (strlen(path) + 1 + \
34 (size_t)(((struct sockaddr_un \
35 *)NULL)->sun_path))
36
37static int _ecore_con_local_init_count = 0;
38
39int
40ecore_con_local_init(void)
41{
42 if (++_ecore_con_local_init_count != 1)
43 return _ecore_con_local_init_count;
44
45 return _ecore_con_local_init_count;
46}
47
48int
49ecore_con_local_shutdown(void)
50{
51 if (--_ecore_con_local_init_count != 0)
52 return _ecore_con_local_init_count;
53
54 return _ecore_con_local_init_count;
55}
56
57int
58ecore_con_local_connect(Ecore_Con_Server *svr,
59 Eina_Bool (*cb_done)(void *data, Ecore_Fd_Handler *fd_handler),
60 void *data __UNUSED__)
61{
62#ifndef HAVE_LOCAL_SOCKETS
63 return 0;
64#else
65 char buf[4096];
66 struct sockaddr_un socket_unix;
67 int curstate = 0;
68 const char *homedir;
69 int socket_unix_len;
70
71 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
72 {
73 homedir = getenv("HOME");
74 if (!homedir)
75 homedir = getenv("TMP");
76
77 if (!homedir)
78 homedir = "/tmp";
79
80 snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", homedir, svr->name,
81 svr->port);
82 }
83 else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
84 {
85 if (svr->port < 0)
86 {
87 if (svr->name[0] == '/')
88 strncpy(buf, svr->name, sizeof(buf));
89 else
90 snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s", svr->name);
91 }
92 else
93 {
94 if (svr->name[0] ==
95 '/')
96 snprintf(buf, sizeof(buf), "%s|%i", svr->name,
97 svr->port);
98 else
99 snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s|%i",
100 svr->name,
101 svr->port);
102 }
103 }
104 else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
105 strncpy(buf, svr->name,
106 sizeof(buf));
107
108 svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
109 if (svr->fd < 0)
110 return 0;
111
112 if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
113 return 0;
114
115 if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
116 return 0;
117
118 if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate,
119 sizeof(curstate)) < 0)
120 return 0;
121
122 socket_unix.sun_family = AF_UNIX;
123
124 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
125 {
126#ifdef HAVE_ABSTRACT_SOCKETS
127 /* copy name insto sun_path, prefixed by null to indicate abstract namespace */
128 snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s",
129 svr->name);
130 socket_unix.sun_path[0] = '\0';
131 socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix,
132 svr->name);
133#else
134 WRN("Your system does not support abstract sockets!");
135 return 0;
136#endif
137 }
138 else
139 {
140 strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
141 socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
142 }
143
144 if (connect(svr->fd, (struct sockaddr *)&socket_unix,
145 socket_unix_len) < 0)
146 return 0;
147
148 svr->path = strdup(buf);
149 if (!svr->path)
150 return 0;
151
152 if (svr->type & ECORE_CON_SSL)
153 ecore_con_ssl_server_init(svr);
154
155 svr->fd_handler =
156 ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
157 cb_done, svr, NULL, NULL);
158 if (!svr->fd_handler)
159 return 0;
160
161 if (!svr->delete_me) ecore_con_event_server_add(svr);
162
163 return 1;
164#endif
165}
166
167int
168ecore_con_local_listen(
169 Ecore_Con_Server *svr,
170 Eina_Bool (*
171 cb_listen)(void *data,
172 Ecore_Fd_Handler *
173 fd_handler),
174 void *data
175 __UNUSED__)
176{
177#ifdef HAVE_LOCAL_SOCKETS
178 char buf[4096];
179 struct sockaddr_un socket_unix;
180 struct linger lin;
181 mode_t pmode;
182 const char *homedir;
183 struct stat st;
184 mode_t mask;
185 int socket_unix_len;
186
187 mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
188
189 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
190 {
191 homedir = getenv("HOME");
192 if (!homedir)
193 homedir = getenv("TMP");
194
195 if (!homedir)
196 homedir = "/tmp";
197
198 mask = S_IRUSR | S_IWUSR | S_IXUSR;
199 snprintf(buf, sizeof(buf), "%s/.ecore", homedir);
200 if (stat(buf, &st) < 0)
201 mkdir(buf, mask);
202
203 snprintf(buf, sizeof(buf), "%s/.ecore/%s", homedir, svr->name);
204 if (stat(buf, &st) < 0)
205 mkdir(buf, mask);
206
207 snprintf(buf,
208 sizeof(buf),
209 "%s/.ecore/%s/%i",
210 homedir,
211 svr->name,
212 svr->port);
213 mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
214 }
215 else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
216 {
217 mask = 0;
218 if (svr->name[0] == '/')
219 {
220 if (svr->port >= 0)
221 snprintf(buf,
222 sizeof(buf),
223 "%s|%i",
224 svr->name,
225 svr->port);
226 else
227 snprintf(buf,
228 sizeof(buf),
229 "%s",
230 svr->name);
231 }
232 else
233 snprintf(buf,
234 sizeof(buf),
235 "/tmp/.ecore_service|%s|%i",
236 svr->name,
237 svr->port);
238 }
239 else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
240 strncpy(buf, svr->name,
241 sizeof(buf));
242
243 pmode = umask(mask);
244start:
245 svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
246 if (svr->fd < 0)
247 goto error_umask;
248
249 if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
250 goto error_umask;
251
252 if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
253 goto error_umask;
254
255 lin.l_onoff = 1;
256 lin.l_linger = 0;
257 if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin,
258 sizeof(struct linger)) < 0)
259 goto error_umask;
260
261 socket_unix.sun_family = AF_UNIX;
262 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
263 {
264#ifdef HAVE_ABSTRACT_SOCKETS
265 /* . is a placeholder */
266 snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s",
267 svr->name);
268 /* first char null indicates abstract namespace */
269 socket_unix.sun_path[0] = '\0';
270 socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix,
271 svr->name);
272#else
273 ERR("Your system does not support abstract sockets!");
274 goto error_umask;
275#endif
276 }
277 else
278 {
279 strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
280 socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
281 }
282
283 if (bind(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
284 {
285 if ((((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER) ||
286 ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)) &&
287 (connect(svr->fd, (struct sockaddr *)&socket_unix,
288 socket_unix_len) < 0) &&
289 (unlink(buf) >= 0))
290 goto start;
291 else
292 goto error_umask;
293 }
294
295 if (listen(svr->fd, 4096) < 0)
296 goto error_umask;
297
298 svr->path = strdup(buf);
299 if (!svr->path)
300 goto error_umask;
301
302 svr->fd_handler =
303 ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
304 cb_listen, svr, NULL, NULL);
305 umask(pmode);
306 if (!svr->fd_handler)
307 goto error;
308
309 return 1;
310
311error_umask:
312 umask(pmode);
313error:
314#endif /* HAVE_LOCAL_SOCKETS */
315 return 0;
316}
317
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_local_win32.c b/libraries/ecore/src/lib/ecore_con/ecore_con_local_win32.c
new file mode 100644
index 0000000..858daa5
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_local_win32.c
@@ -0,0 +1,769 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <process.h>
6
7#include <Evil.h>
8#include <Ecore.h>
9
10#include "Ecore_Con.h"
11#include "ecore_con_private.h"
12
13#define BUFSIZE 512
14
15
16static int _ecore_con_local_init_count = 0;
17
18int
19ecore_con_local_init(void)
20{
21 if (++_ecore_con_local_init_count != 1)
22 return _ecore_con_local_init_count;
23
24 return _ecore_con_local_init_count;
25}
26
27int
28ecore_con_local_shutdown(void)
29{
30 if (--_ecore_con_local_init_count != 0)
31 return _ecore_con_local_init_count;
32
33 return _ecore_con_local_init_count;
34}
35
36
37static Eina_Bool
38_ecore_con_local_win32_server_read_client_handler(void *data, Ecore_Win32_Handler *wh)
39{
40 Ecore_Con_Client *cl;
41 void *buf;
42 DWORD n;
43 Eina_Bool broken_pipe = EINA_FALSE;
44
45 cl = (Ecore_Con_Client *)data;
46
47 if (!ResetEvent(cl->host_server->event_read))
48 return ECORE_CALLBACK_RENEW;
49
50 buf = malloc(cl->host_server->nbr_bytes);
51 if (!buf)
52 return ECORE_CALLBACK_RENEW;
53
54 if (ReadFile(cl->host_server->pipe, buf, cl->host_server->nbr_bytes, &n, NULL))
55 {
56 if (!cl->delete_me)
57 ecore_con_event_client_data(cl, buf, cl->host_server->nbr_bytes, EINA_FALSE);
58 cl->host_server->want_write = 1;
59 }
60 else
61 {
62 if (GetLastError() == ERROR_BROKEN_PIPE)
63 broken_pipe = EINA_TRUE;
64 }
65
66 if (broken_pipe)
67 {
68#if 0
69 char *msg;
70
71 msg = evil_last_error_get();
72 if (msg)
73 {
74 ecore_con_event_client_error(cl, msg);
75 free(msg);
76 }
77#endif
78 if (!cl->delete_me)
79 ecore_con_event_client_del(cl);
80 cl->dead = EINA_TRUE;
81 return ECORE_CALLBACK_CANCEL;
82 }
83
84 if (cl->host_server->want_write)
85 ecore_con_local_win32_client_flush(cl);
86
87 ecore_main_win32_handler_del(wh);
88
89 return ECORE_CALLBACK_DONE;
90}
91
92static Eina_Bool
93_ecore_con_local_win32_server_peek_client_handler(void *data, Ecore_Win32_Handler *wh)
94{
95 Ecore_Con_Client *cl;
96#if 0
97 char *msg;
98#endif
99
100 cl = (Ecore_Con_Client *)data;
101
102 if (!ResetEvent(cl->host_server->event_peek))
103 return ECORE_CALLBACK_RENEW;
104
105#if 0
106 msg = evil_last_error_get();
107 if (msg)
108 {
109 ecore_con_event_server_error(cl->host_server, msg);
110 free(msg);
111 }
112#endif
113 if (!cl->host_server->delete_me)
114 ecore_con_event_server_del(cl->host_server);
115 cl->host_server->dead = EINA_TRUE;
116 return ECORE_CALLBACK_CANCEL;
117
118 ecore_main_win32_handler_del(wh);
119
120 return ECORE_CALLBACK_DONE;
121}
122
123static Eina_Bool
124_ecore_con_local_win32_client_peek_server_handler(void *data, Ecore_Win32_Handler *wh)
125{
126 Ecore_Con_Server *svr;
127#if 0
128 char *msg;
129#endif
130
131 svr = (Ecore_Con_Server *)data;
132
133 if (!ResetEvent(svr->event_peek))
134 return ECORE_CALLBACK_RENEW;
135#if 0
136 msg = evil_last_error_get();
137 if (msg)
138 {
139 ecore_con_event_server_error(svr, msg);
140 free(msg);
141 }
142#endif
143 if (!svr->delete_me)
144 ecore_con_event_server_del(svr);
145 svr->dead = EINA_TRUE;
146 return ECORE_CALLBACK_CANCEL;
147
148 ecore_main_win32_handler_del(wh);
149
150 return ECORE_CALLBACK_DONE;
151}
152
153static Eina_Bool
154_ecore_con_local_win32_client_read_server_handler(void *data, Ecore_Win32_Handler *wh)
155{
156 Ecore_Con_Server *svr;
157 void *buf;
158 DWORD n;
159 Eina_Bool broken_pipe = EINA_FALSE;
160
161 svr = (Ecore_Con_Server *)data;
162
163 if (!ResetEvent(svr->event_read))
164 return ECORE_CALLBACK_RENEW;
165
166 buf = malloc(svr->nbr_bytes);
167 if (!buf)
168 return ECORE_CALLBACK_RENEW;
169
170 if (ReadFile(svr->pipe, buf, svr->nbr_bytes, &n, NULL))
171 {
172 if (!svr->delete_me)
173 ecore_con_event_server_data(svr, buf, svr->nbr_bytes, EINA_FALSE);
174 svr->want_write = 1;
175 }
176 else
177 {
178 if (GetLastError() == ERROR_BROKEN_PIPE)
179 broken_pipe = EINA_TRUE;
180 }
181
182 if (broken_pipe)
183 {
184#if 0
185 char *msg;
186
187 msg = evil_last_error_get();
188 if (msg)
189 {
190 ecore_con_event_server_error(svr, msg);
191 free(msg);
192 }
193#endif
194 if (!svr->delete_me)
195 ecore_con_event_server_del(svr);
196 svr->dead = EINA_TRUE;
197 return ECORE_CALLBACK_CANCEL;
198 }
199
200 if (svr->want_write)
201 ecore_con_local_win32_server_flush(svr);
202
203 ecore_main_win32_handler_del(wh);
204
205 return ECORE_CALLBACK_DONE;
206}
207
208/* thread to read data sent by the server to the client */
209static unsigned int __stdcall
210_ecore_con_local_win32_client_read_server_thread(void *data)
211{
212 Ecore_Con_Server *svr;
213 DWORD nbr_bytes = 0;
214
215 svr = (Ecore_Con_Server *)data;
216
217 svr->read_stopped = EINA_FALSE;
218
219 while (!svr->read_stop)
220 {
221 if (PeekNamedPipe(svr->pipe, NULL, 0, NULL, &nbr_bytes, NULL))
222 {
223 if (nbr_bytes <= 0)
224 continue;
225
226 svr->nbr_bytes = nbr_bytes;
227 if (!SetEvent(svr->event_read))
228 continue;
229 }
230 else
231 {
232 if (GetLastError() == ERROR_BROKEN_PIPE)
233 {
234 if (!SetEvent(svr->event_peek))
235 continue;
236 break;
237 }
238 }
239 }
240
241 printf(" ### %s\n", __FUNCTION__);
242 svr->read_stopped = EINA_TRUE;
243 _endthreadex(0);
244 return 0;
245}
246
247/* thread to read data sent by the client to the server */
248static unsigned int __stdcall
249_ecore_con_local_win32_server_read_client_thread(void *data)
250{
251 Ecore_Con_Client *cl;
252 DWORD nbr_bytes = 0;
253
254 cl = (Ecore_Con_Client *)data;
255
256 cl->host_server->read_stopped = EINA_FALSE;
257
258 while (!cl->host_server->read_stop)
259 {
260 if (PeekNamedPipe(cl->host_server->pipe, NULL, 0, NULL, &nbr_bytes, NULL))
261 {
262 if (nbr_bytes <= 0)
263 continue;
264
265 cl->host_server->nbr_bytes = nbr_bytes;
266 if (!SetEvent(cl->host_server->event_read))
267 continue;
268 }
269 else
270 {
271 if (GetLastError() == ERROR_BROKEN_PIPE)
272 {
273 if (!SetEvent(cl->host_server->event_peek))
274 continue;
275 break;
276 }
277 }
278 }
279
280 printf(" ### %s\n", __FUNCTION__);
281 cl->host_server->read_stopped = EINA_TRUE;
282 _endthreadex(0);
283 return 0;
284}
285
286static Eina_Bool
287_ecore_con_local_win32_client_add(void *data, Ecore_Win32_Handler *wh)
288{
289 Ecore_Con_Client *cl = NULL;
290 Ecore_Con_Server *svr;
291 Ecore_Win32_Handler *handler_read;
292 Ecore_Win32_Handler *handler_peek;
293
294 svr = (Ecore_Con_Server *)data;
295
296 if (!svr->pipe)
297 return ECORE_CALLBACK_CANCEL;
298
299 if (svr->dead)
300 return ECORE_CALLBACK_CANCEL;
301
302 if (svr->delete_me)
303 return ECORE_CALLBACK_CANCEL;
304
305 if ((svr->client_limit >= 0) && (!svr->reject_excess_clients) &&
306 (svr->client_count >= (unsigned int)svr->client_limit))
307 return ECORE_CALLBACK_CANCEL;
308
309 cl = calloc(1, sizeof(Ecore_Con_Client));
310 if (!cl)
311 {
312 ERR("allocation failed");
313 return ECORE_CALLBACK_CANCEL;
314 }
315
316 cl->host_server = svr;
317 ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
318
319 cl->host_server->event_read = CreateEvent(NULL, TRUE, FALSE, NULL);
320 if (!cl->host_server->event_read)
321 {
322 ERR("Can not create event read");
323 goto free_cl;
324 }
325
326 handler_read = ecore_main_win32_handler_add(cl->host_server->event_read,
327 _ecore_con_local_win32_server_read_client_handler,
328 cl);
329 if (!handler_read)
330 {
331 ERR("Can not create handler read");
332 goto close_event_read;
333 }
334
335 cl->host_server->event_peek = CreateEvent(NULL, TRUE, FALSE, NULL);
336 if (!cl->host_server->event_peek)
337 {
338 ERR("Can not create event peek");
339 goto del_handler_read;
340 }
341
342 handler_peek = ecore_main_win32_handler_add(cl->host_server->event_peek,
343 _ecore_con_local_win32_server_peek_client_handler,
344 cl);
345 if (!handler_peek)
346 {
347 ERR("Can not create handler peek");
348 goto close_event_peek;
349 }
350
351 cl->host_server->read_stopped = EINA_TRUE;
352 cl->host_server->thread_read = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_server_read_client_thread, cl, CREATE_SUSPENDED, NULL);
353 if (!cl->host_server->thread_read)
354 {
355 ERR("Can not launch thread");
356 goto del_handler_peek;
357 }
358
359 svr->clients = eina_list_append(svr->clients, cl);
360 svr->client_count++;
361
362 if (!cl->delete_me)
363 ecore_con_event_client_add(cl);
364
365 ecore_main_win32_handler_del(wh);
366
367 ResumeThread(cl->host_server->thread_read);
368 return ECORE_CALLBACK_DONE;
369
370 del_handler_peek:
371 ecore_main_win32_handler_del(handler_peek);
372 close_event_peek:
373 CloseHandle(cl->host_server->event_peek);
374 del_handler_read:
375 ecore_main_win32_handler_del(handler_read);
376 close_event_read:
377 CloseHandle(cl->host_server->event_read);
378 free_cl:
379 free(cl);
380
381 return ECORE_CALLBACK_CANCEL;
382}
383
384static unsigned int __stdcall
385_ecore_con_local_win32_listening(void *data)
386{
387 Ecore_Con_Server *svr;
388 BOOL res;
389
390 svr = (Ecore_Con_Server *)data;
391
392 while (1)
393 {
394 res = ConnectNamedPipe(svr->pipe, NULL);
395 if (!res)
396 {
397 ERR("Opening the connection to the client failed");
398 CloseHandle(svr->pipe);
399 svr->pipe = NULL;
400 }
401 break;
402 }
403
404 DBG("Client connected");
405
406 printf(" ### %s\n", __FUNCTION__);
407 _endthreadex(0);
408 return 0;
409}
410
411Eina_Bool
412ecore_con_local_listen(Ecore_Con_Server *svr)
413{
414 char buf[256];
415 HANDLE thread_listening;
416 Ecore_Win32_Handler *handler;
417
418 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
419 {
420 ERR("Your system does not support abstract sockets!");
421 return EINA_FALSE;
422 }
423
424 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
425 snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", svr->name);
426 else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
427 {
428 const char *computername;
429
430 computername = getenv("CoMPUTERNAME");
431 snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s", computername, svr->name);
432 }
433
434 svr->path = strdup(buf);
435 if (!svr->path)
436 {
437 ERR("Allocation failed");
438 return EINA_FALSE;
439 }
440
441 /*
442 * synchronuous
443 * block mode
444 * wait mode
445 */
446 svr->pipe = CreateNamedPipe(svr->path,
447 PIPE_ACCESS_DUPLEX,
448 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
449 PIPE_UNLIMITED_INSTANCES,
450 BUFSIZE,
451 BUFSIZE,
452 5000,
453 NULL);
454 if (svr->pipe == INVALID_HANDLE_VALUE)
455 {
456 ERR("Creation of the named pipe failed");
457 goto free_path;
458 }
459
460 /*
461 * We use ConnectNamedPipe() to wait for a client to connect.
462 * As the function is blocking, to let the main loop continuing
463 * its iterations, we call ConnectNamedPipe() in a thread
464 */
465 thread_listening = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_listening, svr, CREATE_SUSPENDED, NULL);
466 if (!thread_listening)
467 {
468 ERR("Creation of the listening thread failed");
469 goto close_pipe;
470 }
471
472 handler = ecore_main_win32_handler_add(thread_listening,
473 _ecore_con_local_win32_client_add,
474 svr);
475 if (!handler)
476 {
477 ERR("Creation of the client add handler failed");
478 goto del_handler;
479 }
480
481 svr->read_stopped = EINA_TRUE;
482 ResumeThread(thread_listening);
483
484 return EINA_TRUE;
485
486 del_handler:
487 ecore_main_win32_handler_del(handler);
488 close_pipe:
489 CloseHandle(svr->pipe);
490 free_path:
491 free(svr->path);
492 svr->path = NULL;
493
494 return EINA_FALSE;
495}
496
497void
498ecore_con_local_win32_server_del(Ecore_Con_Server *svr)
499{
500 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
501 return;
502
503 if (((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
504 ((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
505 return;
506
507 svr->read_stop = 1;
508 while (!svr->read_stopped)
509 Sleep(100);
510
511 if (svr->event_peek)
512 CloseHandle(svr->event_peek);
513 svr->event_peek = NULL;
514 if (svr->event_read)
515 CloseHandle(svr->event_read);
516 svr->event_read = NULL;
517 free(svr->path);
518 svr->path = NULL;
519 if (svr->pipe)
520 CloseHandle(svr->pipe);
521 svr->pipe = NULL;
522}
523
524void
525ecore_con_local_win32_client_del(Ecore_Con_Client *cl)
526{
527 if ((cl->host_server->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
528 return;
529
530 if (((cl->host_server->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
531 ((cl->host_server->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
532 return;
533
534 cl->host_server->read_stop = 1;
535 while (!cl->host_server->read_stopped)
536 Sleep(100);
537
538 if (cl->host_server->event_peek)
539 CloseHandle(cl->host_server->event_peek);
540 cl->host_server->event_peek = NULL;
541 if (cl->host_server->event_read)
542 CloseHandle(cl->host_server->event_read);
543 cl->host_server->event_read = NULL;
544 free(cl->host_server->path);
545 cl->host_server->path = NULL;
546 if (cl->host_server->pipe)
547 CloseHandle(cl->host_server->pipe);
548 cl->host_server->pipe = NULL;
549}
550
551Eina_Bool
552ecore_con_local_connect(Ecore_Con_Server *svr,
553 Eina_Bool (*cb_done)(void *data,
554 Ecore_Fd_Handler *fd_handler))
555{
556 char buf[256];
557 Ecore_Win32_Handler *handler_read;
558 Ecore_Win32_Handler *handler_peek;
559
560 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
561 {
562 ERR("Your system does not support abstract sockets!");
563 return EINA_FALSE;
564 }
565
566 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_USER)
567 snprintf(buf, sizeof(buf), "\\\\.\\pipe\\%s", svr->name);
568 else if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_SYSTEM)
569 {
570 const char *computername;
571
572 computername = getenv("COMPUTERNAME");
573 snprintf(buf, sizeof(buf), "\\\\%s\\pipe\\%s", computername, svr->name);
574 }
575
576 while (1)
577 {
578 svr->pipe = CreateFile(buf,
579 GENERIC_READ | GENERIC_WRITE,
580 0,
581 NULL,
582 OPEN_EXISTING,
583 0,
584 NULL);
585 if (svr->pipe != INVALID_HANDLE_VALUE)
586 break;
587
588 /* if pipe not busy, we exit */
589 if (GetLastError() != ERROR_PIPE_BUSY)
590 {
591 ERR("Connection to a server failed");
592 return EINA_FALSE;
593 }
594
595 /* pipe busy, so we wait for it */
596 if (!WaitNamedPipe(buf, NMPWAIT_WAIT_FOREVER))
597 {
598 ERR("Can not wait for a server");
599 goto close_pipe;
600 }
601 }
602
603 svr->path = strdup(buf);
604 if (!svr->path)
605 {
606 ERR("Allocation failed");
607 goto close_pipe;
608 }
609
610 svr->event_read = CreateEvent(NULL, TRUE, FALSE, NULL);
611 if (!svr->event_read)
612 {
613 ERR("Can not create event read");
614 goto free_path;
615 }
616
617 handler_read = ecore_main_win32_handler_add(svr->event_read,
618 _ecore_con_local_win32_client_read_server_handler,
619 svr);
620 if (!handler_read)
621 {
622 ERR("Can not create handler read");
623 goto close_event_read;
624 }
625
626 svr->event_peek = CreateEvent(NULL, TRUE, FALSE, NULL);
627 if (!svr->event_peek)
628 {
629 ERR("Can not create event peek");
630 goto del_handler_read;
631 }
632
633 handler_peek = ecore_main_win32_handler_add(svr->event_peek,
634 _ecore_con_local_win32_client_peek_server_handler,
635 svr);
636 if (!handler_peek)
637 {
638 ERR("Can not create handler peek");
639 goto close_event_peek;
640 }
641
642 svr->thread_read = (HANDLE)_beginthreadex(NULL, 0, _ecore_con_local_win32_client_read_server_thread, svr, CREATE_SUSPENDED, NULL);
643 if (!svr->thread_read)
644 {
645 ERR("Can not launch thread");
646 goto del_handler_peek;
647 }
648
649 if (!svr->delete_me) ecore_con_event_server_add(svr);
650
651 ResumeThread(svr->thread_read);
652
653 return EINA_TRUE;
654
655 del_handler_peek:
656 ecore_main_win32_handler_del(handler_peek);
657 close_event_peek:
658 CloseHandle(svr->event_peek);
659 del_handler_read:
660 ecore_main_win32_handler_del(handler_read);
661 close_event_read:
662 CloseHandle(svr->event_read);
663 free_path:
664 free(svr->path);
665 svr->path = NULL;
666 close_pipe:
667 CloseHandle(svr->pipe);
668
669 return EINA_FALSE;
670}
671
672Eina_Bool
673ecore_con_local_win32_server_flush(Ecore_Con_Server *svr)
674{
675 int num;
676 BOOL res;
677 DWORD written;
678
679 /* This check should never be true */
680 if ((svr->type & ECORE_CON_TYPE) == ECORE_CON_LOCAL_ABSTRACT)
681 return EINA_TRUE;
682
683 if (((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_USER) &&
684 ((svr->type & ECORE_CON_TYPE) != ECORE_CON_LOCAL_SYSTEM))
685 return EINA_FALSE;
686
687 num = eina_binbuf_length_get(svr->buf) - svr->write_buf_offset;
688 if (num <= 0) return EINA_TRUE;
689
690 res = WriteFile(svr->pipe, eina_binbuf_string_get(svr->buf) + svr->write_buf_offset, num, &written, NULL);
691 if (!res)
692 {
693 char *msg;
694
695 msg = evil_last_error_get();
696 if (msg)
697 {
698 ecore_con_event_server_error(svr, msg);
699 free(msg);
700 }
701 if (!svr->delete_me)
702 ecore_con_event_server_del(svr);
703 svr->dead = EINA_TRUE;
704 }
705
706 svr->write_buf_offset += written;
707 if (svr->write_buf_offset >= eina_binbuf_length_get(svr->buf))
708 {
709 svr->write_buf_offset = 0;
710 eina_binbuf_free(svr->buf);
711 svr->buf = NULL;
712 svr->want_write = 0;
713 }
714 else if (written < (DWORD)num)
715 svr->want_write = 1;
716
717 return EINA_TRUE;
718}
719
720Eina_Bool
721ecore_con_local_win32_client_flush(Ecore_Con_Client *cl)
722{
723 Ecore_Con_Type type;
724 int num;
725 BOOL res;
726 DWORD written;
727
728 type = cl->host_server->type & ECORE_CON_TYPE;
729
730 /* This check should never be true */
731 if (type == ECORE_CON_LOCAL_ABSTRACT)
732 return EINA_TRUE;
733
734 if ((type != ECORE_CON_LOCAL_USER) &&
735 (type != ECORE_CON_LOCAL_SYSTEM))
736 return EINA_FALSE;
737
738 num = eina_binbuf_length_get(cl->buf) - cl->buf_offset;
739 if (num <= 0) return EINA_TRUE;
740
741 res = WriteFile(cl->host_server->pipe, eina_binbuf_string_get(cl->buf) + cl->buf_offset, num, &written, NULL);
742 if (!res)
743 {
744 char *msg;
745
746 msg = evil_last_error_get();
747 if (msg)
748 {
749 ecore_con_event_client_error(cl, msg);
750 free(msg);
751 }
752 if (!cl->delete_me)
753 ecore_con_event_client_del(cl);
754 cl->dead = EINA_TRUE;
755 }
756
757 cl->buf_offset += written;
758 if (cl->buf_offset >= eina_binbuf_length_get(cl->buf))
759 {
760 cl->buf_offset = 0;
761 eina_binbuf_free(cl->buf);
762 cl->buf = NULL;
763 cl->host_server->want_write = 0;
764 }
765 else if (written < (DWORD)num)
766 cl->host_server->want_write = 1;
767
768 return EINA_TRUE;
769}
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_private.h b/libraries/ecore/src/lib/ecore_con/ecore_con_private.h
new file mode 100644
index 0000000..f601465
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_private.h
@@ -0,0 +1,321 @@
1#ifndef _ECORE_CON_PRIVATE_H
2#define _ECORE_CON_PRIVATE_H
3
4#include "ecore_private.h"
5#include "Ecore_Con.h"
6
7#define ECORE_MAGIC_CON_SERVER 0x77665544
8#define ECORE_MAGIC_CON_CLIENT 0x77556677
9#define ECORE_MAGIC_CON_URL 0x77074255
10
11#define ECORE_CON_TYPE 0x0f
12#define ECORE_CON_SSL 0xf0
13
14#if USE_GNUTLS
15# include <gnutls/gnutls.h>
16#elif USE_OPENSSL
17# include <openssl/ssl.h>
18#endif
19#ifdef HAVE_CURL
20#include <curl/curl.h>
21#endif
22
23#define READBUFSIZ 65536
24
25extern int _ecore_con_log_dom;
26
27#ifdef ECORE_CON_DEFAULT_LOG_COLOR
28#undef ECORE_LOG_DEFAULT_LOG_COLOR
29#endif
30#define ECORE_CON_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
31
32#ifdef ERR
33# undef ERR
34#endif
35#define ERR(...) EINA_LOG_DOM_ERR(_ecore_con_log_dom, __VA_ARGS__)
36
37#ifdef DBG
38# undef DBG
39#endif
40#define DBG(...) EINA_LOG_DOM_DBG(_ecore_con_log_dom, __VA_ARGS__)
41
42#ifdef INF
43# undef INF
44#endif
45#define INF(...) EINA_LOG_DOM_INFO(_ecore_con_log_dom, __VA_ARGS__)
46
47#ifdef WRN
48# undef WRN
49#endif
50#define WRN(...) EINA_LOG_DOM_WARN(_ecore_con_log_dom, __VA_ARGS__)
51
52#ifdef CRIT
53# undef CRIT
54#endif
55#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_con_log_dom, __VA_ARGS__)
56
57typedef struct _Ecore_Con_Lookup Ecore_Con_Lookup;
58typedef struct _Ecore_Con_Info Ecore_Con_Info;
59
60typedef void (*Ecore_Con_Info_Cb)(void *data, Ecore_Con_Info *infos);
61
62typedef enum _Ecore_Con_State
63{
64 ECORE_CON_CONNECTED,
65 ECORE_CON_DISCONNECTED,
66 ECORE_CON_INPROGRESS
67} Ecore_Con_State;
68
69typedef enum _Ecore_Con_Ssl_Error
70{
71 ECORE_CON_SSL_ERROR_NONE = 0,
72 ECORE_CON_SSL_ERROR_NOT_SUPPORTED,
73 ECORE_CON_SSL_ERROR_INIT_FAILED,
74 ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED,
75 ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED
76} Ecore_Con_Ssl_Error;
77
78typedef enum _Ecore_Con_Ssl_Handshake
79{
80 ECORE_CON_SSL_STATE_DONE = 0,
81 ECORE_CON_SSL_STATE_HANDSHAKING,
82 ECORE_CON_SSL_STATE_INIT
83} Ecore_Con_Ssl_State;
84
85struct _Ecore_Con_Client
86{
87 ECORE_MAGIC;
88 int fd;
89 Ecore_Con_Server *host_server;
90 void *data;
91 Ecore_Fd_Handler *fd_handler;
92 unsigned int buf_offset;
93 Eina_Binbuf *buf;
94 const char *ip;
95 Eina_List *event_count;
96 struct sockaddr *client_addr;
97 int client_addr_len;
98 double start_time;
99 Ecore_Timer *until_deletion;
100 double disconnect_time;
101#if USE_GNUTLS
102 gnutls_datum_t session_ticket;
103 gnutls_session_t session;
104#elif USE_OPENSSL
105 SSL *ssl;
106 int ssl_err;
107#endif
108 Ecore_Con_Ssl_State ssl_state;
109 Eina_Bool handshaking : 1;
110 Eina_Bool upgrade : 1;
111 Eina_Bool dead : 1;
112 Eina_Bool delete_me : 1;
113};
114
115struct _Ecore_Con_Server
116{
117 ECORE_MAGIC;
118 int fd;
119 Ecore_Con_Type type;
120 char *name;
121 int port;
122 char *path;
123 void *data;
124 Ecore_Fd_Handler *fd_handler;
125 Eina_List *clients;
126 unsigned int client_count;
127 Eina_Binbuf *buf;
128 unsigned int write_buf_offset;
129 Eina_List *infos;
130 Eina_List *event_count;
131 int client_limit;
132 pid_t ppid;
133#if USE_GNUTLS
134 gnutls_session_t session;
135 gnutls_anon_client_credentials_t anoncred_c;
136 gnutls_anon_server_credentials_t anoncred_s;
137 gnutls_psk_client_credentials_t pskcred_c;
138 gnutls_psk_server_credentials_t pskcred_s;
139 gnutls_certificate_credentials_t cert;
140 char *cert_file;
141 gnutls_dh_params_t dh_params;
142#elif USE_OPENSSL
143 SSL_CTX *ssl_ctx;
144 SSL *ssl;
145 int ssl_err;
146#endif
147 double start_time;
148 Ecore_Timer *until_deletion;
149 double disconnect_time;
150 double client_disconnect_time;
151 const char *ip;
152 Eina_Bool dead : 1;
153 Eina_Bool created : 1; /* EINA_TRUE if server is our listening server */
154 Eina_Bool connecting : 1; /* EINA_FALSE if just initialized or connected */
155 Eina_Bool handshaking : 1; /* EINA_TRUE if server is ssl handshaking */
156 Eina_Bool upgrade : 1;
157 Eina_Bool ssl_prepared : 1;
158 Eina_Bool use_cert : 1; /* EINA_TRUE if using certificate auth */
159 Ecore_Con_Ssl_State ssl_state; /* current state of ssl handshake on the server */
160 Eina_Bool verify : 1; /* EINA_TRUE if certificates will be verified */
161 Eina_Bool verify_basic : 1; /* EINA_TRUE if certificates will be verified only against the hostname */
162 Eina_Bool reject_excess_clients : 1;
163 Eina_Bool delete_me : 1;
164#ifdef _WIN32
165 Eina_Bool want_write : 1;
166 Eina_Bool read_stop : 1;
167 Eina_Bool read_stopped : 1;
168 HANDLE pipe;
169 HANDLE thread_read;
170 HANDLE event_read;
171 HANDLE event_peek;
172 DWORD nbr_bytes;
173#endif
174};
175
176#ifdef HAVE_CURL
177struct _Ecore_Con_Url
178{
179 ECORE_MAGIC;
180 CURL *curl_easy;
181 struct curl_slist *headers;
182 Eina_List *additional_headers;
183 Eina_List *response_headers;
184 const char *url;
185
186 Ecore_Con_Url_Time time_condition;
187 double timestamp;
188 void *data;
189
190 Ecore_Fd_Handler *fd_handler;
191 int fd;
192 int flags;
193
194 int received;
195 int write_fd;
196
197 Eina_Bool active : 1;
198};
199#endif
200
201struct _Ecore_Con_Info
202{
203 unsigned int size;
204 struct addrinfo info;
205 char ip[NI_MAXHOST];
206 char service[NI_MAXSERV];
207};
208
209struct _Ecore_Con_Lookup
210{
211 Ecore_Con_Dns_Cb done_cb;
212 const void *data;
213};
214
215/* from ecore_con.c */
216void ecore_con_server_infos_del(Ecore_Con_Server *svr, void *info);
217void ecore_con_event_server_data(Ecore_Con_Server *svr, unsigned char *buf, int num, Eina_Bool duplicate);
218void ecore_con_event_server_del(Ecore_Con_Server *svr);
219void ecore_con_event_server_error(Ecore_Con_Server *svr, const char *error);
220void ecore_con_event_client_add(Ecore_Con_Client *cl);
221void ecore_con_event_client_data(Ecore_Con_Client *cl, unsigned char *buf, int num, Eina_Bool duplicate);
222void ecore_con_event_client_del(Ecore_Con_Client *cl);
223void ecore_con_event_client_error(Ecore_Con_Client *cl, const char *error);
224
225/* from ecore_local_win32.c */
226#ifdef _WIN32
227Eina_Bool ecore_con_local_listen(Ecore_Con_Server *svr);
228Eina_Bool ecore_con_local_connect(Ecore_Con_Server *svr,
229 Eina_Bool (*cb_done)(void *data,
230 Ecore_Fd_Handler *fd_handler));
231Eina_Bool ecore_con_local_win32_server_flush(Ecore_Con_Server *svr);
232Eina_Bool ecore_con_local_win32_client_flush(Ecore_Con_Client *cl);
233void ecore_con_local_win32_server_del(Ecore_Con_Server *svr);
234void ecore_con_local_win32_client_del(Ecore_Con_Client *cl);
235#else
236/* from ecore_local.c */
237int ecore_con_local_init(void);
238int ecore_con_local_shutdown(void);
239int ecore_con_local_connect(Ecore_Con_Server *svr,
240 Eina_Bool (*cb_done)(
241 void *data,
242 Ecore_Fd_Handler *fd_handler),
243 void *data);
244int ecore_con_local_listen(Ecore_Con_Server *svr,
245 Eina_Bool (*cb_listen)(
246 void *data,
247 Ecore_Fd_Handler *fd_handler),
248 void *data);
249#endif
250
251/* from ecore_con_info.c */
252int ecore_con_info_init(void);
253int ecore_con_info_shutdown(void);
254int ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
255 Ecore_Con_Info_Cb done_cb,
256 void *data);
257int ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
258 Ecore_Con_Info_Cb done_cb,
259 void *data);
260int ecore_con_info_udp_connect(Ecore_Con_Server *svr,
261 Ecore_Con_Info_Cb done_cb,
262 void *data);
263int ecore_con_info_udp_listen(Ecore_Con_Server *svr,
264 Ecore_Con_Info_Cb done_cb,
265 void *data);
266int ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
267 Ecore_Con_Info_Cb done_cb,
268 void *data);
269void ecore_con_info_data_clear(void *info);
270
271void ecore_con_event_server_add(Ecore_Con_Server *svr);
272
273
274/* from ecore_con_ssl.c */
275Ecore_Con_Ssl_Error ecore_con_ssl_init(void);
276Ecore_Con_Ssl_Error ecore_con_ssl_shutdown(void);
277Ecore_Con_Ssl_Error ecore_con_ssl_server_prepare(Ecore_Con_Server *svr, int ssl_type);
278Ecore_Con_Ssl_Error ecore_con_ssl_server_init(Ecore_Con_Server *svr);
279Ecore_Con_Ssl_Error ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr);
280int ecore_con_ssl_server_read(Ecore_Con_Server *svr,
281 unsigned char *buf,
282 int size);
283int ecore_con_ssl_server_write(Ecore_Con_Server *svr,
284 const unsigned char *buf,
285 int size);
286Ecore_Con_Ssl_Error ecore_con_ssl_client_init(Ecore_Con_Client *svr);
287Ecore_Con_Ssl_Error ecore_con_ssl_client_shutdown(Ecore_Con_Client *svr);
288int ecore_con_ssl_client_read(Ecore_Con_Client *svr,
289 unsigned char *buf,
290 int size);
291int ecore_con_ssl_client_write(Ecore_Con_Client *svr,
292 const unsigned char *buf,
293 int size);
294
295int ecore_con_info_get(Ecore_Con_Server *svr,
296 Ecore_Con_Info_Cb done_cb,
297 void *data,
298 struct addrinfo *hints);
299
300
301#define GENERIC_ALLOC_FREE_HEADER(TYPE, Type) \
302 TYPE *Type##_alloc(void); \
303 void Type##_free(TYPE *e);
304
305GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Add, ecore_con_event_client_add);
306GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Del, ecore_con_event_client_del);
307GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Write, ecore_con_event_client_write);
308GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Data, ecore_con_event_client_data);
309GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Error, ecore_con_event_server_error);
310GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Client_Error, ecore_con_event_client_error);
311GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Add, ecore_con_event_server_add);
312GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Del, ecore_con_event_server_del);
313GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Write, ecore_con_event_server_write);
314GENERIC_ALLOC_FREE_HEADER(Ecore_Con_Event_Server_Data, ecore_con_event_server_data);
315
316void ecore_con_mempool_init(void);
317void ecore_con_mempool_shutdown(void);
318
319#undef GENERIC_ALLOC_FREE_HEADER
320
321#endif
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c b/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c
new file mode 100644
index 0000000..c352e94
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_ssl.c
@@ -0,0 +1,1777 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#if USE_GNUTLS
6# include <gnutls/gnutls.h>
7# include <gnutls/x509.h>
8# include <gcrypt.h>
9#elif USE_OPENSSL
10# include <openssl/ssl.h>
11# include <openssl/err.h>
12# include <openssl/dh.h>
13#endif
14
15#ifdef HAVE_WS2TCPIP_H
16# include <ws2tcpip.h>
17#endif
18
19#include "Ecore.h"
20#include "ecore_con_private.h"
21
22EAPI int ECORE_CON_EVENT_CLIENT_UPGRADE = 0;
23EAPI int ECORE_CON_EVENT_SERVER_UPGRADE = 0;
24
25static int _init_con_ssl_init_count = 0;
26
27#ifdef USE_GNUTLS
28# ifdef EINA_HAVE_THREADS
29GCRY_THREAD_OPTION_PTHREAD_IMPL;
30# endif
31
32static int _client_connected = 0;
33
34# define SSL_SUFFIX(ssl_func) ssl_func ## _gnutls
35# define _ECORE_CON_SSL_AVAILABLE 1
36
37#elif USE_OPENSSL
38
39# define SSL_SUFFIX(ssl_func) ssl_func ## _openssl
40# define _ECORE_CON_SSL_AVAILABLE 2
41
42#else
43# define SSL_SUFFIX(ssl_func) ssl_func ## _none
44# define _ECORE_CON_SSL_AVAILABLE 0
45
46#endif
47
48#if USE_GNUTLS
49static void
50_gnutls_print_errors(void *conn, int type, int ret)
51{
52 char buf[1024];
53
54 if (!ret) return;
55
56 snprintf(buf, sizeof(buf), "GNUTLS error: %s - %s", gnutls_strerror_name(ret), gnutls_strerror(ret));
57 if (type == ECORE_CON_EVENT_CLIENT_ERROR)
58 ecore_con_event_client_error(conn, buf);
59 else
60 ecore_con_event_server_error(conn, buf);
61}
62
63#ifdef ISCOMFITOR
64static void
65_gnutls_log_func(int level,
66 const char *str)
67{
68 DBG("|<%d>| %s", level, str);
69}
70#endif
71
72static const char *
73SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_description_t status)
74{
75 switch (status)
76 {
77 case GNUTLS_HANDSHAKE_HELLO_REQUEST:
78 return "Hello request";
79
80 case GNUTLS_HANDSHAKE_CLIENT_HELLO:
81 return "Client hello";
82
83 case GNUTLS_HANDSHAKE_SERVER_HELLO:
84 return "Server hello";
85
86 case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET:
87 return "New session ticket";
88
89 case GNUTLS_HANDSHAKE_CERTIFICATE_PKT:
90 return "Certificate packet";
91
92 case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE:
93 return "Server key exchange";
94
95 case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:
96 return "Certificate request";
97
98 case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE:
99 return "Server hello done";
100
101 case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY:
102 return "Certificate verify";
103
104 case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE:
105 return "Client key exchange";
106
107 case GNUTLS_HANDSHAKE_FINISHED:
108 return "Finished";
109
110 case GNUTLS_HANDSHAKE_SUPPLEMENTAL:
111 return "Supplemental";
112 }
113 return NULL;
114}
115
116#elif USE_OPENSSL
117
118static void
119_openssl_print_errors(void *conn, int type)
120{
121 char buf[1024];
122 do
123 {
124 unsigned long err;
125
126 err = ERR_get_error();
127 if (!err) break;
128 snprintf(buf, sizeof(buf), "OpenSSL error: %s", ERR_reason_error_string(err));
129 if (type == ECORE_CON_EVENT_CLIENT_ERROR)
130 ecore_con_event_client_error(conn, buf);
131 else
132 ecore_con_event_server_error(conn, buf);
133
134 } while (1);
135}
136
137static Eina_Bool
138_openssl_name_verify(const char *name, const char *svrname)
139{
140 if (name[0] == '*')
141 {
142 /* we allow *.domain.TLD with a wildcard, but nothing else */
143 const char *p, *s;
144
145 EINA_SAFETY_ON_TRUE_RETURN_VAL((name[1] != '.') || (!name[2]), EINA_FALSE);
146 p = strchr(name + 1, '*');
147 EINA_SAFETY_ON_TRUE_RETURN_VAL(!!p, EINA_FALSE);
148 /* verify that we have a domain of at least *.X.TLD and not *.TLD */
149 p = strchr(name + 2, '.');
150 EINA_SAFETY_ON_TRUE_RETURN_VAL(!p, EINA_FALSE);
151 s = strchr(svrname, '.');
152 EINA_SAFETY_ON_TRUE_RETURN_VAL(!s, EINA_FALSE);
153 /* same as above for the stored name */
154 EINA_SAFETY_ON_TRUE_RETURN_VAL(!strchr(s + 1, '.'), EINA_FALSE);
155 EINA_SAFETY_ON_TRUE_RETURN_VAL(strcasecmp(s, name + 1), EINA_FALSE);
156 }
157 else
158 EINA_SAFETY_ON_TRUE_RETURN_VAL(strcasecmp(name, svrname), EINA_FALSE);
159 return EINA_TRUE;
160}
161
162#endif
163
164#define SSL_ERROR_CHECK_GOTO_ERROR(X) \
165 do \
166 { \
167 if ((X)) \
168 { \
169 ERR("Error at %s:%s:%d!", __FILE__, __PRETTY_FUNCTION__, __LINE__); \
170 goto error; \
171 } \
172 } \
173 while (0)
174
175static Ecore_Con_Ssl_Error
176 SSL_SUFFIX(_ecore_con_ssl_init) (void);
177static Ecore_Con_Ssl_Error
178 SSL_SUFFIX(_ecore_con_ssl_shutdown) (void);
179
180static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (Ecore_Con_Server * svr, const char *ca_file);
181static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (Ecore_Con_Server * svr, const char *crl_file);
182static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (Ecore_Con_Server * svr, const char *cert);
183static Eina_Bool SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (Ecore_Con_Server * svr, const char *key_file);
184
185static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_prepare) (Ecore_Con_Server * svr, int ssl_type);
186static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_init) (Ecore_Con_Server * svr);
187static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (Ecore_Con_Server *svr);
188static int SSL_SUFFIX(_ecore_con_ssl_server_read) (Ecore_Con_Server *svr, unsigned char *buf, int size);
189static int SSL_SUFFIX(_ecore_con_ssl_server_write) (Ecore_Con_Server *svr, const unsigned char *buf, int size);
190
191static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_init) (Ecore_Con_Client * cl);
192static Ecore_Con_Ssl_Error SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (Ecore_Con_Client *cl);
193static int SSL_SUFFIX(_ecore_con_ssl_client_read) (Ecore_Con_Client * cl,
194 unsigned char *buf, int size);
195static int SSL_SUFFIX(_ecore_con_ssl_client_write) (Ecore_Con_Client * cl,
196 const unsigned char *buf, int size);
197
198/*
199 * General SSL API
200 */
201
202Ecore_Con_Ssl_Error
203ecore_con_ssl_init(void)
204{
205 if (!_init_con_ssl_init_count++)
206 {
207 SSL_SUFFIX(_ecore_con_ssl_init) ();
208#if _ECORE_CON_SSL_AVAILABLE != 0
209 ECORE_CON_EVENT_CLIENT_UPGRADE = ecore_event_type_new();
210 ECORE_CON_EVENT_SERVER_UPGRADE = ecore_event_type_new();
211#endif
212 }
213
214 return _init_con_ssl_init_count;
215}
216
217Ecore_Con_Ssl_Error
218ecore_con_ssl_shutdown(void)
219{
220 if (!--_init_con_ssl_init_count)
221 SSL_SUFFIX(_ecore_con_ssl_shutdown) ();
222
223 return _init_con_ssl_init_count;
224}
225
226Ecore_Con_Ssl_Error
227ecore_con_ssl_server_prepare(Ecore_Con_Server *svr,
228 int ssl_type)
229{
230 if (!ssl_type)
231 return ECORE_CON_SSL_ERROR_NONE;
232 return SSL_SUFFIX(_ecore_con_ssl_server_prepare) (svr, ssl_type);
233}
234
235Ecore_Con_Ssl_Error
236ecore_con_ssl_server_init(Ecore_Con_Server *svr)
237{
238 if (!(svr->type & ECORE_CON_SSL))
239 return ECORE_CON_SSL_ERROR_NONE;
240 return SSL_SUFFIX(_ecore_con_ssl_server_init) (svr);
241}
242
243Ecore_Con_Ssl_Error
244ecore_con_ssl_server_shutdown(Ecore_Con_Server *svr)
245{
246 if (!(svr->type & ECORE_CON_SSL))
247 return ECORE_CON_SSL_ERROR_NONE;
248 return SSL_SUFFIX(_ecore_con_ssl_server_shutdown) (svr);
249}
250
251int
252ecore_con_ssl_server_read(Ecore_Con_Server *svr,
253 unsigned char *buf,
254 int size)
255{
256 return SSL_SUFFIX(_ecore_con_ssl_server_read) (svr, buf, size);
257}
258
259int
260ecore_con_ssl_server_write(Ecore_Con_Server *svr,
261 const unsigned char *buf,
262 int size)
263{
264 return SSL_SUFFIX(_ecore_con_ssl_server_write) (svr, buf, size);
265}
266
267Ecore_Con_Ssl_Error
268ecore_con_ssl_client_init(Ecore_Con_Client *cl)
269{
270 if (!(cl->host_server->type & ECORE_CON_SSL))
271 return ECORE_CON_SSL_ERROR_NONE;
272 return SSL_SUFFIX(_ecore_con_ssl_client_init) (cl);
273}
274
275Ecore_Con_Ssl_Error
276ecore_con_ssl_client_shutdown(Ecore_Con_Client *cl)
277{
278 if (!(cl->host_server->type & ECORE_CON_SSL))
279 return ECORE_CON_SSL_ERROR_NONE;
280 return SSL_SUFFIX(_ecore_con_ssl_client_shutdown) (cl);
281}
282
283int
284ecore_con_ssl_client_read(Ecore_Con_Client *cl,
285 unsigned char *buf,
286 int size)
287{
288 return SSL_SUFFIX(_ecore_con_ssl_client_read) (cl, buf, size);
289}
290
291int
292ecore_con_ssl_client_write(Ecore_Con_Client *cl,
293 const unsigned char *buf,
294 int size)
295{
296 return SSL_SUFFIX(_ecore_con_ssl_client_write) (cl, buf, size);
297}
298
299/**
300 * Returns if SSL support is available
301 * @return 1 if SSL is available and provided by gnutls, 2 if provided by openssl,
302 * 0 if it is not available.
303 * @ingroup Ecore_Con_Client_Group
304 */
305EAPI int
306ecore_con_ssl_available_get(void)
307{
308 return _ECORE_CON_SSL_AVAILABLE;
309}
310
311/**
312 * @addtogroup Ecore_Con_SSL_Group Ecore Connection SSL Functions
313 *
314 * Functions that operate on Ecore connection objects pertaining to SSL.
315 *
316 * @{
317 */
318
319/**
320 * @brief Enable certificate verification on a server object
321 *
322 * Call this function on a server object before main loop has started
323 * to enable verification of certificates against loaded certificates.
324 * @param svr The server object
325 */
326EAPI void
327ecore_con_ssl_server_verify(Ecore_Con_Server *svr)
328{
329 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
330 {
331 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_verify");
332 return;
333 }
334 svr->verify = EINA_TRUE;
335}
336
337/**
338 * @brief Enable hostname-based certificate verification on a server object
339 *
340 * Call this function on a server object before main loop has started
341 * to enable verification of certificates using ONLY their hostnames.
342 * @param svr The server object
343 * @note This function has no effect when used on a listening server created by
344 * ecore_con_server_add
345 * @since 1.1
346 */
347EAPI void
348ecore_con_ssl_server_verify_basic(Ecore_Con_Server *svr)
349{
350 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
351 {
352 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__);
353 return;
354 }
355 svr->verify_basic = EINA_TRUE;
356}
357
358/**
359 * @brief Add an ssl certificate for use in ecore_con functions.
360 *
361 * Use this function to add a SSL PEM certificate.
362 * Simply specify the cert here to use it in the server object for connecting or listening.
363 * If there is an error loading the certificate, an error will automatically be logged.
364 * @param cert The path to the certificate.
365 * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE.
366 */
367
368EAPI Eina_Bool
369ecore_con_ssl_server_cert_add(Ecore_Con_Server *svr,
370 const char *cert)
371{
372 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
373 {
374 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_cert_add");
375 return EINA_FALSE;
376 }
377
378 return SSL_SUFFIX(_ecore_con_ssl_server_cert_add) (svr, cert);
379}
380
381/**
382 * @brief Add an ssl CA file for use in ecore_con functions.
383 *
384 * Use this function to add a SSL PEM CA file.
385 * Simply specify the file here to use it in the server object for connecting or listening.
386 * If there is an error loading the CAs, an error will automatically be logged.
387 * @param ca_file The path to the CA file.
388 * @return EINA_FALSE if the file cannot be loaded, otherwise EINA_TRUE.
389 */
390
391EAPI Eina_Bool
392ecore_con_ssl_server_cafile_add(Ecore_Con_Server *svr,
393 const char *ca_file)
394{
395 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
396 {
397 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_cafile_add");
398 return EINA_FALSE;
399 }
400
401 return SSL_SUFFIX(_ecore_con_ssl_server_cafile_add) (svr, ca_file);
402}
403
404/**
405 * @brief Add an ssl private key for use in ecore_con functions.
406 *
407 * Use this function to add a SSL PEM private key
408 * Simply specify the key file here to use it in the server object for connecting or listening.
409 * If there is an error loading the key, an error will automatically be logged.
410 * @param key_file The path to the key file.
411 * @return EINA_FALSE if the file cannot be loaded,
412 * otherwise EINA_TRUE.
413 */
414
415EAPI Eina_Bool
416ecore_con_ssl_server_privkey_add(Ecore_Con_Server *svr,
417 const char *key_file)
418{
419 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
420 {
421 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_privkey_add");
422 return EINA_FALSE;
423 }
424
425 return SSL_SUFFIX(_ecore_con_ssl_server_privkey_add) (svr, key_file);
426}
427
428/**
429 * @brief Add an ssl CRL for use in ecore_con functions.
430 *
431 * Use this function to add a SSL PEM CRL file
432 * Simply specify the CRL file here to use it in the server object for connecting or listening.
433 * If there is an error loading the CRL, an error will automatically be logged.
434 * @param crl_file The path to the CRL file.
435 * @return EINA_FALSE if the file cannot be loaded,
436 * otherwise EINA_TRUE.
437 */
438
439EAPI Eina_Bool
440ecore_con_ssl_server_crl_add(Ecore_Con_Server *svr,
441 const char *crl_file)
442{
443 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
444 {
445 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, "ecore_con_ssl_server_crl_add");
446 return EINA_FALSE;
447 }
448
449 return SSL_SUFFIX(_ecore_con_ssl_server_crl_add) (svr, crl_file);
450}
451
452/**
453 * @brief Upgrade a connection to a specified level of encryption
454 *
455 * Use this function to begin an SSL handshake on a connection (STARTTLS or similar).
456 * Once the upgrade has been completed, an ECORE_CON_EVENT_SERVER_UPGRADE event will be emitted.
457 * The connection should be treated as disconnected until the next event.
458 * @param svr The server object
459 * @param ssl_type The SSL connection type (ONLY).
460 * @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE.
461 * @note This function is NEVER to be used on a server object created with ecore_con_server_add
462 * @warning Setting a wrong value for @p compl_type WILL mess up your program.
463 * @since 1.1
464 */
465
466EAPI Eina_Bool
467ecore_con_ssl_server_upgrade(Ecore_Con_Server *svr, Ecore_Con_Type ssl_type)
468{
469 if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER))
470 {
471 ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, __func__);
472 return EINA_FALSE;
473 }
474#if _ECORE_CON_SSL_AVAILABLE == 0
475 return EINA_FALSE;
476#endif
477
478 if (!svr->ssl_prepared)
479 {
480 if (ecore_con_ssl_server_prepare(svr, ssl_type))
481 return EINA_FALSE;
482 }
483 svr->type |= ssl_type;
484 svr->upgrade = EINA_TRUE;
485 svr->handshaking = EINA_TRUE;
486 svr->ssl_state = ECORE_CON_SSL_STATE_INIT;
487 return !SSL_SUFFIX(_ecore_con_ssl_server_init) (svr);
488}
489
490/**
491 * @brief Upgrade a connection to a specified level of encryption
492 *
493 * Use this function to begin an SSL handshake on a connection (STARTTLS or similar).
494 * Once the upgrade has been completed, an ECORE_CON_EVENT_CLIENT_UPGRADE event will be emitted.
495 * The connection should be treated as disconnected until the next event.
496 * @param cl The client object
497 * @param compl_type The SSL connection type (ONLY).
498 * @return EINA_FALSE if the connection cannot be upgraded, otherwise EINA_TRUE.
499 * @warning Setting a wrong value for @p compl_type WILL mess up your program.
500 * @since 1.1
501 */
502
503EAPI Eina_Bool
504ecore_con_ssl_client_upgrade(Ecore_Con_Client *cl, Ecore_Con_Type ssl_type)
505{
506 if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
507 {
508 ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, __func__);
509 return EINA_FALSE;
510 }
511#if _ECORE_CON_SSL_AVAILABLE == 0
512 return EINA_FALSE;
513#endif
514
515 if (!cl->host_server->ssl_prepared)
516 {
517 if (ecore_con_ssl_server_prepare(cl->host_server, ssl_type))
518 return EINA_FALSE;
519 }
520 cl->host_server->type |= ssl_type;
521 cl->upgrade = EINA_TRUE;
522 cl->host_server->upgrade = EINA_TRUE;
523 cl->handshaking = EINA_TRUE;
524 cl->ssl_state = ECORE_CON_SSL_STATE_INIT;
525 return SSL_SUFFIX(_ecore_con_ssl_client_init) (cl);
526}
527
528/**
529 * @}
530 */
531
532#if USE_GNUTLS
533
534/*
535 * GnuTLS
536 */
537
538static Ecore_Con_Ssl_Error
539_ecore_con_ssl_init_gnutls(void)
540{
541#ifdef EINA_HAVE_THREADS
542 if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread))
543 WRN("YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!");
544#endif
545 if (gnutls_global_init())
546 return ECORE_CON_SSL_ERROR_INIT_FAILED;
547
548#ifdef ISCOMFITOR
549 gnutls_global_set_log_level(9);
550 gnutls_global_set_log_function(_gnutls_log_func);
551#endif
552 return ECORE_CON_SSL_ERROR_NONE;
553}
554
555static Ecore_Con_Ssl_Error
556_ecore_con_ssl_shutdown_gnutls(void)
557{
558 gnutls_global_deinit();
559
560 return ECORE_CON_SSL_ERROR_NONE;
561}
562
563static Ecore_Con_Ssl_Error
564_ecore_con_ssl_server_prepare_gnutls(Ecore_Con_Server *svr,
565 int ssl_type)
566{
567 int ret;
568
569 if (ssl_type & ECORE_CON_USE_SSL2)
570 return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
571
572 switch (ssl_type)
573 {
574 case ECORE_CON_USE_SSL3:
575 case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT:
576 case ECORE_CON_USE_TLS:
577 case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
578 case ECORE_CON_USE_MIXED:
579 case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
580 break;
581
582 default:
583 return ECORE_CON_SSL_ERROR_NONE;
584 }
585
586 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_allocate_credentials(&svr->cert));
587
588 if (svr->use_cert)
589 {
590 if (svr->created)
591 {
592 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_dh_params_init(&svr->dh_params));
593 INF("Generating DH params");
594 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_dh_params_generate2(svr->dh_params, 1024));
595
596 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_server_credentials(&svr->anoncred_s));
597 /* TODO: implement PSK */
598 // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_psk_allocate_server_credentials(&svr->pskcred_s));
599
600 gnutls_anon_set_server_dh_params(svr->anoncred_s, svr->dh_params);
601 gnutls_certificate_set_dh_params(svr->cert, svr->dh_params);
602 //gnutls_psk_set_server_dh_params(svr->pskcred_s, svr->dh_params);
603 INF("DH params successfully generated and applied!");
604 }
605 else
606 {
607 //SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_psk_allocate_client_credentials(&svr->pskcred_c));
608 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_anon_allocate_client_credentials(&svr->anoncred_c));
609 }
610 }
611
612 svr->ssl_prepared = EINA_TRUE;
613 return ECORE_CON_SSL_ERROR_NONE;
614
615error:
616 _gnutls_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR, ret);
617 _ecore_con_ssl_server_shutdown_gnutls(svr);
618 return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
619}
620
621
622static Ecore_Con_Ssl_Error
623_ecore_con_ssl_server_init_gnutls(Ecore_Con_Server *svr)
624{
625 const gnutls_datum_t *cert_list;
626 unsigned int iter, cert_list_size;
627 gnutls_x509_crt_t cert = NULL;
628 const char *priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0";
629 int ret = 0;
630
631 switch (svr->ssl_state)
632 {
633 case ECORE_CON_SSL_STATE_DONE:
634 return ECORE_CON_SSL_ERROR_NONE;
635
636 case ECORE_CON_SSL_STATE_INIT:
637 if (svr->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */
638 return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
639
640 switch (svr->type & ECORE_CON_SSL)
641 {
642 case ECORE_CON_USE_SSL3:
643 case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT:
644 priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-TLS1.0:!VERS-TLS1.1";
645 break;
646
647 case ECORE_CON_USE_TLS:
648 case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
649 priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-SSL3.0";
650 break;
651
652 case ECORE_CON_USE_MIXED:
653 case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
654 break;
655
656 default:
657 return ECORE_CON_SSL_ERROR_NONE;
658 }
659
660 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&svr->session, GNUTLS_CLIENT));
661 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_client(svr->session));
662 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_server_name_set(svr->session, GNUTLS_NAME_DNS, svr->name, strlen(svr->name)));
663 INF("Applying priority string: %s", priority);
664 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(svr->session, priority, NULL));
665 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_CERTIFICATE, svr->cert));
666 // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_PSK, svr->pskcred_c));
667 if (!svr->use_cert)
668 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(svr->session, GNUTLS_CRD_ANON, svr->anoncred_c));
669
670 gnutls_dh_set_prime_bits(svr->session, 512);
671 gnutls_transport_set_ptr(svr->session, (gnutls_transport_ptr_t)((intptr_t)svr->fd));
672 svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
673
674 case ECORE_CON_SSL_STATE_HANDSHAKING:
675 if (!svr->session)
676 {
677 DBG("Server was previously lost, going to error condition");
678 goto error;
679 }
680 ret = gnutls_handshake(svr->session);
681 DBG("calling gnutls_handshake(): returned with '%s'", gnutls_strerror_name(ret));
682 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret));
683 if (!ret)
684 {
685 svr->handshaking = EINA_FALSE;
686 svr->ssl_state = ECORE_CON_SSL_STATE_DONE;
687 }
688 else
689 {
690 if (gnutls_record_get_direction(svr->session))
691 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
692 else
693 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
694 return ECORE_CON_SSL_ERROR_NONE;
695 }
696
697 default:
698 break;
699 }
700
701 if ((!svr->verify) && (!svr->verify_basic))
702 /* not verifying certificates, so we're done! */
703 return ECORE_CON_SSL_ERROR_NONE;
704 if (svr->verify)
705 {
706 /* use CRL/CA lists to verify */
707 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(svr->session, &iter));
708 if (iter & GNUTLS_CERT_INVALID)
709 ERR("The certificate is not trusted.");
710 else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND)
711 ERR("The certificate hasn't got a known issuer.");
712 else if (iter & GNUTLS_CERT_REVOKED)
713 ERR("The certificate has been revoked.");
714 else if (iter & GNUTLS_CERT_EXPIRED)
715 ERR("The certificate has expired");
716 else if (iter & GNUTLS_CERT_NOT_ACTIVATED)
717 ERR("The certificate is not yet activated");
718
719 if (iter)
720 goto error;
721 }
722 if (gnutls_certificate_type_get(svr->session) != GNUTLS_CRT_X509)
723 {
724 ERR("Warning: PGP certificates are not yet supported!");
725 goto error;
726 }
727
728 SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(svr->session, &cert_list_size)));
729 SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size);
730
731 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert));
732 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
733
734 SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, svr->name));
735 gnutls_x509_crt_deinit(cert);
736 DBG("SSL certificate verification succeeded!");
737 return ECORE_CON_SSL_ERROR_NONE;
738
739error:
740 _gnutls_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR, ret);
741 if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED))
742 ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(svr->session)));
743 if (svr->session && (svr->ssl_state != ECORE_CON_SSL_STATE_DONE))
744 {
745 ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(svr->session)));
746 ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(svr->session)));
747 }
748 if (cert)
749 gnutls_x509_crt_deinit(cert);
750 _ecore_con_ssl_server_shutdown_gnutls(svr);
751 return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
752}
753
754static Eina_Bool
755_ecore_con_ssl_server_cafile_add_gnutls(Ecore_Con_Server *svr,
756 const char *ca_file)
757{
758 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_trust_file(svr->cert, ca_file,
759 GNUTLS_X509_FMT_PEM) < 1);
760
761 return EINA_TRUE;
762error:
763 ERR("Could not load CA file!");
764 return EINA_FALSE;
765}
766
767static Eina_Bool
768_ecore_con_ssl_server_crl_add_gnutls(Ecore_Con_Server *svr,
769 const char *crl_file)
770{
771 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_crl_file(svr->cert, crl_file,
772 GNUTLS_X509_FMT_PEM) < 1);
773
774 return EINA_TRUE;
775error:
776 ERR("Could not load CRL file!");
777 return EINA_FALSE;
778}
779
780static Eina_Bool
781_ecore_con_ssl_server_privkey_add_gnutls(Ecore_Con_Server *svr,
782 const char *key_file)
783{
784 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_certificate_set_x509_key_file(svr->cert, svr->cert_file, key_file,
785 GNUTLS_X509_FMT_PEM));
786
787 return EINA_TRUE;
788error:
789 ERR("Could not load certificate/key file!");
790 return EINA_FALSE;
791}
792
793static Eina_Bool
794_ecore_con_ssl_server_cert_add_gnutls(Ecore_Con_Server *svr,
795 const char *cert_file)
796{
797 if (!(svr->cert_file = strdup(cert_file)))
798 return EINA_FALSE;
799
800 return EINA_TRUE;
801}
802
803static Ecore_Con_Ssl_Error
804_ecore_con_ssl_server_shutdown_gnutls(Ecore_Con_Server *svr)
805{
806 if (svr->session)
807 {
808 gnutls_bye(svr->session, GNUTLS_SHUT_RDWR);
809 gnutls_deinit(svr->session);
810 }
811
812 free(svr->cert_file);
813 svr->cert_file = NULL;
814 if (svr->cert)
815 gnutls_certificate_free_credentials(svr->cert);
816 svr->cert = NULL;
817
818 if ((svr->type & ECORE_CON_SSL) && svr->created)
819 {
820 if (svr->dh_params)
821 {
822 gnutls_dh_params_deinit(svr->dh_params);
823 svr->dh_params = NULL;
824 }
825 if (svr->anoncred_s)
826 gnutls_anon_free_server_credentials(svr->anoncred_s);
827 // if (svr->pskcred_s)
828 // gnutls_psk_free_server_credentials(svr->pskcred_s);
829
830 svr->anoncred_s = NULL;
831 svr->pskcred_s = NULL;
832 }
833 else if (svr->type & ECORE_CON_SSL)
834 {
835 if (svr->anoncred_c)
836 gnutls_anon_free_client_credentials(svr->anoncred_c);
837 // if (svr->pskcred_c)
838 // gnutls_psk_free_client_credentials(svr->pskcred_c);
839
840 svr->anoncred_c = NULL;
841 svr->pskcred_c = NULL;
842 }
843
844 svr->session = NULL;
845
846 return ECORE_CON_SSL_ERROR_NONE;
847}
848
849static int
850_ecore_con_ssl_server_read_gnutls(Ecore_Con_Server *svr,
851 unsigned char *buf,
852 int size)
853{
854 int num;
855
856 if (svr->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING)
857 {
858 DBG("Continuing gnutls handshake");
859 if (!_ecore_con_ssl_server_init_gnutls(svr))
860 return 0;
861 return -1;
862 }
863
864 num = gnutls_record_recv(svr->session, buf, size);
865 if (num > 0)
866 return num;
867
868 if (num == GNUTLS_E_REHANDSHAKE)
869 {
870 WRN("Rehandshake request ignored");
871 return 0;
872
873 svr->handshaking = EINA_TRUE;
874 svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
875 if (!_ecore_con_ssl_server_init_gnutls(svr))
876 return 0;
877 }
878 else if ((!gnutls_error_is_fatal(num)) && (num != GNUTLS_E_SUCCESS))
879 return 0;
880
881 return -1;
882}
883
884static int
885_ecore_con_ssl_server_write_gnutls(Ecore_Con_Server *svr,
886 const unsigned char *buf,
887 int size)
888{
889 int num;
890
891 if (svr->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING)
892 {
893 DBG("Continuing gnutls handshake");
894 if (!_ecore_con_ssl_server_init_gnutls(svr))
895 return 0;
896 return -1;
897 }
898
899 num = gnutls_record_send(svr->session, buf, size);
900 if (num > 0)
901 return num;
902
903 if (num == GNUTLS_E_REHANDSHAKE)
904 {
905 WRN("Rehandshake request ignored");
906 return 0;
907/* this is only partly functional I think? */
908 svr->handshaking = EINA_TRUE;
909 svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
910 if (!_ecore_con_ssl_server_init_gnutls(svr))
911 return 0;
912 }
913 else if (!gnutls_error_is_fatal(num))
914 return 0;
915
916 return -1;
917}
918
919static Ecore_Con_Ssl_Error
920_ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl)
921{
922 const gnutls_datum_t *cert_list;
923 unsigned int iter, cert_list_size;
924 const char *priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0";
925 int ret = 0;
926
927 switch (cl->ssl_state)
928 {
929 case ECORE_CON_SSL_STATE_DONE:
930 return ECORE_CON_SSL_ERROR_NONE;
931
932 case ECORE_CON_SSL_STATE_INIT:
933 if (cl->host_server->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */
934 return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
935
936 switch (cl->host_server->type & ECORE_CON_SSL)
937 {
938 case ECORE_CON_USE_SSL3:
939 case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT:
940 priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-TLS1.0:!VERS-TLS1.1";
941 break;
942
943 case ECORE_CON_USE_TLS:
944 case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
945 priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-SSL3.0";
946 break;
947
948 case ECORE_CON_USE_MIXED:
949 case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
950 break;
951
952 default:
953 return ECORE_CON_SSL_ERROR_NONE;
954 }
955
956 _client_connected++;
957
958 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&cl->session, GNUTLS_SERVER));
959 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_key_generate(&cl->session_ticket));
960 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_server(cl->session, &cl->session_ticket));
961 INF("Applying priority string: %s", priority);
962 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(cl->session, priority, NULL));
963 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_CERTIFICATE, cl->host_server->cert));
964 // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_PSK, cl->host_server->pskcred_s));
965 if (!cl->host_server->use_cert)
966 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->host_server->anoncred_s));
967
968 gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST);
969
970 gnutls_dh_set_prime_bits(cl->session, 2048);
971 gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)((intptr_t)cl->fd));
972 cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
973
974 case ECORE_CON_SSL_STATE_HANDSHAKING:
975 if (!cl->session)
976 {
977 DBG("Client was previously lost, going to error condition");
978 goto error;
979 }
980 DBG("calling gnutls_handshake()");
981 ret = gnutls_handshake(cl->session);
982 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret));
983
984 if (!ret)
985 {
986 cl->handshaking = EINA_FALSE;
987 cl->ssl_state = ECORE_CON_SSL_STATE_DONE;
988 }
989 else
990 {
991 if (gnutls_record_get_direction(cl->session))
992 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
993 else
994 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
995 return ECORE_CON_SSL_ERROR_NONE;
996 }
997
998 default:
999 break;
1000 }
1001
1002 if (!cl->host_server->verify)
1003 /* not verifying certificates, so we're done! */
1004 return ECORE_CON_SSL_ERROR_NONE;
1005 /* use CRL/CA lists to verify */
1006 SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(cl->session, &iter));
1007 if (iter & GNUTLS_CERT_INVALID)
1008 ERR("The certificate is not trusted.");
1009 else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND)
1010 ERR("The certificate hasn't got a known issuer.");
1011 else if (iter & GNUTLS_CERT_REVOKED)
1012 ERR("The certificate has been revoked.");
1013 else if (iter & GNUTLS_CERT_EXPIRED)
1014 ERR("The certificate has expired");
1015 else if (iter & GNUTLS_CERT_NOT_ACTIVATED)
1016 ERR("The certificate is not yet activated");
1017
1018 if (iter)
1019 goto error;
1020 if (gnutls_certificate_type_get(cl->session) != GNUTLS_CRT_X509)
1021 {
1022 ERR("Warning: PGP certificates are not yet supported!");
1023 goto error;
1024 }
1025
1026 SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size)));
1027 SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size);
1028
1029/*
1030 gnutls_x509_crt_t cert = NULL;
1031 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_init(&cert));
1032 SSL_ERROR_CHECK_GOTO_ERROR(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER));
1033
1034 SSL_ERROR_CHECK_GOTO_ERROR(!gnutls_x509_crt_check_hostname(cert, cl->host_server->name));
1035 gnutls_x509_crt_deinit(cert);
1036*/
1037 DBG("SSL certificate verification succeeded!");
1038 return ECORE_CON_SSL_ERROR_NONE;
1039
1040error:
1041 _gnutls_print_errors(cl, ECORE_CON_EVENT_CLIENT_ERROR, ret);
1042 if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED))
1043 ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(cl->session)));
1044 if (cl->session && (cl->ssl_state != ECORE_CON_SSL_STATE_DONE))
1045 {
1046 ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(cl->session)));
1047 ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(cl->session)));
1048 }
1049/*
1050 if (cert)
1051 gnutls_x509_crt_deinit(cert);
1052*/
1053 _ecore_con_ssl_client_shutdown_gnutls(cl);
1054 return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
1055}
1056
1057static Ecore_Con_Ssl_Error
1058_ecore_con_ssl_client_shutdown_gnutls(Ecore_Con_Client *cl)
1059{
1060 if (cl->session)
1061 {
1062 gnutls_bye(cl->session, GNUTLS_SHUT_RDWR);
1063 gnutls_deinit(cl->session);
1064 gnutls_free(cl->session_ticket.data);
1065 cl->session_ticket.data = NULL;
1066 }
1067
1068 cl->session = NULL;
1069
1070 return ECORE_CON_SSL_ERROR_NONE;
1071}
1072
1073static int
1074_ecore_con_ssl_client_read_gnutls(Ecore_Con_Client *cl,
1075 unsigned char *buf,
1076 int size)
1077{
1078 int num;
1079
1080 if (cl->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING)
1081 {
1082 if (!_ecore_con_ssl_client_init_gnutls(cl))
1083 return 0;
1084 return -1;
1085 }
1086
1087 num = gnutls_record_recv(cl->session, buf, size);
1088 if (num > 0)
1089 return num;
1090
1091 if (num == GNUTLS_E_REHANDSHAKE)
1092 {
1093 WRN("Rehandshake request ignored");
1094 return 0;
1095 cl->handshaking = EINA_TRUE;
1096 cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
1097 if (!_ecore_con_ssl_client_init_gnutls(cl))
1098 return 0;
1099 WRN("Rehandshake request ignored");
1100 return 0;
1101 }
1102 else if ((!gnutls_error_is_fatal(num)) && (num != GNUTLS_E_SUCCESS))
1103 return 0;
1104
1105 return -1;
1106}
1107
1108static int
1109_ecore_con_ssl_client_write_gnutls(Ecore_Con_Client *cl,
1110 const unsigned char *buf,
1111 int size)
1112{
1113 int num;
1114
1115 if (cl->ssl_state == ECORE_CON_SSL_STATE_HANDSHAKING)
1116 {
1117 if (!_ecore_con_ssl_client_init_gnutls(cl))
1118 return 0;
1119 return -1;
1120 }
1121
1122 num = gnutls_record_send(cl->session, buf, size);
1123 if (num > 0)
1124 return num;
1125
1126 if (num == GNUTLS_E_REHANDSHAKE)
1127 {
1128 WRN("Rehandshake request ignored");
1129 return 0;
1130 cl->handshaking = EINA_TRUE;
1131 cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
1132 if (!_ecore_con_ssl_client_init_gnutls(cl))
1133 return 0;
1134 }
1135 else if (!gnutls_error_is_fatal(num))
1136 return 0;
1137
1138 return -1;
1139}
1140
1141#elif USE_OPENSSL && !USE_GNUTLS
1142
1143/*
1144 * OpenSSL
1145 */
1146
1147static Ecore_Con_Ssl_Error
1148_ecore_con_ssl_init_openssl(void)
1149{
1150 SSL_library_init();
1151 SSL_load_error_strings();
1152 OpenSSL_add_all_algorithms();
1153
1154 return ECORE_CON_SSL_ERROR_NONE;
1155}
1156
1157static Ecore_Con_Ssl_Error
1158_ecore_con_ssl_shutdown_openssl(void)
1159{
1160 ERR_free_strings();
1161 EVP_cleanup();
1162 return ECORE_CON_SSL_ERROR_NONE;
1163}
1164
1165static Ecore_Con_Ssl_Error
1166_ecore_con_ssl_server_prepare_openssl(Ecore_Con_Server *svr,
1167 int ssl_type)
1168{
1169 long options;
1170 int dh = 0;
1171
1172 if (ssl_type & ECORE_CON_USE_SSL2)
1173 return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED;
1174
1175 switch (ssl_type)
1176 {
1177 case ECORE_CON_USE_SSL3:
1178 case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT:
1179 if (!svr->created)
1180 SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())));
1181 else
1182 SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv3_server_method())));
1183 break;
1184
1185 case ECORE_CON_USE_TLS:
1186 case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT:
1187 if (!svr->created)
1188 SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())));
1189 else
1190 SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(TLSv1_server_method())));
1191 break;
1192
1193 case ECORE_CON_USE_MIXED:
1194 case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT:
1195 if (!svr->created)
1196 SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_client_method())));
1197 else
1198 SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl_ctx = SSL_CTX_new(SSLv23_server_method())));
1199 options = SSL_CTX_get_options(svr->ssl_ctx);
1200 SSL_CTX_set_options(svr->ssl_ctx, options | SSL_OP_NO_SSLv2 | SSL_OP_SINGLE_DH_USE);
1201 break;
1202
1203 default:
1204 return ECORE_CON_SSL_ERROR_NONE;
1205 }
1206
1207 if ((!svr->use_cert) && svr->created)
1208 {
1209 DH *dh_params;
1210 INF("Generating DH params");
1211 SSL_ERROR_CHECK_GOTO_ERROR(!(dh_params = DH_new()));
1212 SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_parameters_ex(dh_params, 1024, DH_GENERATOR_5, NULL));
1213 SSL_ERROR_CHECK_GOTO_ERROR(!DH_check(dh_params, &dh));
1214 SSL_ERROR_CHECK_GOTO_ERROR((dh & DH_CHECK_P_NOT_PRIME) || (dh & DH_CHECK_P_NOT_SAFE_PRIME));
1215 SSL_ERROR_CHECK_GOTO_ERROR(!DH_generate_key(dh_params));
1216 SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_tmp_dh(svr->ssl_ctx, dh_params));
1217 DH_free(dh_params);
1218 INF("DH params successfully generated and applied!");
1219 SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:@STRENGTH"));
1220 }
1221 else if (!svr->use_cert)
1222 SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_set_cipher_list(svr->ssl_ctx, "aNULL:!eNULL:!LOW:!EXPORT:!ECDH:RSA:AES:!PSK:@STRENGTH"));
1223
1224 return ECORE_CON_SSL_ERROR_NONE;
1225
1226error:
1227 if (dh)
1228 {
1229 if (dh & DH_CHECK_P_NOT_PRIME)
1230 ERR("openssl error: dh_params could not generate a prime!");
1231 else
1232 ERR("openssl error: dh_params could not generate a safe prime!");
1233 }
1234 else
1235 _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR);
1236 _ecore_con_ssl_server_shutdown_openssl(svr);
1237 return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
1238}
1239
1240static Ecore_Con_Ssl_Error
1241_ecore_con_ssl_server_init_openssl(Ecore_Con_Server *svr)
1242{
1243 int ret = -1;
1244
1245 switch (svr->ssl_state)
1246 {
1247 case ECORE_CON_SSL_STATE_DONE:
1248 return ECORE_CON_SSL_ERROR_NONE;
1249
1250 case ECORE_CON_SSL_STATE_INIT:
1251 SSL_ERROR_CHECK_GOTO_ERROR(!(svr->ssl = SSL_new(svr->ssl_ctx)));
1252
1253 SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(svr->ssl, svr->fd));
1254 SSL_set_connect_state(svr->ssl);
1255 svr->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
1256
1257 case ECORE_CON_SSL_STATE_HANDSHAKING:
1258 if (!svr->ssl)
1259 {
1260 DBG("Server was previously lost, going to error condition");
1261 goto error;
1262 }
1263 ret = SSL_do_handshake(svr->ssl);
1264 svr->ssl_err = SSL_get_error(svr->ssl, ret);
1265 SSL_ERROR_CHECK_GOTO_ERROR((svr->ssl_err == SSL_ERROR_SYSCALL) || (svr->ssl_err == SSL_ERROR_SSL));
1266
1267 if (ret == 1)
1268 {
1269 svr->handshaking = EINA_FALSE;
1270 svr->ssl_state = ECORE_CON_SSL_STATE_DONE;
1271 }
1272 else
1273 {
1274 if (svr->ssl_err == SSL_ERROR_WANT_READ)
1275 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
1276 else if (svr->ssl_err == SSL_ERROR_WANT_WRITE)
1277 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
1278 return ECORE_CON_SSL_ERROR_NONE;
1279 }
1280
1281 default:
1282 break;
1283 }
1284
1285#ifdef ISCOMFITOR
1286 {
1287 /* print session info into DBG */
1288 SSL_SESSION *s;
1289 BIO *b;
1290 char log[4096];
1291
1292 memset(log, 0, sizeof(log));
1293 s = SSL_get_session(svr->ssl);
1294 b = BIO_new(BIO_s_mem());
1295 SSL_SESSION_print(b, s);
1296 while (BIO_read(b, log, sizeof(log)) > 0)
1297 DBG("%s", log);
1298
1299 BIO_free(b);
1300 }
1301#endif
1302 if ((!svr->verify) && (!svr->verify_basic))
1303 /* not verifying certificates, so we're done! */
1304 return ECORE_CON_SSL_ERROR_NONE;
1305
1306 {
1307 X509 *cert;
1308 SSL_set_verify(svr->ssl, SSL_VERIFY_PEER, NULL);
1309 /* use CRL/CA lists to verify */
1310 cert = SSL_get_peer_certificate(svr->ssl);
1311 if (cert)
1312 {
1313 char buf[256] = {0};
1314 if (svr->verify)
1315 SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(svr->ssl));
1316 X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_subject_alt_name, buf, sizeof(buf));
1317 if (buf[0])
1318 SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name));
1319 else
1320 {
1321 X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName, buf, sizeof(buf));
1322 SSL_ERROR_CHECK_GOTO_ERROR(!_openssl_name_verify(buf, svr->name));
1323 }
1324 }
1325 }
1326
1327 DBG("SSL certificate verification succeeded!");
1328
1329 return ECORE_CON_SSL_ERROR_NONE;
1330
1331error:
1332 _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR);
1333 _ecore_con_ssl_server_shutdown_openssl(svr);
1334 return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
1335}
1336
1337static Eina_Bool
1338_ecore_con_ssl_server_cafile_add_openssl(Ecore_Con_Server *svr,
1339 const char *ca_file)
1340{
1341 SSL_ERROR_CHECK_GOTO_ERROR(!SSL_CTX_load_verify_locations(svr->ssl_ctx, ca_file, NULL));
1342 return EINA_TRUE;
1343
1344error:
1345 _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR);
1346 return EINA_FALSE;
1347}
1348
1349static Eina_Bool
1350_ecore_con_ssl_server_crl_add_openssl(Ecore_Con_Server *svr,
1351 const char *crl_file)
1352{
1353 X509_STORE *st;
1354 X509_LOOKUP *lu;
1355 static Eina_Bool flag = EINA_FALSE;
1356
1357 SSL_ERROR_CHECK_GOTO_ERROR(!(st = SSL_CTX_get_cert_store(svr->ssl_ctx)));
1358 SSL_ERROR_CHECK_GOTO_ERROR(!(lu = X509_STORE_add_lookup(st, X509_LOOKUP_file())));
1359 SSL_ERROR_CHECK_GOTO_ERROR(X509_load_crl_file(lu, crl_file, X509_FILETYPE_PEM) < 1);
1360 if (!flag)
1361 {
1362 X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
1363 flag = EINA_TRUE;
1364 }
1365
1366 return EINA_TRUE;
1367
1368error:
1369 _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR);
1370 return EINA_FALSE;
1371}
1372
1373static Eina_Bool
1374_ecore_con_ssl_server_privkey_add_openssl(Ecore_Con_Server *svr,
1375 const char *key_file)
1376{
1377 FILE *fp = NULL;
1378 EVP_PKEY *privkey = NULL;
1379
1380 if (!(fp = fopen(key_file, "r")))
1381 goto error;
1382
1383 SSL_ERROR_CHECK_GOTO_ERROR(!(privkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)));
1384
1385 fclose(fp);
1386 SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_use_PrivateKey(svr->ssl_ctx, privkey) < 1);
1387 SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_check_private_key(svr->ssl_ctx) < 1);
1388
1389 return EINA_TRUE;
1390
1391error:
1392 if (fp)
1393 fclose(fp);
1394 _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR);
1395 return EINA_FALSE;
1396}
1397
1398static Eina_Bool
1399_ecore_con_ssl_server_cert_add_openssl(Ecore_Con_Server *svr,
1400 const char *cert_file)
1401{
1402 FILE *fp = NULL;
1403 X509 *cert = NULL;
1404
1405 if (!(fp = fopen(cert_file, "r")))
1406 goto error;
1407
1408 SSL_ERROR_CHECK_GOTO_ERROR(!(cert = PEM_read_X509(fp, NULL, NULL, NULL)));
1409
1410 fclose(fp);
1411
1412 SSL_ERROR_CHECK_GOTO_ERROR(SSL_CTX_use_certificate(svr->ssl_ctx, cert) < 1);
1413
1414 return EINA_TRUE;
1415
1416error:
1417 if (fp)
1418 fclose(fp);
1419 _openssl_print_errors(svr, ECORE_CON_EVENT_SERVER_ERROR);
1420 return EINA_FALSE;
1421}
1422
1423static Ecore_Con_Ssl_Error
1424_ecore_con_ssl_server_shutdown_openssl(Ecore_Con_Server *svr)
1425{
1426 if (svr->ssl)
1427 {
1428 if (!SSL_shutdown(svr->ssl))
1429 SSL_shutdown(svr->ssl);
1430
1431 SSL_free(svr->ssl);
1432 }
1433
1434 if (svr->ssl_ctx)
1435 SSL_CTX_free(svr->ssl_ctx);
1436
1437 svr->ssl = NULL;
1438 svr->ssl_ctx = NULL;
1439 svr->ssl_err = SSL_ERROR_NONE;
1440
1441 return ECORE_CON_SSL_ERROR_NONE;
1442}
1443
1444static int
1445_ecore_con_ssl_server_read_openssl(Ecore_Con_Server *svr,
1446 unsigned char *buf,
1447 int size)
1448{
1449 int num;
1450
1451 if (!svr->ssl) return -1;
1452 num = SSL_read(svr->ssl, buf, size);
1453 svr->ssl_err = SSL_get_error(svr->ssl, num);
1454
1455 if (svr->fd_handler)
1456 {
1457 if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ)
1458 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
1459 else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE)
1460 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
1461 }
1462
1463 if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) ||
1464 (svr->ssl_err == SSL_ERROR_SYSCALL) ||
1465 (svr->ssl_err == SSL_ERROR_SSL))
1466 return -1;
1467
1468 if (num < 0)
1469 return 0;
1470
1471 return num;
1472}
1473
1474static int
1475_ecore_con_ssl_server_write_openssl(Ecore_Con_Server *svr,
1476 const unsigned char *buf,
1477 int size)
1478{
1479 int num;
1480
1481 num = SSL_write(svr->ssl, buf, size);
1482 svr->ssl_err = SSL_get_error(svr->ssl, num);
1483
1484 if (svr->fd_handler)
1485 {
1486 if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_READ)
1487 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ);
1488 else if (svr->ssl && svr->ssl_err == SSL_ERROR_WANT_WRITE)
1489 ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE);
1490 }
1491
1492 if ((svr->ssl_err == SSL_ERROR_ZERO_RETURN) ||
1493 (svr->ssl_err == SSL_ERROR_SYSCALL) ||
1494 (svr->ssl_err == SSL_ERROR_SSL))
1495 return -1;
1496
1497 if (num < 0)
1498 return 0;
1499
1500 return num;
1501}
1502
1503static Ecore_Con_Ssl_Error
1504_ecore_con_ssl_client_init_openssl(Ecore_Con_Client *cl)
1505{
1506 int ret = -1;
1507 switch (cl->ssl_state)
1508 {
1509 case ECORE_CON_SSL_STATE_DONE:
1510 return ECORE_CON_SSL_ERROR_NONE;
1511
1512 case ECORE_CON_SSL_STATE_INIT:
1513 SSL_ERROR_CHECK_GOTO_ERROR(!(cl->ssl = SSL_new(cl->host_server->ssl_ctx)));
1514
1515 SSL_ERROR_CHECK_GOTO_ERROR(!SSL_set_fd(cl->ssl, cl->fd));
1516 SSL_set_accept_state(cl->ssl);
1517 cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING;
1518
1519 case ECORE_CON_SSL_STATE_HANDSHAKING:
1520 if (!cl->ssl)
1521 {
1522 DBG("Client was previously lost, going to error condition");
1523 goto error;
1524 }
1525 ret = SSL_do_handshake(cl->ssl);
1526 cl->ssl_err = SSL_get_error(cl->ssl, ret);
1527 SSL_ERROR_CHECK_GOTO_ERROR((cl->ssl_err == SSL_ERROR_SYSCALL) || (cl->ssl_err == SSL_ERROR_SSL));
1528 if (ret == 1)
1529 {
1530 cl->handshaking = EINA_FALSE;
1531 cl->ssl_state = ECORE_CON_SSL_STATE_DONE;
1532 }
1533 else
1534 {
1535 if (cl->ssl_err == SSL_ERROR_WANT_READ)
1536 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
1537 else if (cl->ssl_err == SSL_ERROR_WANT_WRITE)
1538 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
1539 return ECORE_CON_SSL_ERROR_NONE;
1540 }
1541
1542 default:
1543 break;
1544 }
1545
1546#ifdef ISCOMFITOR
1547 {
1548 /* print session info into DBG */
1549 SSL_SESSION *s;
1550 BIO *b;
1551 char log[4096];
1552
1553 memset(log, 0, sizeof(log));
1554 s = SSL_get_session(cl->ssl);
1555 b = BIO_new(BIO_s_mem());
1556 SSL_SESSION_print(b, s);
1557 while (BIO_read(b, log, sizeof(log)) > 0)
1558 DBG("%s", log);
1559
1560 BIO_free(b);
1561 }
1562#endif
1563
1564 if (!cl->host_server->verify)
1565 /* not verifying certificates, so we're done! */
1566 return ECORE_CON_SSL_ERROR_NONE;
1567 SSL_set_verify(cl->ssl, SSL_VERIFY_PEER, NULL);
1568 /* use CRL/CA lists to verify */
1569 if (SSL_get_peer_certificate(cl->ssl))
1570 SSL_ERROR_CHECK_GOTO_ERROR(SSL_get_verify_result(cl->ssl));
1571
1572 return ECORE_CON_SSL_ERROR_NONE;
1573
1574error:
1575 _openssl_print_errors(cl, ECORE_CON_EVENT_CLIENT_ERROR);
1576 _ecore_con_ssl_client_shutdown_openssl(cl);
1577 return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED;
1578}
1579
1580static Ecore_Con_Ssl_Error
1581_ecore_con_ssl_client_shutdown_openssl(Ecore_Con_Client *cl)
1582{
1583 if (cl->ssl)
1584 {
1585 if (!SSL_shutdown(cl->ssl))
1586 SSL_shutdown(cl->ssl);
1587
1588 SSL_free(cl->ssl);
1589 }
1590
1591 cl->ssl = NULL;
1592 cl->ssl_err = SSL_ERROR_NONE;
1593
1594 return ECORE_CON_SSL_ERROR_NONE;
1595}
1596
1597static int
1598_ecore_con_ssl_client_read_openssl(Ecore_Con_Client *cl,
1599 unsigned char *buf,
1600 int size)
1601{
1602 int num;
1603
1604 if (!cl->ssl) return -1;
1605 num = SSL_read(cl->ssl, buf, size);
1606 cl->ssl_err = SSL_get_error(cl->ssl, num);
1607
1608 if (cl->fd_handler)
1609 {
1610 if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ)
1611 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
1612 else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE)
1613 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
1614 }
1615
1616 if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) ||
1617 (cl->ssl_err == SSL_ERROR_SYSCALL) ||
1618 (cl->ssl_err == SSL_ERROR_SSL))
1619 return -1;
1620
1621 if (num < 0)
1622 return 0;
1623
1624 return num;
1625}
1626
1627static int
1628_ecore_con_ssl_client_write_openssl(Ecore_Con_Client *cl,
1629 const unsigned char *buf,
1630 int size)
1631{
1632 int num;
1633
1634 num = SSL_write(cl->ssl, buf, size);
1635 cl->ssl_err = SSL_get_error(cl->ssl, num);
1636
1637 if (cl->fd_handler)
1638 {
1639 if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_READ)
1640 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ);
1641 else if (cl->ssl && cl->ssl_err == SSL_ERROR_WANT_WRITE)
1642 ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE);
1643 }
1644
1645 if ((cl->ssl_err == SSL_ERROR_ZERO_RETURN) ||
1646 (cl->ssl_err == SSL_ERROR_SYSCALL) ||
1647 (cl->ssl_err == SSL_ERROR_SSL))
1648 return -1;
1649
1650 if (num < 0)
1651 return 0;
1652
1653 return num;
1654}
1655
1656#else
1657
1658/*
1659 * No Ssl
1660 */
1661
1662static Ecore_Con_Ssl_Error
1663_ecore_con_ssl_init_none(void)
1664{
1665 return ECORE_CON_SSL_ERROR_NONE;
1666}
1667
1668static Ecore_Con_Ssl_Error
1669_ecore_con_ssl_shutdown_none(void)
1670{
1671 return ECORE_CON_SSL_ERROR_NONE;
1672}
1673
1674static Ecore_Con_Ssl_Error
1675_ecore_con_ssl_server_prepare_none(Ecore_Con_Server *svr __UNUSED__,
1676 int ssl_type __UNUSED__)
1677{
1678 return ECORE_CON_SSL_ERROR_NONE;
1679}
1680
1681static Ecore_Con_Ssl_Error
1682_ecore_con_ssl_server_upgrade_none(Ecore_Con_Server *svr __UNUSED__)
1683{
1684 return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
1685}
1686
1687static Ecore_Con_Ssl_Error
1688_ecore_con_ssl_server_init_none(Ecore_Con_Server *svr __UNUSED__)
1689{
1690 return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
1691}
1692
1693static Eina_Bool
1694_ecore_con_ssl_server_cafile_add_none(Ecore_Con_Server *svr __UNUSED__,
1695 const char *ca_file __UNUSED__)
1696{
1697 return EINA_FALSE;
1698}
1699
1700static Eina_Bool
1701_ecore_con_ssl_server_cert_add_none(Ecore_Con_Server *svr __UNUSED__,
1702 const char *cert_file __UNUSED__)
1703{
1704 return EINA_FALSE;
1705}
1706
1707static Eina_Bool
1708_ecore_con_ssl_server_privkey_add_none(Ecore_Con_Server *svr __UNUSED__,
1709 const char *key_file __UNUSED__)
1710{
1711 return EINA_FALSE;
1712}
1713
1714static Eina_Bool
1715_ecore_con_ssl_server_crl_add_none(Ecore_Con_Server *svr __UNUSED__,
1716 const char *crl_file __UNUSED__)
1717{
1718 return EINA_FALSE;
1719}
1720
1721static Ecore_Con_Ssl_Error
1722_ecore_con_ssl_server_shutdown_none(Ecore_Con_Server *svr __UNUSED__)
1723{
1724 return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
1725}
1726
1727static int
1728_ecore_con_ssl_server_read_none(Ecore_Con_Server *svr __UNUSED__,
1729 unsigned char *buf __UNUSED__,
1730 int size __UNUSED__)
1731{
1732 return -1;
1733}
1734
1735static int
1736_ecore_con_ssl_server_write_none(Ecore_Con_Server *svr __UNUSED__,
1737 const unsigned char *buf __UNUSED__,
1738 int size __UNUSED__)
1739{
1740 return -1;
1741}
1742
1743static Ecore_Con_Ssl_Error
1744_ecore_con_ssl_client_upgrade_none(Ecore_Con_Client *cl __UNUSED__)
1745{
1746 return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
1747}
1748
1749static Ecore_Con_Ssl_Error
1750_ecore_con_ssl_client_init_none(Ecore_Con_Client *cl __UNUSED__)
1751{
1752 return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
1753}
1754
1755static Ecore_Con_Ssl_Error
1756_ecore_con_ssl_client_shutdown_none(Ecore_Con_Client *cl __UNUSED__)
1757{
1758 return ECORE_CON_SSL_ERROR_NOT_SUPPORTED;
1759}
1760
1761static int
1762_ecore_con_ssl_client_read_none(Ecore_Con_Client *cl __UNUSED__,
1763 unsigned char *buf __UNUSED__,
1764 int size __UNUSED__)
1765{
1766 return -1;
1767}
1768
1769static int
1770_ecore_con_ssl_client_write_none(Ecore_Con_Client *cl __UNUSED__,
1771 const unsigned char *buf __UNUSED__,
1772 int size __UNUSED__)
1773{
1774 return -1;
1775}
1776
1777#endif
diff --git a/libraries/ecore/src/lib/ecore_con/ecore_con_url.c b/libraries/ecore/src/lib/ecore_con/ecore_con_url.c
new file mode 100644
index 0000000..cfcf095
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_con/ecore_con_url.c
@@ -0,0 +1,1572 @@
1/*
2 * For info on how to use libcurl, see:
3 * http://curl.haxx.se/libcurl/c/libcurl-tutorial.html
4 */
5
6/*
7 * FIXME: Support more CURL features...
8 */
9
10#ifdef HAVE_CONFIG_H
11# include <config.h>
12#endif
13
14#include <string.h>
15#include <errno.h>
16#include <sys/stat.h>
17#include <sys/types.h>
18#include <unistd.h>
19
20#ifdef HAVE_WS2TCPIP_H
21# include <ws2tcpip.h>
22#endif
23
24#ifdef HAVE_ESCAPE
25# include <Escape.h>
26#endif
27
28#include "Ecore.h"
29#include "ecore_private.h"
30#include "Ecore_Con.h"
31#include "ecore_con_private.h"
32
33int ECORE_CON_EVENT_URL_DATA = 0;
34int ECORE_CON_EVENT_URL_COMPLETE = 0;
35int ECORE_CON_EVENT_URL_PROGRESS = 0;
36
37#ifdef HAVE_CURL
38static Eina_Bool _ecore_con_url_fd_handler(void *data,
39 Ecore_Fd_Handler *fd_handler);
40static Eina_Bool _ecore_con_url_perform(Ecore_Con_Url *url_con);
41static size_t _ecore_con_url_header_cb(void *ptr,
42 size_t size,
43 size_t nitems,
44 void *stream);
45static size_t _ecore_con_url_data_cb(void *buffer,
46 size_t size,
47 size_t nitems,
48 void *userp);
49static int _ecore_con_url_progress_cb(void *clientp,
50 double dltotal,
51 double dlnow,
52 double ultotal,
53 double ulnow);
54static size_t _ecore_con_url_read_cb(void *ptr,
55 size_t size,
56 size_t nitems,
57 void *stream);
58static void _ecore_con_event_url_free(void *data __UNUSED__,
59 void *ev);
60static int _ecore_con_url_process_completed_jobs(
61 Ecore_Con_Url *url_con_to_match);
62static Eina_Bool _ecore_con_url_idler_handler(void *data);
63
64static Ecore_Idler *_fd_idler_handler = NULL;
65static Eina_List *_url_con_list = NULL;
66static CURLM *_curlm = NULL;
67static fd_set _current_fd_set;
68static int _init_count = 0;
69static Ecore_Timer *_curl_timeout = NULL;
70static Eina_Bool pipelining = EINA_FALSE;
71
72typedef struct _Ecore_Con_Url_Event Ecore_Con_Url_Event;
73struct _Ecore_Con_Url_Event
74{
75 int type;
76 void *ev;
77};
78
79static Eina_Bool
80_url_complete_idler_cb(void *data)
81{
82 Ecore_Con_Url_Event *lev;
83
84 lev = data;
85 ecore_event_add(lev->type, lev->ev, _ecore_con_event_url_free, NULL);
86 free(lev);
87
88 return ECORE_CALLBACK_CANCEL;
89}
90
91static void
92_url_complete_push_event(int type,
93 void *ev)
94{
95 Ecore_Con_Url_Event *lev;
96
97 lev = malloc(sizeof(Ecore_Con_Url_Event));
98 lev->type = type;
99 lev->ev = ev;
100
101 ecore_idler_add(_url_complete_idler_cb, lev);
102}
103
104#endif
105
106/**
107 * @addtogroup Ecore_Con_Url_Group Ecore URL Connection Functions
108 *
109 * @{
110 */
111
112EAPI int
113ecore_con_url_init(void)
114{
115#ifdef HAVE_CURL
116 _init_count++;
117
118 if (_init_count > 1)
119 return _init_count;
120
121 if (!ECORE_CON_EVENT_URL_DATA)
122 {
123 ECORE_CON_EVENT_URL_DATA = ecore_event_type_new();
124 ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new();
125 ECORE_CON_EVENT_URL_PROGRESS = ecore_event_type_new();
126 }
127
128 if (!_curlm)
129 {
130 long ms;
131
132 FD_ZERO(&_current_fd_set);
133 if (curl_global_init(CURL_GLOBAL_ALL))
134 {
135 while (_url_con_list)
136 ecore_con_url_free(eina_list_data_get(_url_con_list));
137 return 0;
138 }
139
140 _curlm = curl_multi_init();
141 if (!_curlm)
142 {
143 while (_url_con_list)
144 ecore_con_url_free(eina_list_data_get(_url_con_list));
145
146 _init_count--;
147 return 0;
148 }
149
150 curl_multi_timeout(_curlm, &ms);
151 if (ms <= 0)
152 ms = 1000;
153
154 _curl_timeout =
155 ecore_timer_add((double)ms / 1000, _ecore_con_url_idler_handler,
156 (void *)0xACE);
157 ecore_timer_freeze(_curl_timeout);
158 }
159
160 return 1;
161#else
162 return 0;
163#endif
164}
165
166EAPI int
167ecore_con_url_shutdown(void)
168{
169#ifdef HAVE_CURL
170 if (!_init_count)
171 return 0;
172
173 _init_count--;
174
175 if (_init_count != 0)
176 return _init_count;
177
178 if (_fd_idler_handler)
179 ecore_idler_del(_fd_idler_handler);
180
181 _fd_idler_handler = NULL;
182
183 if (_curl_timeout)
184 ecore_timer_del(_curl_timeout);
185
186 _curl_timeout = NULL;
187
188 while (_url_con_list)
189 ecore_con_url_free(eina_list_data_get(_url_con_list));
190
191 if (_curlm)
192 {
193 curl_multi_cleanup(_curlm);
194 _curlm = NULL;
195 }
196
197 curl_global_cleanup();
198#endif
199 return 1;
200}
201
202EAPI void
203ecore_con_url_pipeline_set(Eina_Bool enable)
204{
205#ifdef HAVE_CURL
206 if (enable)
207 curl_multi_setopt(_curlm, CURLMOPT_PIPELINING, 1);
208 else
209 curl_multi_setopt(_curlm, CURLMOPT_PIPELINING, 0);
210 pipelining = enable;
211#else
212 return;
213 (void)enable;
214#endif
215}
216
217EAPI Eina_Bool
218ecore_con_url_pipeline_get(void)
219{
220#ifdef HAVE_CURL
221 return pipelining;
222#endif
223 return EINA_FALSE;
224}
225
226EAPI Ecore_Con_Url *
227ecore_con_url_new(const char *url)
228{
229#ifdef HAVE_CURL
230 Ecore_Con_Url *url_con;
231 CURLcode ret;
232
233 if (!_init_count)
234 return NULL;
235
236 url_con = calloc(1, sizeof(Ecore_Con_Url));
237 if (!url_con)
238 return NULL;
239
240 url_con->fd = -1;
241 url_con->write_fd = -1;
242
243 url_con->curl_easy = curl_easy_init();
244 if (!url_con->curl_easy)
245 {
246 free(url_con);
247 return NULL;
248 }
249
250 ECORE_MAGIC_SET(url_con, ECORE_MAGIC_CON_URL);
251
252 if (!ecore_con_url_url_set(url_con, url))
253 {
254 ecore_con_url_free(url_con);
255 return NULL;
256 }
257
258 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_ENCODING, "gzip,deflate");
259 if (ret != CURLE_OK)
260 {
261 ERR("Could not set CURLOPT_ENCODING to \"gzip,deflate\": %s",
262 curl_easy_strerror(ret));
263 ecore_con_url_free(url_con);
264 return NULL;
265 }
266
267 curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEFUNCTION,
268 _ecore_con_url_data_cb);
269 curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEDATA, url_con);
270
271 curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION,
272 _ecore_con_url_progress_cb);
273 curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSDATA, url_con);
274 curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_FALSE);
275
276 curl_easy_setopt(url_con->curl_easy, CURLOPT_HEADERFUNCTION,
277 _ecore_con_url_header_cb);
278 curl_easy_setopt(url_con->curl_easy, CURLOPT_HEADERDATA, url_con);
279
280 /*
281 * FIXME: Check that these timeouts are sensible defaults
282 * FIXME: Provide a means to change these timeouts
283 */
284 curl_easy_setopt(url_con->curl_easy, CURLOPT_CONNECTTIMEOUT, 30);
285 curl_easy_setopt(url_con->curl_easy, CURLOPT_FOLLOWLOCATION, 1);
286
287 return url_con;
288#else
289 return NULL;
290 url = NULL;
291#endif
292}
293
294EAPI Ecore_Con_Url *
295ecore_con_url_custom_new(const char *url,
296 const char *custom_request)
297{
298#ifdef HAVE_CURL
299 Ecore_Con_Url *url_con;
300 CURLcode ret;
301
302 if (!url)
303 return NULL;
304
305 if (!custom_request)
306 return NULL;
307
308 url_con = ecore_con_url_new(url);
309
310 if (!url_con)
311 return NULL;
312
313 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_CUSTOMREQUEST, custom_request);
314 if (ret != CURLE_OK)
315 {
316 ERR("Could not set a custom request string: %s",
317 curl_easy_strerror(ret));
318 ecore_con_url_free(url_con);
319 return NULL;
320 }
321
322 return url_con;
323#else
324 return NULL;
325 url = NULL;
326 custom_request = NULL;
327#endif
328}
329
330EAPI void
331ecore_con_url_free(Ecore_Con_Url *url_con)
332{
333#ifdef HAVE_CURL
334 char *s;
335 CURLMcode ret;
336
337 if (!url_con)
338 return;
339
340 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
341 {
342 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_free");
343 return;
344 }
345
346 ECORE_MAGIC_SET(url_con, ECORE_MAGIC_NONE);
347 if(url_con->fd != -1)
348 {
349 FD_CLR(url_con->fd, &_current_fd_set);
350 if (url_con->fd_handler)
351 ecore_main_fd_handler_del(url_con->fd_handler);
352
353 url_con->fd = -1;
354 url_con->fd_handler = NULL;
355 }
356
357 if (url_con->curl_easy)
358 {
359 // FIXME: For an unknown reason, progress continue to arrive after destruction
360 // this prevent any further call to the callback.
361 curl_easy_setopt(url_con->curl_easy, CURLOPT_PROGRESSFUNCTION, NULL);
362 curl_easy_setopt(url_con->curl_easy, CURLOPT_NOPROGRESS, EINA_TRUE);
363
364 if (url_con->active)
365 {
366 url_con->active = EINA_FALSE;
367
368 ret = curl_multi_remove_handle(_curlm, url_con->curl_easy);
369 if (ret != CURLM_OK)
370 ERR("curl_multi_remove_handle failed: %s",
371 curl_multi_strerror(ret));
372 }
373
374 curl_easy_cleanup(url_con->curl_easy);
375 }
376
377 _url_con_list = eina_list_remove(_url_con_list, url_con);
378 curl_slist_free_all(url_con->headers);
379 EINA_LIST_FREE(url_con->additional_headers, s)
380 free(s);
381 EINA_LIST_FREE(url_con->response_headers, s)
382 free(s);
383 eina_stringshare_del(url_con->url);
384 free(url_con);
385#else
386 return;
387 (void)url_con;
388#endif
389}
390
391EAPI const char *
392ecore_con_url_url_get(Ecore_Con_Url *url_con)
393{
394#ifdef HAVE_CURL
395 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
396 {
397 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, __func__);
398 return NULL;
399 }
400 return url_con->url;
401#else
402 return NULL;
403 (void)url_con;
404#endif
405}
406
407EAPI Eina_Bool
408ecore_con_url_url_set(Ecore_Con_Url *url_con,
409 const char *url)
410{
411#ifdef HAVE_CURL
412 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
413 {
414 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_url_set");
415 return EINA_FALSE;
416 }
417
418 if (url_con->active)
419 return EINA_FALSE;
420
421 eina_stringshare_replace(&url_con->url, url);
422
423 if (url_con->url)
424 curl_easy_setopt(url_con->curl_easy, CURLOPT_URL,
425 url_con->url);
426 else
427 curl_easy_setopt(url_con->curl_easy, CURLOPT_URL, "");
428
429 return EINA_TRUE;
430#else
431 return EINA_FALSE;
432 (void)url;
433 (void)url_con;
434#endif
435}
436
437EAPI void
438ecore_con_url_data_set(Ecore_Con_Url *url_con,
439 void *data)
440{
441#ifdef HAVE_CURL
442 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
443 {
444 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_set");
445 return;
446 }
447
448 url_con->data = data;
449#else
450 return;
451 url_con = NULL;
452 data = NULL;
453#endif
454}
455
456EAPI void
457ecore_con_url_additional_header_add(Ecore_Con_Url *url_con,
458 const char *key,
459 const char *value)
460{
461#ifdef HAVE_CURL
462 char *tmp;
463
464 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
465 {
466 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
467 "ecore_con_url_additional_header_add");
468 return;
469 }
470
471 tmp = malloc(strlen(key) + strlen(value) + 3);
472 if (!tmp)
473 return;
474
475 sprintf(tmp, "%s: %s", key, value);
476 url_con->additional_headers = eina_list_append(url_con->additional_headers,
477 tmp);
478#else
479 return;
480 url_con = NULL;
481 key = NULL;
482 value = NULL;
483#endif
484}
485
486EAPI void
487ecore_con_url_additional_headers_clear(Ecore_Con_Url *url_con)
488{
489#ifdef HAVE_CURL
490 char *s;
491
492 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
493 {
494 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
495 "ecore_con_url_additional_headers_clear");
496 return;
497 }
498
499 EINA_LIST_FREE(url_con->additional_headers, s)
500 free(s);
501#else
502 return;
503 url_con = NULL;
504#endif
505}
506
507EAPI void *
508ecore_con_url_data_get(Ecore_Con_Url *url_con)
509{
510#ifdef HAVE_CURL
511 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
512 {
513 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_get");
514 return NULL;
515 }
516
517 return url_con->data;
518#else
519 return NULL;
520 url_con = NULL;
521#endif
522}
523
524EAPI void
525ecore_con_url_time(Ecore_Con_Url *url_con,
526 Ecore_Con_Url_Time condition,
527 double timestamp)
528{
529#ifdef HAVE_CURL
530 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
531 {
532 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_time");
533 return;
534 }
535
536 url_con->time_condition = condition;
537 url_con->timestamp = timestamp;
538#else
539 return;
540 (void)url_con;
541 (void)condition;
542 (void)timestamp;
543#endif
544}
545
546EAPI void
547ecore_con_url_fd_set(Ecore_Con_Url *url_con,
548 int fd)
549{
550#ifdef HAVE_CURL
551 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
552 {
553 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_set");
554 return;
555 }
556
557 url_con->write_fd = fd;
558#else
559 return;
560 (void)url_con;
561 (void)fd;
562#endif
563}
564
565EAPI int
566ecore_con_url_received_bytes_get(Ecore_Con_Url *url_con)
567{
568#ifdef HAVE_CURL
569 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
570 {
571 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
572 "ecore_con_url_received_bytes_get");
573 return -1;
574 }
575
576 return url_con->received;
577#else
578 return 0;
579 (void)url_con;
580#endif
581}
582
583EAPI const Eina_List *
584ecore_con_url_response_headers_get(Ecore_Con_Url *url_con)
585{
586#ifdef HAVE_CURL
587 return url_con->response_headers;
588#else
589 return NULL;
590 (void)url_con;
591#endif
592}
593
594EAPI Eina_Bool
595ecore_con_url_httpauth_set(Ecore_Con_Url *url_con,
596 const char *username,
597 const char *password,
598 Eina_Bool safe)
599{
600#ifdef HAVE_CURL
601 CURLcode ret;
602
603 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
604 {
605 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
606 "ecore_con_url_httpauth_set");
607 return EINA_FALSE;
608 }
609
610# if LIBCURL_VERSION_NUM >= 0x071301
611 if ((username) && (password))
612 {
613 if (safe)
614 curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPAUTH,
615 CURLAUTH_ANYSAFE);
616 else
617 curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
618
619 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_USERNAME, username);
620 if (ret != CURLE_OK)
621 {
622 ERR("Could not set username for HTTP authentication: %s",
623 curl_easy_strerror(ret));
624 return EINA_FALSE;
625 }
626
627 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_PASSWORD, password);
628 if (ret != CURLE_OK)
629 {
630 ERR("Could not set password for HTTP authentication: %s",
631 curl_easy_strerror(ret));
632 return EINA_FALSE;
633 }
634
635 return EINA_TRUE;
636 }
637# endif
638#else
639 return EINA_FALSE;
640 (void)url_con;
641 (void)username;
642 (void)password;
643 (void)safe;
644#endif
645
646 return EINA_FALSE;
647}
648
649#define MODE_AUTO 0
650#define MODE_GET 1
651#define MODE_POST 2
652
653static Eina_Bool
654_ecore_con_url_send(Ecore_Con_Url *url_con,
655 int mode,
656 const void *data,
657 long length,
658 const char *content_type)
659{
660#ifdef HAVE_CURL
661 Eina_List *l;
662 const char *s;
663 char tmp[256];
664
665 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
666 {
667 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_send");
668 return EINA_FALSE;
669 }
670
671 if (url_con->active)
672 return EINA_FALSE;
673
674 if (!url_con->url)
675 return EINA_FALSE;
676
677 /* Free response headers from previous send() calls */
678 EINA_LIST_FREE(url_con->response_headers, s)
679 free((char *)s);
680 url_con->response_headers = NULL;
681
682 curl_slist_free_all(url_con->headers);
683 url_con->headers = NULL;
684
685 if ((mode == MODE_POST) || (mode == MODE_AUTO))
686 {
687 if (data)
688 {
689 if ((content_type) && (strlen(content_type) < 200))
690 {
691 snprintf(tmp, sizeof(tmp), "Content-Type: %s", content_type);
692 url_con->headers = curl_slist_append(url_con->headers, tmp);
693 }
694
695 curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDS, data);
696 curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, length);
697 }
698 else curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, 0);
699 if (mode == MODE_POST)
700 curl_easy_setopt(url_con->curl_easy, CURLOPT_POST, 1);
701 }
702
703 switch (url_con->time_condition)
704 {
705 case ECORE_CON_URL_TIME_NONE:
706 curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION,
707 CURL_TIMECOND_NONE);
708 break;
709
710 case ECORE_CON_URL_TIME_IFMODSINCE:
711 curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION,
712 CURL_TIMECOND_IFMODSINCE);
713 curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE,
714 (long)url_con->timestamp);
715 break;
716
717 case ECORE_CON_URL_TIME_IFUNMODSINCE:
718 curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMECONDITION,
719 CURL_TIMECOND_IFUNMODSINCE);
720 curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEVALUE,
721 (long)url_con->timestamp);
722 break;
723 }
724
725 /* Additional headers */
726 EINA_LIST_FOREACH(url_con->additional_headers, l, s)
727 url_con->headers = curl_slist_append(url_con->headers, s);
728
729 curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPHEADER, url_con->headers);
730
731 url_con->received = 0;
732
733 return _ecore_con_url_perform(url_con);
734#else
735 return EINA_FALSE;
736 (void)url_con;
737 (void)mode;
738 (void)data;
739 (void)length;
740 (void)content_type;
741#endif
742}
743
744EINA_DEPRECATED EAPI Eina_Bool
745ecore_con_url_send(Ecore_Con_Url *url_con,
746 const void *data,
747 long length,
748 const char *content_type)
749{
750 return _ecore_con_url_send(url_con, MODE_AUTO, data, length, content_type);
751}
752
753EAPI Eina_Bool
754ecore_con_url_get(Ecore_Con_Url *url_con)
755{
756 return _ecore_con_url_send(url_con, MODE_GET, NULL, 0, NULL);
757}
758
759EAPI Eina_Bool
760ecore_con_url_post(Ecore_Con_Url *url_con,
761 const void *data,
762 long length,
763 const char *content_type)
764{
765 return _ecore_con_url_send(url_con, MODE_POST, data, length, content_type);
766}
767
768EAPI Eina_Bool
769ecore_con_url_ftp_upload(Ecore_Con_Url *url_con,
770 const char *filename,
771 const char *user,
772 const char *pass,
773 const char *upload_dir)
774{
775#ifdef HAVE_CURL
776 char url[4096];
777 char userpwd[4096];
778 FILE *fd;
779 struct stat file_info;
780 CURLcode ret;
781
782 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
783 {
784 ECORE_MAGIC_FAIL(url_con,
785 ECORE_MAGIC_CON_URL,
786 "ecore_con_url_ftp_upload");
787 return EINA_FALSE;
788 }
789
790 if (url_con->active)
791 return EINA_FALSE;
792
793 if (!url_con->url)
794 return EINA_FALSE;
795
796 if (filename)
797 {
798 if (stat(filename, &file_info))
799 return EINA_FALSE;
800
801 snprintf(userpwd, sizeof(userpwd), "%s:%s", user, pass);
802 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_USERPWD, userpwd);
803 if (ret != CURLE_OK)
804 {
805 ERR("Could not set username and password for FTP upload: %s",
806 curl_easy_strerror(ret));
807 return EINA_FALSE;
808 }
809
810 char tmp[PATH_MAX];
811 snprintf(tmp, PATH_MAX, "%s", filename);
812
813 if (upload_dir)
814 snprintf(url, sizeof(url), "ftp://%s/%s/%s", url_con->url,
815 upload_dir, basename(tmp));
816 else
817 snprintf(url, sizeof(url), "ftp://%s/%s", url_con->url,
818 basename(tmp));
819
820 if (!ecore_con_url_url_set(url_con, url))
821 return EINA_FALSE;
822
823 curl_easy_setopt(url_con->curl_easy, CURLOPT_INFILESIZE_LARGE,
824 (curl_off_t)file_info.st_size);
825 curl_easy_setopt(url_con->curl_easy, CURLOPT_UPLOAD, 1);
826 curl_easy_setopt(url_con->curl_easy, CURLOPT_READFUNCTION,
827 _ecore_con_url_read_cb);
828
829 fd = fopen(filename, "rb");
830 if (!fd)
831 {
832 ERR("Could not open \"%s\" for FTP upload", filename);
833 return EINA_FALSE;
834 }
835 curl_easy_setopt(url_con->curl_easy, CURLOPT_READDATA, fd);
836
837 return _ecore_con_url_perform(url_con);
838 }
839#else
840 return EINA_FALSE;
841 (void)url_con;
842 (void)filename;
843 (void)user;
844 (void)pass;
845 (void)upload_dir;
846#endif
847
848 return EINA_FALSE;
849}
850
851EAPI void
852ecore_con_url_cookies_init(Ecore_Con_Url *url_con)
853{
854#ifdef HAVE_CURL
855 if (!url_con)
856 return;
857
858 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
859 {
860 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
861 "ecore_con_url_cookies_init");
862 return;
863 }
864
865 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEFILE, "");
866#else
867 return;
868 (void)url_con;
869#endif
870}
871
872EAPI void
873ecore_con_url_cookies_ignore_old_session_set(Ecore_Con_Url *url_con, Eina_Bool ignore)
874{
875#ifdef HAVE_CURL
876 if (!url_con)
877 return;
878
879 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
880 {
881 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
882 "ecore_con_url_cookies_ignore_old_session_set");
883 return;
884 }
885
886 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIESESSION, ignore);
887#else
888 return;
889 (void)url_con;
890 (void)ignore;
891#endif
892}
893
894EAPI void
895ecore_con_url_cookies_clear(Ecore_Con_Url *url_con)
896{
897#ifdef HAVE_CURL
898 if (!url_con)
899 return;
900
901 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
902 {
903 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
904 "ecore_con_url_cookies_clear");
905 return;
906 }
907
908 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "ALL");
909#else
910 return;
911 (void)url_con;
912#endif
913}
914
915EAPI void
916ecore_con_url_cookies_session_clear(Ecore_Con_Url *url_con)
917{
918#ifdef HAVE_CURL
919 if (!url_con)
920 return;
921
922 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
923 {
924 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
925 "ecore_con_url_cookies_session_clear");
926 return;
927 }
928
929 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "SESS");
930#else
931 return;
932 (void)url_con;
933#endif
934}
935
936EAPI void
937ecore_con_url_cookies_file_add(Ecore_Con_Url *url_con, const char * const file_name)
938{
939#ifdef HAVE_CURL
940 if (!url_con)
941 return;
942
943 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
944 {
945 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
946 "ecore_con_url_cookies_file_add");
947 return;
948 }
949
950 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEFILE, file_name);
951#else
952 return;
953 (void)url_con;
954 (void)file_name;
955#endif
956}
957
958EAPI Eina_Bool
959ecore_con_url_cookies_jar_file_set(Ecore_Con_Url *url_con, const char * const cookiejar_file)
960{
961#ifdef HAVE_CURL
962 CURLcode ret;
963
964 if (!url_con)
965 return EINA_FALSE;
966
967 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
968 {
969 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
970 "ecore_con_url_cookies_jar_file_set");
971 return EINA_FALSE;
972 }
973
974 ret = curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIEJAR,
975 cookiejar_file);
976 if (ret != CURLE_OK)
977 {
978 ERR("Setting the cookie-jar name failed: %s",
979 curl_easy_strerror(ret));
980 return EINA_FALSE;
981 }
982
983 return EINA_TRUE;
984#else
985 return EINA_FALSE;
986 (void)url_con;
987 (void)cookiejar_file;
988#endif
989}
990
991EAPI void
992ecore_con_url_cookies_jar_write(Ecore_Con_Url *url_con)
993{
994#ifdef HAVE_CURL
995 if (!url_con)
996 return;
997
998 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
999 {
1000 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
1001 "ecore_con_url_cookies_jar_write");
1002 return;
1003 }
1004
1005 curl_easy_setopt(url_con->curl_easy, CURLOPT_COOKIELIST, "FLUSH");
1006#else
1007 return;
1008 (void)url_con;
1009#endif
1010}
1011
1012EAPI void
1013ecore_con_url_verbose_set(Ecore_Con_Url *url_con,
1014 Eina_Bool verbose)
1015{
1016#ifdef HAVE_CURL
1017 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
1018 {
1019 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
1020 "ecore_con_url_verbose_set");
1021 return;
1022 }
1023
1024 if (url_con->active)
1025 return;
1026
1027 if (!url_con->url)
1028 return;
1029
1030 curl_easy_setopt(url_con->curl_easy, CURLOPT_VERBOSE, (int)verbose);
1031#else
1032 return;
1033 (void)url_con;
1034 (void)verbose;
1035#endif
1036}
1037
1038EAPI void
1039ecore_con_url_ftp_use_epsv_set(Ecore_Con_Url *url_con,
1040 Eina_Bool use_epsv)
1041{
1042#ifdef HAVE_CURL
1043 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
1044 {
1045 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
1046 "ecore_con_url_ftp_use_epsv_set");
1047 return;
1048 }
1049
1050 if (url_con->active)
1051 return;
1052
1053 if (!url_con->url)
1054 return;
1055
1056 curl_easy_setopt(url_con->curl_easy, CURLOPT_FTP_USE_EPSV, (int)use_epsv);
1057#else
1058 return;
1059 (void)url_con;
1060 (void)use_epsv;
1061#endif
1062}
1063
1064/**
1065 * Toggle libcurl's verify peer's certificate option.
1066 *
1067 * If @p verify is @c EINA_TRUE, libcurl will verify
1068 * the authenticity of the peer's certificate, otherwise
1069 * it will not. Default behavior of libcurl is to check
1070 * peer's certificate.
1071 *
1072 * @param url_con Ecore_Con_Url instance which will be acted upon.
1073 * @param verify Whether or not libcurl will check peer's certificate.
1074 * @since 1.1.0
1075 */
1076EAPI void
1077ecore_con_url_ssl_verify_peer_set(Ecore_Con_Url *url_con,
1078 Eina_Bool verify)
1079{
1080#ifdef HAVE_CURL
1081 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
1082 {
1083 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL,
1084 "ecore_con_url_ssl_verify_peer_set");
1085 return;
1086 }
1087
1088 if (url_con->active)
1089 return;
1090
1091 if (!url_con->url)
1092 return;
1093
1094 curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, (int)verify);
1095#else
1096 return;
1097 (void)url_con;
1098 (void)verify;
1099#endif
1100}
1101
1102/**
1103 * Set a custom CA to trust for SSL/TLS connections.
1104 *
1105 * Specify the path of a file (in PEM format) containing one or more
1106 * CA certificate(s) to use for the validation of the server certificate.
1107 *
1108 * This function can also disable CA validation if @p ca_path is @c NULL.
1109 * However, the server certificate still needs to be valid for the connection
1110 * to succeed (i.e., the certificate must concern the server the
1111 * connection is made to).
1112 *
1113 * @param url_con Connection object that will use the custom CA.
1114 * @param ca_path Path to a CA certificate(s) file or @c NULL to disable
1115 * CA validation.
1116 *
1117 * @return @c 0 on success. When cURL is used, non-zero return values
1118 * are equal to cURL error codes.
1119 */
1120EAPI int
1121ecore_con_url_ssl_ca_set(Ecore_Con_Url *url_con, const char *ca_path)
1122{
1123 int res = -1;
1124
1125#ifdef HAVE_CURL
1126 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
1127 {
1128 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_ssl_ca_set");
1129 return -1;
1130 }
1131
1132 if (url_con->active) return -1;
1133 if (!url_con->url) return -1;
1134 if (ca_path == NULL)
1135 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 0);
1136 else
1137 {
1138 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_SSL_VERIFYPEER, 1);
1139 if (!res)
1140 res = curl_easy_setopt(url_con->curl_easy, CURLOPT_CAINFO, ca_path);
1141 }
1142#else
1143 return -1;
1144 (void)url_con;
1145 (void)ca_path;
1146#endif
1147
1148 return res;
1149}
1150
1151
1152/**
1153 * @}
1154 */
1155
1156#ifdef HAVE_CURL
1157static int
1158_ecore_con_url_suspend_fd_handler(void)
1159{
1160 Eina_List *l;
1161 Ecore_Con_Url *url_con;
1162 int deleted = 0;
1163
1164 if (!_url_con_list)
1165 return 0;
1166
1167 EINA_LIST_FOREACH(_url_con_list, l, url_con)
1168 {
1169 if (url_con->active && url_con->fd_handler)
1170 {
1171 ecore_main_fd_handler_del(url_con->fd_handler);
1172 url_con->fd_handler = NULL;
1173 deleted++;
1174 }
1175 }
1176
1177 return deleted;
1178}
1179
1180static int
1181_ecore_con_url_restart_fd_handler(void)
1182{
1183 Eina_List *l;
1184 Ecore_Con_Url *url_con;
1185 int activated = 0;
1186
1187 if (!_url_con_list)
1188 return 0;
1189
1190 EINA_LIST_FOREACH(_url_con_list, l, url_con)
1191 {
1192 if (!url_con->fd_handler && url_con->fd != -1)
1193 {
1194 url_con->fd_handler =
1195 ecore_main_fd_handler_add(url_con->fd, url_con->flags,
1196 _ecore_con_url_fd_handler,
1197 NULL, NULL, NULL);
1198 activated++;
1199 }
1200 }
1201
1202 return activated;
1203}
1204
1205static size_t
1206_ecore_con_url_data_cb(void *buffer,
1207 size_t size,
1208 size_t nitems,
1209 void *userp)
1210{
1211 Ecore_Con_Url *url_con;
1212 Ecore_Con_Event_Url_Data *e;
1213 size_t real_size = size * nitems;
1214
1215 url_con = (Ecore_Con_Url *)userp;
1216
1217 if (!url_con)
1218 return -1;
1219
1220 if (!ECORE_MAGIC_CHECK(url_con, ECORE_MAGIC_CON_URL))
1221 {
1222 ECORE_MAGIC_FAIL(url_con, ECORE_MAGIC_CON_URL, "ecore_con_url_data_cb");
1223 return -1;
1224 }
1225
1226 url_con->received += real_size;
1227
1228 if (url_con->write_fd < 0)
1229 {
1230 e =
1231 malloc(sizeof(Ecore_Con_Event_Url_Data) + sizeof(unsigned char) *
1232 (real_size - 1));
1233 if (e)
1234 {
1235 e->url_con = url_con;
1236 e->size = real_size;
1237 memcpy(e->data, buffer, real_size);
1238 ecore_event_add(ECORE_CON_EVENT_URL_DATA, e,
1239 _ecore_con_event_url_free, NULL);
1240 }
1241 }
1242 else
1243 {
1244 ssize_t count = 0;
1245 size_t total_size = real_size;
1246 size_t offset = 0;
1247
1248 while (total_size > 0)
1249 {
1250 count = write(url_con->write_fd,
1251 (char *)buffer + offset,
1252 total_size);
1253 if (count < 0)
1254 {
1255 if (errno != EAGAIN && errno != EINTR)
1256 return -1;
1257 }
1258 else
1259 {
1260 total_size -= count;
1261 offset += count;
1262 }
1263 }
1264 }
1265
1266 return real_size;
1267}
1268
1269#define ECORE_CON_URL_TRANSMISSION(Transmit, Event, Url_con, Total, Now) \
1270 { \
1271 Ecore_Con_Event_Url_Progress *e; \
1272 if ((Total != 0) || (Now != 0)) \
1273 { \
1274 e = calloc(1, sizeof(Ecore_Con_Event_Url_Progress)); \
1275 if (e) \
1276 { \
1277 e->url_con = url_con; \
1278 e->total = Total; \
1279 e->now = Now; \
1280 ecore_event_add(Event, e, _ecore_con_event_url_free, NULL); \
1281 } \
1282 } \
1283 }
1284
1285static size_t
1286_ecore_con_url_header_cb(void *ptr,
1287 size_t size,
1288 size_t nitems,
1289 void *stream)
1290{
1291 size_t real_size = size * nitems;
1292 Ecore_Con_Url *url_con = stream;
1293
1294 char *header = malloc(sizeof(char) * (real_size + 1));
1295 if (!header)
1296 return real_size;
1297
1298 memcpy(header, ptr, real_size);
1299 header[real_size] = '\0';
1300
1301 url_con->response_headers = eina_list_append(url_con->response_headers,
1302 header);
1303
1304 return real_size;
1305}
1306
1307static int
1308_ecore_con_url_progress_cb(void *clientp,
1309 double dltotal,
1310 double dlnow,
1311 double ultotal,
1312 double ulnow)
1313{
1314 Ecore_Con_Event_Url_Progress *e;
1315 Ecore_Con_Url *url_con;
1316
1317 url_con = clientp;
1318
1319 e = malloc(sizeof(Ecore_Con_Event_Url_Progress));
1320 if (e)
1321 {
1322 e->url_con = url_con;
1323 e->down.total = dltotal;
1324 e->down.now = dlnow;
1325 e->up.total = ultotal;
1326 e->up.now = ulnow;
1327 ecore_event_add(ECORE_CON_EVENT_URL_PROGRESS, e,
1328 _ecore_con_event_url_free, NULL);
1329 }
1330
1331 return 0;
1332}
1333
1334static size_t
1335_ecore_con_url_read_cb(void *ptr,
1336 size_t size,
1337 size_t nitems,
1338 void *stream)
1339{
1340 size_t retcode = fread(ptr, size, nitems, stream);
1341
1342 if (ferror((FILE *)stream))
1343 {
1344 fclose(stream);
1345 return CURL_READFUNC_ABORT;
1346 }
1347 else if (retcode == 0)
1348 {
1349 fclose((FILE *)stream);
1350 return 0;
1351 }
1352
1353#ifdef _WIN32
1354 INF("*** We read %Iu bytes from file", retcode);
1355#else
1356 INF("*** We read %zu bytes from file", retcode);
1357#endif
1358 return retcode;
1359}
1360
1361static Eina_Bool
1362_ecore_con_url_perform(Ecore_Con_Url *url_con)
1363{
1364 fd_set read_set, write_set, exc_set;
1365 int fd_max, fd;
1366 int flags, still_running;
1367 int completed_immediately = 0;
1368 CURLMcode ret;
1369
1370 _url_con_list = eina_list_append(_url_con_list, url_con);
1371
1372 url_con->active = EINA_TRUE;
1373 curl_multi_add_handle(_curlm, url_con->curl_easy);
1374 curl_multi_perform(_curlm, &still_running);
1375
1376 completed_immediately = _ecore_con_url_process_completed_jobs(url_con);
1377
1378 if (!completed_immediately)
1379 {
1380 if (url_con->fd_handler)
1381 ecore_main_fd_handler_del(url_con->fd_handler);
1382
1383 url_con->fd_handler = NULL;
1384
1385 /* url_con still active -- set up an fd_handler */
1386 FD_ZERO(&read_set);
1387 FD_ZERO(&write_set);
1388 FD_ZERO(&exc_set);
1389
1390 /* Stupid curl, why can't I get the fd to the current added job? */
1391 ret = curl_multi_fdset(_curlm, &read_set, &write_set, &exc_set,
1392 &fd_max);
1393 if (ret != CURLM_OK)
1394 {
1395 ERR("curl_multi_fdset failed: %s", curl_multi_strerror(ret));
1396 return EINA_FALSE;
1397 }
1398
1399 for (fd = 0; fd <= fd_max; fd++)
1400 {
1401 if (!FD_ISSET(fd, &_current_fd_set))
1402 {
1403 flags = 0;
1404 if (FD_ISSET(fd, &read_set))
1405 flags |= ECORE_FD_READ;
1406
1407 if (FD_ISSET(fd, &write_set))
1408 flags |= ECORE_FD_WRITE;
1409
1410 if (FD_ISSET(fd, &exc_set))
1411 flags |= ECORE_FD_ERROR;
1412
1413 if (flags)
1414 {
1415 long ms = 0;
1416
1417 ret = curl_multi_timeout(_curlm, &ms);
1418 if (ret != CURLM_OK)
1419 ERR("curl_multi_timeout failed: %s",
1420 curl_multi_strerror(ret));
1421
1422 if (ms == 0)
1423 ms = 1000;
1424
1425 FD_SET(fd, &_current_fd_set);
1426 url_con->fd = fd;
1427 url_con->flags = flags;
1428 url_con->fd_handler =
1429 ecore_main_fd_handler_add(fd, flags,
1430 _ecore_con_url_fd_handler,
1431 NULL, NULL, NULL);
1432 break;
1433 }
1434 }
1435 }
1436 if (!url_con->fd_handler)
1437 {
1438 /* Failed to set up an fd_handler */
1439 ecore_timer_freeze(_curl_timeout);
1440
1441 ret = curl_multi_remove_handle(_curlm, url_con->curl_easy);
1442 if (ret != CURLM_OK)
1443 ERR("curl_multi_remove_handle failed: %s",
1444 curl_multi_strerror(ret));
1445
1446 url_con->active = EINA_FALSE;
1447 url_con->fd = -1;
1448 return EINA_FALSE;
1449 }
1450
1451 ecore_timer_thaw(_curl_timeout);
1452 }
1453
1454 return EINA_TRUE;
1455}
1456
1457static Eina_Bool
1458_ecore_con_url_idler_handler(void *data)
1459{
1460 int done, still_running;
1461
1462 done = (curl_multi_perform(_curlm, &still_running) != CURLM_CALL_MULTI_PERFORM);
1463
1464 _ecore_con_url_process_completed_jobs(NULL);
1465
1466 if (done)
1467 {
1468 _ecore_con_url_restart_fd_handler();
1469 _fd_idler_handler = NULL;
1470
1471 if (!_url_con_list)
1472 ecore_timer_freeze(_curl_timeout);
1473
1474 return data ==
1475 (void *)0xACE ? ECORE_CALLBACK_RENEW : ECORE_CALLBACK_CANCEL;
1476 }
1477
1478 return ECORE_CALLBACK_RENEW;
1479}
1480
1481static Eina_Bool
1482_ecore_con_url_fd_handler(void *data __UNUSED__,
1483 Ecore_Fd_Handler *fd_handler __UNUSED__)
1484{
1485 _ecore_con_url_suspend_fd_handler();
1486
1487 if (!_fd_idler_handler)
1488 _fd_idler_handler = ecore_idler_add(
1489 _ecore_con_url_idler_handler, NULL);
1490
1491 return ECORE_CALLBACK_RENEW;
1492}
1493
1494static int
1495_ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match)
1496{
1497 Eina_List *l;
1498 Ecore_Con_Url *url_con;
1499 Ecore_Con_Event_Url_Complete *e;
1500 CURLMsg *curlmsg;
1501 CURLMcode ret;
1502 int n_remaining;
1503 int job_matched = 0;
1504
1505 /* Loop jobs and check if any are done */
1506 while ((curlmsg = curl_multi_info_read(_curlm, &n_remaining)))
1507 {
1508 if (curlmsg->msg != CURLMSG_DONE)
1509 continue;
1510
1511 /* find the job which is done */
1512 EINA_LIST_FOREACH(_url_con_list, l, url_con)
1513 {
1514 if (curlmsg->easy_handle == url_con->curl_easy)
1515 {
1516 if (url_con_to_match &&
1517 (url_con == url_con_to_match))
1518 job_matched = 1;
1519
1520 if(url_con->fd != -1)
1521 {
1522 FD_CLR(url_con->fd, &_current_fd_set);
1523 if (url_con->fd_handler)
1524 ecore_main_fd_handler_del(
1525 url_con->fd_handler);
1526
1527 url_con->fd = -1;
1528 url_con->fd_handler = NULL;
1529 }
1530
1531 _url_con_list = eina_list_remove(_url_con_list, url_con);
1532 url_con->active = EINA_FALSE;
1533 e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete));
1534 if (e)
1535 {
1536 e->url_con = url_con;
1537 e->status = 0;
1538 if (curlmsg->data.result == CURLE_OK)
1539 {
1540 long status; /* curl API uses long, not int */
1541
1542 status = 0;
1543 curl_easy_getinfo(curlmsg->easy_handle,
1544 CURLINFO_RESPONSE_CODE,
1545 &status);
1546 e->status = status;
1547 }
1548
1549 _url_complete_push_event(ECORE_CON_EVENT_URL_COMPLETE, e);
1550 }
1551
1552 ret = curl_multi_remove_handle(_curlm, url_con->curl_easy);
1553 if (ret != CURLM_OK)
1554 ERR("curl_multi_remove_handle failed: %s",
1555 curl_multi_strerror(ret));
1556
1557 break;
1558 }
1559 }
1560 }
1561
1562 return job_matched;
1563}
1564
1565static void
1566_ecore_con_event_url_free(void *data __UNUSED__,
1567 void *ev)
1568{
1569 free(ev);
1570}
1571
1572#endif