diff options
Diffstat (limited to 'src/examples/ecore/efl_net_server_simple_example.c')
-rw-r--r-- | src/examples/ecore/efl_net_server_simple_example.c | 559 |
1 files changed, 559 insertions, 0 deletions
diff --git a/src/examples/ecore/efl_net_server_simple_example.c b/src/examples/ecore/efl_net_server_simple_example.c new file mode 100644 index 0000000..a7dc2b7 --- /dev/null +++ b/src/examples/ecore/efl_net_server_simple_example.c | |||
@@ -0,0 +1,559 @@ | |||
1 | #define EFL_BETA_API_SUPPORT 1 | ||
2 | #define EFL_EO_API_SUPPORT 1 | ||
3 | #include <Ecore.h> | ||
4 | #include <Ecore_Con.h> | ||
5 | #include <Ecore_Getopt.h> | ||
6 | #include <fcntl.h> | ||
7 | |||
8 | static int retval = EXIT_SUCCESS; | ||
9 | static Eina_Bool echo = EINA_FALSE; | ||
10 | static double timeout = 10.0; | ||
11 | |||
12 | /* NOTE: client i/o events are only used as debug, you can omit these */ | ||
13 | |||
14 | static void | ||
15 | _client_can_read_changed(void *data EINA_UNUSED, const Efl_Event *event) | ||
16 | { | ||
17 | fprintf(stderr, "INFO: client %s can_read=%d\n", | ||
18 | efl_net_socket_address_remote_get(event->object), | ||
19 | efl_io_reader_can_read_get(event->object)); | ||
20 | } | ||
21 | |||
22 | static void | ||
23 | _client_can_write_changed(void *data EINA_UNUSED, const Efl_Event *event) | ||
24 | { | ||
25 | fprintf(stderr, "INFO: client %s can_write=%d\n", | ||
26 | efl_net_socket_address_remote_get(event->object), | ||
27 | efl_io_writer_can_write_get(event->object)); | ||
28 | } | ||
29 | |||
30 | static void | ||
31 | _client_eos(void *data EINA_UNUSED, const Efl_Event *event) | ||
32 | { | ||
33 | fprintf(stderr, "INFO: client %s eos.\n", | ||
34 | efl_net_socket_address_remote_get(event->object)); | ||
35 | } | ||
36 | |||
37 | static void | ||
38 | _client_read_finished(void *data EINA_UNUSED, const Efl_Event *event) | ||
39 | { | ||
40 | Eina_Slice s; | ||
41 | |||
42 | /* on _error() we close it, then do not read as it has nothing */ | ||
43 | if (efl_io_closer_closed_get(event->object)) | ||
44 | return; | ||
45 | |||
46 | if (echo) return; | ||
47 | |||
48 | if (efl_io_buffered_stream_slice_get(event->object, &s)) | ||
49 | { | ||
50 | fprintf(stderr, | ||
51 | "-- BEGIN RECEIVED DATA --\n" | ||
52 | EINA_SLICE_STR_FMT | ||
53 | "-- END RECEIVED DATA--\n", | ||
54 | EINA_SLICE_STR_PRINT(s)); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | static void | ||
59 | _client_closed(void *data EINA_UNUSED, const Efl_Event *event) | ||
60 | { | ||
61 | fprintf(stderr, "INFO: client %s closed.\n", | ||
62 | efl_net_socket_address_remote_get(event->object)); | ||
63 | } | ||
64 | |||
65 | /* this is the only event that matters, from here we remove our extra | ||
66 | * reference from the client and let it be deleted. | ||
67 | */ | ||
68 | static void | ||
69 | _client_finished(void *data EINA_UNUSED, const Efl_Event *event) | ||
70 | { | ||
71 | fprintf(stderr, "INFO: client %s finished sending and receiving, remove extra reference.\n", | ||
72 | efl_net_socket_address_remote_get(event->object)); | ||
73 | if (!efl_io_closer_closed_get(event->object)) | ||
74 | efl_io_closer_close(event->object); | ||
75 | efl_unref(event->object); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * On errors, such as ETIMEDOUT, we want to close the client if not | ||
80 | * happened yet. | ||
81 | */ | ||
82 | static void | ||
83 | _client_error(void *data EINA_UNUSED, const Efl_Event *event) | ||
84 | { | ||
85 | Eina_Error *perr = event->info; | ||
86 | fprintf(stderr, "ERROR: client %s error: %s\n", | ||
87 | efl_net_socket_address_remote_get(event->object), | ||
88 | eina_error_msg_get(*perr)); | ||
89 | if (!efl_io_closer_closed_get(event->object)) | ||
90 | efl_io_closer_close(event->object); | ||
91 | } | ||
92 | |||
93 | EFL_CALLBACKS_ARRAY_DEFINE(client_cbs, | ||
94 | { EFL_IO_READER_EVENT_CAN_READ_CHANGED, _client_can_read_changed }, | ||
95 | { EFL_IO_READER_EVENT_EOS, _client_eos }, | ||
96 | { EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, _client_can_write_changed }, | ||
97 | { EFL_IO_CLOSER_EVENT_CLOSED, _client_closed }, | ||
98 | { EFL_IO_BUFFERED_STREAM_EVENT_READ_FINISHED, _client_read_finished }, | ||
99 | { EFL_IO_BUFFERED_STREAM_EVENT_FINISHED, _client_finished }, | ||
100 | { EFL_IO_BUFFERED_STREAM_EVENT_ERROR, _client_error }); | ||
101 | |||
102 | |||
103 | /* copier events are of interest, you should hook to at least "done" | ||
104 | * and "error" | ||
105 | */ | ||
106 | |||
107 | /* echo copier is about the same socket, you can close it right away */ | ||
108 | |||
109 | static void | ||
110 | _echo_copier_done(void *data EINA_UNUSED, const Efl_Event *event) | ||
111 | { | ||
112 | Eo *copier = event->object; | ||
113 | fprintf(stderr, "INFO: echo copier done, close and del %p\n", copier); | ||
114 | efl_del(copier); /* set to close_on_destructor, will auto close copier and client */ | ||
115 | } | ||
116 | |||
117 | static void | ||
118 | _echo_copier_error(void *data EINA_UNUSED, const Efl_Event *event) | ||
119 | { | ||
120 | Eo *copier = event->object; | ||
121 | const Eina_Error *perr = event->info; | ||
122 | |||
123 | if (*perr == ETIMEDOUT) | ||
124 | { | ||
125 | Eo *client = efl_io_copier_source_get(copier); | ||
126 | fprintf(stderr, "INFO: client '%s' timed out, delete it.\n", | ||
127 | efl_net_socket_address_remote_get(client)); | ||
128 | efl_del(copier); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | retval = EXIT_FAILURE; | ||
133 | |||
134 | fprintf(stderr, "ERROR: echo copier %p failed %d '%s', close and del.\n", | ||
135 | copier, *perr, eina_error_msg_get(*perr)); | ||
136 | |||
137 | efl_del(copier); | ||
138 | } | ||
139 | |||
140 | EFL_CALLBACKS_ARRAY_DEFINE(echo_copier_cbs, | ||
141 | { EFL_IO_COPIER_EVENT_DONE, _echo_copier_done }, | ||
142 | { EFL_IO_COPIER_EVENT_ERROR, _echo_copier_error}); | ||
143 | |||
144 | /* server events are mandatory, afterall you need to define what's | ||
145 | * going to happen after a client socket is connected. This is the | ||
146 | * "client,add" event. | ||
147 | * | ||
148 | * if clients_limit and clients_reject_excess are set, then | ||
149 | * "client,rejected" is dispatched for rejected sockets, they contain | ||
150 | * the string with socket identification. | ||
151 | */ | ||
152 | static void | ||
153 | _server_client_add(void *data EINA_UNUSED, const Efl_Event *event) | ||
154 | { | ||
155 | Efl_Net_Socket *client = event->info; | ||
156 | |||
157 | fprintf(stderr, "INFO: accepted client %s\n", | ||
158 | efl_net_socket_address_remote_get(client)); | ||
159 | |||
160 | /* to use a client, you must efl_ref() it. */ | ||
161 | efl_ref(client); | ||
162 | |||
163 | /* | ||
164 | * monitor the client if it's done and for debug purposes | ||
165 | * (optional) | ||
166 | */ | ||
167 | efl_event_callback_array_add(client, client_cbs(), NULL); | ||
168 | |||
169 | efl_io_buffered_stream_inactivity_timeout_set(client, timeout); | ||
170 | |||
171 | /* | ||
172 | * Since sockets are reader/writer/closer objects, we can use the | ||
173 | * Efl_Io_Copier utility. | ||
174 | */ | ||
175 | |||
176 | if (echo) | ||
177 | { | ||
178 | /* | ||
179 | * An echo copier is pretty simple, use the socket as both | ||
180 | * source and destination. | ||
181 | * | ||
182 | * This is the same as efl_net_server_example.c | ||
183 | */ | ||
184 | Eo *echo_copier = efl_add(EFL_IO_COPIER_CLASS, efl_parent_get(client), | ||
185 | efl_io_copier_source_set(efl_added, client), | ||
186 | efl_io_copier_destination_set(efl_added, client), | ||
187 | efl_event_callback_array_add(efl_added, echo_copier_cbs(), client), | ||
188 | efl_io_closer_close_on_destructor_set(efl_added, EINA_TRUE) /* we want to auto-close as we have a single copier */ | ||
189 | ); | ||
190 | |||
191 | fprintf(stderr, "INFO: using an echo copier=%p for client %s\n", | ||
192 | echo_copier, efl_net_socket_address_remote_get(client)); | ||
193 | return; | ||
194 | } | ||
195 | else | ||
196 | { | ||
197 | /* | ||
198 | * Here is where the "simple" kicks in, instead of all the | ||
199 | * complexity listed in efl_net_server_example.c, we just | ||
200 | * "write & forget" the "Hello World!" and wait for all data | ||
201 | * to be received with a simple "finished" event. | ||
202 | */ | ||
203 | Eina_Slice slice = EINA_SLICE_STR_LITERAL("Hello World!"); | ||
204 | |||
205 | efl_io_writer_write(client, &slice, NULL); | ||
206 | efl_io_buffered_stream_eos_mark(client); /* say that's it */ | ||
207 | } | ||
208 | } | ||
209 | |||
210 | static void | ||
211 | _server_client_rejected(void *data EINA_UNUSED, const Efl_Event *event) | ||
212 | { | ||
213 | const char *client_address = event->info; | ||
214 | fprintf(stderr, "INFO: rejected client %s\n", client_address); | ||
215 | } | ||
216 | |||
217 | static void | ||
218 | _server_error(void *data EINA_UNUSED, const Efl_Event *event) | ||
219 | { | ||
220 | const Eina_Error *perr = event->info; | ||
221 | fprintf(stderr, "ERROR: %d '%s'\n", *perr, eina_error_msg_get(*perr)); | ||
222 | retval = EXIT_FAILURE; | ||
223 | ecore_main_loop_quit(); | ||
224 | } | ||
225 | |||
226 | static void | ||
227 | _server_serving(void *data EINA_UNUSED, const Efl_Event *event) | ||
228 | { | ||
229 | fprintf(stderr, "INFO: serving at %s\n", | ||
230 | efl_net_server_address_get(event->object)); | ||
231 | |||
232 | if (efl_class_get(event->object) == EFL_NET_SERVER_TCP_CLASS) | ||
233 | { | ||
234 | fprintf(stderr, | ||
235 | "TCP options:\n" | ||
236 | " - IPv6 only: %u\n", | ||
237 | efl_net_server_tcp_ipv6_only_get(event->object)); | ||
238 | } | ||
239 | else if (efl_class_get(event->object) == EFL_NET_SERVER_UDP_CLASS) | ||
240 | { | ||
241 | Eina_Iterator *it; | ||
242 | const char *str; | ||
243 | |||
244 | fprintf(stderr, | ||
245 | "UDP options:\n" | ||
246 | " - IPv6 only: %u\n" | ||
247 | " - don't route: %u\n" | ||
248 | " - multicast TTL: %u\n" | ||
249 | " - multicast loopback: %u\n" | ||
250 | " - multicast groups:\n", | ||
251 | efl_net_server_udp_ipv6_only_get(event->object), | ||
252 | efl_net_server_udp_dont_route_get(event->object), | ||
253 | efl_net_server_udp_multicast_time_to_live_get(event->object), | ||
254 | efl_net_server_udp_multicast_loopback_get(event->object)); | ||
255 | |||
256 | it = efl_net_server_udp_multicast_groups_get(event->object); | ||
257 | EINA_ITERATOR_FOREACH(it, str) | ||
258 | fprintf(stderr, " * %s\n", str); | ||
259 | eina_iterator_free(it); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | EFL_CALLBACKS_ARRAY_DEFINE(server_cbs, | ||
264 | { EFL_NET_SERVER_EVENT_CLIENT_ADD, _server_client_add }, | ||
265 | { EFL_NET_SERVER_EVENT_CLIENT_REJECTED, _server_client_rejected }, | ||
266 | { EFL_NET_SERVER_EVENT_ERROR, _server_error }, | ||
267 | { EFL_NET_SERVER_EVENT_SERVING, _server_serving }); | ||
268 | |||
269 | static const char * protocols[] = { | ||
270 | "tcp", | ||
271 | "udp", | ||
272 | "ssl", | ||
273 | #ifndef _WIN32 | ||
274 | "unix", | ||
275 | #endif | ||
276 | NULL | ||
277 | }; | ||
278 | |||
279 | static const char *ciphers_strs[] = { | ||
280 | "auto", | ||
281 | "sslv3", | ||
282 | "tlsv1", | ||
283 | "tlsv1.1", | ||
284 | "tlsv1.2", | ||
285 | NULL | ||
286 | }; | ||
287 | |||
288 | static const Ecore_Getopt options = { | ||
289 | "efl_net_server_example", /* program name */ | ||
290 | NULL, /* usage line */ | ||
291 | "1", /* version */ | ||
292 | "(C) 2016 Enlightenment Project", /* copyright */ | ||
293 | "BSD 2-Clause", /* license */ | ||
294 | /* long description, may be multiline and contain \n */ | ||
295 | "Example of Efl_Net_Server objects usage.\n" | ||
296 | "\n" | ||
297 | "This example spawns a server of the given protocol at the given address.", | ||
298 | EINA_FALSE, | ||
299 | { | ||
300 | ECORE_GETOPT_STORE_TRUE('e', "echo", | ||
301 | "Behave as 'echo' server, send back to client all the data receive"), | ||
302 | ECORE_GETOPT_STORE_TRUE(0, "socket-activated", | ||
303 | "Try to use $LISTEN_FDS from systemd, if not do a regular serve()"), | ||
304 | ECORE_GETOPT_STORE_UINT('l', "clients-limit", | ||
305 | "If set will limit number of clients to accept"), | ||
306 | ECORE_GETOPT_STORE_TRUE('r', "clients-reject-excess", | ||
307 | "Immediately reject excess clients (over limit)"), | ||
308 | ECORE_GETOPT_STORE_FALSE(0, "ipv4-on-ipv6", | ||
309 | "IPv4 clients will be automatically converted into IPv6 and handled transparently."), | ||
310 | ECORE_GETOPT_STORE_DOUBLE('t', "inactivity-timeout", | ||
311 | "The timeout in seconds to disconnect a client. The timeout is restarted for each client when there is some activity. It's particularly useful for UDP where there is no disconnection event."), | ||
312 | |||
313 | ECORE_GETOPT_VERSION('V', "version"), | ||
314 | ECORE_GETOPT_COPYRIGHT('C', "copyright"), | ||
315 | ECORE_GETOPT_LICENSE('L', "license"), | ||
316 | ECORE_GETOPT_HELP('h', "help"), | ||
317 | |||
318 | ECORE_GETOPT_CATEGORY("udp", "UDP options"), | ||
319 | ECORE_GETOPT_STORE_TRUE(0, "udp-dont-route", | ||
320 | "If true, datagrams won't be routed using a gateway, being restricted to the local network."), | ||
321 | ECORE_GETOPT_STORE_UINT(0, "udp-multicast-ttl", | ||
322 | "Multicast time to live in number of hops from 0-255. Defaults to 1 (only local network)."), | ||
323 | ECORE_GETOPT_STORE_FALSE(0, "udp-multicast-noloopback", | ||
324 | "Disable multicast loopback."), | ||
325 | ECORE_GETOPT_APPEND('M', "udp-multicast-group", "Join a multicast group in the form 'IP@INTERFACE', with optional '@INTERFACE', where INTERFACE is the IP address of the interface to join the multicast.", ECORE_GETOPT_TYPE_STR), | ||
326 | |||
327 | ECORE_GETOPT_CATEGORY("ssl", "SSL options"), | ||
328 | ECORE_GETOPT_CHOICE('c', "ssl-cipher", "Cipher to use, defaults to 'auto'", ciphers_strs), | ||
329 | ECORE_GETOPT_APPEND(0, "ssl-certificate", "certificate path to use.", ECORE_GETOPT_TYPE_STR), | ||
330 | ECORE_GETOPT_APPEND(0, "ssl-private-key", "private key path to use.", ECORE_GETOPT_TYPE_STR), | ||
331 | ECORE_GETOPT_APPEND(0, "ssl-crl", "certificate revogation list to use.", ECORE_GETOPT_TYPE_STR), | ||
332 | ECORE_GETOPT_APPEND(0, "ssl-ca", "certificate authorities path to use.", ECORE_GETOPT_TYPE_STR), | ||
333 | |||
334 | ECORE_GETOPT_CHOICE_METAVAR(0, NULL, "The server protocol.", "protocol", | ||
335 | protocols), | ||
336 | ECORE_GETOPT_STORE_METAVAR_STR(0, NULL, | ||
337 | "The server address to listen, such as " | ||
338 | "IPv4:PORT, [IPv6]:PORT, Unix socket path...", | ||
339 | "address"), | ||
340 | |||
341 | ECORE_GETOPT_SENTINEL | ||
342 | } | ||
343 | }; | ||
344 | |||
345 | int | ||
346 | main(int argc, char **argv) | ||
347 | { | ||
348 | const Efl_Class *cls; | ||
349 | char *protocol = NULL; | ||
350 | char *address = NULL; | ||
351 | Eina_List *udp_mcast_groups = NULL; | ||
352 | char *str; | ||
353 | unsigned int clients_limit = 0; | ||
354 | unsigned udp_mcast_ttl = 1; | ||
355 | Eina_Bool clients_reject_excess = EINA_FALSE; | ||
356 | Eina_Bool ipv6_only = EINA_TRUE; | ||
357 | Eina_Bool udp_dont_route = EINA_FALSE; | ||
358 | Eina_Bool udp_mcast_loopback = EINA_TRUE; | ||
359 | Eina_List *certificates = NULL; | ||
360 | Eina_List *private_keys = NULL; | ||
361 | Eina_List *crls = NULL; | ||
362 | Eina_List *cas = NULL; | ||
363 | char *cipher_choice = NULL; | ||
364 | Eina_Bool socket_activated = EINA_FALSE; | ||
365 | Eina_Bool quit_option = EINA_FALSE; | ||
366 | Ecore_Getopt_Value values[] = { | ||
367 | ECORE_GETOPT_VALUE_BOOL(echo), | ||
368 | ECORE_GETOPT_VALUE_BOOL(socket_activated), | ||
369 | ECORE_GETOPT_VALUE_UINT(clients_limit), | ||
370 | ECORE_GETOPT_VALUE_BOOL(clients_reject_excess), | ||
371 | ECORE_GETOPT_VALUE_BOOL(ipv6_only), | ||
372 | ECORE_GETOPT_VALUE_DOUBLE(timeout), | ||
373 | |||
374 | /* standard block to provide version, copyright, license and help */ | ||
375 | ECORE_GETOPT_VALUE_BOOL(quit_option), /* -V/--version quits */ | ||
376 | ECORE_GETOPT_VALUE_BOOL(quit_option), /* -C/--copyright quits */ | ||
377 | ECORE_GETOPT_VALUE_BOOL(quit_option), /* -L/--license quits */ | ||
378 | ECORE_GETOPT_VALUE_BOOL(quit_option), /* -h/--help quits */ | ||
379 | |||
380 | ECORE_GETOPT_VALUE_BOOL(quit_option), /* category: udp */ | ||
381 | ECORE_GETOPT_VALUE_BOOL(udp_dont_route), | ||
382 | ECORE_GETOPT_VALUE_UINT(udp_mcast_ttl), | ||
383 | ECORE_GETOPT_VALUE_BOOL(udp_mcast_loopback), | ||
384 | ECORE_GETOPT_VALUE_LIST(udp_mcast_groups), | ||
385 | |||
386 | ECORE_GETOPT_VALUE_BOOL(quit_option), /* category: ssl */ | ||
387 | ECORE_GETOPT_VALUE_STR(cipher_choice), | ||
388 | ECORE_GETOPT_VALUE_LIST(certificates), | ||
389 | ECORE_GETOPT_VALUE_LIST(private_keys), | ||
390 | ECORE_GETOPT_VALUE_LIST(crls), | ||
391 | ECORE_GETOPT_VALUE_LIST(cas), | ||
392 | |||
393 | /* positional argument */ | ||
394 | ECORE_GETOPT_VALUE_STR(protocol), | ||
395 | ECORE_GETOPT_VALUE_STR(address), | ||
396 | |||
397 | ECORE_GETOPT_VALUE_NONE /* sentinel */ | ||
398 | }; | ||
399 | int args; | ||
400 | Eo *simple_server, *server; | ||
401 | Eina_Error err; | ||
402 | |||
403 | ecore_init(); | ||
404 | ecore_con_init(); | ||
405 | |||
406 | args = ecore_getopt_parse(&options, values, argc, argv); | ||
407 | if (args < 0) | ||
408 | { | ||
409 | fputs("ERROR: Could not parse command line options.\n", stderr); | ||
410 | retval = EXIT_FAILURE; | ||
411 | goto end; | ||
412 | } | ||
413 | |||
414 | if (quit_option) goto end; | ||
415 | |||
416 | args = ecore_getopt_parse_positional(&options, values, argc, argv, args); | ||
417 | if (args < 0) | ||
418 | { | ||
419 | fputs("ERROR: Could not parse positional arguments.\n", stderr); | ||
420 | retval = EXIT_FAILURE; | ||
421 | goto end; | ||
422 | } | ||
423 | |||
424 | if (!protocol) | ||
425 | { | ||
426 | fputs("ERROR: missing protocol.\n", stderr); | ||
427 | retval = EXIT_FAILURE; | ||
428 | goto end; | ||
429 | } | ||
430 | |||
431 | if (strcmp(protocol, "tcp") == 0) cls = EFL_NET_SERVER_TCP_CLASS; | ||
432 | else if (strcmp(protocol, "udp") == 0) cls = EFL_NET_SERVER_UDP_CLASS; | ||
433 | else if (strcmp(protocol, "ssl") == 0) cls = EFL_NET_SERVER_SSL_CLASS; | ||
434 | #ifndef _WIN32 | ||
435 | else if (strcmp(protocol, "unix") == 0) cls = EFL_NET_SERVER_UNIX_CLASS; | ||
436 | #endif | ||
437 | else | ||
438 | { | ||
439 | fprintf(stderr, "ERROR: unsupported protocol: %s\n", protocol); | ||
440 | goto end; | ||
441 | } | ||
442 | |||
443 | simple_server = efl_add(EFL_NET_SERVER_SIMPLE_CLASS, ecore_main_loop_get(), /* it's mandatory to use a main loop provider as the server parent */ | ||
444 | efl_net_server_simple_inner_class_set(efl_added, cls), /* alternatively you could create the inner server and set with efl_net_server_simple_inner_server_set() */ | ||
445 | efl_net_server_clients_limit_set(efl_added, | ||
446 | clients_limit, | ||
447 | clients_reject_excess), /* optional */ | ||
448 | efl_event_callback_array_add(efl_added, server_cbs(), NULL)); /* mandatory to have "client,add" in order to be useful */ | ||
449 | if (!simple_server) | ||
450 | { | ||
451 | fprintf(stderr, "ERROR: could not create simple server for class %p (%s)\n", | ||
452 | cls, efl_class_name_get(cls)); | ||
453 | goto end; | ||
454 | } | ||
455 | |||
456 | /* get the inner server so we can configure it for each protocol */ | ||
457 | server = efl_net_server_simple_inner_server_get(simple_server); | ||
458 | |||
459 | if (cls == EFL_NET_SERVER_TCP_CLASS) | ||
460 | { | ||
461 | efl_net_server_tcp_ipv6_only_set(server, ipv6_only); | ||
462 | efl_net_server_fd_close_on_exec_set(server, EINA_TRUE); /* recommended */ | ||
463 | efl_net_server_fd_reuse_address_set(server, EINA_TRUE); /* optional, but nice for testing */ | ||
464 | efl_net_server_fd_reuse_port_set(server, EINA_TRUE); /* optional, but nice for testing... not secure unless you know what you're doing */ | ||
465 | |||
466 | if (socket_activated) efl_net_server_fd_socket_activate(server, address); | ||
467 | } | ||
468 | else if (cls == EFL_NET_SERVER_UDP_CLASS) | ||
469 | { | ||
470 | const Eina_List *lst; | ||
471 | |||
472 | efl_net_server_udp_ipv6_only_set(server, ipv6_only); | ||
473 | efl_net_server_udp_dont_route_set(server, udp_dont_route); | ||
474 | |||
475 | efl_net_server_udp_multicast_time_to_live_set(server, udp_mcast_ttl); | ||
476 | efl_net_server_udp_multicast_loopback_set(server, udp_mcast_loopback); | ||
477 | |||
478 | EINA_LIST_FOREACH(udp_mcast_groups, lst, str) | ||
479 | efl_net_server_udp_multicast_join(server, str); | ||
480 | |||
481 | |||
482 | efl_net_server_fd_close_on_exec_set(server, EINA_TRUE); /* recommended */ | ||
483 | efl_net_server_fd_reuse_address_set(server, EINA_TRUE); /* optional, but nice for testing */ | ||
484 | efl_net_server_fd_reuse_port_set(server, EINA_TRUE); /* optional, but nice for testing... not secure unless you know what you're doing */ | ||
485 | if (socket_activated) efl_net_server_fd_socket_activate(server, address); | ||
486 | } | ||
487 | else if (cls == EFL_NET_SERVER_SSL_CLASS) | ||
488 | { | ||
489 | Eo *ssl_ctx; | ||
490 | Efl_Net_Ssl_Cipher cipher = EFL_NET_SSL_CIPHER_AUTO; | ||
491 | if (cipher_choice) | ||
492 | { | ||
493 | if (strcmp(cipher_choice, "auto") == 0) | ||
494 | cipher = EFL_NET_SSL_CIPHER_AUTO; | ||
495 | else if (strcmp(cipher_choice, "sslv3") == 0) | ||
496 | cipher = EFL_NET_SSL_CIPHER_SSLV3; | ||
497 | else if (strcmp(cipher_choice, "tlsv1") == 0) | ||
498 | cipher = EFL_NET_SSL_CIPHER_TLSV1; | ||
499 | else if (strcmp(cipher_choice, "tlsv1.1") == 0) | ||
500 | cipher = EFL_NET_SSL_CIPHER_TLSV1_1; | ||
501 | else if (strcmp(cipher_choice, "tlsv1.2") == 0) | ||
502 | cipher = EFL_NET_SSL_CIPHER_TLSV1_2; | ||
503 | } | ||
504 | |||
505 | ssl_ctx = efl_add(EFL_NET_SSL_CONTEXT_CLASS, NULL, | ||
506 | efl_net_ssl_context_certificates_set(efl_added, eina_list_iterator_new(certificates)), | ||
507 | efl_net_ssl_context_private_keys_set(efl_added, eina_list_iterator_new(private_keys)), | ||
508 | efl_net_ssl_context_certificate_revogation_lists_set(efl_added, eina_list_iterator_new(crls)), | ||
509 | efl_net_ssl_context_certificate_authorities_set(efl_added, eina_list_iterator_new(cas)), | ||
510 | efl_net_ssl_context_setup(efl_added, cipher, EINA_FALSE /* a server! */)); | ||
511 | |||
512 | efl_net_server_ssl_context_set(server, ssl_ctx); | ||
513 | |||
514 | efl_net_server_ssl_close_on_exec_set(server, EINA_TRUE); /* recommended */ | ||
515 | efl_net_server_ssl_reuse_address_set(server, EINA_TRUE); /* optional, but nice for testing */ | ||
516 | efl_net_server_ssl_reuse_port_set(server, EINA_TRUE); /* optional, but nice for testing... not secure unless you know what you're doing */ | ||
517 | if (socket_activated) efl_net_server_ssl_socket_activate(server, address); | ||
518 | } | ||
519 | #ifndef _WIN32 | ||
520 | else if (cls == EFL_NET_SERVER_UNIX_CLASS) | ||
521 | { | ||
522 | efl_net_server_unix_unlink_before_bind_set(server, EINA_TRUE); /* makes testing easier */ | ||
523 | if (socket_activated) efl_net_server_fd_socket_activate(server, address); | ||
524 | } | ||
525 | #endif | ||
526 | |||
527 | /* an explicit call to efl_net_server_serve() after the object is | ||
528 | * constructed allows for more complex setup, such as interacting | ||
529 | * with the object to add more properties that couldn't be done | ||
530 | * during efl_add(). | ||
531 | */ | ||
532 | if (!efl_net_server_serving_get(simple_server)) | ||
533 | { | ||
534 | if (socket_activated) | ||
535 | fprintf(stderr, "WARNING: --socket-activated, but not able to use $LISTEN_FDS descriptors. Try to start the server...\n"); | ||
536 | |||
537 | err = efl_net_server_serve(simple_server, address); | ||
538 | if (err) | ||
539 | { | ||
540 | fprintf(stderr, "ERROR: could not serve(%s): %s\n", | ||
541 | address, eina_error_msg_get(err)); | ||
542 | goto end_server; | ||
543 | } | ||
544 | } | ||
545 | |||
546 | ecore_main_loop_begin(); | ||
547 | |||
548 | end_server: | ||
549 | efl_del(simple_server); | ||
550 | simple_server = NULL; | ||
551 | |||
552 | end: | ||
553 | EINA_LIST_FREE(udp_mcast_groups, str) | ||
554 | free(str); | ||
555 | ecore_con_shutdown(); | ||
556 | ecore_shutdown(); | ||
557 | |||
558 | return retval; | ||
559 | } | ||