implement client side TCP support
authorLennart Poettering <lennart@poettering.net>
Thu, 15 Jul 2004 00:16:27 +0000 (00:16 +0000)
committerLennart Poettering <lennart@poettering.net>
Thu, 15 Jul 2004 00:16:27 +0000 (00:16 +0000)
git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@67 fefdeb5f-60dc-0310-8127-8f9354f1896f

src/cli-command.c
src/polyp.c
src/protocol-native-spec.h
src/socket-client.c
src/socket-client.h
src/todo

index 06e0eb3..bf3ab0c 100644 (file)
@@ -193,9 +193,10 @@ static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct
         return -1;
     }
 
-    if (*verbose)
+    if (*verbose) {
         snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index);
-    pa_strbuf_puts(buf, txt);
+        pa_strbuf_puts(buf, txt);
+    }
     return 0;
 }
 
index fde0c68..75187d7 100644 (file)
@@ -2,6 +2,9 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
 
 #include "polyp.h"
 #include "protocol-native-spec.h"
@@ -21,6 +24,7 @@
 
 #define DEFAULT_TIMEOUT (5*60)
 #define DEFAULT_SERVER "/tmp/polypaudio/native"
+#define DEFAULT_PORT "4713"
 
 struct pa_context {
     char *name;
@@ -284,7 +288,7 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i
     struct pa_context *c = userdata;
     struct pa_tagstruct *t;
     uint32_t tag;
-    assert(client && io && c && c->state == CONTEXT_CONNECTING);
+    assert(client && c && c->state == CONTEXT_CONNECTING);
 
     pa_socket_client_free(client);
     c->client = NULL;
@@ -318,6 +322,36 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i
     c->state = CONTEXT_AUTHORIZING;
 }
 
+static struct sockaddr *resolve_server(const char *server, size_t *len) {
+    struct sockaddr *sa;
+    struct addrinfo hints, *result = NULL;
+    char *port;
+    assert(server && len);
+
+    if ((port = strrchr(server, ':')))
+        port++;
+    if (!port)
+        port = DEFAULT_PORT;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = PF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = 0;
+
+    if (getaddrinfo(server, port, &hints, &result) != 0)
+        return NULL;
+    assert(result);
+    
+    sa = malloc(*len = result->ai_addrlen);
+    assert(sa);
+    memcpy(sa, result->ai_addr, *len);
+
+    freeaddrinfo(result);
+    
+    return sa;
+    
+}
+
 int pa_context_connect(struct pa_context *c, const char *server, void (*complete) (struct pa_context*c, int success, void *userdata), void *userdata) {
     assert(c && c->state == CONTEXT_UNCONNECTED);
 
@@ -326,10 +360,33 @@ int pa_context_connect(struct pa_context *c, const char *server, void (*complete
         return -1;
     }
 
+    if (!server)
+        if (!(server = getenv("POLYP_SERVER")))
+            server = DEFAULT_SERVER;
+
     assert(!c->client);
-    if (!(c->client = pa_socket_client_new_unix(c->mainloop, server ? server : DEFAULT_SERVER))) {
-        c->error = PA_ERROR_CONNECTIONREFUSED;
-        return -1;
+    
+    if (*server == '/') {
+        if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
+            c->error = PA_ERROR_CONNECTIONREFUSED;
+            return -1;
+        }
+    } else {
+        struct sockaddr* sa;
+        size_t sa_len;
+
+        if (!(sa = resolve_server(server, &sa_len))) {
+            c->error = PA_ERROR_INVALIDSERVER;
+            return -1;
+        }
+
+        c->client = pa_socket_client_new_sockaddr(c->mainloop, sa, sa_len);
+        free(sa);
+
+        if (!c->client) {
+            c->error = PA_ERROR_CONNECTIONREFUSED;
+            return -1;
+        }
     }
 
     c->connect_complete_callback = complete;
index 5e67fe7..78dc06c 100644 (file)
@@ -35,6 +35,7 @@ enum {
     PA_ERROR_INTERNAL,
     PA_ERROR_CONNECTIONTERMINATED,
     PA_ERROR_KILLED,
+    PA_ERROR_INVALIDSERVER,
     PA_ERROR_MAX
 };
 
index 8b2bd38..b1e609a 100644 (file)
@@ -80,7 +80,7 @@ static void connect_fixed_cb(struct pa_mainloop_api *m, void *id, void *userdata
 
 static void connect_io_cb(struct pa_mainloop_api*m, void *id, int fd, enum pa_mainloop_api_io_events events, void *userdata) {
     struct pa_socket_client *c = userdata;
-    assert(m && c && c->io_source == id && fd >= 0 && events == PA_MAINLOOP_API_IO_EVENT_OUTPUT);
+    assert(m && c && c->io_source == id && fd >= 0);
     m->cancel_io(m, c->io_source);
     c->io_source = NULL;
     do_call(c);
@@ -93,7 +93,7 @@ static int do_connect(struct pa_socket_client *c, const struct sockaddr *sa, soc
     pa_make_nonblock_fd(c->fd);
     
     if ((r = connect(c->fd, sa, len)) < 0) {
-        if (r != EINPROGRESS) {
+        if (errno != EINPROGRESS) {
             fprintf(stderr, "connect(): %s\n", strerror(errno));
             return -1;
         }
@@ -165,7 +165,34 @@ fail:
     pa_socket_client_free(c);
     return NULL;
 }
+
+struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen) {
+    struct pa_socket_client *c;
+    assert(m && sa);
+    c = pa_socket_client_new(m);
+    assert(c);
+
+    if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) {
+        fprintf(stderr, "socket(): %s\n", strerror(errno));
+        goto fail;
+    }
+
+    if (sa->sa_family == AF_INET)
+        pa_socket_tcp_low_delay(c->fd);
+    else
+        pa_socket_low_delay(c->fd);
+
+    if (do_connect(c, sa, salen) < 0)
+        goto fail;
     
+    return c;
+
+fail:
+    pa_socket_client_free(c);
+    return NULL;
+    
+}
+
 void pa_socket_client_free(struct pa_socket_client *c) {
     assert(c && c->mainloop);
     if (c->io_source)
index 046cc3a..8575378 100644 (file)
@@ -11,6 +11,7 @@ struct pa_socket_client;
 
 struct pa_socket_client* pa_socket_client_new_ipv4(struct pa_mainloop_api *m, uint32_t address, uint16_t port);
 struct pa_socket_client* pa_socket_client_new_unix(struct pa_mainloop_api *m, const char *filename);
+struct pa_socket_client* pa_socket_client_new_sockaddr(struct pa_mainloop_api *m, const struct sockaddr *sa, size_t salen);
 
 void pa_socket_client_free(struct pa_socket_client *c);
 
index db007d9..2bec6f1 100644 (file)
--- a/src/todo
+++ b/src/todo
@@ -1,8 +1,10 @@
+- modargs memory leak
+
+- clean secure directory handling (with username)
+
 - native library/protocol:
        more functions (esp. latency)
 
-- daemonizing
-
 - prefix modules/libraries with pa_
 
 - xmms+esound latency testing
@@ -25,6 +27,7 @@
 - doxygen
 - make mcalign merge chunks
 - modinfo
+- daemonizing
 
 drivers:
 - libao