diff --git a/common.c b/common.c index 4bdb78ab..f87b7d29 100644 --- a/common.c +++ b/common.c @@ -93,8 +93,6 @@ #include #endif - - #ifdef CONFIG_ALSA void set_alsa_out_dev(char *); #endif @@ -1611,13 +1609,13 @@ char *get_version_string() { char *version_string = malloc(1024); if (version_string) { #ifdef CONFIG_USE_GIT_VERSION_STRING - if (git_version_string[0] != '\0') - strcpy(version_string, git_version_string); - else + if (git_version_string[0] != '\0') + strcpy(version_string, git_version_string); + else #endif - strcpy(version_string, PACKAGE_VERSION); + strcpy(version_string, PACKAGE_VERSION); #ifdef CONFIG_AIRPLAY_2 - strcat(version_string, "-AirPlay2"); + strcat(version_string, "-AirPlay2"); #endif #ifdef CONFIG_APPLE_ALAC strcat(version_string, "-alac"); @@ -1945,7 +1943,7 @@ int get_device_id(uint8_t *id, int int_length) { struct ifaddrs *ifa = NULL; int i = 0; uint8_t *t = id; - for (i = 0; i < int_length ; i++) { + for (i = 0; i < int_length; i++) { *t++ = 0; } diff --git a/common.h b/common.h index 48769527..26e9e17d 100644 --- a/common.h +++ b/common.h @@ -210,10 +210,10 @@ typedef struct { char *configfile; char *regtype; // The regtype is the service type followed by the protocol, separated by a dot, by // default “_raop._tcp.” for AirPlay 1. - char *regtype2; // The regtype is the service type followed by the protocol, separated by a dot, by - // default “_raop._tcp.” for AirPlay 2. - char *interface; // a string containg the interface name, or NULL if nothing specified - int interface_index; // only valid if the interface string is non-NULL + char *regtype2; // The regtype is the service type followed by the protocol, separated by a dot, + // by default “_raop._tcp.” for AirPlay 2. + char *interface; // a string containg the interface name, or NULL if nothing specified + int interface_index; // only valid if the interface string is non-NULL double audio_backend_buffer_desired_length; // this will be the length in seconds of the // audio backend buffer -- the DAC buffer for ALSA double audio_backend_buffer_interpolation_threshold_in_seconds; // below this, soxr interpolation @@ -498,7 +498,6 @@ int get_device_id(uint8_t *id, int int_length); extern char git_version_string[]; #endif - #endif // _COMMON_H #ifdef __cplusplus diff --git a/mdns.c b/mdns.c index 073e346c..4e44e38f 100644 --- a/mdns.c +++ b/mdns.c @@ -81,7 +81,8 @@ void mdns_register(char **txt_records, char **secondary_txt_records) { for (b = mdns_backends; *b; b++) { if (strcmp((*b)->name, config.mdns_name) != 0) // Not the one we are looking for continue; - int error = (*b)->mdns_register(ap1_service_name, config.service_name, config.port, txt_records, secondary_txt_records); + int error = (*b)->mdns_register(ap1_service_name, config.service_name, config.port, + txt_records, secondary_txt_records); if (error >= 0) { config.mdns = *b; } @@ -93,7 +94,8 @@ void mdns_register(char **txt_records, char **secondary_txt_records) { } else { // default -- pick the first back end for (b = mdns_backends; *b; b++) { - int error = (*b)->mdns_register(ap1_service_name, config.service_name, config.port, txt_records, secondary_txt_records); + int error = (*b)->mdns_register(ap1_service_name, config.service_name, config.port, + txt_records, secondary_txt_records); if (error >= 0) { config.mdns = *b; break; diff --git a/mdns.h b/mdns.h index 30900c78..dc6e30d9 100644 --- a/mdns.h +++ b/mdns.h @@ -17,7 +17,8 @@ void mdns_ls_backends(void); typedef struct { char *name; - int (*mdns_register)(char *ap1name, char *ap2name, int port, char **txt_records, char **secondary_txt_records); + int (*mdns_register)(char *ap1name, char *ap2name, int port, char **txt_records, + char **secondary_txt_records); void (*mdns_unregister)(void); void (*mdns_dacp_monitor_start)(); void (*mdns_dacp_monitor_set_id)(const char *); diff --git a/mdns_avahi.c b/mdns_avahi.c index 4873639c..bf24ddba 100644 --- a/mdns_avahi.c +++ b/mdns_avahi.c @@ -243,24 +243,24 @@ static void register_service(AvahiClient *c) { selected_interface = AVAHI_IF_UNSPEC; if (ap2_text_record_string_list) { ret = avahi_entry_group_add_service_strlst(group, selected_interface, AVAHI_PROTO_UNSPEC, 0, - ap2_service_name, config.regtype2, NULL, NULL, port, - ap2_text_record_string_list); + ap2_service_name, config.regtype2, NULL, NULL, + port, ap2_text_record_string_list); } if ((ret == 0) && (text_record_string_list)) { ret = avahi_entry_group_add_service_strlst(group, selected_interface, AVAHI_PROTO_UNSPEC, 0, service_name, config.regtype, NULL, NULL, port, text_record_string_list); } - if (ret == 0) { - ret = avahi_entry_group_commit(group); - debug(2, "avahi: avahi_entry_group_commit %d", ret); - if (ret < 0) - debug(1, "avahi: avahi_entry_group_commit failed"); - } else if (ret < 0) { - debug(1, "avahi: avahi_entry_group_add_service failed"); - } else { - debug(1, "avahi: unexpected positive return"); - } + if (ret == 0) { + ret = avahi_entry_group_commit(group); + debug(2, "avahi: avahi_entry_group_commit %d", ret); + if (ret < 0) + debug(1, "avahi: avahi_entry_group_commit failed"); + } else if (ret < 0) { + debug(1, "avahi: avahi_entry_group_add_service failed"); + } else { + debug(1, "avahi: unexpected positive return"); + } } } @@ -318,7 +318,8 @@ static void client_callback(AvahiClient *c, AvahiClientState state, } } -static int avahi_register(char *ap1name, char *ap2name, int srvport, char **txt_records,char **secondary_txt_records) { +static int avahi_register(char *ap1name, char *ap2name, int srvport, char **txt_records, + char **secondary_txt_records) { // debug(1, "avahi_register."); service_name = strdup(ap1name); if (ap2name != NULL) @@ -327,7 +328,8 @@ static int avahi_register(char *ap1name, char *ap2name, int srvport, char **txt_ text_record_string_list = avahi_string_list_new_from_array((const char **)txt_records, -1); if (secondary_txt_records != NULL) - ap2_text_record_string_list = avahi_string_list_new_from_array((const char **)secondary_txt_records, -1); + ap2_text_record_string_list = + avahi_string_list_new_from_array((const char **)secondary_txt_records, -1); port = srvport; @@ -390,7 +392,6 @@ static void avahi_unregister(void) { } else debug(1, "avahi attempt to free NULL text_record_string_list"); - if (ap2_text_record_string_list) { debug(2, "avahi free ap_2text_record_string_list"); avahi_string_list_free(ap2_text_record_string_list); diff --git a/player.c b/player.c index 46aa9d3e..c8402524 100644 --- a/player.c +++ b/player.c @@ -925,80 +925,83 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) { int flush_needed = 0; int drop_request = 0; if (conn->flush_requested == 1) { - if (conn->flush_rtp_timestamp == 0) { - debug(1, "flush request: flush frame 0 -- flush assumed to be needed."); - flush_needed = 1; - drop_request = 1; - } else { - debug(1,"flush"); - if ((conn->ab_synced) && ((conn->ab_write - conn->ab_read) > 0)) { - abuf_t *firstPacket = conn->audio_buffer + BUFIDX(conn->ab_read); - abuf_t *lastPacket = conn->audio_buffer + BUFIDX(conn->ab_write - 1); - if ((firstPacket != NULL) && (firstPacket->ready)) { - // discard flushes more than 10 seconds into the future -- they are probably bogus - uint32_t first_frame_in_buffer = firstPacket->given_timestamp; - int32_t offset_from_first_frame = - (int32_t)(conn->flush_rtp_timestamp - first_frame_in_buffer); - if (offset_from_first_frame > (int)conn->input_rate * 10) { - debug(1, + if (conn->flush_rtp_timestamp == 0) { + debug(1, "flush request: flush frame 0 -- flush assumed to be needed."); + flush_needed = 1; + drop_request = 1; + } else { + if ((conn->ab_synced) && ((conn->ab_write - conn->ab_read) > 0)) { + abuf_t *firstPacket = conn->audio_buffer + BUFIDX(conn->ab_read); + abuf_t *lastPacket = conn->audio_buffer + BUFIDX(conn->ab_write - 1); + if ((firstPacket != NULL) && (firstPacket->ready)) { + // discard flushes more than 10 seconds into the future -- they are probably bogus + uint32_t first_frame_in_buffer = firstPacket->given_timestamp; + int32_t offset_from_first_frame = + (int32_t)(conn->flush_rtp_timestamp - first_frame_in_buffer); + if (offset_from_first_frame > (int)conn->input_rate * 10) { + debug( + 1, "flush request: sanity check -- flush frame %u is too far into the future from " "the first frame %u -- discarded.", conn->flush_rtp_timestamp, first_frame_in_buffer); - drop_request = 1; - } else { - if ((lastPacket != NULL) && (lastPacket->ready)) { - // we have enough information to check if the flush is needed or can be discarded - uint32_t last_frame_in_buffer = - lastPacket->given_timestamp + lastPacket->length - 1; - // now we have to work out if the flush frame is in the buffer - // if it is later than the end of the buffer, flush everything and keep the request - // active. if it is in the buffer, we need to flush part of the buffer. Actually we - // flush the entire buffer and drop the request. if it is before the buffer, no - // flush is needed. Drop the request. - if (offset_from_first_frame > 0) { - int32_t offset_to_last_frame = - (int32_t)(last_frame_in_buffer - conn->flush_rtp_timestamp); - if (offset_to_last_frame >= 0) { - debug(2, + drop_request = 1; + } else { + if ((lastPacket != NULL) && (lastPacket->ready)) { + // we have enough information to check if the flush is needed or can be discarded + uint32_t last_frame_in_buffer = + lastPacket->given_timestamp + lastPacket->length - 1; + // now we have to work out if the flush frame is in the buffer + // if it is later than the end of the buffer, flush everything and keep the + // request active. if it is in the buffer, we need to flush part of the buffer. + // Actually we flush the entire buffer and drop the request. if it is before the + // buffer, no flush is needed. Drop the request. + if (offset_from_first_frame > 0) { + int32_t offset_to_last_frame = + (int32_t)(last_frame_in_buffer - conn->flush_rtp_timestamp); + if (offset_to_last_frame >= 0) { + debug( + 2, "flush request: flush frame %u active -- buffer contains %u frames, from " "%u to %u", conn->flush_rtp_timestamp, last_frame_in_buffer - first_frame_in_buffer + 1, first_frame_in_buffer, last_frame_in_buffer); - drop_request = 1; - flush_needed = 1; + drop_request = 1; + flush_needed = 1; + } else { + debug(2, + "flush request: flush frame %u pending -- buffer contains %u frames, " + "from " + "%u to %u", + conn->flush_rtp_timestamp, + last_frame_in_buffer - first_frame_in_buffer + 1, first_frame_in_buffer, + last_frame_in_buffer); + flush_needed = 1; + } } else { - debug( - 2, - "flush request: flush frame %u pending -- buffer contains %u frames, from " - "%u to %u", - conn->flush_rtp_timestamp, last_frame_in_buffer - first_frame_in_buffer + 1, - first_frame_in_buffer, last_frame_in_buffer); - flush_needed = 1; + debug(2, + "flush request: flush frame %u expired -- buffer contains %u frames, " + "from %u " + "to %u", + conn->flush_rtp_timestamp, + last_frame_in_buffer - first_frame_in_buffer + 1, first_frame_in_buffer, + last_frame_in_buffer); + drop_request = 1; } - } else { - debug( - 2, - "flush request: flush frame %u expired -- buffer contains %u frames, from %u " - "to %u", - conn->flush_rtp_timestamp, last_frame_in_buffer - first_frame_in_buffer + 1, - first_frame_in_buffer, last_frame_in_buffer); - drop_request = 1; } } } + } else { + debug(3, + "flush request: flush frame %u -- buffer not synced or empty: synced: %d, " + "ab_read: " + "%u, ab_write: %u", + conn->flush_rtp_timestamp, conn->ab_synced, conn->ab_read, conn->ab_write); + conn->flush_requested = 0; // remove the request + // leave flush request pending and don't do a buffer flush, because there isn't one } - } else { - debug( - 3, - "flush request: flush frame %u -- buffer not synced or empty: synced: %d, ab_read: " - "%u, ab_write: %u", - conn->flush_rtp_timestamp, conn->ab_synced, conn->ab_read, conn->ab_write); - conn->flush_requested = 0; // remove the request - // leave flush request pending and don't do a buffer flush, because there isn't one } } - } if (flush_needed) { debug(2, "flush request: flush done."); ab_resync(conn); // no cancellation points @@ -1075,7 +1078,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) { int64_t lt = conn->first_packet_time_to_play - local_time_now; - debug(1, "Connection %d: Lead time for first frame %" PRId64 ": %f seconds.", + debug(2, "Connection %d: Lead time for first frame %" PRId64 ": %f seconds.", conn->connection_number, conn->first_packet_timestamp, lt * 0.000000001); int64_t lateness = local_time_now - conn->first_packet_time_to_play; @@ -1980,7 +1983,7 @@ void *player_thread_func(void *arg) { pthread_setcancelstate(oldState, NULL); double initial_volume = config.airplay_volume; // default - if (conn->initial_airplay_volume_set) // if we have been given an initial volume + if (conn->initial_airplay_volume_set) // if we have been given an initial volume initial_volume = conn->initial_airplay_volume; // set the default volume to whatever it was before, as stored in the config airplay_volume debug(2, "Set initial volume to %f.", initial_volume); @@ -2243,7 +2246,7 @@ void *player_thread_func(void *arg) { // remove the bias when reporting the error to make it the true error - debug(1, + debug(2, "first frame sync error (positive --> late): %" PRId64 " frames, %.3f mS at %d frames per second output.", sync_error + first_frame_early_bias, @@ -2309,8 +2312,11 @@ void *player_thread_func(void *arg) { int64_t filler_length = (int64_t)(config.resyncthreshold * config.output_rate); // number of samples if ((sync_error > 0) && (sync_error > filler_length)) { - debug(1, "Large positive sync error of: %" PRId64 " frames (%f seconds), with frame: %u.", - sync_error, (sync_error * 1.0) / config.output_rate, inframe->given_timestamp); + debug(1, + "Large positive sync error of: %" PRId64 + " frames (%f seconds), with frame: %u.", + sync_error, (sync_error * 1.0) / config.output_rate, + inframe->given_timestamp); int64_t local_frames_to_drop = sync_error / conn->output_sample_ratio; uint32_t frames_to_drop_sized = local_frames_to_drop; do_flush(inframe->given_timestamp + frames_to_drop_sized, conn); @@ -2318,7 +2324,8 @@ void *player_thread_func(void *arg) { debug(1, "Large negative sync error of: %" PRId64 " frames (%f seconds), with frame: %" PRIu32 ".", - sync_error, (sync_error * 1.0) / config.output_rate,inframe->given_timestamp); + sync_error, (sync_error * 1.0) / config.output_rate, + inframe->given_timestamp); int64_t silence_length = -sync_error; if (silence_length > (filler_length * 5)) silence_length = filler_length * 5; diff --git a/player.h b/player.h index d3f4e63c..fbffb04e 100644 --- a/player.h +++ b/player.h @@ -122,16 +122,17 @@ typedef struct { ap2_buffer plain_buf; } ap2_pairing; -/* -typedef struct file_cipher_context { - struct pair_cipher_context *cipher_context; - int active; // can be created during a pair setup but not activated until next read - int fd; - void *input_plaintext_buffer; - void *input_plaintext_buffer_toq; - size_t input_plaintext_buffer_bytes_occupied; -} file_cipher_context; -*/ +// flush requests are stored in order of flushFromSeq +// on the basis that block numbers are monotonic modulo 2^24 +typedef struct flush_request_t { + int flushNow; // if true, the flushFrom stuff is invalid + uint32_t flushFromSeq; + uint32_t flushFromTS; + uint32_t flushUntilSeq; + uint32_t flushUntilTS; + struct flush_request_t *next; +} flush_request_t; + #endif typedef struct { @@ -294,6 +295,7 @@ typedef struct { uint64_t last_anchor_time_of_update; ssize_t ap2_audio_buffer_size; + flush_request_t *flush_requests; // if non-null, there are flush requests, mutex protected int ap2_flush_requested; int ap2_flush_from_valid; uint32_t ap2_flush_from_rtp_timestamp; diff --git a/ptp-utilities.c b/ptp-utilities.c index 32225767..12a0890c 100644 --- a/ptp-utilities.c +++ b/ptp-utilities.c @@ -60,7 +60,8 @@ int get_nqptp_data(struct shm_structure *nqptp_data) { return response; } -int ptp_get_clock_info(uint64_t *actual_clock_id, uint64_t *raw_offset, uint64_t *mastership_start_time) { +int ptp_get_clock_info(uint64_t *actual_clock_id, uint64_t *raw_offset, + uint64_t *mastership_start_time) { int response = clock_ok; pthread_cleanup_debug_mutex_lock(&ptp_access_mutex, 10000, 1); if (actual_clock_id != NULL) diff --git a/ptp-utilities.h b/ptp-utilities.h index 1a7349fc..a0ce1604 100644 --- a/ptp-utilities.h +++ b/ptp-utilities.h @@ -29,7 +29,8 @@ #include "config.h" #include -int ptp_get_clock_info(uint64_t *actual_clock_id, uint64_t *raw_offset, uint64_t *mastership_start_time); +int ptp_get_clock_info(uint64_t *actual_clock_id, uint64_t *raw_offset, + uint64_t *mastership_start_time); void ptp_send_control_message_string(const char *msg); diff --git a/rtp.c b/rtp.c index b96bb5a4..a4994301 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 " @@ -1213,7 +1213,8 @@ void set_ptp_anchor_info(rtsp_conn_info *conn, uint64_t clock_id, uint32_t rtpti debug(2, "Connection %d: Set Anchor Clock: %" PRIx64 ".", conn->connection_number, clock_id); conn->anchor_clock_is_new = 1; } - // debug(1,"set anchor info clock: %" PRIx64", rtptime: %u, networktime: %" PRIx64 ".", clock_id, rtptime, networktime); + // debug(1,"set anchor info clock: %" PRIx64", rtptime: %u, networktime: %" PRIx64 ".", clock_id, + // rtptime, networktime); conn->anchor_remote_info_is_valid = 1; conn->anchor_rtptime = rtptime; conn->anchor_time = networktime; @@ -1247,7 +1248,8 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, // wait at least this time before using the new master clock if (duration_of_mastership < 700000000) { response = clock_not_ready; - } else if ((duration_of_mastership > 5000000000) || (conn->last_anchor_info_is_valid == 0)) { + } else if ((duration_of_mastership > 5000000000) || + (conn->last_anchor_info_is_valid == 0)) { // use the master clock if it's at least this old or we have no alternative // and at least it is the minimum age. conn->last_anchor_rtptime = conn->anchor_rtptime; @@ -1255,7 +1257,8 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, conn->last_anchor_time_of_update = get_absolute_time_in_ns(); conn->last_anchor_info_is_valid = 1; if (conn->anchor_clock_is_new != 0) - debug(1,"Connection %d: New anchor clock %" PRIx64 " recognised.", conn->connection_number, conn->anchor_clock); + debug(2, "Connection %d: New anchor clock %" PRIx64 " recognised.", + conn->connection_number, conn->anchor_clock); conn->anchor_clock_is_new = 0; } } else { @@ -1266,13 +1269,17 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, // so, if the anchor has not changed, it must be that the master clock has changed if (conn->anchor_clock_is_new != 0) - debug(1,"Connection %d: Anchor clock has changed to %" PRIx64 ", master clock is: %" PRIx64 ".", conn->connection_number, conn->anchor_clock, actual_clock_id); + debug(1, + "Connection %d: Anchor clock has changed to %" PRIx64 ", master clock is: %" PRIx64 + ".", + conn->connection_number, conn->anchor_clock, actual_clock_id); if ((conn->last_anchor_info_is_valid != 0) && (conn->anchor_clock_is_new == 0)) { int64_t time_since_last_update = get_absolute_time_in_ns() - conn->last_anchor_time_of_update; if (time_since_last_update > 5000000000) { - debug(1, "Connection %d: Master clock has changed to %" PRIx64 ".", conn->connection_number, actual_clock_id); + debug(1, "Connection %d: Master clock has changed to %" PRIx64 ".", + conn->connection_number, actual_clock_id); // here we adjust the time of the anchor rtptime // we know its local time, so we use the new clocks's offset to // calculate what time that must be on the new clock @@ -1280,7 +1287,7 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, conn->anchor_clock = actual_clock_id; } } else { - response = clock_not_valid; // no current clock information and no previous clock info + response = clock_not_valid; // no current clock information and no previous clock info } } } else { @@ -1296,7 +1303,8 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, actual_clock_id); break; case clock_not_ready: - debug(2, "Connection %d: NQPTP master clock %" PRIx64 " is available but not ready.", conn->connection_number, actual_clock_id); + debug(2, "Connection %d: NQPTP master clock %" PRIx64 " is available but not ready.", + conn->connection_number, actual_clock_id); break; case clock_service_unavailable: debug(1, "Connection %d: NQPTP clock is not available.", conn->connection_number); @@ -1310,7 +1318,7 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, debug(1, "Connection %d: Can not access NQPTP clock information.", conn->connection_number); break; case clock_no_master: - debug(1, "Connection %d: No NQPTP master clock.", conn->connection_number); + debug(2, "Connection %d: No NQPTP master clock.", conn->connection_number); break; case clock_no_anchor_info: debug(1, "Connection %d: No Clock Anchor.", conn->connection_number); @@ -1922,6 +1930,37 @@ void rtp_buffered_audio_cleanup_handler(__attribute__((unused)) void *arg) { debug(2, "Buffered Audio Receiver Cleanup Done."); } +// not used right now, but potentially useful for understanding flush requests +void display_flush_requests(int activeOnly, uint32_t currentSeq, uint32_t currentTS, + rtsp_conn_info *conn) { + if (conn->flush_requests == NULL) { + if (activeOnly == 0) + debug(1, "No flush requests."); + } else { + flush_request_t *t = conn->flush_requests; + do { + if (t->flushNow) { + debug(1, "immediate flush to untilSeq: %u, untilTS: %u.", t->flushUntilSeq, + t->flushUntilTS); + } else { + if (activeOnly == 0) + debug(1, "fromSeq: %u, fromTS: %u, to untilSeq: %u, untilTS: %u.", t->flushFromSeq, + t->flushFromTS, t->flushUntilSeq, t->flushUntilTS); + else if ((activeOnly == 1) && + (currentSeq >= + (t->flushFromSeq - + 1))) // the -1 is because you might have to trim the end of the previous block + debug(1, + "fromSeq: %u, fromTS: %u, to untilSeq: %u, untilTS: %u, with currentSeq: %u, " + "currentTS: %u.", + t->flushFromSeq, t->flushFromTS, t->flushUntilSeq, t->flushUntilTS, currentSeq, + currentTS); + } + t = t->next; + } while (t != NULL); + } +} + void *rtp_buffered_audio_processor(void *arg) { rtsp_conn_info *conn = (rtsp_conn_info *)arg; pthread_cleanup_push(rtp_buffered_audio_cleanup_handler, arg); @@ -2046,7 +2085,7 @@ void *rtp_buffered_audio_processor(void *arg) { int pcm_buffer_occupancy = 0; int pcm_buffer_read_point = 0; // offset to where the next buffer should come from uint32_t pcm_buffer_read_point_rtptime = 0; - uint32_t expected_rtptime; + // uint32_t expected_rtptime; uint64_t blocks_read = 0; int flush_requested = 0; @@ -2054,8 +2093,8 @@ void *rtp_buffered_audio_processor(void *arg) { int streaming_has_started = 0; int play_enabled = 0; uint32_t flush_from_timestamp; - int dump_block_info = 0; double requested_lead_time = 0.100; // normal lead time minimum + reset_buffer(conn); // in case there is any garbage in the player do { int flush_is_delayed = 0; int flush_newly_requested = 0; @@ -2068,12 +2107,11 @@ void *rtp_buffered_audio_processor(void *arg) { int flush_request_active = 0; if (conn->ap2_flush_requested) { - if (conn->ap2_flush_from_valid == 0) {// i.e. a flush from right now + if (conn->ap2_flush_from_valid == 0) { // i.e. a flush from right now flush_request_active = 1; flush_is_delayed = 0; } else { flush_is_delayed = 1; - dump_block_info = 1; flush_from_timestamp = conn->ap2_flush_from_rtp_timestamp; int32_t blocks_to_start_of_flush = conn->ap2_flush_from_sequence_number - seq_no; if (blocks_to_start_of_flush <= 0) { @@ -2086,29 +2124,29 @@ void *rtp_buffered_audio_processor(void *arg) { if (flush_requested == 0) { // here, a flush has been newly requested - debug(1,"Flush requested:"); + debug(2, "Flush requested."); if (conn->ap2_flush_from_valid) { - debug(1," fromTS: %u", conn->ap2_flush_from_rtp_timestamp); - debug(1," fromSeq: %u", conn->ap2_flush_from_sequence_number); - debug(1,"--"); + debug(2, " fromTS: %u", conn->ap2_flush_from_rtp_timestamp); + debug(2, " fromSeq: %u", conn->ap2_flush_from_sequence_number); + debug(2, "--"); } - debug(1," untilTS: %u", conn->ap2_flush_until_rtp_timestamp); - debug(1," untilSeq: %u", conn->ap2_flush_until_sequence_number); - debug(1,"--"); - debug(1," currentTS_Start: %u", pcm_buffer_read_point_rtptime); - uint32_t fib = (pcm_buffer_occupancy - pcm_buffer_read_point) / 4; - debug(1," framesInBuffer: %u", fib); - uint32_t endTS = fib + pcm_buffer_read_point_rtptime; - debug(1," currentTS_End: %u", endTS); // a frame occupies 4 bytes - debug(1," currentSeq: %u", seq_no); + debug(2, " untilTS: %u", conn->ap2_flush_until_rtp_timestamp); + debug(2, " untilSeq: %u", conn->ap2_flush_until_sequence_number); + debug(2, "--"); + debug(2, " currentTS_Start: %u", pcm_buffer_read_point_rtptime); + uint32_t fib = (pcm_buffer_occupancy - pcm_buffer_read_point) / 4; + debug(2, " framesInBuffer: %u", fib); + uint32_t endTS = fib + pcm_buffer_read_point_rtptime; + debug(2, " currentTS_End: %u", endTS); // a frame occupies 4 bytes + debug(2, " currentSeq: %u", seq_no); - flush_newly_requested = 1; + flush_newly_requested = 1; } // blocks_read to ensure seq_no is valid if ((blocks_read != 0) && (seq_no >= flushUntilSeq)) { // we have reached or overshot the flushUntilSeq block - // if (flushUntilSeq != seq_no) - debug(1,"flushUntilSeq %u reached or overshot at %u.", flushUntilSeq, seq_no); + if (flushUntilSeq != seq_no) + debug(1, "flushUntilSeq %u reached or overshot at %u.", flushUntilSeq, seq_no); conn->ap2_flush_requested = 0; flush_request_active = 0; flush_newly_requested = 0; @@ -2123,10 +2161,9 @@ void *rtp_buffered_audio_processor(void *arg) { play_enabled = conn->ap2_play_enabled; debug_mutex_unlock(&conn->flush_mutex, 3); - // do this outside the flush mutex if (flush_newly_complete) { - debug(1,"Flush Complete."); + debug(2, "Flush Complete."); blocks_read = 0; } @@ -2137,14 +2174,13 @@ void *rtp_buffered_audio_processor(void *arg) { reset_buffer(conn); if (flush_is_delayed == 0) { - debug(1,"Immediate Buffered Audio Flush Started."); - //player_full_flush(conn); + debug(2, "Immediate Buffered Audio Flush Started."); + // player_full_flush(conn); streaming_has_started = 0; pcm_buffer_occupancy = 0; pcm_buffer_read_point = 0; - dump_block_info = 0; } else { - debug(1,"Delayed Buffered Audio Flush Started."); + debug(2, "Delayed Buffered Audio Flush Started."); streaming_has_started = 0; pcm_buffer_occupancy = 0; pcm_buffer_read_point = 0; @@ -2182,22 +2218,26 @@ void *rtp_buffered_audio_processor(void *arg) { 0) { int64_t lead_time = buffer_should_be_time - get_absolute_time_in_ns(); // debug(1,"lead time in buffered_audio is %f milliseconds.", lead_time * 0.000001); - if (blocks_read > 1) { - if ((lead_time >= (int64_t)(requested_lead_time * 1000000000)) || - (streaming_has_started != 0)) { - if (streaming_has_started == 0) - debug(1, "Connection %d: buffered audio starting frame: %u, lead time: %f seconds.", conn->connection_number, pcm_buffer_read_point_rtptime, + if (blocks_read > 2) { + if ((lead_time >= (int64_t)(requested_lead_time * 1000000000)) || + (streaming_has_started != 0)) { + if (streaming_has_started == 0) + debug( + 2, + "Connection %d: buffered audio starting frame: %u, lead time: %f seconds.", + conn->connection_number, pcm_buffer_read_point_rtptime, 0.000000001 * lead_time); - //else { - //if (expected_rtptime != pcm_buffer_read_point_rtptime) - // debug(1,"actual rtptime is %u, expected rtptime is %u.", pcm_buffer_read_point_rtptime, expected_rtptime); - //} - expected_rtptime = pcm_buffer_read_point_rtptime + 352; - player_put_packet(0, 0, pcm_buffer_read_point_rtptime, - pcm_buffer + pcm_buffer_read_point, 352, conn); - streaming_has_started++; - usleep(2000); - } + // else { + // if (expected_rtptime != pcm_buffer_read_point_rtptime) + // debug(1,"actual rtptime is %u, expected rtptime is %u.", + // pcm_buffer_read_point_rtptime, expected_rtptime); + //} + // expected_rtptime = pcm_buffer_read_point_rtptime + 352; + player_put_packet(0, 0, pcm_buffer_read_point_rtptime, + pcm_buffer + pcm_buffer_read_point, 352, conn); + streaming_has_started++; + usleep(2000); + } } pcm_buffer_read_point_rtptime += 352; @@ -2273,38 +2313,6 @@ void *rtp_buffered_audio_processor(void *arg) { // uint8_t marker = 0; // uint8_t payload_type = 0; -/* - if (dump_block_info != 0) { - if ((flush_requested) && (seq_no < flushUntilSeq)) - debug(1, "block %u, rtptime %u, should be skipped.", seq_no, timestamp); - else - debug(1, "block %u, rtptime %u, should be decoded and used.", seq_no, timestamp); - - if (((flush_requested != 0) && (seq_no == flushUntilSeq)) || ((flush_requested == 0) && (new_buffer_needed))) { - debug(1, "block %u, rtptime %u, will be decoded and used.", seq_no, timestamp); - } - } -*/ - -/* - if ((blocks_read != 0) && (seq_no != previous_seq_no + 1)) { - if (previous_seq_no != 0) - debug(1, "block discontinuity: from sequence number %u to sequence number %u.", - previous_seq_no, seq_no); - if (pcm_buffer_occupancy != 0) { - debug(1, - "rtptime discontinuity! Existing pcm buffer contents with timestamp " - "%u, seq_no %u to new block with timestamp %u, seq_no %u", - pcm_buffer_read_point_rtptime, previous_seq_no, timestamp, seq_no); - pcm_buffer_occupancy = 0; - } - // if still playing, this is a problem -- need to reset the player - if (play_enabled) - player_full_flush(conn); - } -*/ - - // previous_seq_no = seq_no; // at this point, we can check if we can to flush this packet -- we won't have @@ -2313,18 +2321,21 @@ void *rtp_buffered_audio_processor(void *arg) { if ((flush_requested) && (seq_no >= flushUntilSeq)) { uint64_t should_be_time; - if ((frame_to_local_time(timestamp, &should_be_time, conn) == - 0) && (play_enabled)) { - // play enabled will be off when this is a full flush and the anchor information is not valid + if ((frame_to_local_time(timestamp, &should_be_time, conn) == 0) && (play_enabled)) { + // play enabled will be off when this is a full flush and the anchor information is not + // valid int64_t lead_time = should_be_time - get_absolute_time_in_ns(); - debug(1,"flush completed to seq: %u with rtptime: %u, lead time: 0x%" PRIx64 " nanoseconds, i.e. %f sec.", seq_no, timestamp, lead_time, lead_time * 0.000000001); + debug(2, + "flush completed to seq: %u with rtptime: %u, lead time: 0x%" PRIx64 + " nanoseconds, i.e. %f sec.", + seq_no, timestamp, lead_time, lead_time * 0.000000001); } else { - debug(1,"flush completed to seq: %u with rtptime: %u.", seq_no, timestamp); + debug(2, "flush completed to seq: %u with rtptime: %u.", seq_no, timestamp); } } - if (((flush_requested != 0) && (seq_no == flushUntilSeq)) || ((flush_requested == 0) && (new_buffer_needed))) { - + if (((flush_requested != 0) && (seq_no == flushUntilSeq)) || + ((flush_requested == 0) && (new_buffer_needed))) { // if we are here because of a flush request, it must be the case that // flushing the pcm buffer wasn't enough, as the request would have been turned off by now @@ -2337,11 +2348,11 @@ void *rtp_buffered_audio_processor(void *arg) { if (pcm_buffer_occupancy == 0) { // they should match and the read point should be zero - // if ((blocks_read != 0) && (pcm_buffer_read_point_rtptime != timestamp)) { + // if ((blocks_read != 0) && (pcm_buffer_read_point_rtptime != timestamp)) { // debug(2, "set pcm_buffer_read_point_rtptime from %u to %u.", // pcm_buffer_read_point_rtptime, timestamp); - pcm_buffer_read_point_rtptime = timestamp; - pcm_buffer_read_point = 0; + pcm_buffer_read_point_rtptime = timestamp; + pcm_buffer_read_point = 0; //} } @@ -2425,12 +2436,19 @@ void *rtp_buffered_audio_processor(void *arg) { // copy the PCM audio into the PCM buffer. // make sure it's big enough first - // also, check it if needs to be truncated but to an impending delayed flush_is_delayed + // also, check it if needs to be truncated but to an impending delayed + // flush_is_delayed if (flush_is_delayed) { // see if the flush_from_timestamp is in the buffer - int32_t samples_remaining = (flush_from_timestamp - pcm_buffer_read_point_rtptime); - if ((samples_remaining > 0) && ((samples_remaining * 4) < dst_bufsize)) { - debug(1,"samples remaining before flush: %d, number of samples %d. flushFromTS: %u, pcm_buffer_read_point_rtptime: %u.", samples_remaining, dst_bufsize/4, flush_from_timestamp, pcm_buffer_read_point_rtptime); + int32_t samples_remaining = + (flush_from_timestamp - pcm_buffer_read_point_rtptime); + if ((samples_remaining > 0) && + ((samples_remaining * 4) < dst_bufsize)) { + debug(2, + "samples remaining before flush: %d, number of samples %d. " + "flushFromTS: %u, pcm_buffer_read_point_rtptime: %u.", + samples_remaining, dst_bufsize / 4, flush_from_timestamp, + pcm_buffer_read_point_rtptime); dst_bufsize = samples_remaining * 4; } } diff --git a/rtsp.c b/rtsp.c index 3ef47ba1..88bf2125 100644 --- a/rtsp.c +++ b/rtsp.c @@ -513,6 +513,49 @@ void cleanup_threads(void) { } } +void add_flush_request(int flushNow, uint32_t flushFromSeq, uint32_t flushFromTS, + uint32_t flushUntilSeq, uint32_t flushUntilTS, rtsp_conn_info *conn) { + // immediate flush requests are added sequentially. Don't know how more than one could arise, TBH + flush_request_t **t = &conn->flush_requests; + int done = 0; + do { + flush_request_t *u = *t; + if ((u == NULL) || ((u->flushNow == 0) && (flushNow != 0)) || + (flushFromSeq < u->flushFromSeq) || + ((flushFromSeq == u->flushFromSeq) && (flushFromTS < u->flushFromTS))) { + flush_request_t *n = (flush_request_t *)calloc(sizeof(flush_request_t), 1); + n->flushNow = flushNow; + n->flushFromSeq = flushFromSeq; + n->flushFromTS = flushFromTS; + n->flushUntilSeq = flushUntilSeq; + n->flushUntilTS = flushUntilTS; + n->next = u; + *t = n; + done = 1; + } else { + t = &u->next; + } + } while (done == 0); +} + +void display_all_flush_requests(rtsp_conn_info *conn) { + if (conn->flush_requests == NULL) { + debug(1, "No flush requests."); + } else { + flush_request_t *t = conn->flush_requests; + do { + if (t->flushNow) { + debug(1, "immediate flush to untilSeq: %u, untilTS: %u.", t->flushUntilSeq, + t->flushUntilTS); + } else { + debug(1, "fromSeq: %u, fromTS: %u, to untilSeq: %u, untilTS: %u.", t->flushFromSeq, + t->flushFromTS, t->flushUntilSeq, t->flushUntilTS); + } + t = t->next; + } while (t != NULL); + } +} + // park a null at the line ending, and return the next line pointer // accept \r, \n, or \r\n static char *nextline(char *in, int inbuf) { @@ -1324,7 +1367,7 @@ void handle_flushbuffered(rtsp_conn_info *conn, rtsp_message *req, rtsp_message } else { plist_get_uint_val(item, &flushFromTS); if (flushFromValid == 0) - debug(1,"flushFromTS without flushFromSeq!"); + debug(1, "flushFromTS without flushFromSeq!"); debug(2, "flushFromTS is %" PRId64 ".", flushFromTS); } @@ -1345,23 +1388,52 @@ void handle_flushbuffered(rtsp_conn_info *conn, rtsp_message *req, rtsp_message } debug_mutex_lock(&conn->flush_mutex, 1000, 1); - conn->ap2_flush_from_valid = flushFromValid; - // a flush with from... components will not be followed by a setanchoe (i.e. a play) + // a flush with from... components will not be followed by a setanchor (i.e. a play) // if it's a flush that will be followed by a setanchor (i.e. a play) then stop play now. if (flushFromValid == 0) conn->ap2_play_enabled = 0; - conn->ap2_flush_from_sequence_number = flushFromSeq; - conn->ap2_flush_from_rtp_timestamp = flushFromTS; + // add the exact request as made to the linked list (not used for anything but diagnostics now) + // int flushNow = 0; + // if (flushFromValid == 0) + // flushNow = 1; + // add_flush_request(flushNow, flushFromSeq, flushFromTS, flushUntilSeq, flushUntilTS, conn); + + // now, if it's an immediate flush, replace the existing request, if any + // but it if's a deferred flush and there is an existing deferred request, + // only update the flushUntil stuff -- that seems to preserve + // the intended semantics + + // so, always replace these conn->ap2_flush_until_sequence_number = flushUntilSeq; conn->ap2_flush_until_rtp_timestamp = flushUntilTS; + + if ((conn->ap2_flush_requested != 0) && (conn->ap2_flush_from_valid != 0) && + (flushFromValid != 0)) { + // if there is a request already, and it's a deferred request, and the current request is also + // deferred... do nothing! -- leave the starting point in place. Yeah, yeah, we know de Morgan's + // Law, but this seems clearer + } else { + conn->ap2_flush_from_sequence_number = flushFromSeq; + conn->ap2_flush_from_rtp_timestamp = flushFromTS; + } + + conn->ap2_flush_from_valid = flushFromValid; conn->ap2_flush_requested = 1; + + // reflect the possibly updated flush request + // add_flush_request(flushNow, conn->ap2_flush_from_sequence_number, + // conn->ap2_flush_from_rtp_timestamp, conn->ap2_flush_until_sequence_number, + // conn->ap2_flush_until_rtp_timestamp, conn); + debug_mutex_unlock(&conn->flush_mutex, 3); if (flushFromValid) - debug(1,"Deferred Flush Requested"); + debug(2, "Deferred Flush Requested"); else - debug(1,"Immediate Flush Requested"); + debug(2, "Immediate Flush Requested"); + + // display_all_flush_requests(conn); resp->respcode = 200; } @@ -2316,7 +2388,8 @@ void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *req, if (!strncmp(cp, "volume: ", strlen("volume: "))) { float volume = atof(cp + strlen("volume: ")); - debug(1, "Connection %d: request to set AirPlay Volume to: %f.", conn->connection_number, volume); + debug(2, "Connection %d: request to set AirPlay Volume to: %f.", conn->connection_number, + volume); // if we are playing, go ahead and change the volume if (try_to_hold_play_lock(conn) == 0) { player_volume(volume, conn); @@ -2337,7 +2410,8 @@ void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *req, } else #endif { - debug(1, "Connection %d, unrecognised parameter: \"%s\" (%d)\n", conn->connection_number, cp, strlen(cp)); + debug(1, "Connection %d, unrecognised parameter: \"%s\" (%d)\n", conn->connection_number, cp, + strlen(cp)); } cp = next; } @@ -3058,7 +3132,8 @@ static void handle_get_parameter(__attribute__((unused)) rtsp_conn_info *conn, r if ((req->content) && (req->contentlength == strlen("volume\r\n")) && strstr(req->content, "volume") == req->content) { - debug(2,"Connection %d: Current volume (%.6f) requested", conn->connection_number, config.airplay_volume); + debug(2, "Connection %d: Current volume (%.6f) requested", conn->connection_number, + config.airplay_volume); char *p = malloc(128); // will be automatically deallocated with the response is deleted if (p) { resp->content = p; @@ -3153,11 +3228,13 @@ static void handle_set_parameter(rtsp_conn_info *conn, rtsp_message *req, rtsp_m // debug(2, "received parameters in SET_PARAMETER request."); handle_set_parameter_parameter(conn, req, resp); // this could be volume or progress } else { - debug(1, "Connection %d: received unknown Content-Type \"%s\" in SET_PARAMETER request.", conn->connection_number, ct); - debug_print_msg_headers(1,req); + debug(1, "Connection %d: received unknown Content-Type \"%s\" in SET_PARAMETER request.", + conn->connection_number, ct); + debug_print_msg_headers(1, req); } } else { - debug(1, "Connection %d: missing Content-Type header in SET_PARAMETER request.", conn->connection_number); + debug(1, "Connection %d: missing Content-Type header in SET_PARAMETER request.", + conn->connection_number); } resp->respcode = 200; } @@ -3449,7 +3526,7 @@ static void apple_challenge(int fd, rtsp_message *req, rtsp_message *resp) { char *hdr = msg_get_header(req, "Apple-Challenge"); if (!hdr) return; - debug(1,"Apple Challenge"); + debug(1, "Apple Challenge"); SOCKADDR fdsa; socklen_t sa_len = sizeof(fdsa); getsockname(fd, (struct sockaddr *)&fdsa, &sa_len); @@ -4119,8 +4196,8 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) { maxfd = sockfd[i]; } - char **t1; // ap1 test records - char **t2; // two text records + char **t1; // ap1 test records + char **t2; // two text records t1 = NULL; t2 = NULL; @@ -4130,14 +4207,14 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) { char **p = txt_records; t1 = p; // first set of text records -// make up a firmware version + // make up a firmware version char firmware_version[64]; #ifdef CONFIG_USE_GIT_VERSION_STRING - if (git_version_string[0] != '\0') - snprintf(firmware_version, sizeof(firmware_version), "fv=%s",git_version_string); - else + if (git_version_string[0] != '\0') + snprintf(firmware_version, sizeof(firmware_version), "fv=%s", git_version_string); + else #endif - snprintf(firmware_version, sizeof(firmware_version), "fv=%s",PACKAGE_VERSION); + snprintf(firmware_version, sizeof(firmware_version), "fv=%s", PACKAGE_VERSION); #ifdef CONFIG_AIRPLAY_2 char ap1_featuresString[64]; @@ -4152,7 +4229,7 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) { pkString_make(pkString + strlen("pk="), sizeof(pkString) - strlen("pk="), config.airplay_device_id); -// the ap1 text record is different if it is set up for ap2 + // the ap1 text record is different if it is set up for ap2 *p++ = "cn=0,1"; *p++ = "da=true"; *p++ = "et=0,4"; @@ -4198,7 +4275,6 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) { *p++ = NULL; #endif - #ifdef CONFIG_AIRPLAY_2 // make up a secondary set of text records char *secondary_txt_records[64]; @@ -4233,8 +4309,7 @@ void *rtsp_listen_loop(__attribute((unused)) void *arg) { *p++ = NULL; #endif - - mdns_register(t1,t2); + mdns_register(t1, t2); pthread_setcancelstate(oldState, NULL); int acceptfd; diff --git a/shairport.c b/shairport.c index b2d8886c..d143de66 100644 --- a/shairport.c +++ b/shairport.c @@ -1421,7 +1421,6 @@ void exit_function() { free(config.regtype2); #endif - #ifdef CONFIG_LIBDAEMON if (this_is_the_daemon_process) { daemon_retval_send(0); @@ -2038,39 +2037,34 @@ int main(int argc, char **argv) { pthread_create(&soxr_time_check_thread, NULL, &soxr_time_check, NULL); #endif -/* - uint8_t ap_md5[16]; + /* + uint8_t ap_md5[16]; -#ifdef CONFIG_OPENSSL - MD5_CTX ctx; - MD5_Init(&ctx); - MD5_Update(&ctx, config.service_name, strlen(config.service_name)); - MD5_Final(ap_md5, &ctx); -#endif + #ifdef CONFIG_OPENSSL + MD5_CTX ctx; + MD5_Init(&ctx); + MD5_Update(&ctx, config.service_name, strlen(config.service_name)); + MD5_Final(ap_md5, &ctx); + #endif -#ifdef CONFIG_MBEDTLS -#if MBEDTLS_VERSION_MINOR >= 7 - mbedtls_md5_context tctx; - mbedtls_md5_starts_ret(&tctx); - mbedtls_md5_update_ret(&tctx, (unsigned char *)config.service_name, strlen(config.service_name)); - mbedtls_md5_finish_ret(&tctx, ap_md5); -#else - mbedtls_md5_context tctx; - mbedtls_md5_starts(&tctx); - mbedtls_md5_update(&tctx, (unsigned char *)config.service_name, strlen(config.service_name)); - mbedtls_md5_finish(&tctx, ap_md5); -#endif -#endif + #ifdef CONFIG_MBEDTLS + #if MBEDTLS_VERSION_MINOR >= 7 + mbedtls_md5_context tctx; + mbedtls_md5_starts_ret(&tctx); + mbedtls_md5_update_ret(&tctx, (unsigned char *)config.service_name, + strlen(config.service_name)); mbedtls_md5_finish_ret(&tctx, ap_md5); #else mbedtls_md5_context + tctx; mbedtls_md5_starts(&tctx); mbedtls_md5_update(&tctx, (unsigned char *)config.service_name, + strlen(config.service_name)); mbedtls_md5_finish(&tctx, ap_md5); #endif #endif -#ifdef CONFIG_POLARSSL - md5_context tctx; - md5_starts(&tctx); - md5_update(&tctx, (unsigned char *)config.service_name, strlen(config.service_name)); - md5_finish(&tctx, ap_md5); -#endif + #ifdef CONFIG_POLARSSL + md5_context tctx; + md5_starts(&tctx); + md5_update(&tctx, (unsigned char *)config.service_name, strlen(config.service_name)); + md5_finish(&tctx, ap_md5); + #endif - memcpy(config.hw_addr, ap_md5, sizeof(config.hw_addr)); -*/ + memcpy(config.hw_addr, ap_md5, sizeof(config.hw_addr)); + */ #ifdef CONFIG_METADATA metadata_init(); // create the metadata pipe if necessary