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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										65
									
								
								src/polyp.c
									
										
									
									
									
								
							
							
						
						
									
										65
									
								
								src/polyp.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@ enum {
 | 
			
		|||
    PA_ERROR_INTERNAL,
 | 
			
		||||
    PA_ERROR_CONNECTIONTERMINATED,
 | 
			
		||||
    PA_ERROR_KILLED,
 | 
			
		||||
    PA_ERROR_INVALIDSERVER,
 | 
			
		||||
    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) {
 | 
			
		||||
    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;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -166,6 +166,33 @@ fail:
 | 
			
		|||
    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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								src/todo
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue