2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
16 #ifdef HAVE_SYS_SOCKET_H
17 # include <sys/socket.h>
24 #ifdef HAVE_WS2TCPIP_H
25 # include <ws2tcpip.h>
33 #include <ecore_private.h>
35 #include "Ecore_Con.h"
36 #include "ecore_con_private.h"
39 #define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
40 #define LENGTH_OF_ABSTRACT_SOCKADDR_UN(s, path) (strlen(path) + 1 + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
43 static int _ecore_con_local_init_count = 0;
46 ecore_con_local_init(void)
48 if (++_ecore_con_local_init_count != 1)
49 return _ecore_con_local_init_count;
51 return _ecore_con_local_init_count;
55 ecore_con_local_shutdown(void)
57 if (--_ecore_con_local_init_count != 0)
58 return _ecore_con_local_init_count;
60 return _ecore_con_local_init_count;
64 ecore_con_local_connect(Ecore_Con_Server *svr,
65 int (*cb_done)(void *data, Ecore_Fd_Handler *fd_handler),
66 void *data __UNUSED__,
67 void (*cb_free)(void *data, void *ev))
70 struct sockaddr_un socket_unix;
75 if (svr->type == ECORE_CON_LOCAL_USER)
77 homedir = getenv("HOME");
78 if (!homedir) homedir = getenv("TMP");
79 if (!homedir) homedir = "/tmp";
80 snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", homedir, svr->name, svr->port);
82 else if (svr->type == ECORE_CON_LOCAL_SYSTEM)
86 if (svr->name[0] == '/')
87 strncpy(buf, svr->name, sizeof(buf));
89 snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s", svr->name);
93 if (svr->name[0] == '/')
94 snprintf(buf, sizeof(buf), "%s|%i", svr->name, svr->port);
96 snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s|%i", svr->name, svr->port);
99 else if (svr->type == ECORE_CON_LOCAL_ABSTRACT)
100 strncpy(buf, svr->name, sizeof(buf));
102 svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
103 if (svr->fd < 0) return 0;
104 if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) return 0;
105 if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) return 0;
106 if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)) < 0) return 0;
107 socket_unix.sun_family = AF_UNIX;
109 if (svr->type == ECORE_CON_LOCAL_ABSTRACT)
111 #ifdef HAVE_ABSTRACT_SOCKETS
112 /* copy name insto sun_path, prefixed by null to indicate abstract namespace */
113 snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s", svr->name);
114 socket_unix.sun_path[0] = '\0';
115 socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix, svr->name);
117 WRN("Your system does not support abstract sockets!");
123 strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
124 socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
127 if (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
129 svr->path = strdup(buf);
130 if (!svr->path) return 0;
132 if (svr->type & ECORE_CON_SSL)
133 ecore_con_ssl_server_init(svr);
136 ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
137 cb_done, svr, NULL, NULL);
138 if (!svr->fd_handler) return 0;
142 /* we got our server! */
143 Ecore_Con_Event_Server_Add *e;
145 e = calloc(1, sizeof(Ecore_Con_Event_Server_Add));
150 ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, e,
159 ecore_con_local_listen(Ecore_Con_Server *svr,
160 int (*cb_listen)(void *data, Ecore_Fd_Handler *fd_handler),
161 void *data __UNUSED__)
164 struct sockaddr_un socket_unix;
172 mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
174 if (svr->type == ECORE_CON_LOCAL_USER)
176 homedir = getenv("HOME");
177 if (!homedir) homedir = getenv("TMP");
178 if (!homedir) homedir = "/tmp";
179 mask = S_IRUSR | S_IWUSR | S_IXUSR;
180 snprintf(buf, sizeof(buf), "%s/.ecore", homedir);
181 if (stat(buf, &st) < 0) mkdir(buf, mask);
182 snprintf(buf, sizeof(buf), "%s/.ecore/%s", homedir, svr->name);
183 if (stat(buf, &st) < 0) mkdir(buf, mask);
184 snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", homedir, svr->name, svr->port);
185 mask = S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
187 else if (svr->type == ECORE_CON_LOCAL_SYSTEM)
190 if (svr->name[0] == '/')
193 snprintf(buf, sizeof(buf), "%s|%i", svr->name, svr->port);
195 snprintf(buf, sizeof(buf), "%s", svr->name);
198 snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s|%i", svr->name, svr->port);
200 else if (svr->type == ECORE_CON_LOCAL_ABSTRACT)
201 strncpy(buf, svr->name, sizeof(buf));
204 svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
205 if (svr->fd < 0) goto error_umask;
206 if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error_umask;
207 if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error_umask;
210 if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, (const void *)&lin, sizeof(struct linger)) < 0) goto error_umask;
211 socket_unix.sun_family = AF_UNIX;
212 if (svr->type == ECORE_CON_LOCAL_ABSTRACT)
214 #ifdef HAVE_ABSTRACT_SOCKETS
215 /* . is a placeholder */
216 snprintf(socket_unix.sun_path, sizeof(socket_unix.sun_path), ".%s", svr->name);
217 /* first char null indicates abstract namespace */
218 socket_unix.sun_path[0] = '\0';
219 socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix, svr->name);
221 ERR("Your system does not support abstract sockets!");
227 strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
228 socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
230 if (bind(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
232 if (((svr->type == ECORE_CON_LOCAL_USER) || (svr->type == ECORE_CON_LOCAL_SYSTEM)) &&
233 (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) &&
239 if (listen(svr->fd, 4096) < 0) goto error_umask;
240 svr->path = strdup(buf);
241 if (!svr->path) goto error_umask;
243 ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
244 cb_listen, svr, NULL, NULL);
246 if (!svr->fd_handler) goto error;