]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
BB. Fix a crash that occurred in AP2 mode if no configuration file was present, duh.
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Tue, 4 Jan 2022 18:06:16 +0000 (18:06 +0000)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Tue, 4 Jan 2022 18:06:16 +0000 (18:06 +0000)
shairport.c

index 86d073c8291cc46ac85f56e199e3261fb4287047..765732cc08c855b657ebbc25567bc531e6eb65a4 100644 (file)
@@ -2,7 +2,7 @@
  * Shairport, an Apple Airplay receiver
  * Copyright (c) James Laird 2013
  * All rights reserved.
- * Modifications and additions (c) Mike Brady 2014--2021
+ * Modifications and additions (c) Mike Brady 2014--2022
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -469,6 +469,44 @@ int parse_options(int argc, char **argv) {
   // not made active again (not used)
 #endif
 
+#ifdef CONFIG_AIRPLAY_2
+  // the features code is a 64-bit number, but in the mDNS advertisement, the least significant 32
+  // bit are given first for example, if the features number is 0x1C340405F4A00, it will be given as
+  // features=0x405F4A00,0x1C340 in the mDNS string, and in a signed decimal number in the plist:
+  // 496155702020608 this setting here is the source of both the plist features response and the
+  // mDNS string.
+  // note: 0x300401F4A00 works but with weird delays and stuff
+  // config.airplay_features = 0x1C340405FCA00;
+  uint64_t mask =
+      ((uint64_t)1 << 17) | ((uint64_t)1 << 16) | ((uint64_t)1 << 15) | ((uint64_t)1 << 50);
+  config.airplay_features =
+      0x1C340405D4A00 & (~mask); // APX + Authentication4 (b14) with no metadata (see below)
+  // Advertised with mDNS and returned with GET /info, see
+  // https://openairplay.github.io/airplay-spec/status_flags.html 0x4: Audio cable attached, no PIN
+  // required (transient pairing), 0x204: Audio cable attached, OneTimePairingRequired 0x604: Audio
+  // cable attached, OneTimePairingRequired, device was setup for Homekit access control
+  config.airplay_statusflags = 0x04;
+  // Set to NULL to work with transient pairing
+  config.airplay_pin = NULL;
+
+  // use the start of the config.hw_addr and the PID to generate the default airplay_device_id
+  uint64_t temporary_airplay_id = nctoh64(config.hw_addr);
+  temporary_airplay_id =
+      temporary_airplay_id >> 16; // we only use the first 6 bytes but have imported 8.
+
+  // now generate a UUID
+  // from https://stackoverflow.com/questions/51053568/generating-a-random-uuid-in-c
+  // with thanks
+  uuid_t binuuid;
+  uuid_generate_random(binuuid);
+
+  char *uuid = malloc(UUID_STR_LEN);
+  // Produces a UUID string at uuid consisting of lower-case letters
+  uuid_unparse_lower(binuuid, uuid);
+  config.airplay_pi = uuid;
+
+#endif
+
   // config_setting_t *setting;
   const char *str = 0;
   int value = 0;
@@ -1150,6 +1188,21 @@ int parse_options(int argc, char **argv) {
           "avahi enabled, or disable remote control.");
     }
 #endif
+#endif
+
+#ifdef CONFIG_AIRPLAY_2
+    int64_t aid;
+
+    // replace the airplay_device_id with this, if provided
+    if (config_lookup_int64(config.cfg, "general.airplay_device_id", &aid)) {
+      temporary_airplay_id = aid;
+    }
+
+    // add the airplay_device_id_offset if provided
+    if (config_lookup_int64(config.cfg, "general.airplay_device_id_offset", &aid)) {
+      temporary_airplay_id += aid;
+    }
+
 #endif
   }
 
@@ -1218,6 +1271,44 @@ int parse_options(int argc, char **argv) {
 
   // here, we are finally finished reading the options
 
+  // finish the Airplay 2 options
+
+#ifdef CONFIG_AIRPLAY_2
+
+  char shared_memory_interface_name[256] = "";
+  snprintf(shared_memory_interface_name, sizeof(shared_memory_interface_name), "/%s-%" PRIx64 "",
+           config.appName, temporary_airplay_id);
+  // 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[temporary_airplay_id & 0xF];
+    temporary_airplay_id = temporary_airplay_id >> 4;
+    apids[i * 3] = hexchar[temporary_airplay_id & 0xF];
+    temporary_airplay_id = temporary_airplay_id >> 4;
+    if (i != 0)
+      apids[i * 3 - 1] = ':';
+  }
+
+  config.airplay_device_id = strdup(apids);
+
+#ifdef CONFIG_METADATA
+  // If we are asking for metadata, turn on the relevant bits
+  if (config.metadata_enabled != 0) {
+    config.airplay_features |= (1 << 17) | (1 << 16); // 16 is progress, 17 is text
+    // If we are asking for artwork, turn on the relevant bit
+    if (config.get_coverart)
+      config.airplay_features |= (1 << 15); // 15 is artwork
+  }
+#endif
+
+#endif
+
 #ifdef CONFIG_LIBDAEMON
   if ((daemonisewith) && (daemonisewithout))
     die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have selected "
@@ -1792,86 +1883,13 @@ int main(int argc, char **argv) {
 #endif
 
 #ifdef CONFIG_AIRPLAY_2
-  // the features code is a 64-bit number, but in the mDNS advertisement, the least significant 32
-  // bit are given first for example, if the features number is 0x1C340405F4A00, it will be given as
-  // features=0x405F4A00,0x1C340 in the mDNS string, and in a signed decimal number in the plist:
-  // 496155702020608 this setting here is the source of both the plist features response and the
-  // mDNS string.
-  // note: 0x300401F4A00 works but with weird delays and stuff
-  // config.airplay_features = 0x1C340405FCA00;
-  uint64_t mask =
-      ((uint64_t)1 << 17) | ((uint64_t)1 << 16) | ((uint64_t)1 << 15) | ((uint64_t)1 << 50);
-  config.airplay_features =
-      0x1C340405D4A00 & (~mask); // APX + Authentication4 (b14) with no metadata (see below)
-  // Advertised with mDNS and returned with GET /info, see
-  // https://openairplay.github.io/airplay-spec/status_flags.html 0x4: Audio cable attached, no PIN
-  // required (transient pairing), 0x204: Audio cable attached, OneTimePairingRequired 0x604: Audio
-  // cable attached, OneTimePairingRequired, device was setup for Homekit access control
-
-#ifdef CONFIG_METADATA
-  // If we are asking for metadata, turn on the relevant bits
-  if (config.metadata_enabled != 0) {
-    config.airplay_features |= (1 << 17) | (1 << 16); // 16 is progress, 17 is text
-    // If we are asking for artwork, turn on the relevant bit
-    if (config.get_coverart)
-      config.airplay_features |= (1 << 15); // 15 is artwork
-  }
-#endif
-
-  debug(1, "Features: 0x%" PRIx64 ".", config.airplay_features);
-  config.airplay_statusflags = 0x04;
-  // Set to NULL to work with transient pairing
-  config.airplay_pin = NULL;
-
-  // 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 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];
-    apid = apid >> 4;
-    apids[i * 3] = hexchar[apid & 0xF];
-    apid = apid >> 4;
-    if (i != 0)
-      apids[i * 3 - 1] = ':';
-  }
-
-  config.airplay_device_id = strdup(apids);
-
-  // now generate a UUID
-  // from https://stackoverflow.com/questions/51053568/generating-a-random-uuid-in-c
-  // with thanks
-  uuid_t binuuid;
-  uuid_generate_random(binuuid);
-
-  char *uuid = malloc(UUID_STR_LEN);
-  // Produces a UUID string at uuid consisting of lower-case letters
-  uuid_unparse_lower(binuuid, uuid);
-  config.airplay_pi = uuid;
-  debug(1, "Started in Airplay 2 mode on device \"%s\"!", config.airplay_device_id);
+  uint64_t apf = config.airplay_features;
+  uint64_t apfh = config.airplay_features;
+  apfh = apfh >> 32;
+  uint32_t apf32 = apf;
+  uint32_t apfh32 = apfh;
+  debug(1, "Started in Airplay 2 mode with features 0x%" PRIx32 ",0x%" PRIx32 " on device \"%s\"!",
+        apf32, apfh32, config.airplay_device_id);
 #else
   debug(1, "Started in Airplay 1 mode!");
 #endif