From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Mon, 27 Dec 2021 12:19:01 +0000 (+0000) Subject: Begin to get SPS to give a unique shm interface name to nqptp. Also clang format X-Git-Tag: 4.1-rc1~24^2~317 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=966d68bdec9655eefc5cac9ad82d38eae4cfdc42;p=thirdparty%2Fshairport-sync.git Begin to get SPS to give a unique shm interface name to nqptp. Also clang format --- diff --git a/common.h b/common.h index f4139e56..904b9279 100644 --- a/common.h +++ b/common.h @@ -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; diff --git a/mqtt.c b/mqtt.c index 912d618c..462ebd2a 100644 --- a/mqtt.c +++ b/mqtt.c @@ -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; - } } } diff --git a/nqptp-shm-structures.h b/nqptp-shm-structures.h index f4db8c6e..82837778 100644 --- a/nqptp-shm-structures.h +++ b/nqptp-shm-structures.h @@ -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 diff --git a/player.c b/player.c index db7ec169..27b8e692 100644 --- a/player.c +++ b/player.c @@ -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) { diff --git a/ptp-utilities.c b/ptp-utilities.c index fa1c6407..78a43ed4 100644 --- a/ptp-utilities.c +++ b/ptp-utilities.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #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 */ + /* 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"); + /* 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."); } - /* Deallocate the socket */ - close(s); } diff --git a/rtp.c b/rtp.c index 348ac869..cf53c545 100644 --- a/rtp.c +++ b/rtp.c @@ -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 " diff --git a/rtsp.c b/rtsp.c index cd76c537..17fcf397 100644 --- a/rtsp.c +++ b/rtsp.c @@ -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 diff --git a/shairport.c b/shairport.c index 88db7924..eaa020fa 100644 --- a/shairport.c +++ b/shairport.c @@ -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);