diff --git a/README.html b/README.html index 595cb2b..60f2ceb 100644 --- a/README.html +++ b/README.html @@ -1,4 +1,4 @@ -

UxPlay 1.43: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix.

+

UxPlay 1.44: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix.

This project is a GPLv3 unix AirPlay2 server which now also works on macOS. Its main use is to act like an AppleTV for screen-mirroring (with audio) of iOS/macOS clients (iPads, iPhones, MacBooks) in a window on the server display (with the possibility of sharing that window on screen-sharing applications such as Zoom) on a host running Linux, macOS, or other unix, using Apple’s AirPlay Mirror protocol first available in iOS 5. (Details of what is known about the AirPlay2 protocol can be found here and here). Note that Apple DRM (as in Apple TV app content) cannot be decrypted by UxPlay.

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 DNS-SD “Service Discovery” service is necessary, it is not necessary that the local network also be of the “.local” mDNS-based type). On Linux and BSD Unix servers, this is usually provided by Avahi, through the avahi-daemon service, and is included in most Linux distributions (this service can also be provided by macOS, iOS or Windows servers).

Since v1.38, UxPlay now also supports the Airplay audio-only protocol as well as AirPlay Mirror protocol, and (when the client screen is not being mirrored) can play Apple Lossless (ALAC) audio streamed from the client without video (the accompanying cover-art and metadata is not displayed). The initial connection to the client can be either AirPlay audio or Airplay Mirror mode. An Airplay Mirror connection (with “Advanced Audio Coding” AAC-ELD lossy-compression audio) switches to ALAC if the mirrow window is closed and an AirPlay audio connection is started, and back again to AAC if a new Airplay Mirror connection is made.

@@ -56,7 +56,7 @@

The “OpenGL renderer” window created on Linux by “-vs glimagesink” sometimes does not close properly when its “close” button is clicked. (this is a GStreamer issue). You may need to terminate uxplay with Ctrl-C to close a “zombie” OpenGl window.

GStreamer issues: To troubleshoot GStreamer execute “export GST_DEBUG=2” to set the GStreamer debug-level environment-variable in the terminal where you will run uxplay, so that you see warning and error messages; (replace “2” by “4” to see much (much) more of what is happening inside GStreamer). Run “gst-inspect-1.0” to see which GStreamer plugins are installed on your system.

Some extra GStreamer packages for special plugins may need to be installed (or reinstalled: a user using a Wayland display system as an alternative to X11 reported that after reinstalling Lubuntu 18.4, UxPlay would not work until gstreamer1.0-x was installed, presumably for Wayland’s X11-compatibility mode). Different distributions may break up GStreamer 1.x into packages in different ways; the packages listed above in the build instructions should bring in other required GStreamer packages as dependencies, but will not install all possible plugins.

-

Use with non-Apple clients: one user tried to use UxPlay with an airmypc client (a non-free commercial Windows application that can mirror a Windows screen on an Apple TV using AirPlay mirror protocol). While airmypc can mirror to a true AppleTV and some other AirPlay receivers, UxPlay appears to correctly pair with this client, but then fails to decrypt both the audio and video streams. Possibly a different variant of the AirPlay encryption/decryption protocol not supported by UxPlay is used by this client. Without further information, there is no obvious fix. UxPlay reports itself to clients as an “AirTunes/220.68” server.

+

Use with non-Apple clients: third-party Windows-bases AirPlay clients such as AirMyPC typically use an older protocol that omits the hashing of the audio AES key with the “shared secret” ecdh_secret created during the initial pairing-handshake between client and server. Omission of this step was necessary for successful decryption of audio and video streams from the AirMyPC client, which emulates an old version of iOS, and reports its sourceVersion as 280.33. The line #define OLD_PROTOCOL_CLIENT "280.33" in lib/global.h makes UxPlay skip the aeskey hashing step when the client reports this or an older value as its sourceVersion. If both audio and video decryption fail when using another third-party client, and uxplay -d output shows that it reports a later sourceVersion, try increasing the value in global.h.

Usage:

Options:

-n server_name (Default: UxPlay); server_name@_hostname_ will be the name that appears offering AirPlay services to your iPad, iPhone etc, where hostname is the name of the server running uxplay. This will also now be the name shown above the mirror display (X11) window.

@@ -77,6 +77,7 @@

-as 0 (or just -a) suppresses playing of streamed audio, but displays streamed video.

-t timeout will cause the server to relaunch (without stopping uxplay) if no connections have been present during the previous timeout seconds. (You may wish to use this because the Server may not be visible to new Clients that were inactive when the Server was launched, and an idle Bonjour registration also eventually becomes unavailable for new connections.) The timer only starts once a Client has first made a mirror connection and then has disconnected with “Stop Mirrroring”. This option should not be used if the display window is an OpenGL window on macOS, as such an OpenGL window created by GStreamer does not terminate correctly (it causes a segfault) if it is still open when the GStreamer pipeline is closed.

ChangeLog

+

1.44 2021-12-13 no hash of aeskey with ecdh_secret if sourceVersion <= 280.33 (now supports AirMyPC)

1.43 2021-12-07 Various internal changes, such as tests for successful decryption, uniform treatment of informational/debug messages, etc., updated README.

1.42 2021-11-20 Fix MAC detection to work with modern Linux interface naming practices, MacOS and *BSD.

1.41 2021-11-11 Further cleanups of multiple audio format support (internal changes, separated RAOP and GStreamer audio/video startup)

@@ -103,6 +104,7 @@
  • UxPlay now builds on macOS.

  • The hostname of the server running uxplay is now appended to the AirPlay server name, which is now displayed as name@hostname, where name is “UxPlay”, (or whatever is set with the -n option).

  • Added support for audio-only streaming with original (non-Mirror) AirPlay protocol, with Apple Lossless (ALAC) audio.

  • +
  • Added suppport for the older AirPlay protocol used by third-party Windows-based AirPlay mirror emulators such as AirMyPC.

  • Disclaimer

    All the resources in this repository are written using only freely available information from the internet. The code and related resources are meant for educational purposes only. It is the responsibility of the user to make sure all local laws are adhered to.

    diff --git a/README.md b/README.md index d255a56..0e1119b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# UxPlay 1.43: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix. +# UxPlay 1.44: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix. This project is a GPLv3 unix AirPlay2 server which now also works on macOS. Its main use is to act like an AppleTV for screen-mirroring (with audio) of iOS/macOS clients @@ -251,12 +251,13 @@ reported that after reinstalling Lubuntu 18.4, UxPlay would not work until gstr Different distributions may break up GStreamer 1.x into packages in different ways; the packages listed above in the build instructions should bring in other required GStreamer packages as dependencies, but will not install all possible plugins. -**Use with non-Apple clients**: one user tried to use UxPlay with an *airmypc* client (a non-free commercial -Windows application that can mirror a Windows screen on an Apple TV using AirPlay mirror protocol). While *airmypc* -can mirror to a true AppleTV and some other AirPlay receivers, UxPlay appears to correctly pair with this client, but -then fails to decrypt both the audio and video streams. Possibly a different variant of the AirPlay encryption/decryption -protocol not supported by UxPlay is used by this client. Without further information, there is no obvious fix. -UxPlay reports itself to clients as an "AirTunes/220.68" server. +**Use with non-Apple clients**: third-party Windows-bases AirPlay clients such as AirMyPC typically use an older protocol +that omits the hashing of the audio AES key with the "shared secret" ```ecdh_secret``` created during the initial +pairing-handshake between client and server. Omission of this step was necessary for successful decryption of audio and video +streams from the AirMyPC client, which emulates an old version of iOS, and reports its ```sourceVersion``` as ```280.33```. + The line ```#define OLD_PROTOCOL_CLIENT "280.33"``` in ```lib/global.h``` makes UxPlay skip the aeskey hashing step when the client +reports this or an older value as its sourceVersion. If both audio and video decryption fail when using another third-party client, and +```uxplay -d``` output shows that it reports a later sourceVersion, try increasing the value in global.h. # **Usage:** @@ -362,6 +363,8 @@ Also: image transforms that had been added to RPiPlay have been ported to UxPlay # ChangeLog +1.44 2021-12-13 no hash of aeskey with ecdh_secret if sourceVersion <= 280.33 (now supports AirMyPC) + 1.43 2021-12-07 Various internal changes, such as tests for successful decryption, uniform treatment of informational/debug messages, etc., updated README. @@ -466,6 +469,8 @@ is compiled.) On macOS, Avahi is not used. 12. Added support for audio-only streaming with original (non-Mirror) AirPlay protocol, with Apple Lossless (ALAC) audio. +13. Added suppport for the older AirPlay protocol used by third-party Windows-based AirPlay mirror emulators such as AirMyPC. + # Disclaimer All the resources in this repository are written using only freely available information from the internet. The code and related resources are meant for educational purposes only. It is the responsibility of the user to make sure all local laws are adhered to. diff --git a/README.txt b/README.txt index 004013c..8063aa6 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,4 @@ -UxPlay 1.43: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix. +UxPlay 1.44: AirPlay/AirPlay-Mirror server for Linux, macOS, and Unix. ====================================================================== This project is a GPLv3 unix AirPlay2 server which now also works on @@ -333,16 +333,18 @@ GStreamer 1.x into packages in different ways; the packages listed above in the build instructions should bring in other required GStreamer packages as dependencies, but will not install all possible plugins. -**Use with non-Apple clients**: one user tried to use UxPlay with an -*airmypc* client (a non-free commercial Windows application that can -mirror a Windows screen on an Apple TV using AirPlay mirror protocol). -While *airmypc* can mirror to a true AppleTV and some other AirPlay -receivers, UxPlay appears to correctly pair with this client, but then -fails to decrypt both the audio and video streams. Possibly a different -variant of the AirPlay encryption/decryption protocol not supported by -UxPlay is used by this client. Without further information, there is no -obvious fix. UxPlay reports itself to clients as an "AirTunes/220.68" -server. +**Use with non-Apple clients**: third-party Windows-bases AirPlay +clients such as AirMyPC typically use an older protocol that omits the +hashing of the audio AES key with the "shared secret" `ecdh_secret` +created during the initial pairing-handshake between client and server. +Omission of this step was necessary for successful decryption of audio +and video streams from the AirMyPC client, which emulates an old version +of iOS, and reports its `sourceVersion` as `280.33`. The line +`#define OLD_PROTOCOL_CLIENT "280.33"` in `lib/global.h` makes UxPlay +skip the aeskey hashing step when the client reports this or an older +value as its sourceVersion. If both audio and video decryption fail when +using another third-party client, and `uxplay -d` output shows that it +reports a later sourceVersion, try increasing the value in global.h. **Usage:** ========== @@ -459,6 +461,9 @@ still open when the GStreamer pipeline is closed.* ChangeLog ========= +1.44 2021-12-13 no hash of aeskey with ecdh\_secret if sourceVersion \<= +280.33 (now supports AirMyPC) + 1.43 2021-12-07 Various internal changes, such as tests for successful decryption, uniform treatment of informational/debug messages, etc., updated README. @@ -582,6 +587,9 @@ Improvements since the original UxPlay by antimof: 12. Added support for audio-only streaming with original (non-Mirror) AirPlay protocol, with Apple Lossless (ALAC) audio. +13. Added suppport for the older AirPlay protocol used by third-party + Windows-based AirPlay mirror emulators such as AirMyPC. + Disclaimer ========== diff --git a/lib/global.h b/lib/global.h index aa4f6bd..b330f15 100755 --- a/lib/global.h +++ b/lib/global.h @@ -5,6 +5,7 @@ #define GLOBAL_MODEL "AppleTV2,1" #define GLOBAL_VERSION "220.68" +#define OLD_PROTOCOL_CLIENT "280.33" #define MAX_HWADDR_LEN 6 #endif diff --git a/lib/mirror_buffer.c b/lib/mirror_buffer.c index faaa800..208cca5 100755 --- a/lib/mirror_buffer.c +++ b/lib/mirror_buffer.c @@ -34,19 +34,13 @@ struct mirror_buffer_s { /* AES key and IV */ // Need secondary processing to use unsigned char aeskey[RAOP_AESKEY_LEN]; - unsigned char ecdh_secret[32]; }; void mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, uint64_t streamConnectionID) { - sha_ctx_t *ctx = sha_init(); - unsigned char eaeskey[64] = {}; + unsigned char eaeskey[16]; memcpy(eaeskey, mirror_buffer->aeskey, 16); - sha_update(ctx, eaeskey, 16); - sha_update(ctx, mirror_buffer->ecdh_secret, 32); - sha_final(ctx, eaeskey, NULL); - unsigned char hash1[64]; unsigned char hash2[64]; char* skey = "AirPlayStreamKey"; @@ -55,7 +49,8 @@ mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, uint64_t streamConnection unsigned char sivall[255]; sprintf((char*) skeyall, "%s%" PRIu64, skey, streamConnectionID); sprintf((char*) sivall, "%s%" PRIu64, siv, streamConnectionID); - sha_reset(ctx); + + sha_ctx_t *ctx = sha_init(); sha_update(ctx, skeyall, strlen((char*) skeyall)); sha_update(ctx, eaeskey, 16); sha_final(ctx, hash1, NULL); @@ -82,22 +77,18 @@ mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, uint64_t streamConnection } mirror_buffer_t * -mirror_buffer_init(logger_t *logger, - const unsigned char *aeskey, - const unsigned char *ecdh_secret) +mirror_buffer_init(logger_t *logger, const unsigned char *aeskey) { mirror_buffer_t *mirror_buffer; assert(aeskey); - assert(ecdh_secret); mirror_buffer = calloc(1, sizeof(mirror_buffer_t)); if (!mirror_buffer) { return NULL; } memcpy(mirror_buffer->aeskey, aeskey, RAOP_AESKEY_LEN); - memcpy(mirror_buffer->ecdh_secret, ecdh_secret, 32); mirror_buffer->logger = logger; mirror_buffer->nextDecryptCount = 0; - //mirror_buffer_init_aes(mirror_buffer, aeskey, ecdh_secret, streamConnectionID); + //mirror_buffer_init_aes(mirror_buffer, aeskey, streamConnectionID); return mirror_buffer; } diff --git a/lib/mirror_buffer.h b/lib/mirror_buffer.h index f64b340..4a45f9f 100755 --- a/lib/mirror_buffer.h +++ b/lib/mirror_buffer.h @@ -21,9 +21,7 @@ typedef struct mirror_buffer_s mirror_buffer_t; -mirror_buffer_t *mirror_buffer_init( logger_t *logger, - const unsigned char *aeskey, - const unsigned char *ecdh_secret); +mirror_buffer_t *mirror_buffer_init( logger_t *logger, const unsigned char *aeskey); void mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, uint64_t streamConnectionID); void mirror_buffer_decrypt(mirror_buffer_t *raop_mirror, unsigned char* input, unsigned char* output, int datalen); void mirror_buffer_destroy(mirror_buffer_t *mirror_buffer); diff --git a/lib/raop_buffer.c b/lib/raop_buffer.c index 1352e93..fc0f890 100755 --- a/lib/raop_buffer.c +++ b/lib/raop_buffer.c @@ -57,24 +57,20 @@ struct raop_buffer_s { raop_buffer_entry_t entries[RAOP_BUFFER_LENGTH]; }; -void -raop_buffer_init_key_iv(raop_buffer_t *raop_buffer, - const unsigned char *aeskey, - const unsigned char *aesiv, - const unsigned char *ecdh_secret) +raop_buffer_t * +raop_buffer_init(logger_t *logger, + const unsigned char *aeskey, + const unsigned char *aesiv) { - - // Initialization key - unsigned char eaeskey[64]; - memcpy(eaeskey, aeskey, 16); - - sha_ctx_t *ctx = sha_init(); - sha_update(ctx, eaeskey, 16); - sha_update(ctx, ecdh_secret, 32); - sha_final(ctx, eaeskey, NULL); - sha_destroy(ctx); - - memcpy(raop_buffer->aeskey, eaeskey, 16); + raop_buffer_t *raop_buffer; + assert(aeskey); + assert(aesiv); + raop_buffer = calloc(1, sizeof(raop_buffer_t)); + if (!raop_buffer) { + return NULL; + } + raop_buffer->logger = logger; + memcpy(raop_buffer->aeskey, aeskey, RAOP_AESKEY_LEN); memcpy(raop_buffer->aesiv, aesiv, RAOP_AESIV_LEN); #ifdef DUMP_AUDIO @@ -84,24 +80,6 @@ raop_buffer_init_key_iv(raop_buffer_t *raop_buffer, fclose(file_keyiv); } #endif -} - -raop_buffer_t * -raop_buffer_init(logger_t *logger, - const unsigned char *aeskey, - const unsigned char *aesiv, - const unsigned char *ecdh_secret) -{ - raop_buffer_t *raop_buffer; - assert(aeskey); - assert(aesiv); - assert(ecdh_secret); - raop_buffer = calloc(1, sizeof(raop_buffer_t)); - if (!raop_buffer) { - return NULL; - } - raop_buffer->logger = logger; - raop_buffer_init_key_iv(raop_buffer, aeskey, aesiv, ecdh_secret); for (int i = 0; i < RAOP_BUFFER_LENGTH; i++) { raop_buffer_entry_t *entry = &raop_buffer->entries[i]; diff --git a/lib/raop_buffer.h b/lib/raop_buffer.h index b03ed5d..542847d 100755 --- a/lib/raop_buffer.h +++ b/lib/raop_buffer.h @@ -24,8 +24,7 @@ typedef int (*raop_resend_cb_t)(void *opaque, unsigned short seqno, unsigned sho raop_buffer_t *raop_buffer_init(logger_t *logger, const unsigned char *aeskey, - const unsigned char *aesiv, - const unsigned char *ecdh_secret); + const unsigned char *aesiv); int raop_buffer_enqueue(raop_buffer_t *raop_buffer, unsigned char *data, unsigned short datalen, uint64_t timestamp, int use_seqnum); void *raop_buffer_dequeue(raop_buffer_t *raop_buffer, unsigned int *length, uint64_t *timestamp, int no_resend); void raop_buffer_handle_resends(raop_buffer_t *raop_buffer, raop_resend_cb_t resend_cb, void *opaque); diff --git a/lib/raop_handlers.h b/lib/raop_handlers.h index 5185cb6..25a8d9e 100755 --- a/lib/raop_handlers.h +++ b/lib/raop_handlers.h @@ -340,10 +340,9 @@ raop_handler_setup(raop_conn_t *conn, // Parsing bplist plist_t req_root_node = NULL; plist_from_bin(data, data_len, &req_root_node); - plist_t req_streams_node = plist_dict_get_item(req_root_node, "streams"); - plist_t req_eiv_node = plist_dict_get_item(req_root_node, "eiv"); plist_t req_ekey_node = plist_dict_get_item(req_root_node, "ekey"); - + plist_t req_eiv_node = plist_dict_get_item(req_root_node, "eiv"); + // For the response plist_t res_root_node = plist_new_dict(); @@ -360,7 +359,7 @@ raop_handler_setup(raop_conn_t *conn, plist_get_data_val(req_eiv_node, &eiv, &eiv_len); memcpy(aesiv, eiv, 16); logger_log(conn->raop->logger, LOGGER_DEBUG, "eiv_len = %llu", eiv_len); - char *str = utils_data_to_string(aesiv, 16, 16); + char* str = utils_data_to_string(aesiv, 16, 16); logger_log(conn->raop->logger, LOGGER_DEBUG, "16 byte aesiv (needed for AES-CBC audio decryption iv):\n%s", str); free(str); @@ -384,6 +383,24 @@ raop_handler_setup(raop_conn_t *conn, str = utils_data_to_string(ecdh_secret, X25519_KEY_SIZE, 16); logger_log(conn->raop->logger, LOGGER_DEBUG, "32 byte shared ecdh_secret:\n%s", str); free(str); + + /* sha-512 hashing of aeskey is skipped where the client has sourceVersion <= OLD_PROTOCOL_CLIENT (defined in global.h) */ + plist_t req_source_version_node = plist_dict_get_item(req_root_node, "sourceVersion"); + char* sourceVersion; + plist_get_string_val(req_source_version_node, &sourceVersion); + logger_log(conn->raop->logger, LOGGER_INFO, "client sourceVersion %s (no hash of aeskey if <= %s)", sourceVersion, OLD_PROTOCOL_CLIENT); + + char *end_ptr; + if (strtoul(sourceVersion, &end_ptr, 10) > strtoul(OLD_PROTOCOL_CLIENT , &end_ptr, 10)) { + unsigned char eaeskey[64] = {0}; + memcpy(eaeskey, aeskey, 16); + sha_ctx_t *ctx = sha_init(); + sha_update(ctx, eaeskey, 16); + sha_update(ctx, ecdh_secret, 32); + sha_final(ctx, eaeskey, NULL); + sha_destroy(ctx); + memcpy(aeskey, eaeskey, 16); + } // Time port uint64_t timing_rport; @@ -395,8 +412,8 @@ raop_handler_setup(raop_conn_t *conn, conn->raop_ntp = raop_ntp_init(conn->raop->logger, conn->remote, conn->remotelen, timing_rport); raop_ntp_start(conn->raop_ntp, &timing_lport); - conn->raop_rtp = raop_rtp_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp, conn->remote, conn->remotelen, aeskey, aesiv, ecdh_secret); - conn->raop_rtp_mirror = raop_rtp_mirror_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp, conn->remote, conn->remotelen, aeskey, ecdh_secret); + conn->raop_rtp = raop_rtp_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp, conn->remote, conn->remotelen, aeskey, aesiv); + conn->raop_rtp_mirror = raop_rtp_mirror_init(conn->raop->logger, &conn->raop->callbacks, conn->raop_ntp, conn->remote, conn->remotelen, aeskey); plist_t res_event_port_node = plist_new_uint(conn->raop->port); plist_t res_timing_port_node = plist_new_uint(timing_lport); @@ -407,6 +424,7 @@ raop_handler_setup(raop_conn_t *conn, } // Process stream setup requests + plist_t req_streams_node = plist_dict_get_item(req_root_node, "streams"); if (PLIST_IS_ARRAY(req_streams_node)) { plist_t res_streams_node = plist_new_array(); diff --git a/lib/raop_rtp.c b/lib/raop_rtp.c index 124ee7b..841187b 100755 --- a/lib/raop_rtp.c +++ b/lib/raop_rtp.c @@ -132,8 +132,8 @@ raop_rtp_parse_remote(raop_rtp_t *raop_rtp, const unsigned char *remote, int rem } raop_rtp_t * -raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, const unsigned char *remote, int remotelen, - const unsigned char *aeskey, const unsigned char *aesiv, const unsigned char *ecdh_secret) +raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, const unsigned char *remote, + int remotelen, const unsigned char *aeskey, const unsigned char *aesiv) { raop_rtp_t *raop_rtp; @@ -156,7 +156,7 @@ raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, co } memcpy(&raop_rtp->callbacks, callbacks, sizeof(raop_callbacks_t)); - raop_rtp->buffer = raop_buffer_init(logger, aeskey, aesiv, ecdh_secret); + raop_rtp->buffer = raop_buffer_init(logger, aeskey, aesiv); if (!raop_rtp->buffer) { free(raop_rtp); return NULL; diff --git a/lib/raop_rtp.h b/lib/raop_rtp.h index 5d66b67..38ccb2b 100755 --- a/lib/raop_rtp.h +++ b/lib/raop_rtp.h @@ -26,8 +26,8 @@ typedef struct raop_rtp_s raop_rtp_t; -raop_rtp_t *raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, const unsigned char *remote, int remotelen, - const unsigned char *aeskey, const unsigned char *aesiv, const unsigned char *ecdh_secret); +raop_rtp_t *raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, const unsigned char *remote, + int remotelen, const unsigned char *aeskey, const unsigned char *aesiv); void raop_rtp_start_audio(raop_rtp_t *raop_rtp, int use_udp, unsigned short control_rport, unsigned short *control_lport, unsigned short *data_lport); diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index 644797e..627006d 100755 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -109,8 +109,7 @@ raop_rtp_parse_remote(raop_rtp_mirror_t *raop_rtp_mirror, const unsigned char *r #define NO_FLUSH (-42) raop_rtp_mirror_t *raop_rtp_mirror_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, - const unsigned char *remote, int remotelen, - const unsigned char *aeskey, const unsigned char *ecdh_secret) + const unsigned char *remote, int remotelen, const unsigned char *aeskey) { raop_rtp_mirror_t *raop_rtp_mirror; @@ -125,7 +124,7 @@ raop_rtp_mirror_t *raop_rtp_mirror_init(logger_t *logger, raop_callbacks_t *call raop_rtp_mirror->ntp = ntp; memcpy(&raop_rtp_mirror->callbacks, callbacks, sizeof(raop_callbacks_t)); - raop_rtp_mirror->buffer = mirror_buffer_init(logger, aeskey, ecdh_secret); + raop_rtp_mirror->buffer = mirror_buffer_init(logger, aeskey); if (!raop_rtp_mirror->buffer) { free(raop_rtp_mirror); return NULL; diff --git a/lib/raop_rtp_mirror.h b/lib/raop_rtp_mirror.h index 13da680..0c22e7d 100755 --- a/lib/raop_rtp_mirror.h +++ b/lib/raop_rtp_mirror.h @@ -24,8 +24,7 @@ typedef struct raop_rtp_mirror_s raop_rtp_mirror_t; typedef struct h264codec_s h264codec_t; raop_rtp_mirror_t *raop_rtp_mirror_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, - const unsigned char *remote, int remotelen, - const unsigned char *aeskey, const unsigned char *ecdh_secret); + const unsigned char *remote, int remotelen, const unsigned char *aeskey); void raop_rtp_init_mirror_aes(raop_rtp_mirror_t *raop_rtp_mirror, uint64_t streamConnectionID); void raop_rtp_start_mirror(raop_rtp_mirror_t *raop_rtp_mirror, int use_udp, unsigned short *mirror_data_lport); void raop_rtp_mirror_stop(raop_rtp_mirror_t *raop_rtp_mirror); diff --git a/uxplay.1 b/uxplay.1 index 1002409..8b5b197 100644 --- a/uxplay.1 +++ b/uxplay.1 @@ -1,11 +1,11 @@ -.TH UXPLAY "1" "December 2021" "1.43" "User Commands" +.TH UXPLAY "1" "December 2021" "1.44" "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.43: An open\-source AirPlay mirroring server based on RPiPlay +UxPlay 1.44: An open\-source AirPlay mirroring server based on RPiPlay .SH OPTIONS .TP .B diff --git a/uxplay.cpp b/uxplay.cpp index f9f0084..5158102 100755 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -36,10 +36,6 @@ #include #endif - - - - #include "log.h" #include "lib/raop.h" #include "lib/stream.h" @@ -48,7 +44,7 @@ #include "renderers/video_renderer.h" #include "renderers/audio_renderer.h" -#define VERSION "1.43" +#define VERSION "1.44" #define DEFAULT_NAME "UxPlay" #define DEFAULT_DEBUG_LOG false @@ -74,7 +70,6 @@ static unsigned char compression_type = 0; static std::string audiosink = "autoaudiosink"; static bool use_audio = true; - gboolean connection_callback (gpointer loop){ if (!connections_stopped) { counter = 0;