summaryrefslogtreecommitdiffstats
path: root/polyp/socket-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'polyp/socket-client.c')
-rw-r--r--polyp/socket-client.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/polyp/socket-client.c b/polyp/socket-client.c
index dffbfe7d..3852c1ad 100644
--- a/polyp/socket-client.c
+++ b/polyp/socket-client.c
@@ -39,6 +39,7 @@
#include "xmalloc.h"
struct pa_socket_client {
+ int ref;
struct pa_mainloop_api *mainloop;
int fd;
struct pa_io_event *io_event;
@@ -52,6 +53,7 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) {
assert(m);
c = pa_xmalloc(sizeof(struct pa_socket_client));
+ c->ref = 1;
c->mainloop = m;
c->fd = -1;
c->io_event = NULL;
@@ -62,38 +64,40 @@ static struct pa_socket_client*pa_socket_client_new(struct pa_mainloop_api *m) {
}
static void do_call(struct pa_socket_client *c) {
- struct pa_iochannel *io;
+ struct pa_iochannel *io = NULL;
int error, lerror;
assert(c && c->callback);
+ pa_socket_client_ref(c);
+
lerror = sizeof(error);
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &error, &lerror) < 0) {
fprintf(stderr, "getsockopt(): %s\n", strerror(errno));
- goto failed;
+ goto finish;
}
if (lerror != sizeof(error)) {
fprintf(stderr, "getsocktop() returned invalid size.\n");
- goto failed;
+ goto finish;
}
if (error != 0) {
fprintf(stderr, "connect(): %s\n", strerror(error));
- goto failed;
+ goto finish;
}
io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
assert(io);
+
+finish:
+ if (!io)
+ close(c->fd);
c->fd = -1;
+
+ assert(c->callback);
c->callback(c, io, c->userdata);
-
- return;
-failed:
- close(c->fd);
- c->fd = -1;
- c->callback(c, NULL, c->userdata);
- return;
+ pa_socket_client_unref(c);
}
static void connect_fixed_cb(struct pa_mainloop_api *m, struct pa_defer_event *e, void *userdata) {
@@ -159,7 +163,7 @@ struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, ui
return c;
fail:
- pa_socket_client_free(c);
+ pa_socket_client_unref(c);
return NULL;
}
@@ -188,7 +192,7 @@ struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, co
return c;
fail:
- pa_socket_client_free(c);
+ pa_socket_client_unref(c);
return NULL;
}
@@ -214,12 +218,12 @@ struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m
return c;
fail:
- pa_socket_client_free(c);
+ pa_socket_client_unref(c);
return NULL;
}
-void pa_socket_client_free(struct pa_socket_client *c) {
+void socket_client_free(struct pa_socket_client *c) {
assert(c && c->mainloop);
if (c->io_event)
c->mainloop->io_free(c->io_event);
@@ -230,6 +234,19 @@ void pa_socket_client_free(struct pa_socket_client *c) {
pa_xfree(c);
}
+void pa_socket_client_unref(struct pa_socket_client *c) {
+ assert(c && c->ref >= 1);
+
+ if (!(--(c->ref)))
+ socket_client_free(c);
+}
+
+struct pa_socket_client* pa_socket_client_ref(struct pa_socket_client *c) {
+ assert(c && c->ref >= 1);
+ c->ref++;
+ return c;
+}
+
void pa_socket_client_set_callback(struct pa_socket_client *c, void (*on_connection)(struct pa_socket_client *c, struct pa_iochannel*io, void *userdata), void *userdata) {
assert(c);
c->callback = on_connection;