rtp meged with lots of AP2 stuff still commented out. But it still works.
This commit is contained in:
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user