From 0e952e3cbeda68a81593f5c9e1ce6a60d955beff Mon Sep 17 00:00:00 2001 From: FD_ Date: Mon, 6 May 2019 17:17:50 +0200 Subject: [PATCH] Updated license information --- README.md | 27 +- lib/CMakeLists.txt | 3 + lib/byteutils.c | 16 +- lib/byteutils.h | 16 +- lib/mirror_buffer.c | 16 +- lib/mirror_buffer.h | 16 +- lib/plist.c | 1065 ----------------------------------------- lib/plist.h | 53 -- lib/raop_ntp.c | 17 +- lib/raop_ntp.h | 17 +- lib/raop_rtp_mirror.c | 16 +- lib/raop_rtp_mirror.h | 16 +- lib/stream.h | 16 +- log.h | 21 +- 14 files changed, 148 insertions(+), 1167 deletions(-) delete mode 100755 lib/plist.c delete mode 100755 lib/plist.h diff --git a/README.md b/README.md index 3d020538..9b708821 100644 --- a/README.md +++ b/README.md @@ -5,28 +5,17 @@ The goal is to make it run smoothly even on a Raspberry Pi Zero. # State -Screen mirroring and audio works. The GPU is used for decoding the h264 -video stream. The Pi has no hardware acceleration for audio (AirPlay uses AAC), -so the FDK-AAC decoder is used for that. +Screen mirroring and audio works for iOS 9 or newer. Recent macOS versions also seem to be compatible. The GPU is used for decoding the h264 video stream. The Pi has no hardware acceleration for audio (AirPlay uses AAC), so the FDK-AAC decoder is used for that. -Both works fine one a Raspberry Pi 3B+. Unfortunately, it seems the Pi Zero -is too slow for decoding audio at a reasonable speed. -In order to get audio decoding fast enough for the Pi Zero, we likely have -to use a different AAC decoder library. +Both works fine one a Raspberry Pi 3B+. Unfortunately, it seems the Pi Zero is too slow for decoding audio at a reasonable speed. In order to get audio decoding fast enough for the Pi Zero, we likely have to use a different AAC decoder library. -By using OpenSSL for AES decryption, I was able to speed up the decryption of -video packets from up to 0.2 seconds to up to 0.007 seconds for large packets -(On the Pi Zero). Average is now more like 0.002 seconds. +By using OpenSSL for AES decryption, I was able to speed up the decryption of video packets from up to 0.2 seconds to up to 0.007 seconds for large packets (On the Pi Zero). Average is now more like 0.002 seconds. -If you are seeing long playback pauses, make sure the DUMP flags are not active. -Disk IO can slow down the whole program when dumping to files. +If you are seeing long playback pauses, make sure the DUMP flags are not active. Disk IO can slow down the whole program when dumping to files. There still are some minor issues. Have a look at the TODO list below. -Please note RPiPlay might not be suitable for remote video playback, as it -lacks a dedicated component for that: It seems like AirPlay on an AppleTV -switches to a standard AirPlay connection when video playback starts, thus -avoiding the re-encoding of the video. +Please note RPiPlay might not be suitable for remote video playback, as it lacks a dedicated component for that: It seems like AirPlay on an AppleTV switches to a standard AirPlay connection when video playback starts, thus avoiding the re-encoding of the video. For details, refer to the [inofficial AirPlay specification](https://nto.github.io/AirPlay.html#screenmirroring). # Building @@ -68,7 +57,7 @@ At the moment, these options are implemented: The code in this repository accumulated from various sources over time. Here is my attempt at listing the various authors and the components they created: -* **dsafa22**: Created an [AirPlay 2 mirroring server](https://github.com/dsafa22/AirplayServer) for Android based on ShairPlay. This project is basically a port of dsafa22's code to the Raspberry Pi, utilizing OpenMAX and OpenSSL for better performance on the Pi. All code in `lib/` with a header crediting `Administrator` is dsafa22's work. License: unknown +* **dsafa22**: Created an [AirPlay 2 mirroring server](https://github.com/dsafa22/AirplayServer) for Android based on ShairPlay. This project is basically a port of dsafa22's code to the Raspberry Pi, utilizing OpenMAX and OpenSSL for better performance on the Pi. All code in `lib/` with a header crediting `Administrator` is dsafa22's work. License: GNU LGPLv2.1+ * **Juho Vähä-Herttua** and contributors: Created an AirPlay audio server called [ShairPlay](https://github.com/juhovh/shairplay), including support for Fairplay based on PlayFair. Most of the code in `lib/` originally stems from this project. License: GNU LGPLv2.1+ * **EstebanKubata**: Created a FairPlay library called [PlayFair](https://github.com/EstebanKubata/playfair). Located in the `lib/playfair` folder. License: GNU GPL * **Jonathan Beck, Nikias Bassen** and contributors: Created a library for plist handling called [libplist](https://github.com/libimobiledevice/libplist). Located in the `lib/plist` folder. License: GNU LGPLv2.1+ @@ -80,7 +69,7 @@ The code in this repository accumulated from various sources over time. Here is # Contributing -I'm not planning to regularly maintain this project. Instead, I'm hoping this project can be improved in a community effort. I'll fix and add as much as I need for personal use, and I count on you to do the same! +I'm afraid I won't have time to regularly maintain this project. Instead, I'm hoping this project can be improved in a community effort. I'll fix and add as much as I need for personal use, and I count on you to do the same! Your contributions are more than welcome! @@ -131,4 +120,4 @@ iOS 11.4 added AirPlay 2 in 2018. Although extensively covered by the media, it' From captures of the traffic between an iOS device running iOS 12.2 and an AppleTV running tvOS 12.2.1, one can see that the communication on the main mirroring HTTP connection is encrypted once the handshake is completed. This could theoretically be part of the new AirPlay 2 protocol. The AppleTV running tvOS 12.2.1 identifies as AirTunes/380.20.1. -When connecting from the same iOS device to an AppleTV 3rd generation (reporting as AirTunes/220.68), the communication is still visible in plain. From the log messages that the iOS device produces when connected to an AppleTV 3rd generation, it becomes apparent that the iOS device is treating this plain protocol as the legacy protocol (as originally introduced with iOS 9). Further research showed that at the moment, all available third-party AirPlay mirroring receivers (servers) are using this legacy protocol. Given Apple considers this a legacy protocol, it can be expected to be removed entirely in the future. This means that all third-party AirPlay receivers will have to be updated to the new (fully encrypted) protocol at some point. \ No newline at end of file +When connecting from the same iOS device to an AppleTV 3rd generation (reporting as AirTunes/220.68), the communication is still visible in plain. From the log messages that the iOS device produces when connected to an AppleTV 3rd generation, it becomes apparent that the iOS device is treating this plain protocol as the legacy protocol (as originally introduced with iOS 9). Further research showed that at the moment, all available third-party AirPlay mirroring receivers (servers) are using this legacy protocol. Given Apple considers this a legacy protocol, it can be expected to be removed entirely in the future. This means that all third-party AirPlay receivers will have to be updated to the new (fully encrypted) protocol at some point. diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 89be9908..b471e78d 100755 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -10,6 +10,9 @@ add_library( play-lib ${DIR_SRCS} ) + +set($ENV{OPENSSL_ROOT_DIR} "/usr/local/opt/openssl@1.1/") +set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl@1.1/") find_package(OpenSSL REQUIRED) target_link_libraries( play-lib diff --git a/lib/byteutils.c b/lib/byteutils.c index 7731f646..c08cb2e7 100755 --- a/lib/byteutils.c +++ b/lib/byteutils.c @@ -1,6 +1,16 @@ -// -// Created by Administrator on 2019/1/10/010. -// +/* + * Copyright (c) 2019 dsafa22, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #include #include "byteutils.h" diff --git a/lib/byteutils.h b/lib/byteutils.h index 25dbd5f9..a3a75637 100755 --- a/lib/byteutils.h +++ b/lib/byteutils.h @@ -1,6 +1,16 @@ -// -// Created by Administrator on 2019/1/10/010. -// +/* + * Copyright (c) 2019 dsafa22, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #ifndef AIRPLAYSERVER_BYTEUTILS_H #define AIRPLAYSERVER_BYTEUTILS_H diff --git a/lib/mirror_buffer.c b/lib/mirror_buffer.c index ab5cf5e9..f8df5453 100755 --- a/lib/mirror_buffer.c +++ b/lib/mirror_buffer.c @@ -1,6 +1,16 @@ -// -// Created by Administrator on 2019/1/29/029. -// +/* + * Copyright (c) 2019 dsafa22, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #include "mirror_buffer.h" #include "raop_rtp.h" diff --git a/lib/mirror_buffer.h b/lib/mirror_buffer.h index 880207c7..f64b340d 100755 --- a/lib/mirror_buffer.h +++ b/lib/mirror_buffer.h @@ -1,6 +1,16 @@ -// -// Created by Administrator on 2019/1/29/029. -// +/* + * Copyright (c) 2019 dsafa22, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #ifndef MIRROR_BUFFER_H #define MIRROR_BUFFER_H diff --git a/lib/plist.c b/lib/plist.c deleted file mode 100755 index c54904e4..00000000 --- a/lib/plist.c +++ /dev/null @@ -1,1065 +0,0 @@ -#include -#include -#include -#include - -#include "plist.h" - -#define BPLIST_HEADER_LEN 8 -#define BPLIST_TRAILER_LEN 32 - -typedef struct { - uint64_t length; - uint8_t *value; -} plist_data_t; - -typedef struct { - uint64_t size; - plist_object_t **values; -} plist_array_t; - -typedef struct { - uint64_t size; - char **keys; - plist_object_t **values; -} plist_dict_t; - -struct plist_object_s { - uint8_t type; - union { - uint8_t value_primitive; - int64_t value_integer; - double value_real; - plist_data_t value_data; - char * value_string; - plist_array_t value_array; - plist_dict_t value_dict; - } value; -}; - -static int -parse_integer(const uint8_t *data, uint64_t dataidx, uint8_t length, int64_t *value) { - assert(data); - assert(value); - - switch (length) { - case 1: - *value = data[dataidx++]; - break; - case 2: - *value = ((int64_t) data[dataidx++]) << 8; - *value |= (int64_t) data[dataidx++]; - break; - case 4: - *value = ((int64_t) data[dataidx++]) << 24; - *value |= ((int64_t) data[dataidx++]) << 16; - *value |= ((int64_t) data[dataidx++]) << 8; - *value |= (int64_t) data[dataidx++]; - break; - case 8: - *value = ((int64_t) data[dataidx++]) << 56; - *value |= ((int64_t) data[dataidx++]) << 48; - *value |= ((int64_t) data[dataidx++]) << 40; - *value |= ((int64_t) data[dataidx++]) << 32; - *value |= ((int64_t) data[dataidx++]) << 24; - *value |= ((int64_t) data[dataidx++]) << 16; - *value |= ((int64_t) data[dataidx++]) << 8; - *value |= (int64_t) data[dataidx++]; - break; - default: - return -1; - } - return length; -} - -static int -serialize_integer(uint8_t *data, uint64_t *dataidx, uint8_t length, int64_t value) -{ - switch (length) { - case 1: - data[(*dataidx)++] = (uint8_t) value; - break; - case 2: - data[(*dataidx)++] = (uint8_t) (value >> 8); - data[(*dataidx)++] = (uint8_t) value; - break; - case 4: - data[(*dataidx)++] = (uint8_t) (value >> 24); - data[(*dataidx)++] = (uint8_t) (value >> 16); - data[(*dataidx)++] = (uint8_t) (value >> 8); - data[(*dataidx)++] = (uint8_t) value; - break; - case 8: - data[(*dataidx)++] = (uint8_t) (value >> 56); - data[(*dataidx)++] = (uint8_t) (value >> 48); - data[(*dataidx)++] = (uint8_t) (value >> 40); - data[(*dataidx)++] = (uint8_t) (value >> 32); - data[(*dataidx)++] = (uint8_t) (value >> 24); - data[(*dataidx)++] = (uint8_t) (value >> 16); - data[(*dataidx)++] = (uint8_t) (value >> 8); - data[(*dataidx)++] = (uint8_t) value; - break; - default: - return -1; - } - return length; -} - -static int -parse_real(const uint8_t *data, uint64_t dataidx, uint64_t length, double *value) -{ - assert(data); - assert(value); - - if (length == 4) { - *value = *((float *) &data[dataidx]); - } else { - *value = *((double *) &data[dataidx]); - } - return length; -} - -static uint8_t -integer_length(int64_t value) { - if (value > 0 && value < (1 << 8)) { - return 1; - } else if (value > 0 && value < (1 << 16)) { - return 2; - } else if (value > 0 && value < ((int64_t) 1 << 32)) { - return 4; - } else { - return 8; - } -} - -static uint8_t -blist_integer_length(int64_t value) { - if (value > 0 && value < (1 << 8)) { - return 0; - } else if (value > 0 && value < (1 << 16)) { - return 1; - } else if (value > 0 && value < ((int64_t) 1 << 32)) { - return 2; - } else { - return 3; - } -} - -static void -bplist_analyze(plist_object_t *object, uint64_t *objects, uint64_t *bytes, uint64_t *refs) -{ - int64_t count; - int64_t i; - - *objects += 1; - if (!object) { - *bytes += 1; - return; - } - if (object->type == PLIST_TYPE_PRIMITIVE) { - *bytes += 1; - } else if (object->type == PLIST_TYPE_INTEGER) { - *bytes += 1+integer_length(object->value.value_integer); - } else if (object->type == PLIST_TYPE_REAL) { - *bytes += 1+8; - } else if (object->type == PLIST_TYPE_DATA) { - uint64_t length = object->value.value_data.length; - if (length < 15) { - *bytes += 1+length; - } else { - *bytes += 1+1+integer_length(length)+length; - } - } else if (object->type == PLIST_TYPE_STRING) { - uint64_t length = strlen(object->value.value_string); - if (length < 15) { - *bytes += 1+length; - } else { - *bytes += 1+1+integer_length(length)+length; - } - } else if (object->type == PLIST_TYPE_ARRAY) { - uint64_t size = object->value.value_array.size; - if (size < 15) { - *bytes += 1; - } else { - *bytes += 1+1+integer_length(size); - } - *refs += size; - for (i=0; ivalue.value_array.values[i], objects, bytes, refs); - } - } else if (object->type == PLIST_TYPE_DICT) { - uint64_t size = object->value.value_dict.size; - if (2*size < 15) { - *bytes += 1; - } else { - *bytes += 1+1+integer_length(2*size); - } - *refs += 2*size; - for (i=0; ivalue.value_dict.keys[i]); - *objects += 1; - if (keylen < 15) { - *bytes += 1+keylen; - } else { - *bytes += 1+1+integer_length(keylen)+keylen; - } - bplist_analyze(object->value.value_dict.values[i], objects, bytes, refs); - } - } -} - -static int64_t -bplist_serialize_string(int64_t *reftab, uint64_t *reftabidx, uint8_t *data, uint64_t *dataidx, char *value) -{ - int64_t length; - int64_t objectid; - - objectid = (int64_t) *reftabidx; - reftab[(*reftabidx)++] = *dataidx; - - length = (int64_t) strlen(value); - if (length < 15) { - data[(*dataidx)++] = PLIST_TYPE_STRING | length; - } else { - data[(*dataidx)++] = PLIST_TYPE_STRING | 0x0f; - data[(*dataidx)++] = PLIST_TYPE_INTEGER | blist_integer_length(length); - serialize_integer(data, dataidx, integer_length(length), length); - } - memcpy(&data[*dataidx], value, length); - *dataidx += length; - - return objectid; -} - -static int64_t -bplist_serialize_object(int64_t *reftab, uint64_t *reftabidx, uint8_t reflen, uint8_t *data, uint64_t *dataidx, plist_object_t *object) -{ - int64_t objectid; - uint64_t i; - - objectid = (int64_t) *reftabidx; - reftab[(*reftabidx)++] = *dataidx; - if (!object) { - data[(*dataidx)++] = 0; - return objectid; - } - if (object->type == PLIST_TYPE_PRIMITIVE) { - data[(*dataidx)++] = PLIST_TYPE_PRIMITIVE | object->value.value_primitive; - } else if (object->type == PLIST_TYPE_INTEGER) { - int64_t value = object->value.value_integer; - data[(*dataidx)++] = PLIST_TYPE_INTEGER | blist_integer_length(value); - serialize_integer(data, dataidx, integer_length(value), value); - } else if (object->type == PLIST_TYPE_REAL) { - data[(*dataidx)++] = PLIST_TYPE_REAL | 3; - memcpy(&data[*dataidx], &object->value.value_real, sizeof(double)); - *dataidx += sizeof(double); - } else if (object->type == PLIST_TYPE_DATA) { - int64_t length = (int64_t) object->value.value_data.length; - if (length < 15) { - data[(*dataidx)++] = PLIST_TYPE_DATA | length; - } else { - data[(*dataidx)++] = PLIST_TYPE_DATA | 0x0f; - data[(*dataidx)++] = PLIST_TYPE_INTEGER | blist_integer_length(length); - serialize_integer(data, dataidx, integer_length(length), length); - } - memcpy(&data[*dataidx], object->value.value_data.value, length); - *dataidx += length; - } else if (object->type == PLIST_TYPE_STRING) { - int64_t length = (int64_t) strlen(object->value.value_string); - if (length < 15) { - data[(*dataidx)++] = PLIST_TYPE_STRING | length; - } else { - data[(*dataidx)++] = PLIST_TYPE_STRING | 0x0f; - data[(*dataidx)++] = PLIST_TYPE_INTEGER | blist_integer_length(length); - serialize_integer(data, dataidx, integer_length(length), length); - } - memcpy(&data[*dataidx], object->value.value_string, length); - *dataidx += length; - } else if (object->type == PLIST_TYPE_ARRAY) { - int64_t size = (int64_t) object->value.value_array.size; - uint64_t valueidx; - - if (size < 15) { - data[(*dataidx)++] = PLIST_TYPE_ARRAY | size; - } else { - data[(*dataidx)++] = PLIST_TYPE_ARRAY | 0x0f; - data[(*dataidx)++] = PLIST_TYPE_INTEGER | blist_integer_length(size); - serialize_integer(data, dataidx, integer_length(size), size); - } - - /* Reserve space for references */ - valueidx = *dataidx; - *dataidx += size * reflen; - for (i=0; ivalue.value_array.values[i]); - serialize_integer(data, &valueidx, reflen, valueid); - } - } else if (object->type == PLIST_TYPE_DICT) { - int64_t size = (int64_t) object->value.value_dict.size; - uint64_t keyidx, valueidx; - - if (size < 15) { - data[(*dataidx)++] = PLIST_TYPE_DICT | size; - } else { - data[(*dataidx)++] = PLIST_TYPE_DICT | 0x0f; - data[(*dataidx)++] = PLIST_TYPE_INTEGER | blist_integer_length(size); - serialize_integer(data, dataidx, integer_length(size), size); - } - keyidx = *dataidx; - *dataidx += size * reflen; - valueidx = *dataidx; - *dataidx += size * reflen; - for (i=0; ivalue.value_dict.keys[i]); - valueid = bplist_serialize_object(reftab, reftabidx, reflen, data, dataidx, object->value.value_dict.values[i]); - serialize_integer(data, &keyidx, reflen, keyid); - serialize_integer(data, &valueidx, reflen, valueid); - } - } - return objectid; -} - -static plist_object_t * -bplist_parse_object(const int64_t *reftab, uint64_t reftablen, uint64_t reftabidx, const uint8_t *data, uint64_t datalen, uint8_t reflen) -{ - plist_object_t *object; - uint64_t dataidx; - uint8_t type; - uint64_t length; - int ret; - - if (reftabidx >= reftablen) { - return NULL; - } - dataidx = reftab[reftabidx]; - if (dataidx >= datalen) { - return NULL; - } - type = data[dataidx++]; - if ((type & 0x0f) < 15) { - length = type & 0x0f; - } else { - uint8_t lentype; - uint64_t lenlength; - int64_t lenvalue; - - if (dataidx >= datalen) { - return NULL; - } - lentype = data[dataidx++]; - if ((lentype & 0xf0) != PLIST_TYPE_INTEGER) { - return NULL; - } - lenlength = (1 << lentype & 0x0f); - if (dataidx + lenlength > datalen) { - return NULL; - } - ret = parse_integer(data, dataidx, lenlength, &lenvalue); - if (ret < 0 || lenvalue < 0) { - return NULL; - } - length = lenvalue; - dataidx += ret; - } - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - - object->type = type & 0xf0; - if (object->type == PLIST_TYPE_PRIMITIVE) { - object->value.value_primitive = type & 0x0f; - } else if (object->type == PLIST_TYPE_INTEGER) { - if (dataidx + (1 << length) > datalen) { - free(object); - return NULL; - } - ret = parse_integer(data, dataidx, (1 << length), &object->value.value_integer); - if (ret < 0) { - free(object); - return NULL; - } - } else if (object->type == PLIST_TYPE_REAL) { - if (dataidx + (1 << length) > datalen) { - free(object); - return NULL; - } - ret = parse_real(data, dataidx, (1 << length), &object->value.value_real); - if (ret < 0) { - free(object); - return NULL; - } - } else if (object->type == PLIST_TYPE_DATA) { - plist_data_t *plist_data; - uint8_t *buffer; - - if (dataidx + length > datalen) { - free(object); - return NULL; - } - buffer = malloc(length); - if (!buffer) { - free(object); - return NULL; - } - memcpy(buffer, data + dataidx, length); - - object->value.value_data.length = length; - object->value.value_data.value = buffer; - } else if (object->type == PLIST_TYPE_STRING) { - char *buffer; - - if (dataidx + length > datalen) { - free(object); - return NULL; - } - buffer = calloc(length + 1, sizeof(char)); - if (!buffer) { - free(object); - return NULL; - } - memcpy(buffer, data + dataidx, length); - object->value.value_string = buffer; - } else if (object->type == PLIST_TYPE_ARRAY) { - plist_object_t **values; - uint64_t i; - - if (dataidx + length * reflen > datalen) { - free(object); - return NULL; - } - values = calloc(length, sizeof(plist_object_t *)); - if (!values) { - free(object); - return NULL; - } - for (i=0; i datalen) { - break; - } - ret = parse_integer(data, dataidx, reflen, &valueidx); - if (ret < 0 || valueidx < 0) { - break; - } - dataidx += reflen; - values[i] = bplist_parse_object(reftab, reftablen, valueidx, data, datalen, reflen); - if (!values[i]) { - break; - } - } - if (i != length) { - for (i=0; ivalue.value_array.size = length; - object->value.value_array.values = values; - } else if (object->type == PLIST_TYPE_DICT) { - char **keys; - plist_object_t **values; - uint64_t ki, vi; - - if (dataidx + 2 * length * reflen > datalen) { - free(object); - return NULL; - } - keys = calloc(length, sizeof(char *)); - if (!keys) { - free(object); - return NULL; - } - values = calloc(length, sizeof(plist_object_t *)); - if (!values) { - free(keys); - free(object); - return NULL; - } - for (ki=0; ki datalen) { - break; - } - ret = parse_integer(data, dataidx, reflen, &keyidx); - if (ret < 0) { - break; - } - dataidx += reflen; - obj = bplist_parse_object(reftab, reftablen, keyidx, data, datalen, reflen); - if (!obj) { - break; - } - if (obj->type != PLIST_TYPE_STRING) { - plist_object_destroy(obj); - break; - } - keys[ki] = obj->value.value_string; - free(obj); - } - for (vi=0; vi datalen) { - break; - } - ret = parse_integer(data, dataidx, reflen, &valueidx); - if (ret < 0) { - break; - } - dataidx += reflen; - values[vi] = bplist_parse_object(reftab, reftablen, valueidx, data, datalen, reflen); - if (!values[vi]) { - break; - } - } - if (ki != length || vi != length) { - uint64_t i; - for (i=0; ivalue.value_dict.size = length; - object->value.value_dict.keys = keys; - object->value.value_dict.values = values; - } else { - /* Currently unhandled type */ - free(object); - return NULL; - } - - return object; -} - -plist_object_t * -plist_object_true() -{ - plist_object_t *object; - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - - object->type = PLIST_TYPE_PRIMITIVE; - object->value.value_primitive = PLIST_PRIMITIVE_TRUE; - - return object; -} - -plist_object_t * -plist_object_false() -{ - plist_object_t *object; - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - - object->type = PLIST_TYPE_PRIMITIVE; - object->value.value_primitive = PLIST_PRIMITIVE_FALSE; - - return object; -} - -plist_object_t * -plist_object_integer(uint64_t value) -{ - plist_object_t *object; - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - - object->type = PLIST_TYPE_INTEGER; - object->value.value_integer = value; - - return object; -} - -plist_object_t * -plist_object_real(double value) -{ - plist_object_t *object; - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - - object->type = PLIST_TYPE_REAL; - object->value.value_real = value; - - return object; -} - -plist_object_t * -plist_object_data(const uint8_t *value, uint32_t valuelen) -{ - plist_object_t *object; - uint8_t *buffer; - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - buffer = malloc(valuelen); - if (!buffer) { - free(object); - return NULL; - } - memcpy(buffer, value, valuelen); - - object->type = PLIST_TYPE_DATA; - object->value.value_data.value = buffer; - object->value.value_data.length = valuelen; - - return object; -} - -plist_object_t * -plist_object_string(const char *value) -{ - plist_object_t *object; - uint64_t valuelen; - char *buffer; - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - valuelen = strlen(value); - buffer = malloc(valuelen + 1); - if (!buffer) { - free(object); - return NULL; - } - memcpy(buffer, value, valuelen + 1); - - object->type = PLIST_TYPE_STRING; - object->value.value_string = buffer; - - return object; -} - -plist_object_t * -plist_object_array(uint32_t size, ...) -{ - plist_object_t *object; - plist_object_t **values; - va_list ap; - uint64_t i; - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - values = calloc(size, sizeof(plist_object_t *)); - if (!values) { - free(object); - return NULL; - } - - va_start(ap, size); - for (i=0; itype = PLIST_TYPE_ARRAY; - object->value.value_array.size = size; - object->value.value_array.values = values; - - return object; -} - -plist_object_t * -plist_object_dict(uint32_t size, ...) -{ - plist_object_t *object; - char **keys; - plist_object_t **values; - va_list ap; - uint64_t i; - - object = calloc(1, sizeof(plist_object_t)); - if (!object) { - return NULL; - } - keys = calloc(size, sizeof(char *)); - if (!keys) { - free(object); - return NULL; - } - values = calloc(size, sizeof(plist_object_t *)); - if (!values) { - free(keys); - free(object); - return NULL; - } - - va_start(ap, size); - for (i=0; itype = PLIST_TYPE_DICT; - object->value.value_dict.size = size; - object->value.value_dict.keys = keys; - object->value.value_dict.values = values; - - return object; -} - -uint8_t -plist_object_get_type(plist_object_t *object) -{ - if (!object) { - return 0xff; - } - return object->type; -} - -int -plist_object_primitive_get_value(plist_object_t *object, uint8_t *value) -{ - if (!object || !value) { - return -1; - } - if (object->type != PLIST_TYPE_PRIMITIVE) { - return -2; - } - *value = object->value.value_primitive; - return 0; -} - -int -plist_object_integer_get_value(plist_object_t *object, int64_t *value) -{ - if (!object || !value) { - return -1; - } - if (object->type != PLIST_TYPE_INTEGER) { - return -2; - } - *value = object->value.value_integer; - return 0; -} - -int -plist_object_real_get_value(plist_object_t *object, double *value) -{ - if (!object || !value) { - return -1; - } - if (object->type != PLIST_TYPE_REAL) { - return -2; - } - *value = object->value.value_real; - return 0; -} - -int -plist_object_data_get_value(plist_object_t *object, const uint8_t **value, uint32_t *valuelen) -{ - if (!object || !value || !valuelen) { - return -1; - } - if (object->type != PLIST_TYPE_DATA) { - return -2; - } - *value = object->value.value_data.value; - *valuelen = object->value.value_data.length; - return 0; -} - -int -plist_object_string_get_value(plist_object_t *object, const char **value) -{ - if (!object || !value) { - return -1; - } - if (object->type != PLIST_TYPE_STRING) { - return -2; - } - *value = object->value.value_string; - return 0; -} - -const plist_object_t * -plist_object_array_get_value(plist_object_t *object, uint32_t idx) -{ - if (!object) { - return NULL; - } - if (object->type != PLIST_TYPE_ARRAY) { - return NULL; - } - if (idx >= object->value.value_array.size) { - return NULL; - } - return object->value.value_array.values[idx]; -} - -const plist_object_t * -plist_object_dict_get_value(plist_object_t *object, const char *key) -{ - int i; - - if (!object || !key) { - return NULL; - } - if (object->type != PLIST_TYPE_DICT) { - return NULL; - } - for (i=0; ivalue.value_dict.size; i++) { - if (!strcmp(key, object->value.value_dict.keys[i])) { - return object->value.value_dict.values[i]; - } - } - return NULL; -} - -plist_object_t * -plist_object_from_bplist(const uint8_t *data, uint32_t datalen) -{ - plist_object_t *object; - const uint8_t *trailer; - uint8_t offlen, reflen; - int64_t objects, rootid, reftaboffset; - int64_t *reftab; - int i; - - if (!data) { - return NULL; - } - if (datalen < BPLIST_TRAILER_LEN) { - return NULL; - } - - trailer = &data[datalen - BPLIST_TRAILER_LEN]; - offlen = trailer[6]; - reflen = trailer[7]; - parse_integer(trailer, 8, 8, &objects); - parse_integer(trailer, 16, 8, &rootid); - parse_integer(trailer, 24, 8, &reftaboffset); - if (objects <= 0) { - return NULL; - } - if (rootid < 0 || rootid >= objects) { - return NULL; - } - if (reftaboffset < BPLIST_HEADER_LEN || reftaboffset + objects*offlen > datalen) { - return NULL; - } - - reftab = calloc(objects, sizeof(int64_t)); - if (!reftab) { - return NULL; - } - for (i=0; itype) { - case PLIST_TYPE_DATA: - free(object->value.value_data.value); - break; - case PLIST_TYPE_STRING: - free(object->value.value_string); - break; - case PLIST_TYPE_ARRAY: - for (i=0; ivalue.value_array.size; i++) { - plist_object_destroy(object->value.value_array.values[i]); - } - free(object->value.value_array.values); - break; - case PLIST_TYPE_DICT: - for (i=0; ivalue.value_dict.size; i++) { - free(object->value.value_dict.keys[i]); - } - free(object->value.value_dict.keys); - for (i=0; ivalue.value_dict.size; i++) { - plist_object_destroy(object->value.value_dict.values[i]); - } - free(object->value.value_dict.values); - break; - } - free(object); -} - -#ifdef MAIN -#include - -#define SAMPLE_BPLIST "\x62\x70\x6c\x69\x73\x74\x30\x30\xd7\x01\x03\x05\x07\x09\x0b\x0d\x02\x04\x06\x08\x0a\x0c\x0e\x54\x74\x72\x75\x65\x08\x55\x66\x61\x6c\x73\x65\x09\x57\x69\x6e\x74\x65\x67\x65\x72\x12\x00\xbc\x61\x4e\x54\x72\x65\x61\x6c\x23\x5d\x1d\x5b\x2a\xca\xc0\xf3\x3f\x54\x64\x61\x74\x61\x44\x64\x61\x74\x61\x56\x73\x74\x72\x69\x6e\x67\x5c\x73\x74\x72\x69\x6e\x67\x20\x76\x61\x6c\x75\x65\x55\x61\x72\x72\x61\x79\xa2\x0f\x10\x55\x66\x69\x72\x73\x74\x56\x73\x65\x63\x6f\x6e\x64\x08\x17\x1c\x1d\x23\x24\x2c\x31\x36\x3f\x44\x49\x50\x5d\x63\x66\x6c\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x73" - -static void -test_decode() -{ - plist_object_t *object; - const uint8_t *indata; - uint32_t indatalen; - plist_object_t *intobj; - int64_t intval; - uint8_t *outdata; - uint32_t outdatalen; - int i; - - indata = (const uint8_t *) SAMPLE_BPLIST; - indatalen = sizeof(SAMPLE_BPLIST)-1; - - object = plist_object_from_bplist(indata, indatalen); - if (!object) { - printf("Error parsing bplist data\n"); - return; - } - intobj = plist_object_dict_get_value(object, "integer"); - plist_object_integer_get_value(intobj, &intval); - printf("Integer value: %d\n", (int) intval); - - plist_object_to_bplist(object, &outdata, &outdatalen); - printf("Parsed and serialized bplist: "); - for (i=0; i -#endif - -#define PLIST_TYPE_PRIMITIVE 0x00 -#define PLIST_TYPE_INTEGER 0x10 -#define PLIST_TYPE_REAL 0x20 -#define PLIST_TYPE_DATA 0x40 -#define PLIST_TYPE_STRING 0x50 -#define PLIST_TYPE_ARRAY 0xA0 -#define PLIST_TYPE_DICT 0xD0 - -#define PLIST_PRIMITIVE_TRUE 0x08 -#define PLIST_PRIMITIVE_FALSE 0x09 - -typedef struct plist_object_s plist_object_t; - -plist_object_t *plist_object_true(); -plist_object_t *plist_object_false(); -plist_object_t *plist_object_integer(uint64_t value); -plist_object_t *plist_object_real(double value); -plist_object_t *plist_object_data(const uint8_t *value, uint32_t valuelen); -plist_object_t *plist_object_string(const char *value); -plist_object_t *plist_object_array(uint32_t size, ...); -plist_object_t *plist_object_dict(uint32_t size, ...); - -uint8_t plist_object_get_type(plist_object_t *object); -int plist_object_primitive_get_value(plist_object_t *object, uint8_t *value); -int plist_object_integer_get_value(plist_object_t *object, int64_t *value); -int plist_object_real_get_value(plist_object_t *object, double *value); -int plist_object_data_get_value(plist_object_t *object, const uint8_t **value, uint32_t *valuelen); -int plist_object_string_get_value(plist_object_t *object, const char **value); -const plist_object_t *plist_object_array_get_value(plist_object_t *object, uint32_t idx); -const plist_object_t *plist_object_dict_get_value(plist_object_t *object, const char *key); - -plist_object_t *plist_object_from_bplist(const uint8_t *data, uint32_t datalen); -int plist_object_to_bplist(plist_object_t *object, uint8_t **data, uint32_t *datalen); - -void plist_object_destroy(plist_object_t *object); - -#endif diff --git a/lib/raop_ntp.c b/lib/raop_ntp.c index 3af7de71..f46b1246 100644 --- a/lib/raop_ntp.c +++ b/lib/raop_ntp.c @@ -1,6 +1,17 @@ -// -// Created by Florian Draschbacher on 2019-04-27. -// +/* + * Copyright (c) 2019 dsafa22, modified by Florian Draschbacher, + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #include #include diff --git a/lib/raop_ntp.h b/lib/raop_ntp.h index 9e19a46d..0dde38ed 100644 --- a/lib/raop_ntp.h +++ b/lib/raop_ntp.h @@ -1,6 +1,17 @@ -// -// Created by Florian Draschbacher on 2019-04-27. -// +/* + * Copyright (c) 2019 dsafa22, modified by Florian Draschbacher, + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #ifndef RAOP_NTP_H #define RAOP_NTP_H diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index 7cc997a3..f983b20c 100755 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -1,6 +1,16 @@ -// -// Created by Administrator on 2019/1/29/029. -// +/* + * Copyright (c) 2019 dsafa22, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #include "raop_rtp_mirror.h" diff --git a/lib/raop_rtp_mirror.h b/lib/raop_rtp_mirror.h index 6b7fe80e..c465ee53 100755 --- a/lib/raop_rtp_mirror.h +++ b/lib/raop_rtp_mirror.h @@ -1,6 +1,16 @@ -// -// Created by Administrator on 2019/1/29/029. -// +/* + * Copyright (c) 2019 dsafa22, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #ifndef RAOP_RTP_MIRROR_H #define RAOP_RTP_MIRROR_H diff --git a/lib/stream.h b/lib/stream.h index f8d2d61d..a643f423 100755 --- a/lib/stream.h +++ b/lib/stream.h @@ -1,6 +1,16 @@ -// -// Created by Administrator on 2019/1/31/031. -// +/* + * Copyright (c) 2019 dsafa22, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ #ifndef AIRPLAYSERVER_STREAM_H #define AIRPLAYSERVER_STREAM_H diff --git a/log.h b/log.h index c50640e2..b2a7de4a 100755 --- a/log.h +++ b/log.h @@ -1,6 +1,21 @@ -// -// Created by Administrator on 2019/1/29/029. -// +/** + * RPiPlay - An open-source AirPlay mirroring server for Raspberry Pi + * Copyright (C) 2019 Florian Draschbacher + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ #ifndef AIRPLAYSERVER_LOG_H #define AIRPLAYSERVER_LOG_H