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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								src/polyp.c
									
										
									
									
									
								
							
							
						
						
									
										61
									
								
								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,11 +360,34 @@ 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))) {
 | 
					    
 | 
				
			||||||
 | 
					    if (*server == '/') {
 | 
				
			||||||
 | 
					        if (!(c->client = pa_socket_client_new_unix(c->mainloop, server))) {
 | 
				
			||||||
            c->error = PA_ERROR_CONNECTIONREFUSED;
 | 
					            c->error = PA_ERROR_CONNECTIONREFUSED;
 | 
				
			||||||
            return -1;
 | 
					            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;
 | 
				
			||||||
    c->connect_complete_userdata = userdata;
 | 
					    c->connect_complete_userdata = userdata;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -166,6 +166,33 @@ fail:
 | 
				
			||||||
    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