# include <winsock2.h>
#endif
-static void _ecore_con_cb_dns_lookup(void *data, struct hostent *he);
-static void _ecore_con_cb_udp_dns_lookup(void *data, struct hostent *he);
+static void _ecore_con_cb_tcp_connect(void *data, Ecore_Con_Info *info);
+static void _ecore_con_cb_udp_connect(void *data, Ecore_Con_Info *info);
+static void _ecore_con_cb_tcp_listen(void *data, Ecore_Con_Info *info);
+static void _ecore_con_cb_udp_listen(void *data, Ecore_Con_Info *info);
+
static void _ecore_con_server_free(Ecore_Con_Server *svr);
static void _ecore_con_client_free(Ecore_Con_Client *cl);
+
static int _ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler);
static int _ecore_con_cl_handler(void *data, Ecore_Fd_Handler *fd_handler);
static int _ecore_con_cl_udp_handler(void *data, Ecore_Fd_Handler *fd_handler);
-static int _ecore_con_mcast_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_svr_udp_handler(void *data, Ecore_Fd_Handler *fd_handler);
static int _ecore_con_svr_cl_handler(void *data, Ecore_Fd_Handler *fd_handler);
+
static void _ecore_con_server_flush(Ecore_Con_Server *svr);
static void _ecore_con_client_flush(Ecore_Con_Client *cl);
+
static void _ecore_con_event_client_add_free(void *data, void *ev);
static void _ecore_con_event_client_del_free(void *data, void *ev);
static void _ecore_con_event_client_data_free(void *data, void *ev);
static Ecore_List *servers = NULL;
static int init_count = 0;
+
#if USE_OPENSSL
static int ssl_init_count = 0;
+static int _ecore_con_init_ssl(Ecore_Con_Server *svr);
+static int _ecore_con_shutdown_ssl(Ecore_Con_Server *svr);
+static int _ecore_con_free_ssl(Ecore_Con_Server *svr);
+
+# define INIT_SSL(svr) _ecore_con_init_ssl(svr)
+# define SHUTDOWN_SSL(svr) _ecore_con_shutdown_ssl(svr)
+# define FREE_SSL(svr) _ecore_con_free_ssl(svr)
+# define UNSET_SSL(svr) \
+ do { \
+ svr->ssl = NULL; \
+ svr->ssl_ctx = NULL; \
+ } while (0)
+#else
+# define INIT_SSL(svr) 0
+# define SHUTDOWN_SSL(svr) 0
+# define FREE_SSL(svr) 0
+# define UNSET_SSL(svr) 0
#endif
#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
/* TODO Remember return value, if it fails, use gethostbyname() */
ecore_con_dns_init();
+ ecore_con_info_init();
servers = ecore_list_new();
ecore_list_destroy(servers);
servers = NULL;
+ ecore_con_info_shutdown();
ecore_con_dns_shutdown();
ecore_shutdown();
Ecore_Con_Type type;
struct sockaddr_in socket_addr;
struct sockaddr_un socket_unix;
- struct ip_mreq mreq;
struct linger lin;
char buf[4096];
- const int on=1;
+ mode_t pmode;
if (port < 0) return NULL;
/* local user socket: FILE: ~/.ecore/[name]/[port] */
svr = calloc(1, sizeof(Ecore_Con_Server));
if (!svr) return NULL;
- type = compl_type;
-#if USE_OPENSSL
- /* unset the SSL flag for the following checks */
- type &= ECORE_CON_TYPE;
-#endif
+ svr->name = strdup(name);
+ if (!svr->name) goto error;
+ svr->type = compl_type;
+ svr->port = port;
+ svr->data = (void *)data;
+ svr->created = 1;
+ svr->reject_excess_clients = 0;
+ svr->client_limit = -1;
+ svr->clients = ecore_list_new();
+ svr->ppid = getpid();
+ /* Set ssl and ssl_ctx fields to NULL */
+ UNSET_SSL(svr);
+
+ type = compl_type & ECORE_CON_TYPE;
if ((type == ECORE_CON_LOCAL_USER) || (type == ECORE_CON_LOCAL_SYSTEM) ||
(type == ECORE_CON_LOCAL_ABSTRACT))
{
const char *homedir;
struct stat st;
- mode_t pmode, mask;
+ mode_t mask;
int socket_unix_len;
if (!name) goto error;
pmode = umask(mask);
start:
svr->fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (svr->fd < 0)
- {
- umask(pmode);
- goto error;
- }
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0)
- {
- umask(pmode);
- goto error;
- }
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0)
- {
- umask(pmode);
- goto error;
- }
+ if (svr->fd < 0) goto error_umask;
+ if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error_umask;
+ if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error_umask;
lin.l_onoff = 1;
lin.l_linger = 0;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0)
- {
- umask(pmode);
- goto error;
- }
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0) goto error_umask;
socket_unix.sun_family = AF_UNIX;
if (type == ECORE_CON_LOCAL_ABSTRACT)
{
socket_unix_len = LENGTH_OF_ABSTRACT_SOCKADDR_UN(&socket_unix, name);
#else
fprintf(stderr, "Your system does not support abstract sockets!\n");
- umask(pmode);
- goto error;
+ goto error_umask;
#endif
}
else
}
if (bind(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
{
- if (connect(svr->fd, (struct sockaddr *)&socket_unix,
- socket_unix_len) < 0)
- {
- if ((type == ECORE_CON_LOCAL_USER) ||
- (type == ECORE_CON_LOCAL_SYSTEM))
- {
- if (unlink(buf) < 0)
- {
- umask(pmode);
- goto error;
- }
- else
- goto start;
- }
- else
- {
- umask(pmode);
- goto error;
- }
- }
- else
- {
- umask(pmode);
- goto error;
- }
- }
- if (listen(svr->fd, 4096) < 0)
- {
- umask(pmode);
- goto error;
+ if ((type == ECORE_CON_LOCAL_USER) || (type == ECORE_CON_LOCAL_SYSTEM) &&
+ (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) &&
+ (unlink(buf) >= 0))
+ goto start;
+ else
+ goto error_umask;
}
+ if (listen(svr->fd, 4096) < 0) goto error_umask;
svr->path = strdup(buf);
- if (!svr->path)
- {
- umask(pmode);
- goto error;
- }
- svr->fd_handler =
+ if (!svr->path) goto error_umask;
+ svr->fd_handler =
ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
_ecore_con_svr_handler, svr, NULL, NULL);
umask(pmode);
if (!svr->fd_handler) goto error;
+
+ INIT_SSL(svr);
}
- else if (type == ECORE_CON_REMOTE_TCP)
- {
- svr->fd = socket(AF_INET, SOCK_STREAM, 0);
- if (svr->fd < 0) goto error;
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
- lin.l_onoff = 1;
- lin.l_linger = 0;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0) goto error;
- socket_addr.sin_family = AF_INET;
- socket_addr.sin_port = htons(port);
- socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- if (bind(svr->fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0) goto error;
- if (listen(svr->fd, 4096) < 0) goto error;
- svr->fd_handler =
- ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
- _ecore_con_svr_handler, svr, NULL, NULL);
- if (!svr->fd_handler) goto error;
- }
- else if (type == ECORE_CON_REMOTE_MCAST)
+
+ if (type == ECORE_CON_REMOTE_TCP)
{
- svr->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if(svr->fd < 0) goto error;
- mreq.imr_multiaddr.s_addr = inet_addr(name);
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,sizeof(mreq)) != 0) goto error;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &on,sizeof(on)) != 0) goto error;
- if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
- if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
- socket_addr.sin_family = AF_INET;
- socket_addr.sin_port = htons(port);
- socket_addr.sin_addr.s_addr = inet_addr(name);
- if (bind(svr->fd, (struct sockaddr *)&socket_addr,sizeof(struct sockaddr_in)) < 0) goto error;
- svr->fd_handler =
- ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
- _ecore_con_mcast_handler, svr, NULL, NULL);
- if (!svr->fd_handler) goto error;
+ /* TCP */
+ if (!ecore_con_info_tcp_listen(svr, _ecore_con_cb_tcp_listen, svr)) goto error;
}
-
-#if USE_OPENSSL
- if (compl_type & ECORE_CON_SSL)
+ else if (type == ECORE_CON_REMOTE_MCAST || type == ECORE_CON_REMOTE_UDP)
{
- if (!ssl_init_count)
- {
- SSL_library_init();
- SSL_load_error_strings();
- }
- ssl_init_count++;
-
- switch (compl_type & ECORE_CON_SSL)
- {
- case ECORE_CON_USE_SSL2:
- if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method())))
- goto error;
- break;
- case ECORE_CON_USE_SSL3:
- if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
- goto error;
- break;
- case ECORE_CON_USE_TLS:
- if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
- goto error;
- break;
- }
-
- if (!(svr->ssl = SSL_new(svr->ssl_ctx)))
- goto error;
-
- SSL_set_fd(svr->ssl, svr->fd);
+ /* UDP and MCAST */
+ if (!ecore_con_info_udp_listen(svr, _ecore_con_cb_udp_listen, svr)) goto error;
}
-#endif
- svr->name = strdup(name);
- if (!svr->name) goto error;
- svr->type = type;
- svr->port = port;
- svr->data = (void *)data;
- svr->created = 1;
- svr->reject_excess_clients = 0;
- svr->client_limit = -1;
- svr->clients = ecore_list_new();
- svr->ppid = getpid();
ecore_list_append(servers, svr);
ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
+
return svr;
+ error_umask:
+ umask(pmode);
error:
if (svr->name) free(svr->name);
if (svr->path) free(svr->path);
if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
if (svr->write_buf) free(svr->write_buf);
if (svr->ip) free(svr->ip);
-#if USE_OPENSSL
- if (svr->ssl) SSL_free(svr->ssl);
- if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
-#endif
+ FREE_SSL(svr);
free(svr);
return NULL;
}
svr = calloc(1, sizeof(Ecore_Con_Server));
if (!svr) return NULL;
- type = compl_type;
-#if USE_OPENSSL
- /* unset the SSL flag for the following checks */
- type &= ECORE_CON_TYPE;
-#endif
+ svr->name = strdup(name);
+ if (!svr->name) goto error;
+ svr->type = compl_type;
+ svr->port = port;
+ svr->data = (void *)data;
+ svr->created = 0;
+ svr->reject_excess_clients = 0;
+ svr->client_limit = -1;
+ svr->clients = ecore_list_new();
+ UNSET_SSL(svr);
+
+ type = compl_type & ECORE_CON_TYPE;
+
if ((type == ECORE_CON_REMOTE_TCP || type == ECORE_CON_REMOTE_UDP) && (port < 0)) return NULL;
if ((type == ECORE_CON_LOCAL_USER) || (type == ECORE_CON_LOCAL_SYSTEM) ||
socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
}
- if (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0) goto error;
+ if (connect(svr->fd, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
+ {
+ perror("connect()");
+ goto error;
+ }
svr->path = strdup(buf);
if (!svr->path) goto error;
- svr->fd_handler =
+ svr->fd_handler =
ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
_ecore_con_cl_handler, svr, NULL, NULL);
if (!svr->fd_handler) goto error;
}
}
- svr->name = strdup(name);
- if (!svr->name) goto error;
- svr->type = compl_type;
- svr->port = port;
- svr->data = (void *)data;
- svr->created = 0;
- svr->reject_excess_clients = 0;
- svr->client_limit = -1;
- svr->clients = ecore_list_new();
- ecore_list_append(servers, svr);
- ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
-
if (type == ECORE_CON_REMOTE_TCP)
{
- if (!ecore_con_dns_lookup(svr->name, _ecore_con_cb_dns_lookup, svr))
- goto error;
+ /* TCP */
+ if (!ecore_con_info_tcp_connect(svr, _ecore_con_cb_tcp_connect, svr)) goto error;
}
else if (type == ECORE_CON_REMOTE_UDP)
{
- if (!ecore_con_dns_lookup(svr->name, _ecore_con_cb_udp_dns_lookup, svr))
- goto error;
+ /* UDP and MCAST */
+ if (!ecore_con_info_udp_connect(svr, _ecore_con_cb_udp_connect, svr)) goto error;
}
+ ecore_list_append(servers, svr);
+ ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER);
+
return svr;
error:
if (svr->path) free(svr->path);
if (svr->fd >= 0) close(svr->fd);
if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler);
-#if USE_OPENSSL
- if (svr->ssl) SSL_free(svr->ssl);
- if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
-#endif
+ FREE_SSL(svr);
free(svr);
return NULL;
}
if (size < 1) return 0;
if (cl->fd_handler)
ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE);
- if (cl->buf)
+
+ if(cl->server && cl->server->type == ECORE_CON_REMOTE_UDP)
{
- unsigned char *newbuf;
+ sendto(cl->server->fd, data, size, 0, (struct sockaddr *) cl->data, sizeof(struct sockaddr_in));
+ }
+ else if (cl->buf)
+ {
+ unsigned char *newbuf;
- newbuf = realloc(cl->buf, cl->buf_size + size);
- if (newbuf) cl->buf = newbuf;
- else return 0;
- memcpy(cl->buf + cl->buf_size, data, size);
- cl->buf_size += size;
+ newbuf = realloc(cl->buf, cl->buf_size + size);
+ if (newbuf) cl->buf = newbuf;
+ else return 0;
+ memcpy(cl->buf + cl->buf_size, data, size);
+ cl->buf_size += size;
}
else
{
EAPI void *
ecore_con_client_del(Ecore_Con_Client *cl)
{
- void *data;
+ void *data = NULL;
if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT))
{
ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, "ecore_con_client_del");
return NULL;
}
- data = cl->data;
+
+ if(cl->data && cl->server && (cl->server->type == ECORE_CON_REMOTE_UDP ||
+ cl->server->type == ECORE_CON_REMOTE_MCAST))
+ free(cl->data);
+ else
+ data = cl->data;
+
cl->data = NULL;
cl->delete_me = 1;
if (cl->event_count > 0)
while (!ecore_list_empty_is(svr->clients))
_ecore_con_client_free(ecore_list_first_remove(svr->clients));
ecore_list_destroy(svr->clients);
- if ((svr->created) && (svr->path) && (svr->ppid == getpid()))
+ if ((svr->created) && (svr->path) && (svr->ppid == getpid()))
unlink(svr->path);
if (svr->fd >= 0) close(svr->fd);
-#if USE_OPENSSL
- if (svr->ssl)
- {
- SSL_shutdown(svr->ssl);
- SSL_free(svr->ssl);
- }
- if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
-#endif
+ SHUTDOWN_SSL(svr);
+ FREE_SSL(svr);
if (svr->name) free(svr->name);
if (svr->path) free(svr->path);
if (svr->ip) free(svr->ip);
fcntl(new_fd, F_SETFD, FD_CLOEXEC);
cl->fd = new_fd;
cl->server = svr;
- cl->fd_handler =
+ cl->fd_handler =
ecore_main_fd_handler_add(cl->fd, ECORE_FD_READ,
_ecore_con_svr_cl_handler, cl, NULL, NULL);
ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
}
static void
-_ecore_con_cb_dns_lookup(void *data, struct hostent *he)
+_ecore_con_cb_tcp_listen(void *data, Ecore_Con_Info *net_info)
+{
+ Ecore_Con_Server *svr;
+ struct linger lin;
+
+ svr = data;
+
+ if(!net_info) goto error;
+
+ svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol);
+ if (svr->fd < 0) goto error;
+ if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
+ if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
+ lin.l_onoff = 1;
+ lin.l_linger = 0;
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0) goto error;
+ if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) goto error;
+ if (listen(svr->fd, 4096) < 0) goto error;
+ svr->fd_handler =
+ ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
+ _ecore_con_svr_handler, svr, NULL, NULL);
+ if (!svr->fd_handler) goto error;
+
+ if (INIT_SSL(svr))
+ goto error;
+
+ return;
+
+ error:
+ FREE_SSL(svr);
+ kill_server(svr);
+}
+
+static void
+_ecore_con_cb_udp_listen(void *data, Ecore_Con_Info *net_info)
+{
+ Ecore_Con_Server *svr;
+ Ecore_Con_Type type;
+ struct ip_mreq mreq;
+ struct ipv6_mreq mreq6;
+ const int on = 1;
+
+ svr = data;
+ type = svr->type;
+ type &= ECORE_CON_TYPE;
+
+ if (!net_info) goto error;
+
+ svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol);
+ if(svr->fd < 0) goto error;
+
+ if (type == ECORE_CON_REMOTE_MCAST)
+ {
+ if (net_info->info.ai_family == AF_INET)
+ {
+ if (!inet_pton(net_info->info.ai_family, net_info->ip, &mreq.imr_multiaddr)) goto error;
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,sizeof(mreq)) != 0) goto error;
+ }
+ else if (net_info->info.ai_family == AF_INET6)
+ {
+ if (!inet_pton(net_info->info.ai_family, net_info->ip, &mreq6.ipv6mr_multiaddr)) goto error;
+ mreq6.ipv6mr_interface = htonl(INADDR_ANY);
+ if (setsockopt(svr->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq6,sizeof(mreq6)) != 0) goto error;
+ }
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &on,sizeof(on)) != 0) goto error;
+ }
+
+ if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
+ if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
+ if (bind(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0) goto error;
+ svr->fd_handler =
+ ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
+ _ecore_con_svr_udp_handler, svr, NULL, NULL);
+ if (!svr->fd_handler) goto error;
+ svr->ip = strdup(net_info->ip);
+
+ if (INIT_SSL(svr))
+ goto error;
+
+ return;
+
+ error:
+ FREE_SSL(svr);
+ kill_server(svr);
+}
+
+static void
+_ecore_con_cb_tcp_connect(void *data, Ecore_Con_Info *net_info)
{
Ecore_Con_Server *svr;
struct sockaddr_in socket_addr;
int curstate = 0;
char buf[64];
- uint32_t ip;
svr = data;
- if (!he) goto error;
- svr->fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (!net_info) goto error;
+ svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol);
if (svr->fd < 0) goto error;
if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0)
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0)
goto error;
- socket_addr.sin_family = AF_INET;
- socket_addr.sin_port = htons(svr->port);
- memcpy((struct in_addr *)&socket_addr.sin_addr,
- he->h_addr, sizeof(struct in_addr));
- if (connect(svr->fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0)
+ if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
{
if (errno != EINPROGRESS)
goto error;
svr->connecting = 1;
- svr->fd_handler =
+ svr->fd_handler =
ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
_ecore_con_cl_handler, svr, NULL, NULL);
}
else
- svr->fd_handler =
+ svr->fd_handler =
ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ,
_ecore_con_cl_handler, svr, NULL, NULL);
if (!svr->fd_handler) goto error;
- ip = socket_addr.sin_addr.s_addr;
- snprintf(buf, sizeof(buf),
- "%i.%i.%i.%i",
- (ip ) & 0xff,
- (ip >> 8 ) & 0xff,
- (ip >> 16) & 0xff,
- (ip >> 24) & 0xff);
- svr->ip = strdup(buf);
-
-#if USE_OPENSSL
- if (svr->type & ECORE_CON_SSL)
- {
- if (!ssl_init_count)
- {
- SSL_library_init();
- SSL_load_error_strings();
- }
- ssl_init_count++;
-
- switch (svr->type & ECORE_CON_SSL)
- {
- case ECORE_CON_USE_SSL2:
- if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method())))
- goto error;
- break;
- case ECORE_CON_USE_SSL3:
- if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
- goto error;
- break;
- case ECORE_CON_USE_TLS:
- if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
- goto error;
- break;
- }
+ svr->ip = strdup(net_info->ip);
- if (!(svr->ssl = SSL_new(svr->ssl_ctx)))
- goto error;
-
- SSL_set_fd(svr->ssl, svr->fd);
- }
-#endif
+ if (INIT_SSL(svr))
+ goto error;
return;
error:
+ FREE_SSL(svr);
kill_server(svr);
}
static void
-_ecore_con_cb_udp_dns_lookup(void *data, struct hostent *he)
+_ecore_con_cb_udp_connect(void *data, Ecore_Con_Info *net_info)
{
Ecore_Con_Server *svr;
struct sockaddr_in socket_addr;
int curstate = 0;
char buf[64];
- uint32_t ip;
svr = data;
- if (!he) goto error;
- svr->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (!net_info) goto error;
+ svr->fd = socket(net_info->info.ai_family, net_info->info.ai_socktype, net_info->info.ai_protocol);
if (svr->fd < 0) goto error;
if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error;
if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error;
- if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0)
+ if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0)
goto error;
- socket_addr.sin_family = AF_INET;
- socket_addr.sin_port = htons(svr->port);
- memcpy((struct in_addr *)&socket_addr.sin_addr,
- he->h_addr, sizeof(struct in_addr));
- if (connect(svr->fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0)
+ if (connect(svr->fd, net_info->info.ai_addr, net_info->info.ai_addrlen) < 0)
goto error;
else
- svr->fd_handler =
+ svr->fd_handler =
ecore_main_fd_handler_add(svr->fd, ECORE_FD_READ | ECORE_FD_WRITE,
_ecore_con_cl_udp_handler, svr, NULL, NULL);
-
if (!svr->fd_handler) goto error;
- ip = socket_addr.sin_addr.s_addr;
- snprintf(buf, sizeof(buf),
- "%i.%i.%i.%i",
- (ip ) & 0xff,
- (ip >> 8 ) & 0xff,
- (ip >> 16) & 0xff,
- (ip >> 24) & 0xff);
- svr->ip = strdup(buf);
+ svr->ip = strdup(net_info->ip);
+
+ if (INIT_SSL(svr))
+ goto error;
return;
error:
+ FREE_SSL(svr);
kill_server(svr);
}
{
unsigned char buf[65536];
int num = 0;
-
+
errno = 0;
num = read(svr->fd, buf, 65536);
if (num > 0)
}
else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE))
_ecore_con_server_flush(svr);
-
+
return 1;
}
static int
-_ecore_con_mcast_handler(void *data, Ecore_Fd_Handler *fd_handler)
+_ecore_con_svr_udp_handler(void *data, Ecore_Fd_Handler *fd_handler)
{
- Ecore_Con_Client *cl;
+ Ecore_Con_Server *svr;
+ Ecore_Con_Client *cl;
- cl = data;
- if (cl->dead) return 1;
- if (cl->delete_me) return 1;
+ svr = data;
+ if (svr->dead) return 1;
+ if (svr->delete_me) return 1;
if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
{
- unsigned char buf[65536];
- int num;
+ unsigned char buf[READBUFSIZ];
+ struct sockaddr_in client_addr;
+ int num, client_addr_len = sizeof(client_addr);
errno = 0;
- num = read(cl->fd, buf, 65536);
+ num = recvfrom(svr->fd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*) &client_addr, &client_addr_len);
+
if (num > 0)
{
- if (!cl->delete_me)
+ if (!svr->delete_me)
{
Ecore_Con_Event_Client_Data *e;
unsigned char *inbuf;
+ uint32_t ip;
+ char ipbuf[64];
+
+ /* Create a new client for use in the client data event */
+ cl = calloc(1, sizeof(Ecore_Con_Client));
+ if(cl == NULL)
+ return 1;
+ cl->buf = NULL;
+ cl->fd = 0;
+ cl->fd_handler = NULL;
+ cl->server = svr;
+ cl->data = calloc(1, sizeof(client_addr));
+ if(cl->data == NULL)
+ {
+ free(cl);
+ return 1;
+ }
+ memcpy(cl->data, &client_addr, sizeof(client_addr));
+ ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT);
+ ecore_list_append(svr->clients, cl);
+
+ ip = client_addr.sin_addr.s_addr;
+ snprintf(ipbuf, sizeof(ipbuf),
+ "%i.%i.%i.%i",
+ (ip ) & 0xff,
+ (ip >> 8 ) & 0xff,
+ (ip >> 16) & 0xff,
+ (ip >> 24) & 0xff);
+ cl->ip = strdup(ipbuf);
inbuf = malloc(num);
if(inbuf == NULL)
- return 1;
+ {
+ free(cl->data);
+ free(cl);
+ return 1;
+ }
+
memcpy(inbuf, buf, num);
-
+
e = calloc(1, sizeof(Ecore_Con_Event_Client_Data));
if (e)
{
- cl->event_count++;
+ svr->event_count++;
e->client = cl;
e->data = inbuf;
e->size = num;
_ecore_con_event_client_data_free,
NULL);
}
+
+ if(!cl->delete_me)
+ {
+ Ecore_Con_Event_Client_Add *add;
+
+ add = calloc(1, sizeof(Ecore_Con_Event_Client_Add));
+ if(add)
+ {
+ /*cl->event_count++;*/
+ add->client = cl;
+ ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, add,
+ _ecore_con_event_client_add_free, NULL);
+ }
+ }
}
if ((errno == EIO) || (errno == EBADF) ||
(errno == EPIPE) || (errno == EINVAL) ||
(errno == ENOSPC) || (num == 0)/* is num == 0 right? */)
{
- if (!cl->delete_me)
+ if (!svr->delete_me)
{
/* we lost our client! */
Ecore_Con_Event_Client_Del *e;
-
+
e = calloc(1, sizeof(Ecore_Con_Event_Client_Del));
if (e)
{
- cl->event_count++;
+ svr->event_count++;
e->client = cl;
ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e,
_ecore_con_event_client_del_free,
NULL);
}
}
- cl->dead = 1;
- if (cl->fd_handler)
- ecore_main_fd_handler_del(cl->fd_handler);
- cl->fd_handler = NULL;
+ svr->dead = 1;
+ if (svr->fd_handler)
+ ecore_main_fd_handler_del(svr->fd_handler);
+ svr->fd_handler = NULL;
}
}
}
if (!svr->write_buf) return;
/* check whether we need to write anything at all.
- * we must not write zero bytes with SSL_write() since it
- * causes undefined behaviour
- */
+ * we must not write zero bytes with SSL_write() since it
+ * causes undefined behaviour
+ */
if (svr->write_buf_size == svr->write_buf_offset)
return;
e = ev;
e->client->event_count--;
if (e->data) free(e->data);
- if ((e->client->event_count == 0) && (e->client->delete_me))
+ if ((e->client->event_count == 0) && (e->client->delete_me) ||
+ (e->client->server && (e->client->server->type == ECORE_CON_REMOTE_UDP ||
+ e->client->server->type == ECORE_CON_REMOTE_MCAST)))
ecore_con_client_del(e->client);
free(e);
}
ecore_con_server_del(e->server);
free(e);
}
+
+#if USE_OPENSSL
+
+static int
+_ecore_con_init_ssl(Ecore_Con_Server *svr)
+{
+ if (svr->type & ECORE_CON_SSL)
+ {
+ if (!ssl_init_count)
+ {
+ SSL_library_init();
+ SSL_load_error_strings();
+ }
+ ssl_init_count++;
+
+ switch (svr->type & ECORE_CON_SSL)
+ {
+ case ECORE_CON_USE_SSL2:
+ if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method())))
+ return 1;
+ break;
+ case ECORE_CON_USE_SSL3:
+ if (!(svr->ssl_ctx = SSL_CTX_new(SSLv3_client_method())))
+ return 1;
+ break;
+ case ECORE_CON_USE_TLS:
+ if (!(svr->ssl_ctx = SSL_CTX_new(TLSv1_client_method())))
+ return 1;
+ break;
+ }
+
+ if (!(svr->ssl = SSL_new(svr->ssl_ctx)))
+ return 1;
+
+ SSL_set_fd(svr->ssl, svr->fd);
+ }
+ return 0;
+}
+
+static int
+_ecore_con_shutdown_ssl(Ecore_Con_Server *svr)
+{
+ if (svr->ssl) SSL_shutdown(svr->ssl);
+ return 0;
+}
+
+static int
+_ecore_con_free_ssl(Ecore_Con_Server *svr)
+{
+ if (svr->ssl) SSL_free(svr->ssl);
+ if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx);
+ UNSET_SSL(svr);
+
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+/*
+ * getaddrinfo with callback
+ *
+ * man getaddrinfo
+ *
+ */
+#include "ecore_private.h"
+#include "Ecore.h"
+#include "ecore_con_private.h"
+
+#include <ctype.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+
+typedef struct _CB_Data CB_Data;
+
+struct _CB_Data
+{
+ Ecore_List2 __list_data;
+ Ecore_Con_Info_Cb cb_done;
+ void *data;
+ Ecore_Fd_Handler *fdh;
+ pid_t pid;
+ Ecore_Event_Handler *handler;
+ int fd2;
+};
+
+
+static void _ecore_con_info_readdata(CB_Data *cbdata);
+static void _ecore_con_info_slave_free(CB_Data *cbdata);
+static int _ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler);
+static int _ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event);
+
+static int info_init = 0;
+static Ecore_List2 *info_slaves = NULL;
+
+EAPI int
+ecore_con_info_init(void)
+{
+ info_init++;
+ return info_init;
+}
+
+EAPI int
+ecore_con_info_shutdown(void)
+{
+ info_init--;
+ if (info_init == 0)
+ {
+ while (info_slaves) _ecore_con_info_slave_free((CB_Data *)info_slaves);
+ }
+ return info_init;
+}
+
+int
+ecore_con_info_tcp_connect(Ecore_Con_Server *svr,
+ Ecore_Con_Info_Cb done_cb,
+ void *data)
+{
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+ hints.ai_addr = NULL;
+
+ return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_tcp_listen(Ecore_Con_Server *svr,
+ Ecore_Con_Info_Cb done_cb,
+ void *data)
+{
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+ hints.ai_addr = NULL;
+
+ return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_udp_connect(Ecore_Con_Server *svr,
+ Ecore_Con_Info_Cb done_cb,
+ void *data)
+{
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+ hints.ai_addr = NULL;
+
+ return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_udp_listen(Ecore_Con_Server *svr,
+ Ecore_Con_Info_Cb done_cb,
+ void *data)
+{
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+ hints.ai_addr = NULL;
+
+ return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+int
+ecore_con_info_mcast_listen(Ecore_Con_Server *svr,
+ Ecore_Con_Info_Cb done_cb,
+ void *data)
+{
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = 0;
+ hints.ai_protocol = IPPROTO_UDP;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+ hints.ai_addr = NULL;
+
+ return ecore_con_info_get(svr, done_cb, data, &hints);
+}
+
+EAPI int
+ecore_con_info_get(Ecore_Con_Server *svr,
+ Ecore_Con_Info_Cb done_cb,
+ void *data,
+ struct addrinfo *hints)
+{
+ CB_Data *cbdata;
+ int fd[2];
+
+ if (pipe(fd) < 0) return 0;
+ cbdata = calloc(1, sizeof(CB_Data));
+ if (!cbdata)
+ {
+ close(fd[0]);
+ close(fd[1]);
+ return 0;
+ }
+ cbdata->cb_done = done_cb;
+ cbdata->data = data;
+ cbdata->fd2 = fd[1];
+ if (!(cbdata->fdh = ecore_main_fd_handler_add(fd[0], ECORE_FD_READ,
+ _ecore_con_info_data_handler,
+ cbdata,
+ NULL, NULL)))
+ {
+ free(cbdata);
+ close(fd[0]);
+ close(fd[1]);
+ return 0;
+ }
+
+ if ((cbdata->pid = fork()) == 0)
+ {
+ Ecore_Con_Info container;
+ struct addrinfo *result;
+ char service[NI_MAXSERV];
+ char hbuf[NI_MAXHOST];
+ char sbuf[NI_MAXSERV];
+
+ /* FIXME with EINA */
+ snprintf(service, NI_MAXSERV, "%i", svr->port);
+ /* CHILD */
+ if (!getaddrinfo(svr->name, service, hints, &result) && result)
+ {
+ memcpy(&container.info, result, sizeof(struct addrinfo));
+ container.info.ai_canonname = NULL;
+ container.info.ai_next = NULL;
+ memcpy(&container.addr, result->ai_addr, sizeof(struct sockaddr));
+ memset(container.ip, 0, sizeof(container.ip));
+ memset(container.service, 0, sizeof(container.service));
+ if (!getnameinfo(&container.addr, container.info.ai_addrlen,
+ hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV))
+ {
+ memcpy(container.ip, hbuf, sizeof(container.ip));
+ memcpy(container.service, sbuf, sizeof(container.service));
+ }
+ write(fd[1], &container, sizeof(Ecore_Con_Info));
+ }
+ else
+ write(fd[1], "", 1);
+
+ close(fd[1]);
+# ifdef __USE_ISOC99
+ _Exit(0);
+# else
+ _exit(0);
+# endif
+ }
+ /* PARENT */
+ cbdata->handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _ecore_con_info_exit_handler, cbdata);
+ close(fd[1]);
+ if (!cbdata->handler)
+ {
+ ecore_main_fd_handler_del(cbdata->fdh);
+ free(cbdata);
+ close(fd[0]);
+ return 0;
+ }
+ info_slaves = _ecore_list2_append(info_slaves, cbdata);
+ return 1;
+}
+
+static void
+_ecore_con_info_readdata(CB_Data *cbdata)
+{
+ Ecore_Con_Info container;
+ ssize_t size;
+
+ size = read(ecore_main_fd_handler_fd_get(cbdata->fdh), &container,
+ sizeof(Ecore_Con_Info));
+ if (size == sizeof(Ecore_Con_Info))
+ {
+ container.info.ai_addr = &container.addr;
+ cbdata->cb_done(cbdata->data, &container);
+ }
+ else
+ cbdata->cb_done(cbdata->data, NULL);
+ cbdata->cb_done = NULL;
+}
+
+static void
+_ecore_con_info_slave_free(CB_Data *cbdata)
+{
+ info_slaves = _ecore_list2_remove(info_slaves, cbdata);
+ close(ecore_main_fd_handler_fd_get(cbdata->fdh));
+ ecore_main_fd_handler_del(cbdata->fdh);
+ ecore_event_handler_del(cbdata->handler);
+ free(cbdata);
+}
+
+static int
+_ecore_con_info_data_handler(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ CB_Data *cbdata;
+
+ cbdata = data;
+ if (cbdata->cb_done)
+ {
+ if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
+ _ecore_con_info_readdata(cbdata);
+ else
+ {
+ cbdata->cb_done(cbdata->data, NULL);
+ cbdata->cb_done = NULL;
+ }
+ }
+ _ecore_con_info_slave_free(cbdata);
+ return 0;
+}
+
+static int
+_ecore_con_info_exit_handler(void *data, int type __UNUSED__, void *event)
+{
+ CB_Data *cbdata;
+ Ecore_Exe_Event_Del *ev;
+
+ ev = event;
+ cbdata = data;
+ if (cbdata->pid != ev->pid) return 1;
+ return 0;
+ _ecore_con_info_slave_free(cbdata);
+ return 0;
+}