implement client side TCP support

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@67 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2004-07-15 00:16:27 +00:00
parent e83b7106ac
commit 1416fef197
6 changed files with 100 additions and 10 deletions

View file

@ -193,9 +193,10 @@ static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct
return -1; return -1;
} }
if (*verbose) if (*verbose) {
snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index); snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index);
pa_strbuf_puts(buf, txt); pa_strbuf_puts(buf, txt);
}
return 0; return 0;
} }

View file

@ -2,6 +2,9 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "polyp.h" #include "polyp.h"
#include "protocol-native-spec.h" #include "protocol-native-spec.h"
@ -21,6 +24,7 @@
#define DEFAULT_TIMEOUT (5*60) #define DEFAULT_TIMEOUT (5*60)
#define DEFAULT_SERVER "/tmp/polypaudio/native" #define DEFAULT_SERVER "/tmp/polypaudio/native"
#define DEFAULT_PORT "4713"
struct pa_context { struct pa_context {
char *name; 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_context *c = userdata;
struct pa_tagstruct *t; struct pa_tagstruct *t;
uint32_t tag; uint32_t tag;
assert(client && io && c && c->state == CONTEXT_CONNECTING); assert(client && c && c->state == CONTEXT_CONNECTING);
pa_socket_client_free(client); pa_socket_client_free(client);
c->client = NULL; c->client = NULL;
@ -318,6 +322,36 @@ static void on_connection(struct pa_socket_client *client, struct pa_iochannel*i
c->state = CONTEXT_AUTHORIZING; 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) { 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); 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; return -1;
} }
if (!server)
if (!(server = getenv("POLYP_SERVER")))
server = DEFAULT_SERVER;
assert(!c->client); assert(!c->client);
if (!(c->client = pa_socket_client_new_unix(c->mainloop, server ? server : DEFAULT_SERVER))) {
c->error = PA_ERROR_CONNECTIONREFUSED; if (*server == '/') {
return -1; 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; c->connect_complete_callback = complete;

View file

@ -35,6 +35,7 @@ enum {
PA_ERROR_INTERNAL, PA_ERROR_INTERNAL,
PA_ERROR_CONNECTIONTERMINATED, PA_ERROR_CONNECTIONTERMINATED,
PA_ERROR_KILLED, PA_ERROR_KILLED,
PA_ERROR_INVALIDSERVER,
PA_ERROR_MAX PA_ERROR_MAX
}; };

View 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) { 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; 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); m->cancel_io(m, c->io_source);
c->io_source = NULL; c->io_source = NULL;
do_call(c); 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); pa_make_nonblock_fd(c->fd);
if ((r = connect(c->fd, sa, len)) < 0) { if ((r = connect(c->fd, sa, len)) < 0) {
if (r != EINPROGRESS) { if (errno != EINPROGRESS) {
fprintf(stderr, "connect(): %s\n", strerror(errno)); fprintf(stderr, "connect(): %s\n", strerror(errno));
return -1; return -1;
} }
@ -165,7 +165,34 @@ fail:
pa_socket_client_free(c); pa_socket_client_free(c);
return NULL; 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) { void pa_socket_client_free(struct pa_socket_client *c) {
assert(c && c->mainloop); assert(c && c->mainloop);
if (c->io_source) if (c->io_source)

View 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_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_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); void pa_socket_client_free(struct pa_socket_client *c);

View file

@ -1,8 +1,10 @@
- modargs memory leak
- clean secure directory handling (with username)
- native library/protocol: - native library/protocol:
more functions (esp. latency) more functions (esp. latency)
- daemonizing
- prefix modules/libraries with pa_ - prefix modules/libraries with pa_
- xmms+esound latency testing - xmms+esound latency testing
@ -25,6 +27,7 @@
- doxygen - doxygen
- make mcalign merge chunks - make mcalign merge chunks
- modinfo - modinfo
- daemonizing
drivers: drivers:
- libao - libao