Begin to get SPS to give a unique shm interface name to nqptp. Also clang format

This commit is contained in:
Mike Brady
2021-12-27 12:19:01 +00:00
parent 3047285039
commit 966d68bdec
8 changed files with 119 additions and 84 deletions
+2 -1
View File
@@ -152,7 +152,7 @@ typedef struct {
int mqtt_publish_cover;
int mqtt_enable_remote;
#endif
uint8_t hw_addr[8]; // only needs 6 but 8 is handy when converting this to a number
uint8_t hw_addr[8]; // only needs 6 but 8 is handy when converting this to a number
int port;
int udp_port_base;
int udp_port_range;
@@ -302,6 +302,7 @@ typedef struct {
char *airplay_device_id; // for the Bonjour advertisement and the GETINFO PList
char *airplay_pin; // non-NULL, 4 char PIN, if required for pairing
char *airplay_pi; // UUID in the Bonjour advertisement and the GETINFO Plist
char *nqptp_shared_memory_interface_name; // client name for nqptp service
#endif
} shairport_cfg;
-1
View File
@@ -199,7 +199,6 @@ void mqtt_process_metadata(uint32_t type, uint32_t code, char *data, uint32_t le
case 'svip':
mqtt_publish("server_ip", data, length);
break;
}
}
}
+4 -7
View File
@@ -20,14 +20,12 @@
#ifndef NQPTP_SHM_STRUCTURES_H
#define NQPTP_SHM_STRUCTURES_H
#define STORAGE_ID "/nqptp"
#define MAX_CLOCKS 32
#define NQPTP_SHM_STRUCTURES_VERSION 6
#define NQPTP_SHM_STRUCTURES_VERSION 7
#define NQPTP_CONTROL_PORT 9000
// the control port will accept a UDP packet with the first letter being:
// "T", followed by a space and then a space-delimited
// list of ip numbers, either IPv4 or IPv6
// The control port will accept a UDP packet with the first letter being:
// "T", followed by the name of the shared memory interface, followed by
// a space and then a space-delimited list of ip numbers, either IPv4 or IPv6
// the whole not to exceed 4096 characters in total
// The IPs will become the new list of timing peers, replacing any previous
@@ -37,7 +35,6 @@
struct shm_structure {
pthread_mutex_t shm_mutex; // for safely accessing the structure
uint16_t version; // check this is equal to NQPTP_SHM_STRUCTURES_VERSION
uint32_t flags; // unused
uint64_t master_clock_id; // the current master clock
char master_clock_ip[64]; // where it's coming from
uint64_t local_time; // the time when the offset was calculated
+12 -10
View File
@@ -1064,21 +1064,23 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
int64_t lt = conn->first_packet_time_to_play - local_time_now;
if (lt < 130000000) {
debug(1, "Connection %d: Short lead time for first frame %" PRId64 ": %f seconds. Flushing 0.5 seconds",
conn->connection_number, conn->first_packet_timestamp, lt * 0.000000001);
debug(1,
"Connection %d: Short lead time for first frame %" PRId64
": %f seconds. Flushing 0.5 seconds",
conn->connection_number, conn->first_packet_timestamp, lt * 0.000000001);
do_flush(conn->first_packet_timestamp + 5 * 4410, conn);
} else {
debug(2, "Connection %d: Lead time for first frame %" PRId64 ": %f seconds.",
conn->connection_number, conn->first_packet_timestamp, lt * 0.000000001);
conn->connection_number, conn->first_packet_timestamp, lt * 0.000000001);
}
/*
int64_t lateness = local_time_now - conn->first_packet_time_to_play;
if (lateness > 0) {
debug(1, "First packet is %" PRId64 " nanoseconds late! Flushing 0.5 seconds",
lateness);
/*
int64_t lateness = local_time_now - conn->first_packet_time_to_play;
if (lateness > 0) {
debug(1, "First packet is %" PRId64 " nanoseconds late! Flushing 0.5
seconds", lateness);
}
*/
}
*/
}
if (conn->first_packet_time_to_play != 0) {
+36 -21
View File
@@ -30,6 +30,7 @@
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#ifdef COMPILE_FOR_FREEBSD
@@ -148,27 +149,41 @@ int ptp_shm_interface_close() {
}
void ptp_send_control_message_string(const char *msg) {
debug(2, "Send control message to NQPTP: \"%s\"", msg);
int s;
unsigned short port = htons(NQPTP_CONTROL_PORT);
struct sockaddr_in server;
size_t full_message_size =
strlen(config.nqptp_shared_memory_interface_name) + strlen(" ") + strlen(msg) + 1;
char *full_message = malloc(full_message_size);
if (full_message != NULL) {
*full_message = '\0';
snprintf(full_message, full_message_size, "%s %s", config.nqptp_shared_memory_interface_name,
msg);
debug(1, "Send control message to NQPTP: \"%s\"", full_message);
int s;
unsigned short port = htons(NQPTP_CONTROL_PORT);
struct sockaddr_in server;
/* Create a datagram socket in the internet domain and use the
* default protocol (UDP).
*/
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
die("Can't open a socket to NQPTP");
/* Create a datagram socket in the internet domain and use the
* default protocol (UDP).
*/
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
die("Can't open a socket to NQPTP");
}
/* Set up the server name */
server.sin_family = AF_INET; /* Internet Domain */
server.sin_port = port; /* Server Port */
server.sin_addr.s_addr = 0; /* Server's Address */
/* Send the message in buf to the server */
if (sendto(s, full_message, full_message_size, 0, (struct sockaddr *)&server, sizeof(server)) <
0) {
die("error sending timing_peer_list to NQPTP");
}
/* Deallocate the socket */
close(s);
/* deallocate the message string */
free(full_message);
} else {
debug(1, "Couldn't allocate memory to prepare a qualified ptp control message string.");
}
/* Set up the server name */
server.sin_family = AF_INET; /* Internet Domain */
server.sin_port = port; /* Server Port */
server.sin_addr.s_addr = 0; /* Server's Address */
/* Send the message in buf to the server */
if (sendto(s, msg, (strlen(msg) + 1), 0, (struct sockaddr *)&server, sizeof(server)) < 0) {
die("error sending timing_peer_list to NQPTP");
}
/* Deallocate the socket */
close(s);
}
+7 -7
View File
@@ -290,8 +290,8 @@ void *rtp_control_receiver(void *arg) {
obfp += 2;
};
*obfp = 0;
// get raw timestamp information
// I think that a good way to understand these timestamps is that
// (1) the rtlt below is the timestamp of the frame that should be playing at the
@@ -302,19 +302,19 @@ void *rtp_control_receiver(void *arg) {
// Thus, (3) the latency can be calculated by subtracting the second from the
// first.
// There must be more to it -- there something missing.
// In addition, it seems that if the value of the short represented by the second
// pair of bytes in the packet is 7
// then an extra time lag is expected to be added, presumably by
// the AirPort Express.
// Best guess is that this delay is 11,025 frames.
uint32_t rtlt = nctohl(&packet[4]); // raw timestamp less latency
uint32_t rt = nctohl(&packet[16]); // raw timestamp
uint32_t fl = nctohs(&packet[2]); //
debug(1,"Sync Packet of %d bytes received: \"%s\", flags: %d, timestamps %u and %u,
giving a latency of %d frames.",plen,obf,fl,rt,rtlt,rt-rtlt);
//debug(1,"Monotonic timestamps are: %" PRId64 " and %" PRId64 "
+21 -20
View File
@@ -536,7 +536,7 @@ void release_play_lock(rtsp_conn_info *conn) {
}
int get_play_lock(rtsp_conn_info *conn) {
debug(2, "Connection %d: request play lock.", conn->connection_number);
debug(2, "Connection %d: request play lock.", conn->connection_number);
// returns -1 if it failed, 0 if it succeeded and 1 if it succeeded but
// interrupted an existing session
int response = 0;
@@ -1176,9 +1176,9 @@ enum rtsp_read_request_response rtsp_read_request(rtsp_conn_info *conn, rtsp_mes
ssize_t buflen = 4096;
#ifdef CONFIG_METADATA
if ((config.metadata_enabled != 0) && (config.get_coverart != 0))
buflen = 1024 * 256; // big enough for typical picture data, which will be base64 encoded
buflen = 1024 * 256; // big enough for typical picture data, which will be base64 encoded
#endif
int release_buffer = 0; // on exit, don't deallocate the buffer if everything was okay
int release_buffer = 0; // on exit, don't deallocate the buffer if everything was okay
char *buf = malloc(buflen + 1); // add a NUL at the end
if (!buf) {
warn("Connection %d: rtsp_read_request: can't get a buffer.", conn->connection_number);
@@ -1348,9 +1348,12 @@ int msg_write_response(rtsp_conn_info *conn, rtsp_message *resp) {
char *string;
};
struct response_t responses[] = {
{200, "OK"}, {400, "Bad Request"}, {403, "Unauthorized"}, {451, "Unavailable"}, {501, "Not Implemented"}};
// 451 is really "Unavailable For Legal Reasons"!
struct response_t responses[] = {{200, "OK"},
{400, "Bad Request"},
{403, "Unauthorized"},
{451, "Unavailable"},
{501, "Not Implemented"}};
// 451 is really "Unavailable For Legal Reasons"!
int found = 0;
char *respcode_text = "Unauthorized";
for (i = 0; i < sizeof(responses) / sizeof(struct response_t); i++) {
@@ -2302,7 +2305,8 @@ void handle_command(__attribute__((unused)) rtsp_conn_info *conn, rtsp_message *
uint64_t length = 0;
plist_get_data_val(the_item, &buff, &length);
// debug(1,"Item %d, length: %" PRId64 " bytes", item_number, length);
if ((buff != NULL) && (length >= strlen("bplist00")) && (strstr(buff, "bplist00") == buff)) {
if ((buff != NULL) && (length >= strlen("bplist00")) &&
(strstr(buff, "bplist00") == buff)) {
// debug(1,"Contains a plist.");
plist_t subsidiary_plist = NULL;
plist_from_memory(buff, length, &subsidiary_plist);
@@ -2756,9 +2760,9 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
memset(buf, 0, sizeof(buf));
inet_ntop(AF_INET6, (void *)&addr6->sin6_addr, buf, sizeof(buf));
// don't insist there are in the same subnet...
//if (!different) {
// debug(1, "%s is in the same subnet as %s.", buf, ip_address);
plist_array_append_item(addresses, plist_new_string(buf));
// if (!different) {
// debug(1, "%s is in the same subnet as %s.", buf, ip_address);
plist_array_append_item(addresses, plist_new_string(buf));
//}
}
}
@@ -2773,12 +2777,12 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
// struct sockaddr_in *mask = (struct sockaddr_in *)(iap->ifa_netmask);
// if ((addr->sin_addr.s_addr & mask->sin_addr.s_addr) ==
// (pa4->sin_addr.s_addr & mask->sin_addr.s_addr)) {
char buf[32];
memset(buf, 0, sizeof(buf));
inet_ntop(AF_INET, (void *)&addr->sin_addr, buf, sizeof(buf));
// no longer insisting they are in the same subnet
// debug(1, "%s is in the same subnet as %s.", buf, ip_address);
plist_array_append_item(addresses, plist_new_string(buf));
char buf[32];
memset(buf, 0, sizeof(buf));
inet_ntop(AF_INET, (void *)&addr->sin_addr, buf, sizeof(buf));
// no longer insisting they are in the same subnet
// debug(1, "%s is in the same subnet as %s.", buf, ip_address);
plist_array_append_item(addresses, plist_new_string(buf));
// }
}
}
@@ -2838,8 +2842,6 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
get_category_string(conn->airplay_stream_category));
mdns_update(NULL, secondary_txt_records);
resp->respcode = 200;
} else {
debug(1, "SETUP on Connection %d: PTP setup -- no timingPeerInfo plist.",
@@ -2875,8 +2877,7 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
plist_dict_set_item(setupResponsePlist, "eventPort",
plist_new_uint(conn->local_event_port));
plist_dict_set_item(setupResponsePlist, "timingPort",
plist_new_uint(0));
plist_dict_set_item(setupResponsePlist, "timingPort", plist_new_uint(0));
cancel_all_RTSP_threads(
remote_control_stream,
conn->connection_number); // kill all the other remote control listeners
+37 -17
View File
@@ -289,7 +289,8 @@ void usage(char *progname) {
#ifdef CONFIG_METADATA
printf(" -M, --metadata-enable ask for metadata from the source and process it.\n");
printf(" --metadata-pipename=PIPE send metadata to PIPE, e.g. "
"--metadata-pipename=/tmp/%s-metadata.\n", config.appName);
"--metadata-pipename=/tmp/%s-metadata.\n",
config.appName);
printf(" The default is /tmp/%s-metadata.\n", config.appName);
printf(" -g, --get-coverart send cover art through the metadata pipe.\n");
#endif
@@ -1262,7 +1263,7 @@ int parse_options(int argc, char **argv) {
strcat(temp_metadata_pipe_name, config.appName);
strcat(temp_metadata_pipe_name, "-metadata");
config.metadata_pipename = strdup(temp_metadata_pipe_name);
debug(1,"default metadata_pipename is \"%s\".", temp_metadata_pipe_name);
debug(1, "default metadata_pipename is \"%s\".", temp_metadata_pipe_name);
}
#endif
@@ -1320,7 +1321,7 @@ int parse_options(int argc, char **argv) {
char temp_pid_dir[4096];
strcpy(temp_pid_dir, "/var/run/");
strcat(temp_pid_dir, config.appName);
debug(1,"default pid filename is \"%s\".", temp_pid_dir);
debug(1, "default pid filename is \"%s\".", temp_pid_dir);
char *use_this_pid_dir = temp_pid_dir;
#endif
// debug(1,"config.piddir \"%s\".",config.piddir);
@@ -1445,6 +1446,14 @@ void exit_function() {
#ifdef CONFIG_AIRPLAY_2
if (config.regtype2)
free(config.regtype2);
if (config.nqptp_shared_memory_interface_name)
free(config.nqptp_shared_memory_interface_name);
if (config.airplay_device_id)
free(config.airplay_device_id);
if (config.airplay_pin)
free(config.airplay_pin);
if (config.airplay_pi)
free(config.airplay_pi);
#endif
#ifdef CONFIG_LIBDAEMON
@@ -1462,6 +1471,7 @@ void exit_function() {
config_destroy(config.cfg);
if (config.appName)
free(config.appName);
// probably should be freeing malloc'ed memory here, including strdup-created strings...
#ifdef CONFIG_LIBDAEMON
@@ -1833,32 +1843,39 @@ int main(int argc, char **argv) {
// use the start of the config.hw_addr and the PID to generate the default airplay_device_id
uint64_t apid = nctoh64(config.hw_addr);
apid = apid >> 16; // we only use the first 6 bytes but have imported 8.
int64_t aid;
// add the airplay_device_id_offset if provided
if (config_lookup_int64(config.cfg, "general.airplay_device_id_offset", &aid)) {
apid += aid;
}
}
// replace the airplay_device_id with this, if provided
if (config_lookup_int64(config.cfg, "general.airplay_device_id", &aid)) {
apid = aid;
}
char apids[6*2+5+1]; // six pairs of digits, 5 colons and a NUL
apids[6*2+5] = 0; // NUL termination
char shared_memory_interface_name[256] = "";
snprintf(shared_memory_interface_name, sizeof(shared_memory_interface_name), "/%s-%" PRIx64 "",
config.appName, apid);
debug(1, "smi name: \"%s\"", shared_memory_interface_name);
config.nqptp_shared_memory_interface_name = strdup(shared_memory_interface_name);
char apids[6 * 2 + 5 + 1]; // six pairs of digits, 5 colons and a NUL
apids[6 * 2 + 5] = 0; // NUL termination
int i;
char hexchar[] = "0123456789abcdef";
for (i = 5; i >= 0; i--) {
apids[i*3+1] = hexchar[apid & 0xF];
apids[i * 3 + 1] = hexchar[apid & 0xF];
apid = apid >> 4;
apids[i*3] = hexchar[apid & 0xF];
apids[i * 3] = hexchar[apid & 0xF];
apid = apid >> 4;
if (i != 0)
apids[i*3-1] = ':';
apids[i * 3 - 1] = ':';
}
config.airplay_device_id = strdup(apids);
// now generate a UUID
@@ -2017,9 +2034,12 @@ int main(int argc, char **argv) {
debug(1, "run_this_after_play_ends action is \"%s\".", strnull(config.cmd_stop));
debug(1, "wait-cmd status is %d.", config.cmd_blocking);
debug(1, "run_this_before_play_begins may return output is %d.", config.cmd_start_returns_output);
debug(1, "run_this_if_an_unfixable_error_is_detected action is \"%s\".", strnull(config.cmd_unfixable));
debug(1, "run_this_before_entering_active_state action is \"%s\".", strnull(config.cmd_active_start));
debug(1, "run_this_after_exiting_active_state action is \"%s\".", strnull(config.cmd_active_stop));
debug(1, "run_this_if_an_unfixable_error_is_detected action is \"%s\".",
strnull(config.cmd_unfixable));
debug(1, "run_this_before_entering_active_state action is \"%s\".",
strnull(config.cmd_active_start));
debug(1, "run_this_after_exiting_active_state action is \"%s\".",
strnull(config.cmd_active_stop));
debug(1, "active_state_timeout is %f seconds.", config.active_state_timeout);
debug(1, "mdns backend \"%s\".", strnull(config.mdns_name));
debug(2, "userSuppliedLatency is %d.", config.userSuppliedLatency);