sigset_t pselect_sigset;
+static uint16_t UDPPortIndex = 0;
+
+void resetFreeUDPPort() {
+ UDPPortIndex = 0;
+}
+
+uint16_t nextFreeUDPPort() {
+
+ if (UDPPortIndex == 0)
+ UDPPortIndex = config.udp_port_base;
+ else if (UDPPortIndex == (config.udp_port_base + config.udp_port_range))
+ UDPPortIndex = config.udp_port_base;
+ else
+ UDPPortIndex++;
+ return UDPPortIndex;
+}
+
int get_requested_connection_state_to_output() { return requested_connection_state_to_output; }
void set_requested_connection_state_to_output(int v) { requested_connection_state_to_output = v; }
uint64_t ranarray64u();
int64_t ranarray64i();
+// if you are breaking in to a session, you need to avoid the ports of the current session
+// if you are law-abiding, then you can reuse the ports.
+// so, you can reset the free UDP ports minder when you're legit, and leave it otherwise
+
+// the downside of using different ports each time is that it might make the firewall
+// rules a bit more complex, as they need to allow more than the minimum three ports.
+// a range of 10 is suggested anyway
+
+void resetFreeUDPPort();
+uint16_t nextFreeUDPPort();
+
volatile int debuglev;
void die(const char *format, ...);
void warn(const char *format, ...);
if ((conn->flush_rtp_timestamp != 0) && (actual_timestamp != conn->flush_rtp_timestamp) &&
(modulo_32_offset(actual_timestamp, conn->flush_rtp_timestamp) <
conn->input_rate * 10)) { // if it's less than 10 seconds
- debug(2, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %" PRIu32
+ debug(3, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %" PRIu32
", flushing to "
"timestamp: %" PRIu32 ".",
seqno, actual_timestamp, conn->flush_rtp_timestamp);
(curframe->given_timestamp != conn->flush_rtp_timestamp) &&
(modulo_32_offset(curframe->given_timestamp, conn->flush_rtp_timestamp) <
conn->input_rate * 10)) { // if it's less than ten seconds
- debug(2, "Dropping flushed packet in buffer_get_frame, seqno %u, timestamp %" PRIu32
+ debug(3, "Dropping flushed packet in buffer_get_frame, seqno %u, timestamp %" PRIu32
", flushing to "
"timestamp: %" PRIu32 ".",
curframe->sequence_number, curframe->given_timestamp, conn->flush_rtp_timestamp);
conn->input_rate / 5) &&
(modulo_32_offset(conn->flush_rtp_timestamp, curframe->given_timestamp) <
conn->input_rate * 10)) {
- debug(2, "Dropping flush request in buffer_get_frame");
+ debug(3, "Dropping flush request in buffer_get_frame");
conn->flush_rtp_timestamp = 0;
}
}
ssize_t nread;
while (1) {
nread = recv(conn->audio_socket, packet, sizeof(packet), 0);
-
+
frame_count++;
- if (frame_count<10)
- debug(1,"Recv'ed %d bytes. First two bytes are %02X,%02X ",nread,packet[0],packet[1]);
- else {
uint64_t local_time_now_fp = get_absolute_time_in_fp();
if (time_of_previous_packet_fp) {
uint32_t actual_timestamp = ntohl(*(uint32_t *)(pktp + 4));
- uint32_t ssid = ntohl(*(uint32_t *)(pktp + 8));
- debug(1, "Audio packet SSID: %08X,%u", ssid,ssid);
+ // uint32_t ssid = ntohl(*(uint32_t *)(pktp + 8));
+ // debug(1, "Audio packet SSID: %08X,%u", ssid,ssid);
// if (packet[1]&0x10)
// debug(1,"Audio packet Extension bit set.");
} else {
debug(1, "Error receiving an audio packet.");
}
- }
}
/*
(drand48() > config.diagnostic_drop_packet_fraction)) {
arrival_time = get_absolute_time_in_fp();
- ssize_t plen = nread;
+ // ssize_t plen = nread;
// debug(1,"Packet Received on Timing Port.");
if (packet[1] == 0xd3) { // timing reply
-
+ /*
char obf[4096];
char *obfp = obf;
int obfc;
};
*obfp=0;
debug(1,"Timing Packet Received: \"%s\"",obf);
-
+ */
// arrival_time = ((uint64_t)att.tv_sec<<32)+((uint64_t)att.tv_nsec<<32)/1000000000;
// departure_time = ((uint64_t)dtt.tv_sec<<32)+((uint64_t)dtt.tv_nsec<<32)/1000000000;
static uint16_t bind_port(int ip_family, const char *self_ip_address, uint32_t scope_id,
int *sock) {
// look for a port in the range, if any was specified.
- uint16_t desired_port = config.udp_port_base;
int ret = 0;
int local_socket = socket(ip_family, SOCK_DGRAM, IPPROTO_UDP);
if (local_socket == -1)
die("Could not allocate a socket.");
SOCKADDR myaddr;
+ int tryCount = 0;
+ uint16_t desired_port;
do {
+ tryCount++;
+ desired_port = nextFreeUDPPort();
memset(&myaddr, 0, sizeof(myaddr));
if (ip_family == AF_INET) {
struct sockaddr_in *sa = (struct sockaddr_in *)&myaddr;
#endif
} while ((ret < 0) && (errno == EADDRINUSE) && (desired_port != 0) &&
- (++desired_port < config.udp_port_base + config.udp_port_range));
+ (tryCount < config.udp_port_range));
// debug(1,"UDP port chosen: %d.",desired_port);
if (ret < 0) {
close(local_socket);
- die("error: could not bind a UDP port! Check the udp_port_range is large enough (>= 10) or "
+ die("error: could not bind a UDP port! Check the udp_port_range is large enough -- it must be at least 3, and 10 or more is suggested -- or "
"check for restrictive firewall settings or a bad router!");
}
char *sp, *p;
sp = NULL; // this is to quieten a compiler warning
- debug(1, "received request: %s", line);
+ debug(3, "RTSP Message Received: \"%s\".", line);
p = strtok_r(line, " ", &sp);
if (!p)
int have_the_player = 0;
- int should_wait = 0;
+ int should_wait = 0; // this will be true if you're trying to break in to the current session
// try to become the current playing_conn
if (have_the_player == 1) {
debug(1, "Connection %d: ANNOUNCE got the player", conn->connection_number);
- usleep(2000000); // this is just to let everything settle a bit
} else {
debug(1, "Connection %d: ANNOUNCE failed to get the player", conn->connection_number);
}
if (have_the_player) {
debug(3, "RTSP conversation thread %d has acquired play lock.", conn->connection_number);
+ // now, if this new session did not break in, then it's okay to reset the next UDP ports
+ // to the start of the range
+
+ if (should_wait == 0) { // will be zero if it didn't need to wait to break in
+ resetFreeUDPPort();
+ }
+
+ /*
{
char *cp = req->content;
int cp_left = req->contentlength;
while (cp_left > 1) {
if (strlen(cp) != 0)
- warn(" %s", cp);
+ debug(1,">>>>>> %s", cp);
cp += strlen(cp) + 1;
cp_left -= strlen(cp) + 1;
}
}
-
+*/
resp->respcode = 456; // 456 - Header Field Not Valid for Resource
if (pssid) {
uint32_t ssid = uatoi(pssid);
- debug(1, "Synchronisation Source Identifier: %08X,%u", ssid,ssid);
+ debug(3, "Synchronisation Source Identifier: %08X,%u", ssid,ssid);
}
if (pminlatency) {
// debug(1, "Connection %d: closing fd %d.",
// conn->connection_number,conn->fd);
close(conn->fd);
- usleep(1000000);
}
if (conn->auth_nonce) {
free(conn->auth_nonce);
debug_mutex_lock(&playing_conn_lock, 1000000 , 3); //get it
if (playing_conn == conn) {
- debug(1, "Connection %d: Unlocking play lock.", conn->connection_number);
+ debug(3, "Connection %d: Unlocking play lock.", conn->connection_number);
playing_conn = NULL;
}
debug_mutex_unlock(&playing_conn_lock, 3);
// mdns_backend = "avahi"; // Run "shairport-sync -h" to get a list of all mdns_backends. The default is the first one.
// port = 5000; // Listen for service requests on this port
// udp_port_base = 6001; // start allocating UDP ports from this port number when needed
-// udp_port_range = 100; // look for free ports in this number of places, starting at the UDP port base. Allow at least 10, though only three are needed in a steady state.
+// udp_port_range = 10; // look for free ports in this number of places, starting at the UDP port base. Allow at least 10, though only three are needed in a steady state.
// drift_tolerance_in_seconds = 0.002; // allow a timing error of this number of seconds of drift away from exact synchronisation before attempting to correct it
// resync_threshold_in_seconds = 0.050; // a synchronisation error greater than this number of seconds will cause resynchronisation; 0 disables it
// ignore_volume_control = "no"; // set this to "yes" if you want the volume to be at 100% no matter what the source's volume control is set to.
/* Get the udp port range setting. This is number of ports that will be tried for free ports ,
* starting at the port base. Only three ports are needed. */
if (config_lookup_int(config.cfg, "general.udp_port_range", &value)) {
- if ((value < 0) || (value > 65535))
- die("Invalid port range \"%sd\". It should be between 0 and 65535, default is 100",
+ if ((value < 3) || (value > 65535))
+ die("Invalid port range \"%sd\". It should be between 3 and 65535, default is 10",
value);
else
config.udp_port_range = value;
1); // we expect to be able to connect to the output device
config.audio_backend_buffer_desired_length = 6615; // 0.15 seconds.
config.udp_port_base = 6001;
- config.udp_port_range = 100;
+ config.udp_port_range = 10;
config.output_format = SPS_FORMAT_S16; // default
config.output_rate = 44100; // default
config.decoders_supported =