mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-03 09:01:50 -05:00
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:
parent
e83b7106ac
commit
1416fef197
6 changed files with 100 additions and 10 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
65
src/polyp.c
65
src/polyp.c
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
7
src/todo
7
src/todo
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue