Merge pull request #210 from FDH2/testing

control clients allowed to connect
This commit is contained in:
fduncanh
2023-09-05 17:15:38 -04:00
committed by GitHub
7 changed files with 186 additions and 17 deletions

View File

@@ -1,6 +1,6 @@
<h1
id="uxplay-1.65-airplay-mirror-and-airplay-audio-server-for-linux-macos-and-unix-now-also-runs-on-windows.">UxPlay
1.65: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix
id="uxplay-1.66-airplay-mirror-and-airplay-audio-server-for-linux-macos-and-unix-now-also-runs-on-windows.">UxPlay
1.66: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix
(now also runs on Windows).</h1>
<h3
id="now-developed-at-the-github-site-httpsgithub.comfdh2uxplay-where-all-user-issues-should-be-posted.">Now
@@ -124,7 +124,7 @@ and <a href="https://emanuelecozzi.net/docs/airplay2">here</a>; see also
<a href="https://pyatv.dev/documentation/protocols">pyatv</a> which
could be a resource for adding modern protocols.) While there is no
guarantee that future iOS releases will keep supporting “Legacy
Protocol”, the recent iOS 16 release continues support.</p>
Protocol”, iOS 17 continues support.</p>
<p>The UxPlay server and its client must be on the same local area
network, on which a <strong>Bonjour/Zeroconf mDNS/DNS-SD server</strong>
is also running (only DNS-SD “Service Discovery” service is strictly
@@ -441,8 +441,11 @@ other problems.</p>
<li><p>By default, UxPlay is locked to its current client until that
client drops the connection; since UxPlay-1.58, the option
<code>-nohold</code> modifies this behavior so that when a new client
requests a connection, it removes the current client and takes
over.</p></li>
requests a connection, it removes the current client and takes over.
UxPlay 1.66 introduces a mechanism ( <code>-restrict</code>,
<code>-allow &lt;id&gt;</code>, <code>-block &lt;id&gt;</code>) to
control which clients are allowed to connect, using their immutable
“clientID”.</p></li>
<li><p>In Mirror mode, GStreamer has a choice of <strong>two</strong>
methods to play video with its accompanying audio: prior to UxPlay-1.64,
the video and audio streams were both played as soon as possible after
@@ -1013,6 +1016,23 @@ when the GStreamer pipeline is closed.</em></p>
<p><strong>-nohold</strong> Drops the current connection when a new
client attempts to connect. Without this option, the current client
maintains exclusive ownership of UxPlay until it disconnects.</p>
<p><strong>-restrict</strong> Restrict clients allowed to connect to
those specified by <code>-allow &lt;clientID&gt;</code>. The ClientID is
the true MAC address (in iOS it is listed in Settings-&gt;General-&gt;Wi
Fi Address), which is displayed by UxPlay when the client attempts to
connect. It has the format <code>XX:XX:XX:XX:XX:XX</code>, X =
0-9,A-F.</p>
<p><strong>-restrict no</strong> Remove restrictions (default). This is
useful as a command-line argument to overide restrictions set in the
Startup file.</p>
<p><strong>-allow <em>id</em></strong> Adds the clientID = <em>id</em>
to the list of allowed clients when client restrictions are being
enforced. Usually this will be an entry in the uxplayrc startup
file.</p>
<p><strong>-block <em>id</em></strong> Always block clients with
clientID = <em>id</em>, even when client restrictions are not being
enforced generally. Usually this will be an entry in the uxplayrc
startup file.</p>
<p><strong>-FPSdata</strong> Turns on monitoring of regular reports
about video streaming performance that are sent by the client. These
will be displayed in the terminal window if this option is used. The
@@ -1366,6 +1386,9 @@ an AppleTV6,2 with sourceVersion 380.20.1 (an AppleTV 4K 1st gen,
introduced 2017, running tvOS 12.2.1), so it does not seem to matter
what UxPlay claims to be.</p>
<h1 id="changelog">Changelog</h1>
<p>1.66 2023-09-05 Fix IPV6 support. Add option to restrict clients to
those on a list of allowed clientIDs, or to block connections from
clients on a list of blocked clientIDs.</p>
<p>1.65.3 2023-07-23 Add RPM spec file; add warning if required
gstreamer libav feature “avdec_aac” is missing: (this occurs in
RPM-based distributions that ship an incomplete FFmpeg for Patent or

View File

@@ -1,4 +1,4 @@
# UxPlay 1.65: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
# UxPlay 1.66: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
### Now developed at the GitHub site [https://github.com/FDH2/UxPlay](https://github.com/FDH2/UxPlay) (where all user issues should be posted).
@@ -86,7 +86,7 @@ Apple's AirPlay2 protocol using "Legacy Protocol", but some features are missing
[here](https://github.com/SteeBono/airplayreceiver/wiki/AirPlay2-Protocol) and
[here](https://emanuelecozzi.net/docs/airplay2); see also [pyatv](https://pyatv.dev/documentation/protocols) which could be
a resource for adding modern protocols.) While there is no guarantee that future
iOS releases will keep supporting "Legacy Protocol", the recent iOS 16 release continues support.
iOS releases will keep supporting "Legacy Protocol", iOS 17 continues support.
The UxPlay server and its client must be on the same local area network,
on which a **Bonjour/Zeroconf mDNS/DNS-SD server** is also running
@@ -361,7 +361,9 @@ help with this or other problems.
* By default, UxPlay is locked to
its current client until that client drops the connection; since UxPlay-1.58, the option `-nohold` modifies this
behavior so that when a new client requests a connection, it removes the current client and takes over.
behavior so that when a new client requests a connection, it removes the current client and takes over. UxPlay 1.66 introduces
a mechanism ( `-restrict`, ``-allow <id>``, ```-block <id>```) to control which clients are allowed to connect, using their
immutable "clientID".
* In Mirror mode, GStreamer has a choice of **two** methods to play video with its accompanying audio: prior to UxPlay-1.64,
the video and audio streams were both played as soon as possible after they arrived (the GStreamer "_sync=false_" method), with
@@ -808,6 +810,19 @@ which will not work if a firewall is running.
**-nohold** Drops the current connection when a new client attempts to connect. Without this option,
the current client maintains exclusive ownership of UxPlay until it disconnects.
**-restrict** Restrict clients allowed to connect to those specified by `-allow <clientID>`. The ClientID is the
true MAC address (in iOS it is listed in Settings->General->Wi Fi Address), which is displayed by UxPlay when
the client attempts to connect. It has the format `XX:XX:XX:XX:XX:XX`, X = 0-9,A-F.
**-restrict no** Remove restrictions (default). This is useful as a command-line argument to overide restrictions set
in the Startup file.
**-allow _id_** Adds the clientID = _id_ to the list of allowed clients when client restrictions
are being enforced. Usually this will be an entry in the uxplayrc startup file.
**-block _id_** Always block clients with clientID = _id_, even when client restrictions are not
being enforced generally. Usually this will be an entry in the uxplayrc startup file.
**-FPSdata** Turns on monitoring of regular reports about video streaming performance
that are sent by the client. These will be displayed in the terminal window if this
option is used. The data is updated by the client at 1 second intervals.
@@ -1084,6 +1099,9 @@ tvOS 12.2.1), so it does not seem to matter what UxPlay claims to be.
# Changelog
1.66 2023-09-05 Fix IPV6 support. Add option to restrict clients to those on a list of allowed clientIDs,
or to block connections from clients on a list of blocked clientIDs.
1.65.3 2023-07-23 Add RPM spec file; add warning if required gstreamer libav feature "avdec_aac" is
missing: (this occurs in RPM-based distributions that ship an incomplete FFmpeg for Patent
or License reasons, and rely on users installing an externally-supplied complete FFmpeg).

View File

@@ -1,4 +1,4 @@
# UxPlay 1.65: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
# UxPlay 1.66: AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
### Now developed at the GitHub site <https://github.com/FDH2/UxPlay> (where all user issues should be posted).
@@ -119,8 +119,8 @@ is publicly known about Apple's AirPlay 2 protocol can be found
and [here](https://emanuelecozzi.net/docs/airplay2); see also
[pyatv](https://pyatv.dev/documentation/protocols) which could be a
resource for adding modern protocols.) While there is no guarantee that
future iOS releases will keep supporting "Legacy Protocol", the recent
iOS 16 release continues support.
future iOS releases will keep supporting "Legacy Protocol", iOS 17
continues support.
The UxPlay server and its client must be on the same local area network,
on which a **Bonjour/Zeroconf mDNS/DNS-SD server** is also running (only
@@ -433,7 +433,10 @@ below for help with this or other problems.
- By default, UxPlay is locked to its current client until that client
drops the connection; since UxPlay-1.58, the option `-nohold`
modifies this behavior so that when a new client requests a
connection, it removes the current client and takes over.
connection, it removes the current client and takes over. UxPlay
1.66 introduces a mechanism ( `-restrict`, `-allow <id>`,
`-block <id>`) to control which clients are allowed to connect,
using their immutable "clientID".
- In Mirror mode, GStreamer has a choice of **two** methods to play
video with its accompanying audio: prior to UxPlay-1.64, the video
@@ -1026,6 +1029,23 @@ closed.*
connect. Without this option, the current client maintains exclusive
ownership of UxPlay until it disconnects.
**-restrict** Restrict clients allowed to connect to those specified by
`-allow <clientID>`. The ClientID is the true MAC address (in iOS it is
listed in Settings-\>General-\>Wi Fi Address), which is displayed by
UxPlay when the client attempts to connect. It has the format
`XX:XX:XX:XX:XX:XX`, X = 0-9,A-F.
**-restrict no** Remove restrictions (default). This is useful as a
command-line argument to overide restrictions set in the Startup file.
**-allow *id*** Adds the clientID = *id* to the list of allowed clients
when client restrictions are being enforced. Usually this will be an
entry in the uxplayrc startup file.
**-block *id*** Always block clients with clientID = *id*, even when
client restrictions are not being enforced generally. Usually this will
be an entry in the uxplayrc startup file.
**-FPSdata** Turns on monitoring of regular reports about video
streaming performance that are sent by the client. These will be
displayed in the terminal window if this option is used. The data is
@@ -1396,6 +1416,10 @@ what UxPlay claims to be.
# Changelog
1.66 2023-09-05 Fix IPV6 support. Add option to restrict clients to
those on a list of allowed clientIDs, or to block connections from
clients on a list of blocked clientIDs.
1.65.3 2023-07-23 Add RPM spec file; add warning if required gstreamer
libav feature "avdec_aac" is missing: (this occurs in RPM-based
distributions that ship an incomplete FFmpeg for Patent or License

View File

@@ -70,6 +70,7 @@ struct raop_callbacks_s {
void (*audio_set_progress)(void *cls, unsigned int start, unsigned int curr, unsigned int end);
void (*audio_get_format)(void *cls, unsigned char *ct, unsigned short *spf, bool *usingScreen, bool *isMedia, uint64_t *audioFormat);
void (*video_report_size)(void *cls, float *width_source, float *height_source, float *width, float *height);
void (*report_client_request) (void *cls, char *deviceid, char *model, char *name, bool *admit);
};
typedef struct raop_callbacks_s raop_callbacks_t;
raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote, int remote_addr_len,

View File

@@ -354,6 +354,33 @@ raop_handler_setup(raop_conn_t *conn,
// First setup
char* eiv = NULL;
uint64_t eiv_len = 0;
char *deviceID = NULL;
char *model = NULL;
char *name = NULL;
bool admit_client = true;
plist_t req_deviceid_node = plist_dict_get_item(req_root_node, "deviceID");
plist_get_string_val(req_deviceid_node, &deviceID);
plist_t req_model_node = plist_dict_get_item(req_root_node, "model");
plist_get_string_val(req_model_node, &model);
plist_t req_name_node = plist_dict_get_item(req_root_node, "name");
plist_get_string_val(req_name_node, &name);
if (conn->raop->callbacks.report_client_request) {
conn->raop->callbacks.report_client_request(conn->raop->callbacks.cls, deviceID, model, name, &admit_client);
}
free (deviceID);
deviceID = NULL;
free (model);
model = NULL;
free (name);
name = NULL;
if (admit_client == false) {
/* client is not authorized to connect */
plist_free(res_root_node);
plist_free(req_root_node);
return;
}
plist_get_data_val(req_eiv_node, &eiv, &eiv_len);
memcpy(aesiv, eiv, 16);
free(eiv);

View File

@@ -1,11 +1,11 @@
.TH UXPLAY "1" "June 2023" "1.65" "User Commands"
.TH UXPLAY "1" "September 2023" "1.66" "User Commands"
.SH NAME
uxplay \- start AirPlay server
.SH SYNOPSIS
.B uxplay
[\fI\,-n name\/\fR] [\fI\,-s wxh\/\fR] [\fI\,-p \/\fR[\fI\,n\/\fR]] [more \fI OPTIONS \/\fR ...]
.SH DESCRIPTION
UxPlay 1.65: An open\-source AirPlay mirroring (+ audio streaming) server:
UxPlay 1.66: An open\-source AirPlay mirroring (+ audio streaming) server:
.SH OPTIONS
.TP
.B
@@ -92,6 +92,16 @@ UxPlay 1.65: An open\-source AirPlay mirroring (+ audio streaming) server:
.TP
\fB\-nohold\fR Drop current connection when new client connects.
.TP
\fB\-restrict\fR Restrict clients to those specified by "-allow clientID".
.IP
Uxplay displays clientID when a client attempts connection.
.IP
Use "-restrict no" for no client restrictions (default).
.PP
\fB\-allow\fR id Permit clientID = id to connect if restrictions are imposed.
.TP
\fB\-block\fR id Always block connections from clientID = id.
.TP
\fB\-FPSdata\fR Show video-streaming performance reports sent by client.
.TP
\fB\-fps\fR n Set maximum allowed streaming framerate, default 30

View File

@@ -59,7 +59,7 @@
#include "renderers/video_renderer.h"
#include "renderers/audio_renderer.h"
#define VERSION "1.65"
#define VERSION "1.66"
#define SECOND_IN_USECS 1000000
#define SECOND_IN_NSECS 1000000000UL
@@ -121,6 +121,9 @@ static int max_connections = 2;
static unsigned short raop_port;
static unsigned short airplay_port;
static uint64_t remote_clock_offset = 0;
static std::vector<std::string> allowed_clients;
static std::vector<std::string> blocked_clients;
static bool restrict_clients;
/* 95 byte png file with a 1x1 white square (single pixel): placeholder for coverart*/
static const unsigned char empty_image[] = {
@@ -442,6 +445,11 @@ static void print_info (char *name) {
printf("-reset n Reset after 3n seconds client silence (default %d, 0=never)\n", NTP_TIMEOUT_LIMIT);
printf("-nc do Not Close video window when client stops mirroring\n");
printf("-nohold Drop current connection when new client connects.\n");
printf("-restrict Restrict clients to those specified by \"-allow <clientID>\"\n");
printf(" UxPlay displays clientID when a client attempts connection\n");
printf(" Use \"-restrict no\" for no client restrictions (default)\n");
printf("-allow <i>Permit clientID = <i> to connect if restrictions are imposed\n");
printf("-block <i>Always block connections from clientID = <i>\n");
printf("-FPSdata Show video-streaming performance reports sent by client.\n");
printf("-fps n Set maximum allowed streaming framerate, default 30\n");
printf("-f {H|V|I}Horizontal|Vertical flip, or both=Inversion=rotate 180 deg\n");
@@ -599,7 +607,24 @@ static void parse_arguments (int argc, char *argv[]) {
// Parse arguments
for (int i = 1; i < argc; i++) {
std::string arg(argv[i]);
if (arg == "-n") {
if (arg == "-allow") {
if (!option_has_value(i, argc, arg, argv[i+1])) exit(1);
i++;
allowed_clients.push_back(argv[i]);
} else if (arg == "-block") {
if (!option_has_value(i, argc, arg, argv[i+1])) exit(1);
i++;
blocked_clients.push_back(argv[i]);
} else if (arg == "-restrict") {
if (i < argc - 1) {
if (strlen(argv[i+1]) == 2 && strncmp(argv[i+1], "no", 2) == 0) {
restrict_clients = false;
i++;
continue;
}
}
restrict_clients = true;
} else if (arg == "-n") {
if (!option_has_value(i, argc, arg, argv[i+1])) exit(1);
server_name = std::string(argv[++i]);
} else if (arg == "-nh") {
@@ -1040,6 +1065,29 @@ static int start_dnssd(std::vector<char> hw_addr, std::string name) {
return 0;
}
static bool check_client(char *deviceid) {
bool ret = false;
int list = allowed_clients.size();
for (int i = 0; i < list ; i++) {
if (!strcmp(deviceid,allowed_clients[i].c_str())) {
ret = true;
break;
}
}
return ret;
}
static bool check_blocked_client(char *deviceid) {
bool ret = false;
int list = blocked_clients.size();
for (int i = 0; i < list ; i++) {
if (!strcmp(deviceid,blocked_clients[i].c_str())) {
ret = true;
break;
}
}
return ret;
}
// Server callbacks
extern "C" void conn_init (void *cls) {
@@ -1079,6 +1127,23 @@ extern "C" void conn_teardown(void *cls, bool *teardown_96, bool *teardown_110)
}
}
extern "C" void report_client_request(void *cls, char *deviceid, char * model, char *name, bool * admit) {
LOGI("connection request from %s (%s) with deviceID = %s\n", name, model, deviceid);
if (restrict_clients) {
*admit = check_client(deviceid);
if (*admit == false) {
LOGI("client connections have been restricted to those with listed deviceID,\nuse \"-allow %s\" to allow this client to connect.\n",
deviceid);
}
} else {
*admit = true;
}
if (check_blocked_client(deviceid)) {
*admit = false;
LOGI("*** attempt to connect by blocked client (clientID %s): DENIED\n", deviceid);
}
}
extern "C" void audio_process (void *cls, raop_ntp_t *ntp, audio_decode_struct *data) {
if (dump_audio) {
dump_audio_to_file(data->data, data->data_len, (data->data)[0] & 0xf0);
@@ -1274,7 +1339,8 @@ int start_raop_server (unsigned short display[5], unsigned short tcp[3], unsigne
raop_cbs.video_report_size = video_report_size;
raop_cbs.audio_set_metadata = audio_set_metadata;
raop_cbs.audio_set_coverart = audio_set_coverart;
raop_cbs.report_client_request = report_client_request;
/* set max number of connections = 2 to protect against capture by new client */
raop = raop_init(max_connections, &raop_cbs);
if (raop == NULL) {