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
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);
die("error: could not bind a UDP port!");
}
-
int sport;
SOCKADDR local;
socklen_t local_len = sizeof(local);
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!");
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;
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");
// 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)
// 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);
typedef struct {
int fd;
stream_cfg stream;
- SOCKADDR remote;
+ SOCKADDR remote,local;
int stop;
int running;
pthread_t thread;
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;
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,