summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-10-26 18:57:37 -0200
committerGustavo Sverzut Barbieri <barbieri@profusion.mobi>2016-10-26 19:01:03 -0200
commit651ff136163bf6fb4986f9dfaff09ca3f212178e (patch)
tree2e2781c5a21babafad44a820cc9bf142dc3afe60 /src
parent84ee276b127443e20a0db70666feefcaf1823559 (diff)
addded efl_net_{socket,dialer,server}_unix
This introduces AF_UNIX server and dialer, these are not available on Windows as in that platform we'll create a custom class for native 'local' communication. In the future we can add a wrapper class Efl.Net.Local that will use the class for each platform, but won't expose its details. For instance, if we ever expose 'credentials' (which I didn't because they are not portable), then it doesn't make sense to try to match that on Windows. The 'Efl.Net.Local' would just stick to the basics: Reader, Writer and Closer APIs.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_Ecore_Con.am13
-rw-r--r--src/examples/ecore/.gitignore1
-rw-r--r--src/examples/ecore/Makefile.am6
-rw-r--r--src/examples/ecore/efl_net_dialer_unix_example.c212
-rw-r--r--src/examples/ecore/efl_net_server_example.c12
-rw-r--r--src/lib/ecore_con/Ecore_Con_Eo.h7
-rw-r--r--src/lib/ecore_con/ecore_con.c68
-rw-r--r--src/lib/ecore_con/ecore_con_private.h3
-rw-r--r--src/lib/ecore_con/efl_net_dialer_unix.c236
-rw-r--r--src/lib/ecore_con/efl_net_dialer_unix.eo22
-rw-r--r--src/lib/ecore_con/efl_net_server_unix.c259
-rw-r--r--src/lib/ecore_con/efl_net_server_unix.eo28
-rw-r--r--src/lib/ecore_con/efl_net_socket_unix.c77
-rw-r--r--src/lib/ecore_con/efl_net_socket_unix.eo13
14 files changed, 950 insertions, 7 deletions
diff --git a/src/Makefile_Ecore_Con.am b/src/Makefile_Ecore_Con.am
index 58a73ae722..49cf65bd07 100644
--- a/src/Makefile_Ecore_Con.am
+++ b/src/Makefile_Ecore_Con.am
@@ -25,6 +25,14 @@ ecore_con_eolian_files = \
25 lib/ecore_con/ecore_con_eet_client_obj.eo \ 25 lib/ecore_con/ecore_con_eet_client_obj.eo \
26 lib/ecore_con/efl_network_url.eo 26 lib/ecore_con/efl_network_url.eo
27 27
28if HAVE_WINDOWS
29else
30ecore_con_eolian_files += \
31 lib/ecore_con/efl_net_socket_unix.eo \
32 lib/ecore_con/efl_net_dialer_unix.eo \
33 lib/ecore_con/efl_net_server_unix.eo
34endif
35
28ecore_con_eolian_type_files = \ 36ecore_con_eolian_type_files = \
29 lib/ecore_con/efl_net_http_types.eot 37 lib/ecore_con/efl_net_http_types.eot
30 38
@@ -94,7 +102,10 @@ EXTRA_DIST2 += lib/ecore_con/ecore_con_legacy.c
94if HAVE_WINDOWS 102if HAVE_WINDOWS
95lib_ecore_con_libecore_con_la_SOURCES += lib/ecore_con/ecore_con_local_win32.c 103lib_ecore_con_libecore_con_la_SOURCES += lib/ecore_con/ecore_con_local_win32.c
96else 104else
97lib_ecore_con_libecore_con_la_SOURCES += lib/ecore_con/ecore_con_local.c 105lib_ecore_con_libecore_con_la_SOURCES += lib/ecore_con/ecore_con_local.c \
106lib/ecore_con/efl_net_socket_unix.c \
107lib/ecore_con/efl_net_dialer_unix.c \
108lib/ecore_con/efl_net_server_unix.c
98endif 109endif
99 110
100lib_ecore_con_libecore_con_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_CON_CFLAGS@ 111lib_ecore_con_libecore_con_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_CON_CFLAGS@
diff --git a/src/examples/ecore/.gitignore b/src/examples/ecore/.gitignore
index 3aaec192ac..fd2d749eac 100644
--- a/src/examples/ecore/.gitignore
+++ b/src/examples/ecore/.gitignore
@@ -55,3 +55,4 @@
55/efl_net_dialer_websocket_example 55/efl_net_dialer_websocket_example
56/efl_net_dialer_websocket_autobahntestee 56/efl_net_dialer_websocket_autobahntestee
57/efl_net_dialer_udp_example 57/efl_net_dialer_udp_example
58/efl_net_dialer_unix_example
diff --git a/src/examples/ecore/Makefile.am b/src/examples/ecore/Makefile.am
index da6b086a3d..a0eb588756 100644
--- a/src/examples/ecore/Makefile.am
+++ b/src/examples/ecore/Makefile.am
@@ -314,6 +314,12 @@ efl_net_dialer_websocket_autobahntestee_LDADD = $(ECORE_CON_COMMON_LDADD)
314efl_net_dialer_udp_example_SOURCES = efl_net_dialer_udp_example.c 314efl_net_dialer_udp_example_SOURCES = efl_net_dialer_udp_example.c
315efl_net_dialer_udp_example_LDADD = $(ECORE_CON_COMMON_LDADD) 315efl_net_dialer_udp_example_LDADD = $(ECORE_CON_COMMON_LDADD)
316 316
317if ! HAVE_WINDOWS
318EXTRA_PROGRAMS += efl_net_dialer_unix_example
319efl_net_dialer_unix_example_SOURCES = efl_net_dialer_unix_example.c
320efl_net_dialer_unix_example_LDADD = $(ECORE_CON_COMMON_LDADD)
321endif
322
317SRCS = \ 323SRCS = \
318ecore_animator_example.c \ 324ecore_animator_example.c \
319ecore_buffer_example.c \ 325ecore_buffer_example.c \
diff --git a/src/examples/ecore/efl_net_dialer_unix_example.c b/src/examples/ecore/efl_net_dialer_unix_example.c
new file mode 100644
index 0000000000..57110ef76e
--- /dev/null
+++ b/src/examples/ecore/efl_net_dialer_unix_example.c
@@ -0,0 +1,212 @@
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#include <ctype.h>
8
9static int retval = EXIT_SUCCESS;
10static Eina_Bool do_read = EINA_FALSE;
11
12static void
13_connected(void *data EINA_UNUSED, const Efl_Event *event)
14{
15 fprintf(stderr,
16 "INFO: connected to '%s' (%s)\n"
17 "INFO: - local address=%s\n"
18 "INFO: - read-after-write=%u\n",
19 efl_net_dialer_address_dial_get(event->object),
20 efl_net_socket_address_remote_get(event->object),
21 efl_net_socket_address_local_get(event->object),
22 do_read);
23}
24
25static void
26_eos(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
27{
28 fprintf(stderr, "INFO: end of stream. \n");
29 ecore_main_loop_quit();
30}
31
32static void
33_can_read(void *data EINA_UNUSED, const Efl_Event *event)
34{
35 char buf[4];
36 Eina_Rw_Slice rw_slice = EINA_SLICE_ARRAY(buf);
37 Eina_Error err;
38 Eina_Bool can_read = efl_io_reader_can_read_get(event->object);
39
40 /* NOTE: this message may appear with can read=0 BEFORE
41 * "read '...'" because efl_io_readr_read() will change the status
42 * of can_read to FALSE prior to return so we can print it!
43 */
44 fprintf(stderr, "INFO: can read=%d\n", can_read);
45 if (!can_read) return;
46 if (!do_read) return;
47
48 err = efl_io_reader_read(event->object, &rw_slice);
49 if (err)
50 {
51 fprintf(stderr, "ERROR: could not read: %s\n", eina_error_msg_get(err));
52 retval = EXIT_FAILURE;
53 ecore_main_loop_quit();
54 return;
55 }
56
57 fprintf(stderr, "INFO: read '" EINA_SLICE_STR_FMT "'\n", EINA_SLICE_STR_PRINT(rw_slice));
58}
59
60static void
61_can_write(void *data EINA_UNUSED, const Efl_Event *event)
62{
63 static Eina_Slice slice = EINA_SLICE_STR_LITERAL("Hello World!");
64 Eina_Slice to_write;
65 Eina_Error err;
66 Eina_Bool can_write = efl_io_writer_can_write_get(event->object);
67
68 /* NOTE: this message may appear with can write=0 BEFORE
69 * "wrote '...'" because efl_io_writer_write() will change the status
70 * of can_write to FALSE prior to return so we can print it!
71 */
72 fprintf(stderr, "INFO: can write=%d (wanted bytes=%zd)\n", can_write, slice.len);
73 if (!can_write) return;
74 if (slice.len == 0) return;
75
76 to_write = slice;
77 err = efl_io_writer_write(event->object, &to_write, &slice);
78 if (err)
79 {
80 fprintf(stderr, "ERROR: could not write: %s\n", eina_error_msg_get(err));
81 retval = EXIT_FAILURE;
82 ecore_main_loop_quit();
83 return;
84 }
85
86 fprintf(stderr, "INFO: wrote '" EINA_SLICE_STR_FMT "', still pending=%zd bytes\n", EINA_SLICE_STR_PRINT(to_write), slice.len);
87
88 if ((!do_read) && (slice.len == 0))
89 {
90 retval = EXIT_SUCCESS;
91 ecore_main_loop_quit();
92 return;
93 }
94}
95
96static void
97_resolved(void *data EINA_UNUSED, const Efl_Event *event)
98{
99 fprintf(stderr, "INFO: resolved %s => %s\n",
100 efl_net_dialer_address_dial_get(event->object),
101 efl_net_socket_address_remote_get(event->object));
102}
103
104static void
105_error(void *data EINA_UNUSED, const Efl_Event *event)
106{
107 const Eina_Error *perr = event->info;
108 fprintf(stderr, "INFO: error: %d '%s'\n", *perr, eina_error_msg_get(*perr));
109 retval = EXIT_FAILURE;
110}
111
112EFL_CALLBACKS_ARRAY_DEFINE(dialer_cbs,
113 { EFL_NET_DIALER_EVENT_CONNECTED, _connected },
114 { EFL_NET_DIALER_EVENT_RESOLVED, _resolved },
115 { EFL_NET_DIALER_EVENT_ERROR, _error },
116 { EFL_IO_READER_EVENT_EOS, _eos },
117 { EFL_IO_READER_EVENT_CAN_READ_CHANGED, _can_read },
118 { EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, _can_write }
119 );
120
121static const Ecore_Getopt options = {
122 "efl_net_dialer_unix_example", /* program name */
123 NULL, /* usage line */
124 "1", /* version */
125 "(C) 2016 Enlightenment Project", /* copyright */
126 "BSD 2-Clause", /* license */
127 /* long description, may be multiline and contain \n */
128 "Example of Efl_Net_Dialer_Unix usage, sending a message and receiving a reply\n",
129 EINA_FALSE,
130 {
131 ECORE_GETOPT_STORE_TRUE('r', "read-after-write", "Do a read after writes are done."),
132 ECORE_GETOPT_VERSION('V', "version"),
133 ECORE_GETOPT_COPYRIGHT('C', "copyright"),
134 ECORE_GETOPT_LICENSE('L', "license"),
135 ECORE_GETOPT_HELP('h', "help"),
136 ECORE_GETOPT_STORE_METAVAR_STR(0, NULL,
137 "The address (URL) to dial", "address"),
138 ECORE_GETOPT_SENTINEL
139 }
140};
141
142int
143main(int argc, char **argv)
144{
145 char *address = NULL;
146 Eina_Bool quit_option = EINA_FALSE;
147 Ecore_Getopt_Value values[] = {
148 ECORE_GETOPT_VALUE_BOOL(do_read),
149
150 /* standard block to provide version, copyright, license and help */
151 ECORE_GETOPT_VALUE_BOOL(quit_option), /* -V/--version quits */
152 ECORE_GETOPT_VALUE_BOOL(quit_option), /* -C/--copyright quits */
153 ECORE_GETOPT_VALUE_BOOL(quit_option), /* -L/--license quits */
154 ECORE_GETOPT_VALUE_BOOL(quit_option), /* -h/--help quits */
155
156 /* positional argument */
157 ECORE_GETOPT_VALUE_STR(address),
158
159 ECORE_GETOPT_VALUE_NONE /* sentinel */
160 };
161 int args;
162 Eo *dialer, *loop;
163 Eina_Error err;
164
165 ecore_init();
166 ecore_con_init();
167
168 args = ecore_getopt_parse(&options, values, argc, argv);
169 if (args < 0)
170 {
171 fputs("ERROR: Could not parse command line options.\n", stderr);
172 retval = EXIT_FAILURE;
173 goto end;
174 }
175
176 if (quit_option) goto end;
177
178 loop = ecore_main_loop_get();
179
180 args = ecore_getopt_parse_positional(&options, values, argc, argv, args);
181 if (args < 0)
182 {
183 fputs("ERROR: Could not parse positional arguments.\n", stderr);
184 retval = EXIT_FAILURE;
185 goto end;
186 }
187
188 dialer = efl_add(EFL_NET_DIALER_UNIX_CLASS, loop,
189 efl_name_set(efl_added, "dialer"),
190 efl_event_callback_array_add(efl_added, dialer_cbs(), NULL));
191
192 err = efl_net_dialer_dial(dialer, address);
193 if (err != 0)
194 {
195 fprintf(stderr, "ERROR: could not dial '%s': %s",
196 address, eina_error_msg_get(err));
197 goto no_mainloop;
198 }
199
200 ecore_main_loop_begin();
201
202 fprintf(stderr, "INFO: main loop finished.\n");
203
204 no_mainloop:
205 efl_del(dialer);
206
207 end:
208 ecore_con_shutdown();
209 ecore_shutdown();
210
211 return retval;
212}
diff --git a/src/examples/ecore/efl_net_server_example.c b/src/examples/ecore/efl_net_server_example.c
index 3bec44ce8f..98f1615da4 100644
--- a/src/examples/ecore/efl_net_server_example.c
+++ b/src/examples/ecore/efl_net_server_example.c
@@ -474,6 +474,9 @@ EFL_CALLBACKS_ARRAY_DEFINE(server_cbs,
474static const char * protocols[] = { 474static const char * protocols[] = {
475 "tcp", 475 "tcp",
476 "udp", 476 "udp",
477#ifndef _WIN32
478 "unix",
479#endif
477 NULL 480 NULL
478}; 481};
479 482
@@ -600,6 +603,9 @@ main(int argc, char **argv)
600 603
601 if (strcmp(protocol, "tcp") == 0) cls = EFL_NET_SERVER_TCP_CLASS; 604 if (strcmp(protocol, "tcp") == 0) cls = EFL_NET_SERVER_TCP_CLASS;
602 else if (strcmp(protocol, "udp") == 0) cls = EFL_NET_SERVER_UDP_CLASS; 605 else if (strcmp(protocol, "udp") == 0) cls = EFL_NET_SERVER_UDP_CLASS;
606#ifndef _WIN32
607 else if (strcmp(protocol, "unix") == 0) cls = EFL_NET_SERVER_UNIX_CLASS;
608#endif
603 else 609 else
604 { 610 {
605 fprintf(stderr, "ERROR: unsupported protocol: %s\n", protocol); 611 fprintf(stderr, "ERROR: unsupported protocol: %s\n", protocol);
@@ -636,6 +642,12 @@ main(int argc, char **argv)
636 EINA_LIST_FOREACH(udp_mcast_groups, lst, str) 642 EINA_LIST_FOREACH(udp_mcast_groups, lst, str)
637 efl_net_server_udp_multicast_join(server, str); 643 efl_net_server_udp_multicast_join(server, str);
638 } 644 }
645#ifndef _WIN32
646 else if (cls == EFL_NET_SERVER_UNIX_CLASS)
647 {
648 efl_net_server_unix_unlink_before_bind_set(server, EINA_TRUE); /* makes testing easier */
649 }
650#endif
639 651
640 /* an explicit call to efl_net_server_serve() after the object is 652 /* an explicit call to efl_net_server_serve() after the object is
641 * constructed allows for more complex setup, such as interacting 653 * constructed allows for more complex setup, such as interacting
diff --git a/src/lib/ecore_con/Ecore_Con_Eo.h b/src/lib/ecore_con/Ecore_Con_Eo.h
index f8198f6971..b3e3bf4046 100644
--- a/src/lib/ecore_con/Ecore_Con_Eo.h
+++ b/src/lib/ecore_con/Ecore_Con_Eo.h
@@ -15,6 +15,13 @@
15#include "efl_net_dialer_tcp.eo.h" 15#include "efl_net_dialer_tcp.eo.h"
16#include "efl_net_server_tcp.eo.h" 16#include "efl_net_server_tcp.eo.h"
17 17
18#ifdef _WIN32
19#else
20#include "efl_net_socket_unix.eo.h"
21#include "efl_net_dialer_unix.eo.h"
22#include "efl_net_server_unix.eo.h"
23#endif
24
18#include "efl_net_socket_udp.eo.h" 25#include "efl_net_socket_udp.eo.h"
19#include "efl_net_dialer_udp.eo.h" 26#include "efl_net_dialer_udp.eo.h"
20#include "efl_net_server_udp.eo.h" 27#include "efl_net_server_udp.eo.h"
diff --git a/src/lib/ecore_con/ecore_con.c b/src/lib/ecore_con/ecore_con.c
index c6b27c8551..9bc3388adc 100644
--- a/src/lib/ecore_con/ecore_con.c
+++ b/src/lib/ecore_con/ecore_con.c
@@ -3027,7 +3027,60 @@ _ecore_con_lookup_done(void *data,
3027#include "efl_network_connector.eo.c" 3027#include "efl_network_connector.eo.c"
3028 3028
3029Eina_Bool 3029Eina_Bool
3030efl_net_ip_port_fmt(char *buf, int buflen, const struct sockaddr *addr) 3030efl_net_unix_fmt(char *buf, size_t buflen, SOCKET fd, const struct sockaddr_un *addr, socklen_t addrlen)
3031{
3032 const char *src = addr->sun_path;
3033 socklen_t pathlen = addrlen - offsetof(struct sockaddr_un, sun_path);
3034
3035 if (addr->sun_family != AF_UNIX)
3036 {
3037 ERR("unsupported address family: %d", addr->sun_family);
3038 return EINA_FALSE;
3039 }
3040
3041 if (addrlen == offsetof(struct sockaddr_un, sun_path))
3042 {
3043 int r = snprintf(buf, buflen, "unnamed:%d", fd);
3044 if (r < 0)
3045 {
3046 ERR("snprintf(): %s", strerror(errno));
3047 return EINA_FALSE;
3048 }
3049 else if ((size_t)r > buflen)
3050 {
3051 ERR("buflen=%zu is too small, required=%d", buflen, r);
3052 return EINA_FALSE;
3053 }
3054 return EINA_TRUE;
3055 }
3056
3057 if (src[0] != '\0')
3058 {
3059 if (buflen < pathlen)
3060 {
3061 ERR("buflen=%zu is too small, required=%u", buflen, pathlen);
3062 return EINA_FALSE;
3063 }
3064 }
3065 else
3066 {
3067 if (buflen < pathlen + sizeof("abstract:") - 2)
3068 {
3069 ERR("buflen=%zu is too small, required=%zu", buflen, pathlen + sizeof("abstract:") - 2);
3070 return EINA_FALSE;
3071 }
3072 memcpy(buf, "abstract:", sizeof("abstract:") - 1);
3073 buf += sizeof("abstract:") - 1;
3074 src++;
3075 }
3076
3077 memcpy(buf, src, pathlen);
3078 buf[pathlen] = '\0';
3079 return EINA_TRUE;
3080}
3081
3082Eina_Bool
3083efl_net_ip_port_fmt(char *buf, size_t buflen, const struct sockaddr *addr)
3031{ 3084{
3032 char p[INET6_ADDRSTRLEN]; 3085 char p[INET6_ADDRSTRLEN];
3033 const void *mem; 3086 const void *mem;
@@ -3069,9 +3122,9 @@ efl_net_ip_port_fmt(char *buf, int buflen, const struct sockaddr *addr)
3069 ERR("could not snprintf(): %s", strerror(errno)); 3122 ERR("could not snprintf(): %s", strerror(errno));
3070 return EINA_FALSE; 3123 return EINA_FALSE;
3071 } 3124 }
3072 else if (r > buflen) 3125 else if ((size_t)r > buflen)
3073 { 3126 {
3074 ERR("buffer is too small: %d, required %d", buflen, r); 3127 ERR("buffer is too small: %zu, required %d", buflen, r);
3075 return EINA_FALSE; 3128 return EINA_FALSE;
3076 } 3129 }
3077 3130
@@ -3294,7 +3347,7 @@ static void
3294_efl_net_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED) 3347_efl_net_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED)
3295{ 3348{
3296 Efl_Net_Connect_Async_Data *d = data; 3349 Efl_Net_Connect_Async_Data *d = data;
3297 char buf[INET6_ADDRSTRLEN + sizeof("[]:65536")] = ""; 3350 char buf[INET6_ADDRSTRLEN + sizeof("[]:65536") + sizeof(struct sockaddr_un)] = "";
3298 int r; 3351 int r;
3299 3352
3300 /* allows ecore_thread_cancel() to cancel at some points, see 3353 /* allows ecore_thread_cancel() to cancel at some points, see
@@ -3319,7 +3372,12 @@ _efl_net_connect_async_run(void *data, Ecore_Thread *thread EINA_UNUSED)
3319 } 3372 }
3320 3373
3321 if (eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG)) 3374 if (eina_log_domain_level_check(_ecore_con_log_dom, EINA_LOG_LEVEL_DBG))
3322 efl_net_ip_port_fmt(buf, sizeof(buf), d->addr); 3375 {
3376 if (d->addr->sa_family == AF_UNIX)
3377 efl_net_unix_fmt(buf, sizeof(buf), d->sockfd, (const struct sockaddr_un *)d->addr, d->addrlen);
3378 else
3379 efl_net_ip_port_fmt(buf, sizeof(buf), d->addr);
3380 }
3323 3381
3324 DBG("connecting fd=%d to %s", d->sockfd, buf); 3382 DBG("connecting fd=%d to %s", d->sockfd, buf);
3325 3383
diff --git a/src/lib/ecore_con/ecore_con_private.h b/src/lib/ecore_con/ecore_con_private.h
index 894356fd20..ef78f96e6c 100644
--- a/src/lib/ecore_con/ecore_con_private.h
+++ b/src/lib/ecore_con/ecore_con_private.h
@@ -402,7 +402,8 @@ void _efl_net_server_udp_client_feed(Eo *client, Eina_Rw_Slice slice);
402 402
403void _efl_net_socket_udp_init(Eo *o, const struct sockaddr *addr, socklen_t addrlen, const char *str); 403void _efl_net_socket_udp_init(Eo *o, const struct sockaddr *addr, socklen_t addrlen, const char *str);
404 404
405Eina_Bool efl_net_ip_port_fmt(char *buf, int buflen, const struct sockaddr *addr); 405Eina_Bool efl_net_unix_fmt(char *buf, size_t buflen, SOCKET fd, const struct sockaddr_un *addr, socklen_t addrlen);
406Eina_Bool efl_net_ip_port_fmt(char *buf, size_t buflen, const struct sockaddr *addr);
406 407
407/** 408/**
408 * @brief splits an address in the format "host:port" in two 409 * @brief splits an address in the format "host:port" in two
diff --git a/src/lib/ecore_con/efl_net_dialer_unix.c b/src/lib/ecore_con/efl_net_dialer_unix.c
new file mode 100644
index 0000000000..d5ead1ba5c
--- /dev/null
+++ b/src/lib/ecore_con/efl_net_dialer_unix.c
@@ -0,0 +1,236 @@
1#define EFL_NET_DIALER_UNIX_PROTECTED 1
2#define EFL_NET_DIALER_PROTECTED 1
3#define EFL_NET_SOCKET_FD_PROTECTED 1
4#define EFL_NET_SOCKET_PROTECTED 1
5#define EFL_IO_READER_PROTECTED 1
6
7#ifdef HAVE_CONFIG_H
8# include <config.h>
9#endif
10
11#include "Ecore.h"
12#include "Ecore_Con.h"
13#include "ecore_con_private.h"
14
15#ifdef HAVE_SYS_SOCKET_H
16# include <sys/socket.h>
17#endif
18#ifdef HAVE_SYS_UN_H
19#include <sys/un.h>
20#endif
21
22#define MY_CLASS EFL_NET_DIALER_UNIX_CLASS
23
24typedef struct _Efl_Net_Dialer_Unix_Data
25{
26 struct {
27 Ecore_Thread *thread;
28 Efl_Future *timeout;
29 } connect;
30 Efl_Future *connect_job;
31 Eina_Stringshare *address_dial;
32 Eina_Bool connected;
33 double timeout_dial;
34} Efl_Net_Dialer_Unix_Data;
35
36EOLIAN static Eo*
37_efl_net_dialer_unix_efl_object_constructor(Eo *o, Efl_Net_Dialer_Unix_Data *pd EINA_UNUSED)
38{
39 o = efl_constructor(efl_super(o, MY_CLASS));
40 if (!o) return NULL;
41
42 efl_net_dialer_timeout_dial_set(o, 30.0);
43 return o;
44}
45
46EOLIAN static void
47_efl_net_dialer_unix_efl_object_destructor(Eo *o, Efl_Net_Dialer_Unix_Data *pd)
48{
49 if (efl_io_closer_close_on_destructor_get(o) &&
50 (!efl_io_closer_closed_get(o)))
51 efl_io_closer_close(o);
52
53 if (pd->connect.thread)
54 {
55 ecore_thread_cancel(pd->connect.thread);
56 pd->connect.thread = NULL;
57 }
58
59 efl_destructor(efl_super(o, MY_CLASS));
60
61 eina_stringshare_replace(&pd->address_dial, NULL);
62}
63
64static void
65_efl_net_dialer_unix_connect_timeout(void *data, const Efl_Event *ev EINA_UNUSED)
66{
67 Eo *o = data;
68 Efl_Net_Dialer_Unix_Data *pd = efl_data_scope_get(o, MY_CLASS);
69 Eina_Error err = ETIMEDOUT;
70
71 if (pd->connect.thread)
72 {
73 ecore_thread_cancel(pd->connect.thread);
74 pd->connect.thread = NULL;
75 }
76
77 efl_ref(o);
78 efl_io_reader_eos_set(o, EINA_TRUE);
79 efl_event_callback_call(o, EFL_NET_DIALER_EVENT_ERROR, &err);
80 efl_unref(o);
81}
82
83static void
84_efl_net_dialer_unix_connected(void *data, const struct sockaddr *addr, socklen_t addrlen EINA_UNUSED, int sockfd, Eina_Error err)
85{
86 Eo *o = data;
87 Efl_Net_Dialer_Unix_Data *pd = efl_data_scope_get(o, MY_CLASS);
88
89 pd->connect.thread = NULL;
90
91 efl_ref(o); /* we're emitting callbacks then continuing the workflow */
92
93 if (err) goto error;
94
95 efl_net_socket_fd_family_set(o, addr->sa_family);
96 efl_loop_fd_set(o, sockfd);
97 if (efl_net_socket_address_remote_get(o))
98 {
99 efl_event_callback_call(o, EFL_NET_DIALER_EVENT_RESOLVED, NULL);
100 efl_net_dialer_connected_set(o, EINA_TRUE);
101 }
102 else
103 {
104 err = EFL_NET_DIALER_ERROR_COULDNT_CONNECT;
105 efl_loop_fd_set(o, INVALID_SOCKET);
106 closesocket(sockfd);
107 goto error;
108 }
109
110 error:
111 if (err)
112 {
113 efl_io_reader_eos_set(o, EINA_TRUE);
114 efl_event_callback_call(o, EFL_NET_DIALER_EVENT_ERROR, &err);
115 }
116
117 efl_unref(o);
118}
119
120EOLIAN static Eina_Error
121_efl_net_dialer_unix_efl_net_dialer_dial(Eo *o, Efl_Net_Dialer_Unix_Data *pd EINA_UNUSED, const char *address)
122{
123 struct sockaddr_un addr = { .sun_family = AF_UNIX };
124 socklen_t addrlen;
125
126 EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL);
127 EINA_SAFETY_ON_TRUE_RETURN_VAL(address[0] == '\0', EINVAL);
128 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_net_dialer_connected_get(o), EISCONN);
129 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(o), EBADF);
130 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_loop_fd_get(o) >= 0, EALREADY);
131
132 if (pd->connect.thread)
133 {
134 ecore_thread_cancel(pd->connect.thread);
135 pd->connect.thread = NULL;
136 }
137
138 if (strncmp(address, "abstract:", strlen("abstract:")) == 0)
139 {
140 const char *path = address + strlen("abstract:");
141 if (strlen(path) + 2 > sizeof(addr.sun_path))
142 {
143 ERR("abstract path is too long: %s", path);
144 return EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST;
145 }
146 addr.sun_path[0] = '\0';
147 memcpy(addr.sun_path + 1, path, strlen(path) + 1);
148 addrlen = strlen(path) + 2 + offsetof(struct sockaddr_un, sun_path);
149 }
150 else
151 {
152 const char *path = address;
153 if (strlen(path) + 1 > sizeof(addr.sun_path))
154 {
155 ERR("path is too long: %s", path);
156 return EFL_NET_DIALER_ERROR_COULDNT_RESOLVE_HOST;
157 }
158 memcpy(addr.sun_path, path, strlen(path) + 1);
159 addrlen = strlen(path) + 1 + offsetof(struct sockaddr_un, sun_path);
160 }
161
162 pd->connect.thread = efl_net_connect_async_new((const struct sockaddr *)&addr, addrlen, SOCK_STREAM, 0,
163 efl_io_closer_close_on_exec_get(o),
164 _efl_net_dialer_unix_connected, o);
165 EINA_SAFETY_ON_NULL_RETURN_VAL(pd->connect.thread, EINVAL);
166
167 efl_net_dialer_address_dial_set(o, address);
168
169 if (pd->connect.timeout)
170 efl_future_cancel(pd->connect.timeout);
171 if (pd->timeout_dial > 0.0)
172 {
173 efl_future_use(&pd->connect.timeout, efl_loop_timeout(efl_loop_get(o), pd->timeout_dial, o));
174 efl_future_then(pd->connect.timeout, _efl_net_dialer_unix_connect_timeout, NULL, NULL, o);
175 efl_future_link(o, pd->connect.timeout);
176 }
177
178 return 0;
179}
180
181EOLIAN static void
182_efl_net_dialer_unix_efl_net_dialer_address_dial_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Unix_Data *pd, const char *address)
183{
184 eina_stringshare_replace(&pd->address_dial, address);
185}
186
187EOLIAN static const char *
188_efl_net_dialer_unix_efl_net_dialer_address_dial_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Unix_Data *pd)
189{
190 return pd->address_dial;
191}
192
193EOLIAN static void
194_efl_net_dialer_unix_efl_net_dialer_timeout_dial_set(Eo *o EINA_UNUSED, Efl_Net_Dialer_Unix_Data *pd, double seconds)
195{
196 pd->timeout_dial = seconds;
197 if (pd->connect.timeout)
198 efl_future_cancel(pd->connect.timeout);
199
200 if ((pd->timeout_dial > 0.0) && (pd->connect.thread))
201 {
202 efl_future_use(&pd->connect.timeout, efl_loop_timeout(efl_loop_get(o), pd->timeout_dial, o));
203 efl_future_then(pd->connect.timeout, _efl_net_dialer_unix_connect_timeout, NULL, NULL, o);
204 }
205}
206
207EOLIAN static double
208_efl_net_dialer_unix_efl_net_dialer_timeout_dial_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Unix_Data *pd)
209{
210 return pd->timeout_dial;
211}
212
213EOLIAN static void
214_efl_net_dialer_unix_efl_net_dialer_connected_set(Eo *o, Efl_Net_Dialer_Unix_Data *pd, Eina_Bool connected)
215{
216 if (pd->connect.timeout)
217 efl_future_cancel(pd->connect.timeout);
218 if (pd->connected == connected) return;
219 pd->connected = connected;
220 if (connected) efl_event_callback_call(o, EFL_NET_DIALER_EVENT_CONNECTED, NULL);
221}
222
223EOLIAN static Eina_Bool
224_efl_net_dialer_unix_efl_net_dialer_connected_get(Eo *o EINA_UNUSED, Efl_Net_Dialer_Unix_Data *pd)
225{
226 return pd->connected;
227}
228
229EOLIAN static Eina_Error
230_efl_net_dialer_unix_efl_io_closer_close(Eo *o, Efl_Net_Dialer_Unix_Data *pd EINA_UNUSED)
231{
232 efl_net_dialer_connected_set(o, EINA_FALSE);
233 return efl_io_closer_close(efl_super(o, MY_CLASS));
234}
235
236#include "efl_net_dialer_unix.eo.c"
diff --git a/src/lib/ecore_con/efl_net_dialer_unix.eo b/src/lib/ecore_con/efl_net_dialer_unix.eo
new file mode 100644
index 0000000000..1169dc6d0a
--- /dev/null
+++ b/src/lib/ecore_con/efl_net_dialer_unix.eo
@@ -0,0 +1,22 @@
1class Efl.Net.Dialer.Unix (Efl.Net.Socket.Unix, Efl.Net.Dialer) {
2 [[Connects to a local AF_UNIX server.
3
4 The dial address is a file system path (portable) or
5 "abstract:ID" (Linux-only extension).
6
7 \@note Proxies are meaningless for AF_UNIX family, thus are not
8 implemented.
9
10 @since 1.19
11 ]]
12
13 implements {
14 Efl.Object.constructor;
15 Efl.Object.destructor;
16 Efl.Net.Dialer.dial;
17 Efl.Net.Dialer.address_dial;
18 Efl.Net.Dialer.connected;
19 Efl.Net.Dialer.timeout_dial;
20 Efl.Io.Closer.close;
21 }
22}
diff --git a/src/lib/ecore_con/efl_net_server_unix.c b/src/lib/ecore_con/efl_net_server_unix.c
new file mode 100644
index 0000000000..845df44259
--- /dev/null
+++ b/src/lib/ecore_con/efl_net_server_unix.c
@@ -0,0 +1,259 @@
1#define EFL_NET_SERVER_UNIX_PROTECTED 1
2#define EFL_NET_SERVER_FD_PROTECTED 1
3#define EFL_NET_SERVER_PROTECTED 1
4#define EFL_LOOP_FD_PROTECTED 1
5
6#ifdef HAVE_CONFIG_H
7# include <config.h>
8#endif
9
10#include "Ecore.h"
11#include "Ecore_Con.h"
12#include "ecore_con_private.h"
13
14#ifdef HAVE_SYS_SOCKET_H
15# include <sys/socket.h>
16#endif
17#ifdef HAVE_SYS_UN_H
18#include <sys/un.h>
19#endif
20
21/* no include EVIL as it's not supposed to be compiled on Windows */
22
23#define MY_CLASS EFL_NET_SERVER_UNIX_CLASS
24
25typedef struct _Efl_Net_Server_Unix_Data
26{
27 Efl_Future *bind_job;
28 Eina_Bool unlink_before_bind;
29} Efl_Net_Server_Unix_Data;
30
31EOLIAN static void
32_efl_net_server_unix_efl_object_destructor(Eo *o, Efl_Net_Server_Unix_Data *pd EINA_UNUSED)
33{
34 SOCKET fd = efl_loop_fd_get(o);
35
36 if (fd != INVALID_SOCKET)
37 {
38 const char *address = efl_net_server_address_get(o);
39 if ((address) && (strncmp(address, "abstract:", strlen("abstract:")) != 0))
40 unlink(address);
41 }
42
43 efl_destructor(efl_super(o, MY_CLASS));
44}
45
46static void
47_efl_net_server_unix_bind_job(void *data, const Efl_Event *event EINA_UNUSED)
48{
49 Eo *o = data;
50 Efl_Net_Server_Unix_Data *pd = efl_data_scope_get(o, MY_CLASS);
51 const char *address = efl_net_server_address_get(o);
52 struct sockaddr_un addr = { .sun_family = AF_UNIX };
53 socklen_t addrlen;
54 SOCKET fd;
55 Eina_Error err = 0;
56 int r;
57
58 pd->bind_job = NULL;
59
60 efl_ref(o); /* we're emitting callbacks then continuing the workflow */
61
62 efl_net_server_fd_family_set(o, AF_UNIX);
63
64 do
65 {
66 fd = efl_net_socket4(AF_UNIX, SOCK_STREAM, 0,
67 efl_net_server_fd_close_on_exec_get(o));
68 if (fd == INVALID_SOCKET)
69 {
70 err = efl_net_socket_error_get();
71 ERR("socket(AF_UNIX, SOCK_STREAM, 0): %s", eina_error_msg_get(err));
72 goto error;
73 }
74
75 if (strncmp(address, "abstract:", strlen("abstract:")) == 0)
76 {
77 const char *path = address + strlen("abstract:");
78 if (strlen(path) + 2 > sizeof(addr.sun_path))
79 {
80 ERR("abstract path is too long: %s", path);
81 err = EFL_NET_SERVER_ERROR_COULDNT_RESOLVE_HOST;
82 }
83 addr.sun_path[0] = '\0';
84 memcpy(addr.sun_path + 1, path, strlen(path) + 1);
85 addrlen = strlen(path) + 2 + offsetof(struct sockaddr_un, sun_path);
86 }
87 else
88 {
89 const char *path = address;
90 if (strlen(path) + 1 > sizeof(addr.sun_path))
91 {
92 ERR("path is too long: %s", path);
93 err = EFL_NET_SERVER_ERROR_COULDNT_RESOLVE_HOST;
94 }
95 memcpy(addr.sun_path, path, strlen(path) + 1);
96 addrlen = strlen(path) + 1 + offsetof(struct sockaddr_un, sun_path);
97 }
98
99 if ((pd->unlink_before_bind) && (addr.sun_path[0] != '\0'))
100 {
101 DBG("unlinking AF_UNIX path '%s'", addr.sun_path);
102 unlink(addr.sun_path);
103 }
104
105 r = bind(fd, (struct sockaddr *)&addr, addrlen);
106 if (r != 0)
107 {
108 err = efl_net_socket_error_get();
109 if ((err == EADDRINUSE) && (pd->unlink_before_bind) && (addr.sun_path[0] != '\0'))
110 {
111 closesocket(fd);
112 err = 0;
113 continue;
114 }
115 DBG("bind(%d, %s): %s", fd, address, eina_error_msg_get(err));
116 goto error;
117 }
118 break;
119 }
120 while (pd->unlink_before_bind);
121
122 efl_loop_fd_set(o, fd);
123
124 r = listen(fd, 0);
125 if (r != 0)
126 {
127 err = efl_net_socket_error_get();
128 DBG("listen(%d): %s", fd, eina_error_msg_get(err));
129 goto error;
130 }
131
132 addrlen = sizeof(addr);
133 if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) != 0)
134 {
135 err = efl_net_socket_error_get();
136 ERR("getsockname(%d): %s", fd, eina_error_msg_get(err));
137 goto error;
138 }
139 else
140 {
141 char str[sizeof(addr) + sizeof("abstract:")];
142 if (!efl_net_unix_fmt(str, sizeof(str), fd, &addr, addrlen))
143 ERR("could not format unix address");
144 else
145 {
146 efl_net_server_address_set(o, str);
147 address = efl_net_server_address_get(o);
148 }
149 }
150
151 DBG("fd=%d serving at %s", fd, address);
152 efl_net_server_serving_set(o, EINA_TRUE);
153
154 error:
155 if (err)
156 {
157 efl_event_callback_call(o, EFL_NET_SERVER_EVENT_ERROR, &err);
158 if (fd) closesocket(fd);
159 efl_loop_fd_set(o, INVALID_SOCKET);
160 }
161
162 efl_unref(o);
163}
164
165EOLIAN static Eina_Error
166_efl_net_server_unix_efl_net_server_serve(Eo *o, Efl_Net_Server_Unix_Data *pd, const char *address)
167{
168 EINA_SAFETY_ON_NULL_RETURN_VAL(address, EINVAL);
169 EINA_SAFETY_ON_TRUE_RETURN_VAL(address[0] == '\0', EINVAL);
170
171 efl_net_server_address_set(o, address);
172
173 if (pd->bind_job)
174 efl_future_cancel(pd->bind_job);
175
176 efl_future_use(&pd->bind_job, efl_loop_job(efl_loop_get(o), o));
177 efl_future_then(pd->bind_job, _efl_net_server_unix_bind_job, NULL, NULL, o);
178 efl_future_link(o, pd->bind_job);
179
180 return 0;
181}
182
183static Efl_Callback_Array_Item *_efl_net_server_unix_client_cbs(void);
184
185static void
186_efl_net_server_unix_client_event_closed(void *data, const Efl_Event *event)
187{
188 Eo *server = data;
189 Eo *client = event->object;
190
191 efl_event_callback_array_del(client, _efl_net_server_unix_client_cbs(), server);
192 if (efl_parent_get(client) == server)
193 efl_parent_set(client, NULL);
194
195 efl_net_server_clients_count_set(server, efl_net_server_clients_count_get(server) - 1);
196}
197
198EFL_CALLBACKS_ARRAY_DEFINE(_efl_net_server_unix_client_cbs,
199 { EFL_IO_CLOSER_EVENT_CLOSED, _efl_net_server_unix_client_event_closed });
200
201static void
202_efl_net_server_unix_efl_net_server_fd_client_add(Eo *o, Efl_Net_Server_Unix_Data *pd EINA_UNUSED, int client_fd)
203{
204 Eo *client = efl_add(EFL_NET_SOCKET_UNIX_CLASS, o,
205 efl_event_callback_array_add(efl_added, _efl_net_server_unix_client_cbs(), o),
206 efl_io_closer_close_on_exec_set(efl_added, efl_net_server_fd_close_on_exec_get(o)),
207 efl_io_closer_close_on_destructor_set(efl_added, EINA_TRUE),
208 efl_loop_fd_set(efl_added, client_fd));
209 if (!client)
210 {
211 ERR("could not create client object fd=%d", client_fd);
212 closesocket(client_fd);
213 return;
214 }
215
216 efl_net_server_clients_count_set(o, efl_net_server_clients_count_get(o) + 1);
217 efl_event_callback_call(o, EFL_NET_SERVER_EVENT_CLIENT_ADD, client);
218
219 if (efl_ref_get(client) == 1) /* users must take a reference themselves */
220 {
221 DBG("client %s was not handled, closing it...",
222 efl_net_socket_address_remote_get(client));
223 efl_del(client);
224 }
225}
226
227static void
228_efl_net_server_unix_efl_net_server_fd_client_reject(Eo *o, Efl_Net_Server_Unix_Data *pd EINA_UNUSED, int client_fd)
229{
230 struct sockaddr_un addr;
231 socklen_t addrlen;
232 char str[sizeof(addr) + sizeof("abstract:")] = "";
233
234 addrlen = sizeof(addr);
235 if (getpeername(client_fd, (struct sockaddr *)&addr, &addrlen) != 0)
236 ERR("getpeername(%d): %s", client_fd, eina_error_msg_get(efl_net_socket_error_get()));
237 else
238 {
239 if (!efl_net_unix_fmt(str, sizeof(str), client_fd, &addr, addrlen))
240 ERR("could not format rejected client unix address fd=%d", client_fd);
241 }
242
243 closesocket(client_fd);
244 efl_event_callback_call(o, EFL_NET_SERVER_EVENT_CLIENT_REJECTED, str);
245}
246
247static void
248_efl_net_server_unix_unlink_before_bind_set(Eo *o EINA_UNUSED, Efl_Net_Server_Unix_Data *pd, Eina_Bool unlink_before_bind)
249{
250 pd->unlink_before_bind = unlink_before_bind;
251}
252
253static Eina_Bool
254_efl_net_server_unix_unlink_before_bind_get(Eo *o EINA_UNUSED, Efl_Net_Server_Unix_Data *pd)
255{
256 return pd->unlink_before_bind;
257}
258
259#include "efl_net_server_unix.eo.c"
diff --git a/src/lib/ecore_con/efl_net_server_unix.eo b/src/lib/ecore_con/efl_net_server_unix.eo
new file mode 100644
index 0000000000..c068a1d8ac
--- /dev/null
+++ b/src/lib/ecore_con/efl_net_server_unix.eo
@@ -0,0 +1,28 @@
1class Efl.Net.Server.Unix (Efl.Net.Server.Fd) {
2 [[An AF_UNIX server.
3
4 @since 1.19
5 ]]
6
7 methods {
8 @property unlink_before_bind {
9 [[AF_UNIX paths may be stale due crashes, remove files and try again.
10
11 If this property is $true, then it will unlink() before
12 bind() is done, repeating this process if EADDRINUSE.
13
14 By default it's false and you will get EADDRINUSE.
15 ]]
16 values {
17 unlink_before_bind: bool; [[if $true, server will unlink() the path before bind() is called.]]
18 }
19 }
20 }
21
22 implements {
23 Efl.Object.destructor;
24 Efl.Net.Server.serve;
25 Efl.Net.Server.Fd.client_add;
26 Efl.Net.Server.Fd.client_reject;
27 }
28}
diff --git a/src/lib/ecore_con/efl_net_socket_unix.c b/src/lib/ecore_con/efl_net_socket_unix.c
new file mode 100644
index 0000000000..2647a4e020
--- /dev/null
+++ b/src/lib/ecore_con/efl_net_socket_unix.c
@@ -0,0 +1,77 @@
1#define EFL_NET_SOCKET_UNIX_PROTECTED 1
2#define EFL_NET_SOCKET_FD_PROTECTED 1
3#define EFL_LOOP_FD_PROTECTED 1
4#define EFL_IO_READER_FD_PROTECTED 1
5#define EFL_IO_WRITER_FD_PROTECTED 1
6#define EFL_IO_CLOSER_FD_PROTECTED 1
7#define EFL_IO_READER_PROTECTED 1
8#define EFL_IO_WRITER_PROTECTED 1
9#define EFL_IO_CLOSER_PROTECTED 1
10#define EFL_NET_SOCKET_PROTECTED 1
11
12#ifdef HAVE_CONFIG_H
13# include <config.h>
14#endif
15
16#include "Ecore.h"
17#include "Ecore_Con.h"
18#include "ecore_con_private.h"
19
20#ifdef HAVE_SYS_SOCKET_H
21# include <sys/socket.h>
22#endif
23#ifdef HAVE_SYS_UN_H
24#include <sys/un.h>
25#endif
26
27/* no include EVIL as it's not supposed to be compiled on Windows */
28
29#define MY_CLASS EFL_NET_SOCKET_UNIX_CLASS
30
31typedef struct _Efl_Net_Socket_Unix_Data
32{
33} Efl_Net_Socket_Unix_Data;
34
35EOLIAN static void
36_efl_net_socket_unix_efl_loop_fd_fd_set(Eo *o, Efl_Net_Socket_Unix_Data *pd EINA_UNUSED, int fd)
37{
38 efl_loop_fd_set(efl_super(o, MY_CLASS), fd);
39
40 if (fd != INVALID_SOCKET)
41 {
42 struct sockaddr_un addr;
43 socklen_t addrlen;
44 int family;
45
46 family = efl_net_socket_fd_family_get(o);
47 if (family == AF_UNSPEC) return;
48 EINA_SAFETY_ON_TRUE_RETURN(family != AF_UNIX);
49
50 addrlen = sizeof(addr);
51 if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) != 0)
52 ERR("getsockname(%d): %s", fd, eina_error_msg_get(efl_net_socket_error_get()));
53 else
54 {
55 char str[sizeof(addr) + sizeof("abstract:")];
56
57 if (!efl_net_unix_fmt(str, sizeof(str), fd, &addr, addrlen))
58 ERR("could not format local unix address");
59 else
60 efl_net_socket_address_local_set(o, str);
61 }
62
63 addrlen = sizeof(addr);
64 if (getpeername(fd, (struct sockaddr *)&addr, &addrlen) != 0)
65 ERR("getpeername(%d): %s", fd, eina_error_msg_get(efl_net_socket_error_get()));
66 else
67 {
68 char str[sizeof(addr) + sizeof("abstract:")];
69 if (!efl_net_unix_fmt(str, sizeof(str), fd, &addr, addrlen))
70 ERR("could not format remote unix address");
71 else
72 efl_net_socket_address_remote_set(o, str);
73 }
74 }
75}
76
77#include "efl_net_socket_unix.eo.c"
diff --git a/src/lib/ecore_con/efl_net_socket_unix.eo b/src/lib/ecore_con/efl_net_socket_unix.eo
new file mode 100644
index 0000000000..48ea4cdcac
--- /dev/null
+++ b/src/lib/ecore_con/efl_net_socket_unix.eo
@@ -0,0 +1,13 @@
1class Efl.Net.Socket.Unix (Efl.Net.Socket.Fd) {
2 [[A base UNIX socket.
3
4 This is the common class and takes an existing FD, usually
5 created by an dialer or server.
6
7 @since 1.19
8 ]]
9
10 implements {
11 Efl.Loop.Fd.fd.set;
12 }
13}