rtp meged with lots of AP2 stuff still commented out. But it still works.

This commit is contained in:
Mike Brady
2021-04-29 15:04:50 +01:00
parent a8caa0f913
commit 8a73d5972c
6 changed files with 1509 additions and 179 deletions
+145
View File
@@ -43,6 +43,9 @@
#include <time.h>
#include <unistd.h>
#include <ifaddrs.h>
#include <netpacket/packet.h>
#ifdef COMPILE_FOR_OSX
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
@@ -266,6 +269,148 @@ uint16_t nextFreeUDPPort() {
return UDPPortIndex;
}
// if port is zero, pick any port
// otherwise, try the given port only
int bind_socket_and_port(int type, int ip_family, const char *self_ip_address, uint32_t scope_id,
uint16_t *port, int *sock) {
int ret = 0; // no error
int local_socket = socket(ip_family, type, 0);
if (local_socket == -1)
ret = errno;
if (ret == 0) {
SOCKADDR myaddr;
memset(&myaddr, 0, sizeof(myaddr));
if (ip_family == AF_INET) {
struct sockaddr_in *sa = (struct sockaddr_in *)&myaddr;
sa->sin_family = AF_INET;
sa->sin_port = ntohs(*port);
inet_pton(AF_INET, self_ip_address, &(sa->sin_addr));
ret = bind(local_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in));
}
#ifdef AF_INET6
if (ip_family == AF_INET6) {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&myaddr;
sa6->sin6_family = AF_INET6;
sa6->sin6_port = ntohs(*port);
inet_pton(AF_INET6, self_ip_address, &(sa6->sin6_addr));
sa6->sin6_scope_id = scope_id;
ret = bind(local_socket, (struct sockaddr *)sa6, sizeof(struct sockaddr_in6));
}
#endif
if (ret < 0) {
ret = errno;
close(local_socket);
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
warn("error %d: \"%s\". Could not bind a port!", errno, errorstring);
} else {
uint16_t sport;
SOCKADDR local;
socklen_t local_len = sizeof(local);
ret = getsockname(local_socket, (struct sockaddr *)&local, &local_len);
if (ret < 0) {
ret = errno;
close(local_socket);
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
warn("error %d: \"%s\". Could not retrieve socket's port!", errno, errorstring);
} else {
#ifdef AF_INET6
if (local.SAFAMILY == AF_INET6) {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&local;
sport = ntohs(sa6->sin6_port);
} else
#endif
{
struct sockaddr_in *sa = (struct sockaddr_in *)&local;
sport = ntohs(sa->sin_port);
}
*sock = local_socket;
*port = sport;
}
}
}
return ret;
}
uint16_t bind_UDP_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.
int ret = 0;
int local_socket = socket(ip_family, SOCK_DGRAM, IPPROTO_UDP);
if (local_socket == -1)
die("Could not allocate a socket.");
/*
int val = 1;
ret = setsockopt(local_socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
if (ret < 0) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "Error %d: \"%s\". Couldn't set SO_REUSEADDR");
}
*/
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;
sa->sin_family = AF_INET;
sa->sin_port = ntohs(desired_port);
inet_pton(AF_INET, self_ip_address, &(sa->sin_addr));
ret = bind(local_socket, (struct sockaddr *)sa, sizeof(struct sockaddr_in));
}
#ifdef AF_INET6
if (ip_family == AF_INET6) {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&myaddr;
sa6->sin6_family = AF_INET6;
sa6->sin6_port = ntohs(desired_port);
inet_pton(AF_INET6, self_ip_address, &(sa6->sin6_addr));
sa6->sin6_scope_id = scope_id;
ret = bind(local_socket, (struct sockaddr *)sa6, sizeof(struct sockaddr_in6));
}
#endif
} while ((ret < 0) && (errno == EADDRINUSE) && (desired_port != 0) &&
(tryCount < config.udp_port_range));
// debug(1,"UDP port chosen: %d.",desired_port);
if (ret < 0) {
close(local_socket);
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
die("error %d: \"%s\". 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! UDP base is %u, range is %u and "
"current suggestion is %u.",
errno, errorstring, config.udp_port_base, config.udp_port_range, desired_port);
}
uint16_t sport;
SOCKADDR local;
socklen_t local_len = sizeof(local);
getsockname(local_socket, (struct sockaddr *)&local, &local_len);
#ifdef AF_INET6
if (local.SAFAMILY == AF_INET6) {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&local;
sport = ntohs(sa6->sin6_port);
} else
#endif
{
struct sockaddr_in *sa = (struct sockaddr_in *)&local;
sport = ntohs(sa->sin_port);
}
*sock = local_socket;
return sport;
}
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; }
+6
View File
@@ -447,4 +447,10 @@ int string_update_with_size(char **str, int *flag, char *s, size_t len);
// from https://stackoverflow.com/questions/13663617/memdup-function-in-c, with thanks
void *memdup(const void *mem, size_t size);
int bind_socket_and_port(int type, int ip_family, const char *self_ip_address, uint32_t scope_id,
uint16_t *port, int *sock);
uint16_t bind_UDP_port(int ip_family, const char *self_ip_address, uint32_t scope_id, int *sock);
#endif // _COMMON_H
+1 -8
View File
@@ -117,13 +117,6 @@ uint32_t modulo_32_offset(uint32_t from, uint32_t to) {
return UINT32_MAX - from + to + 1;
}
uint64_t modulo_64_offset(uint64_t from, uint64_t to) {
if (from <= to)
return to - from;
else
return UINT64_MAX - from + to + 1;
}
void do_flush(uint32_t timestamp, rtsp_conn_info *conn);
static void ab_resync(rtsp_conn_info *conn) {
@@ -1589,7 +1582,7 @@ void player_thread_cleanup_handler(void *arg) {
if (conn->stream.type == ast_apple_lossless)
terminate_decoders(conn);
clear_reference_timestamp(conn);
reset_anchor_info(conn);
conn->rtp_running = 0;
pthread_setcancelstate(oldState, NULL);
}
+73 -4
View File
@@ -21,6 +21,11 @@
#include <openssl/aes.h>
#endif
#ifdef CONFIG_AIRPLAY_2
#include "pair_ap/pair-internal.h"
#include "plist/plist.h"
#endif
#include "alac.h"
#include "audio.h"
@@ -76,6 +81,11 @@ typedef enum {
ast_apple_lossless,
} audio_stream_type;
typedef enum {
ts_ntp,
ts_ptp
} timing_source_type;
typedef struct {
int encrypted;
uint8_t aesiv[16], aeskey[16];
@@ -83,8 +93,20 @@ typedef struct {
audio_stream_type type;
} stream_cfg;
#ifdef CONFIG_AIRPLAY_2
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;
#endif
typedef struct {
int connection_number; // for debug ID purposes, nothing else...
timing_source_type type_of_timing; // are we using NTP or PTP?
int resend_interval; // this is really just for debugging
char *UserAgent; // free this on teardown
int AirPlayVersion; // zero if not an AirPlay session. Used to help calculate latency
@@ -94,7 +116,7 @@ typedef struct {
uint32_t maximum_latency; // set if an a=max-latency: line appears in the ANNOUNCE message; zero
// otherwise
int software_mute_enabled; // if we don't have a real mute that we can use
int unachievable_audio_backend_latency_offset_notified; // set when a latency warning is issued
int fd;
int authorized; // set if a password is required and has been supplied
@@ -214,8 +236,56 @@ typedef struct {
// this is what connects an rtp timestamp to the remote time
uint32_t reference_timestamp;
uint64_t remote_reference_timestamp_time;
int anchor_remote_info_is_valid;
uint64_t anchor_clock;
uint64_t anchor_time; // this is the time according to the clock
uint32_t anchor_rtptime;
#ifdef CONFIG_AIRPLAY_2
pthread_t rtp_event_thread;
pthread_t rtp_ap2_control_thread;
pthread_t rtp_realtime_audio_thread;
pthread_t rtp_buffered_audio_thread;
int pairing_mode;
file_cipher_context control_cipher_context;
struct verifier_setup_context *server_setup_ctx;
int last_anchor_info_is_valid;
uint64_t last_anchor_clock_offset;
uint64_t last_anchor_time_of_update;
uint64_t last_anchor_clock;
ssize_t ap2_audio_buffer_size;
int ap2_flush_requested;
uint32_t ap2_flush_rtp_timestamp;
uint32_t ap2_flush_sequence_number;
int ap2_rate; // protect with flush mutex, 0 means don't play, 1 means play
int ap2_play_enabled; // protect with flush mutex
int event_socket;
SOCKADDR ap2_remote_control_socket_addr; // a socket pointing to the control port of the client
socklen_t ap2_remote_control_socket_addr_length;
int ap2_control_socket;
int realtime_audio_socket;
int buffered_audio_socket;
uint16_t local_event_port;
uint16_t local_ap2_control_port;
uint16_t local_realtime_audio_port;
uint16_t local_buffered_audio_port;
plist_t client_setup_plist;
uint64_t audio_format;
uint64_t compression;
unsigned char *session_key; // needs to be free'd at the end
uint64_t frames_packet;
uint64_t type;
uint64_t networkTimeTimelineID; // the clock ID used by the player
#endif
// used as the initials values for calculating the rate at which the source thinks it's sending
// frames
@@ -272,7 +342,6 @@ typedef struct {
} rtsp_conn_info;
uint32_t modulo_32_offset(uint32_t from, uint32_t to);
uint64_t modulo_64_offset(uint64_t from, uint64_t to);
int player_play(rtsp_conn_info *conn);
int player_stop(rtsp_conn_info *conn);
+1283 -160
View File
File diff suppressed because it is too large Load Diff
+1 -7
View File
@@ -17,17 +17,11 @@ void rtp_setup(SOCKADDR *local, SOCKADDR *remote, uint16_t controlport, uint16_t
void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn);
void rtp_request_client_pause(rtsp_conn_info *conn); // ask the client to pause
void get_reference_timestamp_stuff(uint32_t *timestamp, uint64_t *timestamp_time,
uint64_t *remote_timestamp_time, rtsp_conn_info *conn);
void clear_reference_timestamp(rtsp_conn_info *conn);
void reset_anchor_info(rtsp_conn_info *conn);
int have_timestamp_timing_information(rtsp_conn_info *conn);
int get_frame_play_time(int64_t timestamp, int sample_ratio, uint64_t *time_to_play);
int frame_to_local_time(uint32_t timestamp, uint64_t *time, rtsp_conn_info *conn);
int local_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn);
int sanitised_source_rate_information(uint32_t *frames, uint64_t *time, rtsp_conn_info *conn);
#endif // _RTP_H