From: Mike Brady Date: Sun, 1 May 2016 21:37:57 +0000 (+0100) Subject: Add information about local ip address so we can send back connections to the client... X-Git-Tag: 2.8.3.2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5028cd1f9fc59f6f3d1e5ab7381773fa654a4606;p=thirdparty%2Fshairport-sync.git Add information about local ip address so we can send back connections to the client from the same ip number it used to contact us --- diff --git a/rtp.c b/rtp.c index 79aefa4b..501dc66d 100644 --- a/rtp.c +++ b/rtp.c @@ -59,7 +59,8 @@ typedef struct time_ping_record { static int running = 0; static char client_ip_string[INET6_ADDRSTRLEN]; // the ip string pointing to the client -static short client_ip_family; // AF_INET / AF_INET6 +static char self_ip_string[INET6_ADDRSTRLEN]; // the ip string being used by this program -- it could be one of many, so we need to know it +static short connection_ip_family; // AF_INET / AF_INET6 static uint32_t client_active_remote; // used when you want to control the client... static SOCKADDR rtp_client_control_socket; // a socket pointing to the control port of the client @@ -543,47 +544,27 @@ void *rtp_timing_receiver(void *arg) { return NULL; } -static int bind_port(SOCKADDR *remote, int *sock) { +static int bind_port(int ip_family,const char *self_ip_address, int *sock) { struct addrinfo hints, *info; memset(&hints, 0, sizeof(hints)); - hints.ai_family = remote->SAFAMILY; + hints.ai_family = ip_family; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; - char buffer[10]; + char buffer[20]; // look for a port in the range, if any was specified. int desired_port = config.udp_port_base; int ret; do { snprintf(buffer, 10, "%d", desired_port); - - ret = getaddrinfo(NULL, buffer, &hints, &info); - + ret = getaddrinfo(self_ip_address, buffer, &hints, &info); if (ret < 0) die("failed to get usable addrinfo?! %s.", gai_strerror(ret)); - - *sock = socket(remote->SAFAMILY, SOCK_DGRAM, IPPROTO_UDP); - -/* - // this doesn't compile properly with OpenWrt Barrier Breaker. - #if defined(__linux__) - #ifdef AF_INET6 - // now, if we are on IPv6, prefer a public ipv6 address - if (remote->SAFAMILY==AF_INET6) { - int value = IPV6_PREFER_SRC_PUBLIC; - ret = setsockopt(*sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &value, sizeof(value)); - if (ret<0) - die("error: could not select a preference for public IPv6 address"); - } - #endif - #endif -*/ + *sock = socket(ip_family, SOCK_DGRAM, IPPROTO_UDP); ret = bind(*sock, info->ai_addr, info->ai_addrlen); - freeaddrinfo(info); - } while ((ret<0) && (errno==EADDRINUSE) && (desired_port!=0) && (desired_port++ < config.udp_port_base+config.udp_port_range)); // debug(1,"UDP port chosen: %d.",desired_port); @@ -592,7 +573,6 @@ static int bind_port(SOCKADDR *remote, int *sock) { die("error: could not bind a UDP port!"); } - int sport; SOCKADDR local; socklen_t local_len = sizeof(local); @@ -611,8 +591,13 @@ static int bind_port(SOCKADDR *remote, int *sock) { return sport; } -void rtp_setup(SOCKADDR *remote, int cport, int tport, uint32_t active_remote, int *lsport, +void rtp_setup(SOCKADDR *local, SOCKADDR *remote, int cport, int tport, uint32_t active_remote, int *lsport, int *lcport, int *ltport) { + + // this gets the local and remote ip numbers (and ports used for the TCD stuff) + // we use the local stuff to specify the address we are coming from and + // we use the remote stuff to specify where we're goint to + if (running) die("rtp_setup called with active stream!"); @@ -621,28 +606,39 @@ void rtp_setup(SOCKADDR *remote, int cport, int tport, uint32_t active_remote, i client_active_remote = active_remote; // print out what we know about the client - void *addr; + void *client_addr,*self_addr; char *ipver; - int port; - char portstr[20]; - client_ip_family = remote->SAFAMILY; // keep information about the kind of ip of the client + int client_port,self_port; + char client_port_str[20]; + char self_addr_str[20]; + + connection_ip_family = remote->SAFAMILY; // keep information about the kind of ip of the client + #ifdef AF_INET6 - if (remote->SAFAMILY == AF_INET6) { - struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)remote; - addr = &(sa6->sin6_addr); - port = ntohs(sa6->sin6_port); + if (connection_ip_family == AF_INET6) { ipver = "IPv6"; + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)remote; + client_addr = &(sa6->sin6_addr); + client_port = ntohs(sa6->sin6_port); + sa6 = (struct sockaddr_in6 *)local; + self_addr = &(sa6->sin6_addr); + self_port = ntohs(sa6->sin6_port); } #endif - if (remote->SAFAMILY == AF_INET) { - struct sockaddr_in *sa4 = (struct sockaddr_in *)remote; - addr = &(sa4->sin_addr); - port = ntohs(sa4->sin_port); + if (connection_ip_family == AF_INET) { ipver = "IPv4"; + struct sockaddr_in *sa4 = (struct sockaddr_in *)remote; + client_addr = &(sa4->sin_addr); + client_port = ntohs(sa4->sin_port); + sa4 = (struct sockaddr_in *)local; + self_addr = &(sa4->sin_addr); + self_port = ntohs(sa4->sin_port); } - inet_ntop(remote->SAFAMILY, addr, client_ip_string, + inet_ntop(connection_ip_family, client_addr, client_ip_string, sizeof(client_ip_string)); // keep the client's ip number - debug(1, "Connection from %s: %s:%d", ipver, client_ip_string, port); + inet_ntop(connection_ip_family, self_addr, self_ip_string, + sizeof(self_ip_string)); // keep the client's ip number + debug(1, "Connection via %s from AirPlay client at: %s:%u to this Shairport Sync AirPlay server at: %s:%u.", ipver, client_ip_string, client_port,self_ip_string,self_port); // set up a the record of the remote's control socket struct addrinfo hints; @@ -650,8 +646,9 @@ void rtp_setup(SOCKADDR *remote, int cport, int tport, uint32_t active_remote, i memset(&rtp_client_control_socket, 0, sizeof(rtp_client_control_socket)); memset(&hints, 0, sizeof hints); - hints.ai_family = remote->SAFAMILY; + hints.ai_family = connection_ip_family; hints.ai_socktype = SOCK_DGRAM; + char portstr[20]; snprintf(portstr, 20, "%d", cport); if (getaddrinfo(client_ip_string, portstr, &hints, &servinfo) != 0) die("Can't get address of client's control port"); @@ -667,7 +664,7 @@ void rtp_setup(SOCKADDR *remote, int cport, int tport, uint32_t active_remote, i // set up a the record of the remote's timing socket memset(&rtp_client_timing_socket, 0, sizeof(rtp_client_timing_socket)); memset(&hints, 0, sizeof hints); - hints.ai_family = remote->SAFAMILY; + hints.ai_family = connection_ip_family; hints.ai_socktype = SOCK_DGRAM; snprintf(portstr, 20, "%d", tport); if (getaddrinfo(client_ip_string, portstr, &hints, &servinfo) != 0) @@ -683,9 +680,9 @@ void rtp_setup(SOCKADDR *remote, int cport, int tport, uint32_t active_remote, i // now, we open three sockets -- one for the audio stream, one for the timing and one for the // control - *lsport = bind_port(remote, &audio_socket); - *lcport = bind_port(remote, &control_socket); - *ltport = bind_port(remote, &timing_socket); + *lsport = bind_port(connection_ip_family,self_ip_string,&audio_socket); + *lcport = bind_port(connection_ip_family,self_ip_string,&control_socket); + *ltport = bind_port(connection_ip_family,self_ip_string,&timing_socket); debug(2, "listening for audio, control and timing on ports %d, %d, %d.", *lsport, *lcport, *ltport); diff --git a/rtsp.c b/rtsp.c index e8867042..f101affe 100644 --- a/rtsp.c +++ b/rtsp.c @@ -89,7 +89,7 @@ static pthread_mutex_t reference_counter_lock = PTHREAD_MUTEX_INITIALIZER; typedef struct { int fd; stream_cfg stream; - SOCKADDR remote; + SOCKADDR remote,local; int stop; int running; pthread_t thread; @@ -806,7 +806,7 @@ static void handle_setup(rtsp_conn_info *conn, rtsp_message *req, tport = atoi(p); // rtsp_take_player(); - rtp_setup(&conn->remote, cport, tport, active_remote, &lsport, &lcport, + rtp_setup(&conn->local, &conn->remote, cport, tport, active_remote, &lsport, &lcport, <port); if (!lsport) goto error; @@ -1904,12 +1904,46 @@ void rtsp_listen_loop(void) { memset(conn, 0, sizeof(rtsp_conn_info)); socklen_t slen = sizeof(conn->remote); - debug(1, "New RTSP connection on port %d", config.port); conn->fd = accept(acceptfd, (struct sockaddr *)&conn->remote, &slen); if (conn->fd < 0) { + debug(1, "New RTSP connection on port %d not accepted:", config.port); perror("failed to accept connection"); free(conn); } else { + SOCKADDR *local_info = (SOCKADDR*)&conn->local; + socklen_t size_of_reply = sizeof(*local_info); + memset(local_info,0,sizeof(SOCKADDR)); + if (getsockname(conn->fd, (struct sockaddr*)local_info, &size_of_reply)==0) { + char host[1024]; + char service[20]; + + // IPv4: + if (local_info->SAFAMILY==AF_INET) { + char ip4[INET_ADDRSTRLEN]; // space to hold the IPv4 string + struct sockaddr_in *sa = (struct sockaddr_in*)local_info; // pretend this is loaded with something + + inet_ntop(AF_INET, &(sa->sin_addr), ip4, INET_ADDRSTRLEN); + unsigned short int tport = ntohs(sa->sin_port); + debug(1,"New RTSP connection at: %s:%u", ip4,tport); + } +#ifdef AF_INET6 + if (local_info->SAFAMILY==AF_INET6) { + // IPv6: + + char ip6[INET6_ADDRSTRLEN]; // space to hold the IPv6 string + struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)local_info; ; // pretend this is loaded with something + + inet_ntop(AF_INET6, &(sa6->sin6_addr), ip6, INET6_ADDRSTRLEN); + u_int16_t tport = ntohs(sa6->sin6_port); + + debug(1,"New RTSP connection at: %s:%u", ip6,tport); + } + #endif + + } else { + debug(1,"Error figuring out Shairport Sync's own ipnumber"); + } + usleep(500000); pthread_t rtsp_conversation_thread; ret = pthread_create(&rtsp_conversation_thread, NULL,