add gcd version, less bits on pipe, run socket in non-blocking mode
This commit is contained in:
234
lib/ipc/server.c
234
lib/ipc/server.c
@@ -43,8 +43,6 @@ struct heim_sipc {
|
|||||||
void *mech;
|
void *mech;
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef HAVE_GCD
|
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(HAVE_GCD)
|
#if defined(__APPLE__) && defined(HAVE_GCD)
|
||||||
|
|
||||||
#include "heim_ipcServer.h"
|
#include "heim_ipcServer.h"
|
||||||
@@ -55,6 +53,8 @@ static dispatch_source_t timer;
|
|||||||
static dispatch_queue_t timerq;
|
static dispatch_queue_t timerq;
|
||||||
static uint64_t timeoutvalue;
|
static uint64_t timeoutvalue;
|
||||||
|
|
||||||
|
static dispatch_queue_t eventq;
|
||||||
|
|
||||||
static dispatch_queue_t workq;
|
static dispatch_queue_t workq;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -84,6 +84,7 @@ init_globals(void)
|
|||||||
dispatch_source_set_event_handler(timer, ^{ timer_ev(); } );
|
dispatch_source_set_event_handler(timer, ^{ timer_ev(); } );
|
||||||
|
|
||||||
workq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
workq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||||
|
eventq = dispatch_queue_create("heim-ipc.event-queue", NULL);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +456,10 @@ struct client {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifndef HAVE_GCD
|
#ifndef HAVE_GCD
|
||||||
|
|
||||||
static unsigned num_clients = 0;
|
static unsigned num_clients = 0;
|
||||||
static struct client **clients = NULL;
|
static struct client **clients = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static struct client *
|
static struct client *
|
||||||
add_new_socket(int fd,
|
add_new_socket(int fd,
|
||||||
@@ -466,6 +468,7 @@ add_new_socket(int fd,
|
|||||||
void *userctx)
|
void *userctx)
|
||||||
{
|
{
|
||||||
struct client *c;
|
struct client *c;
|
||||||
|
int one = 1;
|
||||||
|
|
||||||
c = calloc(1, sizeof(*c));
|
c = calloc(1, sizeof(*c));
|
||||||
if (c == NULL)
|
if (c == NULL)
|
||||||
@@ -481,9 +484,13 @@ add_new_socket(int fd,
|
|||||||
c->callback = callback;
|
c->callback = callback;
|
||||||
c->userctx = userctx;
|
c->userctx = userctx;
|
||||||
|
|
||||||
|
(void)ioctl(c->fd, FIONBIO, (void *)&one);
|
||||||
|
|
||||||
|
#ifndef HAVE_GCD
|
||||||
clients = erealloc(clients, sizeof(clients[0]) * (num_clients + 1));
|
clients = erealloc(clients, sizeof(clients[0]) * (num_clients + 1));
|
||||||
clients[num_clients] = c;
|
clients[num_clients] = c;
|
||||||
num_clients++;
|
num_clients++;
|
||||||
|
#endif
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -532,8 +539,96 @@ socket_complete(heim_sipc_call ctx, int returnvalue, heim_idata *reply)
|
|||||||
sc->c = NULL; /* so we can catch double complete */
|
sc->c = NULL; /* so we can catch double complete */
|
||||||
free(sc);
|
free(sc);
|
||||||
|
|
||||||
|
if (c->calls == 0 && (c->flags & WAITING_CLOSE)) {
|
||||||
|
close(c->fd);
|
||||||
|
free(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_read(struct client *c)
|
||||||
|
{
|
||||||
|
ssize_t len;
|
||||||
|
uint32_t dlen;
|
||||||
|
|
||||||
|
if (c->flags & LISTEN_SOCKET) {
|
||||||
|
add_new_socket(c->fd,
|
||||||
|
WAITING_READ,
|
||||||
|
c->callback,
|
||||||
|
c->userctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->ptr - c->len < 1024) {
|
||||||
|
c->inmsg = erealloc(c->inmsg,
|
||||||
|
c->len + 1024);
|
||||||
|
c->len += 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = read(c->fd, c->inmsg + c->ptr, c->len - c->ptr);
|
||||||
|
if (len <= 0) {
|
||||||
|
c->flags |= WAITING_CLOSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c->ptr += len;
|
||||||
|
if (c->ptr > c->len)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
while (c->ptr >= sizeof(dlen)) {
|
||||||
|
struct socket_call *cs;
|
||||||
|
|
||||||
|
memcpy(&dlen, c->inmsg, sizeof(dlen));
|
||||||
|
dlen = ntohl(dlen);
|
||||||
|
|
||||||
|
if (dlen < c->ptr - sizeof(dlen))
|
||||||
|
break;
|
||||||
|
|
||||||
|
cs = emalloc(sizeof(*cs));
|
||||||
|
cs->c = c;
|
||||||
|
cs->in.data = emalloc(dlen);
|
||||||
|
memcpy(cs->in.data, c->inmsg + sizeof(dlen), dlen);
|
||||||
|
cs->in.length = dlen;
|
||||||
|
|
||||||
|
c->ptr -= sizeof(dlen) + dlen;
|
||||||
|
memmove(c->inmsg,
|
||||||
|
c->inmsg + sizeof(dlen) + dlen,
|
||||||
|
c->ptr);
|
||||||
|
|
||||||
|
c->calls++;
|
||||||
|
c->callback(c->userctx, &cs->in,
|
||||||
|
NULL, socket_complete,
|
||||||
|
(heim_sipc_call)cs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_write(struct client *c)
|
||||||
|
{
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
len = write(c->fd, c->outmsg, c->olen);
|
||||||
|
if (len <= 0) {
|
||||||
|
c->flags |= WAITING_CLOSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c->olen != len) {
|
||||||
|
memmove(&c->outmsg[0], &c->outmsg[len], c->olen - len);
|
||||||
|
c->olen -= len;
|
||||||
|
} else {
|
||||||
|
c->olen = 0;
|
||||||
|
free(c->outmsg);
|
||||||
|
c->outmsg = NULL;
|
||||||
|
|
||||||
|
c->flags &= WAITING_WRITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_GCD
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_loop(void)
|
process_loop(void)
|
||||||
{
|
{
|
||||||
@@ -570,104 +665,33 @@ process_loop(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fds[n].revents & POLLIN) {
|
if (fds[n].revents & POLLIN)
|
||||||
ssize_t len;
|
handle_read(clients[n]);
|
||||||
uint32_t dlen;
|
if (fds[n].revents & POLLOUT)
|
||||||
|
handle_write(clients[n]);
|
||||||
if (clients[n]->flags & LISTEN_SOCKET) {
|
|
||||||
add_new_socket(clients[n]->fd,
|
|
||||||
WAITING_READ,
|
|
||||||
clients[n]->callback,
|
|
||||||
clients[n]->userctx);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clients[n]->ptr - clients[n]->len < 1024) {
|
|
||||||
clients[n]->inmsg = erealloc(clients[n]->inmsg,
|
|
||||||
clients[n]->len + 1024);
|
|
||||||
clients[n]->len += 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = read(clients[n]->fd,
|
|
||||||
clients[n]->inmsg + clients[n]->ptr,
|
|
||||||
clients[n]->len - clients[n]->ptr);
|
|
||||||
if (len <= 0) {
|
|
||||||
clients[n]->flags |= WAITING_CLOSE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
clients[n]->ptr += len;
|
|
||||||
if (clients[n]->ptr > clients[n]->len)
|
|
||||||
abort();
|
|
||||||
|
|
||||||
while (clients[n]->ptr >= sizeof(dlen)) {
|
|
||||||
struct socket_call *cs;
|
|
||||||
|
|
||||||
memcpy(&dlen, clients[n]->inmsg, sizeof(dlen));
|
|
||||||
dlen = ntohl(dlen);
|
|
||||||
|
|
||||||
if (dlen < clients[n]->ptr - sizeof(dlen))
|
|
||||||
break;
|
|
||||||
|
|
||||||
cs = emalloc(sizeof(*cs));
|
|
||||||
cs->c = clients[n];
|
|
||||||
cs->in.data = emalloc(dlen);
|
|
||||||
memcpy(cs->in.data, clients[n]->inmsg + sizeof(dlen), dlen);
|
|
||||||
cs->in.length = dlen;
|
|
||||||
|
|
||||||
clients[n]->ptr -= sizeof(dlen) + dlen;
|
|
||||||
memmove(clients[n]->inmsg,
|
|
||||||
clients[n]->inmsg + sizeof(dlen) + dlen,
|
|
||||||
clients[n]->ptr);
|
|
||||||
|
|
||||||
clients[n]->calls++;
|
|
||||||
clients[n]->callback(clients[n]->userctx, &cs->in,
|
|
||||||
NULL, socket_complete,
|
|
||||||
(heim_sipc_call)cs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fds[n].revents & POLLOUT) {
|
|
||||||
ssize_t len;
|
|
||||||
|
|
||||||
len = write(clients[n]->fd,
|
|
||||||
clients[n]->outmsg,
|
|
||||||
clients[n]->olen);
|
|
||||||
if (len <= 0) {
|
|
||||||
clients[n]->flags |= WAITING_CLOSE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (clients[n]->olen != len) {
|
|
||||||
memmove(&clients[n]->outmsg[0],
|
|
||||||
&clients[n]->outmsg[len],
|
|
||||||
clients[n]->olen - len);
|
|
||||||
clients[n]->olen -= len;
|
|
||||||
} else {
|
|
||||||
clients[n]->olen = 0;
|
|
||||||
free(clients[n]->outmsg);
|
|
||||||
clients[n]->outmsg = NULL;
|
|
||||||
|
|
||||||
clients[n]->flags &= WAITING_WRITE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
while (n < num_clients) {
|
while (n < num_clients) {
|
||||||
struct client *c = clients[n];
|
struct client *c = clients[n];
|
||||||
if ((c->flags & WAITING_CLOSE) == 0 || c->calls) {
|
if ((c->flags & WAITING_CLOSE) == 0) {
|
||||||
n++;
|
n++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
close(c->fd);
|
if (c->calls == 0) {
|
||||||
free(c);
|
close(c->fd);
|
||||||
|
free(c);
|
||||||
|
}
|
||||||
clients[n] = clients[num_clients - 1];
|
clients[n] = clients[num_clients - 1];
|
||||||
num_clients--;
|
num_clients--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
free(fds);
|
free(fds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
socket_release(heim_sipc ctx)
|
socket_release(heim_sipc ctx)
|
||||||
{
|
{
|
||||||
@@ -676,25 +700,43 @@ socket_release(heim_sipc ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int
|
int
|
||||||
heim_sipc_launchd_stream_fd_init(int fd,
|
heim_sipc_launchd_stream_fd_init(int fd,
|
||||||
heim_ipc_callback callback,
|
heim_ipc_callback callback,
|
||||||
void *user, heim_sipc *ctx)
|
void *user, heim_sipc *ctx)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_GCD
|
|
||||||
heim_sipc ct = calloc(1, sizeof(*ct));
|
heim_sipc ct = calloc(1, sizeof(*ct));
|
||||||
|
struct client *c;
|
||||||
ct->mech = add_new_socket(fd, LISTEN_SOCKET|WAITING_READ, callback, user);
|
|
||||||
|
c = add_new_socket(fd, LISTEN_SOCKET|WAITING_READ, callback, user);
|
||||||
|
|
||||||
|
#ifndef HAVE_GCD
|
||||||
|
#else
|
||||||
|
dispatch_source_t in, out;
|
||||||
|
|
||||||
|
init_globals();
|
||||||
|
|
||||||
|
in = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, eventq);
|
||||||
|
out = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, eventq);
|
||||||
|
|
||||||
|
dispatch_source_set_event_handler(in, ^{
|
||||||
|
int rw = (c->flags & WAITING_WRITE);
|
||||||
|
handle_read(c);
|
||||||
|
if (rw == 0 && (c->flags & WAITING_WRITE))
|
||||||
|
dispatch_resume(out);
|
||||||
|
});
|
||||||
|
dispatch_source_set_event_handler(out, ^{
|
||||||
|
handle_write(c);
|
||||||
|
if ((c->flags & WAITING_WRITE) == 0)
|
||||||
|
dispatch_suspend(out);
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch_resume(in);
|
||||||
|
#endif
|
||||||
|
ct->mech = c;
|
||||||
ct->release = socket_release;
|
ct->release = socket_release;
|
||||||
*ctx = ct;
|
*ctx = ct;
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
|
||||||
close(fd);
|
|
||||||
*ctx = NULL;
|
|
||||||
return EINVAL;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -734,7 +776,7 @@ heim_sipc_service_unix(const char *service,
|
|||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
chmod(un.sun_path, 0777);
|
chmod(un.sun_path, 0666);
|
||||||
|
|
||||||
return heim_sipc_launchd_stream_fd_init(fd, callback, user, ctx);
|
return heim_sipc_launchd_stream_fd_init(fd, callback, user, ctx);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user