├── .gitignore ├── AirTV-Qt ├── AirTV.icns ├── AirTV.ico ├── AirTV.pro ├── AirTV.qrc ├── AirTV.rc ├── audiocallbacks.cpp ├── audiocallbacks.h ├── audiooutput.cpp ├── audiooutput.h ├── images │ └── airtv.svg ├── main.cpp ├── mainapplication.cpp ├── mainapplication.h ├── mainwindow.ui └── qtsingleapplication │ ├── INSTALL.TXT │ ├── README.TXT │ ├── buildlib │ └── buildlib.pro │ ├── common.pri │ ├── configure │ ├── configure.bat │ ├── doc │ ├── html │ │ ├── classic.css │ │ ├── images │ │ │ └── qt-logo.png │ │ ├── index.html │ │ ├── qtsingleapplication-example-loader.html │ │ ├── qtsingleapplication-example-trivial.html │ │ ├── qtsingleapplication-members.html │ │ ├── qtsingleapplication-obsolete.html │ │ ├── qtsingleapplication.dcf │ │ ├── qtsingleapplication.html │ │ ├── qtsingleapplication.index │ │ ├── qtsingleapplication.qhp │ │ ├── qtsinglecoreapplication-example-console.html │ │ ├── qtsinglecoreapplication-members.html │ │ └── qtsinglecoreapplication.html │ ├── images │ │ └── qt-logo.png │ └── index.qdoc │ ├── examples │ ├── console │ │ ├── console.pro │ │ ├── console.qdoc │ │ └── main.cpp │ ├── examples.pro │ ├── loader │ │ ├── file1.qsl │ │ ├── file2.qsl │ │ ├── loader.pro │ │ ├── loader.qdoc │ │ └── main.cpp │ └── trivial │ │ ├── main.cpp │ │ ├── trivial.pro │ │ └── trivial.qdoc │ ├── qtsingleapplication.pro │ └── src │ ├── QtLockedFile │ ├── QtSingleApplication │ ├── qtlocalpeer.cpp │ ├── qtlocalpeer.h │ ├── qtlockedfile.cpp │ ├── qtlockedfile.h │ ├── qtlockedfile_unix.cpp │ ├── qtlockedfile_win.cpp │ ├── qtsingleapplication.cpp │ ├── qtsingleapplication.h │ ├── qtsingleapplication.pri │ ├── qtsinglecoreapplication.cpp │ ├── qtsinglecoreapplication.h │ └── qtsinglecoreapplication.pri ├── LICENSE ├── Makefile.am ├── README.md ├── airport.key ├── autogen.sh ├── configure.ac ├── include ├── Makefile.am └── shairplay │ ├── dnssd.h │ └── raop.h ├── m4 └── pkg.m4 └── src ├── Makefile.am ├── bindings ├── python │ └── Shairplay.py └── qt4 │ ├── dnssdservice.cpp │ ├── dnssdservice.h │ ├── raopcallbackhandler.cpp │ ├── raopcallbackhandler.h │ ├── raopcallbacks.h │ ├── raopservice.cpp │ └── raopservice.h ├── lib ├── Makefile.am ├── aes_ctr.c ├── aes_ctr.h ├── alac │ ├── Makefile.am │ ├── alac.c │ ├── alac.h │ └── stdint_win.h ├── base64.c ├── base64.h ├── compat.h ├── crypto │ ├── Makefile.am │ ├── aes.c │ ├── bigint.c │ ├── bigint.h │ ├── bigint_impl.h │ ├── config.h │ ├── crypto.h │ ├── hmac.c │ ├── md5.c │ ├── os_port.h │ ├── rc4.c │ └── sha1.c ├── curve25519 │ ├── Makefile.am │ ├── curve25519-donna-c64.c │ ├── curve25519-donna.c │ └── curve25519.h ├── digest.c ├── digest.h ├── dnssd.c ├── dnssd.m ├── dnssdint.h ├── ed25519 │ ├── Makefile.am │ ├── add_scalar.c │ ├── ed25519.h │ ├── fe.c │ ├── fe.h │ ├── fixedint.h │ ├── ge.c │ ├── ge.h │ ├── key_exchange.c │ ├── keypair.c │ ├── license.txt │ ├── precomp_data.h │ ├── sc.c │ ├── sc.h │ ├── seed.c │ ├── sha512.c │ ├── sha512.h │ ├── sign.c │ └── verify.c ├── fairplay.h ├── fairplay_dummy.c ├── fairplay_playfair.c ├── global.h ├── http_parser.c ├── http_parser.h ├── http_request.c ├── http_request.h ├── http_response.c ├── http_response.h ├── httpd.c ├── httpd.h ├── logger.c ├── logger.h ├── memalign.h ├── netutils.c ├── netutils.h ├── pairing.c ├── pairing.h ├── playfair │ ├── LICENSE.md │ ├── Makefile.am │ ├── hand_garble.c │ ├── modified_md5.c │ ├── omg_hax.c │ ├── omg_hax.h │ ├── playfair.c │ ├── playfair.h │ └── sap_hash.c ├── plist.c ├── plist.h ├── raop.c ├── raop_buffer.c ├── raop_buffer.h ├── raop_handlers.h ├── raop_rtp.c ├── raop_rtp.h ├── rsakey.c ├── rsakey.h ├── rsapem.c ├── rsapem.h ├── sdp.c ├── sdp.h ├── sockets.h ├── threads.h ├── utils.c └── utils.h ├── shairplay.c └── test ├── dnssd_test.c ├── dnssd_test.m ├── example.c ├── main.c └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | *-build-* 2 | *.user 3 | *.o 4 | *.DS_Store 5 | *.swp 6 | project.xcworkspace 7 | xcuserdata 8 | 9 | # autotools 10 | Makefile 11 | *.lo 12 | *.in 13 | .deps 14 | .libs 15 | *.la 16 | *.a 17 | m4/ 18 | missing 19 | libtool 20 | ltmain.sh 21 | install-sh 22 | depcomp 23 | configure 24 | config.* 25 | autom4te.cache 26 | aclocal.m4 27 | stamp-h1 28 | src/shairplay 29 | src/test/example 30 | 31 | -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juhovh/shairplay/096b61ad14c90169f438e690d096e3fcf87e504e/AirTV-Qt/AirTV.icns -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juhovh/shairplay/096b61ad14c90169f438e690d096e3fcf87e504e/AirTV-Qt/AirTV.ico -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2011-12-04T00:47:51 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui multimedia phonon svg 8 | 9 | include(qtsingleapplication/src/qtsingleapplication.pri) 10 | 11 | TARGET = AirTV 12 | TEMPLATE = app 13 | ICON = AirTV.icns 14 | RC_FILE = AirTV.rc 15 | 16 | win32 { 17 | LIBS += C:\\QtSDK\\mingw\\lib\\libws2_32.a 18 | QMAKE_LFLAGS += -static-libgcc 19 | } 20 | macx { 21 | QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.5 22 | } 23 | 24 | LIBS += -lshairplay 25 | INCLUDEPATH += ../src/include/ ../src/bindings/qt4/ 26 | SOURCES += main.cpp\ 27 | ../src/bindings/qt4/raopservice.cpp \ 28 | ../src/bindings/qt4/raopcallbackhandler.cpp \ 29 | ../src/bindings/qt4/dnssdservice.cpp \ 30 | audiooutput.cpp \ 31 | mainapplication.cpp \ 32 | audiocallbacks.cpp 33 | 34 | HEADERS += \ 35 | ../src/bindings/qt4/raopservice.h \ 36 | ../src/bindings/qt4/raopcallbacks.h \ 37 | ../src/bindings/qt4/raopcallbackhandler.h \ 38 | ../src/bindings/qt4/dnssdservice.h \ 39 | audiooutput.h \ 40 | mainapplication.h \ 41 | audiocallbacks.h 42 | 43 | FORMS += mainwindow.ui 44 | 45 | RESOURCES += \ 46 | AirTV.qrc 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/airtv.svg 4 | 5 | 6 | -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "AirTV.ico" 2 | -------------------------------------------------------------------------------- /AirTV-Qt/audiocallbacks.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include "audiocallbacks.h" 16 | 17 | AudioCallbacks::AudioCallbacks(QObject *parent) : 18 | RaopAudioHandler(parent) 19 | { 20 | } 21 | 22 | void * AudioCallbacks::audioInit(int bits, int channels, int samplerate) 23 | { 24 | AudioOutput *audioOutput = new AudioOutput(0); 25 | audioOutput->init(bits, channels, samplerate); 26 | audioOutput->start(); 27 | m_outputList.append(audioOutput); 28 | return audioOutput; 29 | } 30 | 31 | void AudioCallbacks::audioProcess(void *session, const QByteArray & buffer) 32 | { 33 | AudioOutput *audioOutput = (AudioOutput*)session; 34 | audioOutput->output(buffer); 35 | } 36 | 37 | void AudioCallbacks::audioDestroy(void *session) 38 | { 39 | AudioOutput *audioOutput = (AudioOutput*)session; 40 | m_outputList.removeAll(audioOutput); 41 | 42 | audioOutput->stop(); 43 | delete audioOutput; 44 | } 45 | 46 | 47 | void AudioCallbacks::audioFlush(void *session) 48 | { 49 | AudioOutput *audioOutput = (AudioOutput*)session; 50 | audioOutput->flush(); 51 | } 52 | 53 | void AudioCallbacks::audioSetVolume(void *session, float volume) 54 | { 55 | AudioOutput *audioOutput = (AudioOutput*)session; 56 | audioOutput->setVolume(volume); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /AirTV-Qt/audiocallbacks.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef AUDIOCALLBACKS_H 16 | #define AUDIOCALLBACKS_H 17 | 18 | #include "raopcallbacks.h" 19 | 20 | #include "audiooutput.h" 21 | 22 | class AudioCallbacks : public RaopAudioHandler 23 | { 24 | Q_OBJECT 25 | public: 26 | explicit AudioCallbacks(QObject *parent = 0); 27 | 28 | virtual void *audioInit(int bits, int channels, int samplerate); 29 | virtual void audioSetVolume(void *session, float volume); 30 | virtual void audioProcess(void *session, const QByteArray &buffer); 31 | virtual void audioFlush(void *session); 32 | virtual void audioDestroy(void *session); 33 | 34 | 35 | private: 36 | QList m_outputList; 37 | 38 | signals: 39 | 40 | public slots: 41 | 42 | }; 43 | 44 | #endif // AUDIOCALLBACKS_H 45 | -------------------------------------------------------------------------------- /AirTV-Qt/audiooutput.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef AUDIOOUTPUT_H 16 | #define AUDIOOUTPUT_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | class AudioOutput : public QIODevice 27 | { 28 | Q_OBJECT 29 | public: 30 | explicit AudioOutput(QObject *parent = 0); 31 | bool init(int bits, int channels, int samplerate); 32 | bool setDevice(QAudioDeviceInfo deviceInfo); 33 | 34 | void start(); 35 | void setVolume(float volume); 36 | void output(const QByteArray & data); 37 | void flush(); 38 | void stop(); 39 | 40 | qint64 readData(char *data, qint64 maxlen); 41 | qint64 writeData(const char *data, qint64 len); 42 | qint64 bytesAvailable() const; 43 | bool isSequential() const; 44 | 45 | private: 46 | void reinit(); 47 | 48 | private: 49 | bool m_initialized; 50 | QByteArray m_buffer; 51 | QAudioFormat m_format; 52 | QAudioDeviceInfo m_deviceInfo; 53 | QAudioOutput* m_output; 54 | float m_volume; 55 | 56 | signals: 57 | 58 | public slots: 59 | 60 | private slots: 61 | void notified(); 62 | void stateChanged(QAudio::State state); 63 | }; 64 | 65 | #endif // AUDIOOUTPUT_H 66 | -------------------------------------------------------------------------------- /AirTV-Qt/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include "mainapplication.h" 19 | #include "videowidget.h" 20 | #include "raopservice.h" 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | QtSingleApplication a(argc, argv); 25 | if (a.isRunning()) { 26 | return 0; 27 | } 28 | a.setApplicationName("AirTV"); 29 | 30 | if (!QSystemTrayIcon::isSystemTrayAvailable()) { 31 | QMessageBox::critical(0, QObject::tr("Systray"), 32 | QObject::tr("I couldn't detect any system tray " 33 | "on this system.")); 34 | return 1; 35 | } 36 | QApplication::setQuitOnLastWindowClosed(false); 37 | 38 | MainApplication m; 39 | QObject::connect(&m, SIGNAL(quitRequested()), &a, SLOT(quit())); 40 | QObject::connect(&a, SIGNAL(aboutToQuit()), &m, SLOT(aboutToQuit())); 41 | 42 | if(m.start()) { 43 | return a.exec(); 44 | } else { 45 | return EXIT_FAILURE; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AirTV-Qt/mainapplication.cpp: -------------------------------------------------------------------------------- 1 | #include "mainapplication.h" 2 | 3 | #include 4 | #include 5 | 6 | MainApplication::MainApplication(QObject *parent) : 7 | QObject(parent) 8 | { 9 | raopService = new RaopService(0); 10 | dnssdService = new DnssdService(0); 11 | trayIconMenu = new QMenu(0); 12 | 13 | quitAction = new QAction(tr("&Quit"), trayIconMenu); 14 | connect(quitAction, SIGNAL(triggered()), this, SIGNAL(quitRequested())); 15 | trayIconMenu->addAction(quitAction); 16 | 17 | // Construct the actual system tray icon 18 | trayIcon = new QSystemTrayIcon(this); 19 | trayIcon->setContextMenu(trayIconMenu); 20 | trayIcon->setIcon(QIcon(":icons/airtv.svg")); 21 | } 22 | 23 | MainApplication::~MainApplication() 24 | { 25 | trayIcon->setContextMenu(0); 26 | delete trayIconMenu; 27 | delete raopService; 28 | } 29 | 30 | bool MainApplication::start() 31 | { 32 | // Initialize the service 33 | bool initSuccess = false; 34 | initSuccess = raopService->init(10, &m_callbacks); 35 | if(!initSuccess) { 36 | qDebug() << "Error initializing raop service"; 37 | return false; 38 | } 39 | initSuccess &= dnssdService->init(); 40 | if(!initSuccess) { 41 | qDebug() << "Error initializing dnssd service"; 42 | return false; 43 | } 44 | 45 | char chwaddr[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB }; 46 | QByteArray hwaddr(chwaddr, sizeof(chwaddr)); 47 | 48 | raopService->start(5000, hwaddr); 49 | dnssdService->registerRaop("Shairplay", 5000, hwaddr); 50 | trayIcon->show(); 51 | return true; 52 | } 53 | 54 | void MainApplication::stop() 55 | { 56 | dnssdService->unregisterRaop(); 57 | raopService->stop(); 58 | trayIcon->hide(); 59 | } 60 | 61 | void MainApplication::aboutToQuit() 62 | { 63 | this->stop(); 64 | } 65 | -------------------------------------------------------------------------------- /AirTV-Qt/mainapplication.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef MAINAPPLICATION_H 16 | #define MAINAPPLICATION_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "raopservice.h" 24 | #include "dnssdservice.h" 25 | #include "audiocallbacks.h" 26 | 27 | class MainApplication : public QObject 28 | { 29 | Q_OBJECT 30 | public: 31 | explicit MainApplication(QObject *parent = 0); 32 | ~MainApplication(); 33 | 34 | bool start(); 35 | void stop(); 36 | 37 | private: 38 | RaopService *raopService; 39 | DnssdService *dnssdService; 40 | AudioCallbacks m_callbacks; 41 | 42 | QSystemTrayIcon *trayIcon; 43 | QMenu *trayIconMenu; 44 | QAction *quitAction; 45 | 46 | signals: 47 | void quitRequested(); 48 | 49 | public slots: 50 | void aboutToQuit(); 51 | }; 52 | 53 | #endif // MAINAPPLICATION_H 54 | -------------------------------------------------------------------------------- /AirTV-Qt/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | MainWindow 3 | 4 | 5 | 6 | 0 7 | 0 8 | 400 9 | 300 10 | 11 | 12 | 13 | MainWindow 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/README.TXT: -------------------------------------------------------------------------------- 1 | Qt Solutions Component: Single Application 2 | 3 | The QtSingleApplication component provides support for 4 | applications that can be only started once per user. 5 | 6 | 7 | 8 | Version history: 9 | 10 | 2.0: - Version 1.3 ported to Qt 4. 11 | 12 | 2.1: - Fix compilation problem on Mac. 13 | 14 | 2.2: - Really fix the Mac compilation problem. 15 | - Mac: fix crash due to wrong object releasing. 16 | - Mac: Fix memory leak. 17 | 18 | 2.3: - Windows: Force creation of internal widget to make it work 19 | with Qt 4.2. 20 | 21 | 2.4: - Fix the system for automatic window raising on message 22 | reception. NOTE: minor API change. 23 | 24 | 2.5: - Mac: Fix isRunning() to work and report correctly. 25 | 26 | 2.6: - - initialize() is now obsolete, no longer necessary to call 27 | it 28 | - - Fixed race condition where multiple instances migth be started 29 | - - QtSingleCoreApplication variant provided for non-GUI (console) 30 | usage 31 | - Complete reimplementation. Visible changes: 32 | - LGPL release. 33 | 34 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/buildlib/buildlib.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE=lib 2 | CONFIG += qt dll qtsingleapplication-buildlib 3 | mac:CONFIG += absolute_library_soname 4 | win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all 5 | include(../src/qtsingleapplication.pri) 6 | TARGET = $$QTSINGLEAPPLICATION_LIBNAME 7 | DESTDIR = $$QTSINGLEAPPLICATION_LIBDIR 8 | win32 { 9 | DLLDESTDIR = $$[QT_INSTALL_BINS] 10 | QMAKE_DISTCLEAN += $$[QT_INSTALL_BINS]\\$${QTSINGLEAPPLICATION_LIBNAME}.dll 11 | } 12 | target.path = $$DESTDIR 13 | INSTALLS += target 14 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/common.pri: -------------------------------------------------------------------------------- 1 | infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtsingleapplication-uselib 2 | TEMPLATE += fakelib 3 | QTSINGLEAPPLICATION_LIBNAME = $$qtLibraryTarget(QtSolutions_SingleApplication-head) 4 | TEMPLATE -= fakelib 5 | QTSINGLEAPPLICATION_LIBDIR = $$PWD/lib 6 | unix:qtsingleapplication-uselib:!qtsingleapplication-buildlib:QMAKE_RPATHDIR += $$QTSINGLEAPPLICATION_LIBDIR 7 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "x$1" != "x" -a "x$1" != "x-library" ]; then 4 | echo "Usage: $0 [-library]" 5 | echo 6 | echo "-library: Build the component as a dynamic library (DLL). Default is to" 7 | echo " include the component source code directly in the application." 8 | echo 9 | exit 0 10 | fi 11 | 12 | rm -f config.pri 13 | if [ "x$1" = "x-library" ]; then 14 | echo "Configuring to build this component as a dynamic library." 15 | echo "SOLUTIONS_LIBRARY = yes" > config.pri 16 | fi 17 | 18 | echo 19 | echo "This component is now configured." 20 | echo 21 | echo "To build the component library (if requested) and example(s)," 22 | echo "run qmake and your make command." 23 | echo 24 | echo "To remove or reconfigure, run make distclean." 25 | echo 26 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/configure.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem 4 | rem "Main" 5 | rem 6 | 7 | if not "%1"=="" ( 8 | if not "%1"=="-library" ( 9 | call :PrintUsage 10 | goto EOF 11 | ) 12 | ) 13 | 14 | if exist config.pri. del config.pri 15 | if "%1"=="-library" ( 16 | echo Configuring to build this component as a dynamic library. 17 | echo SOLUTIONS_LIBRARY = yes > config.pri 18 | ) 19 | 20 | echo . 21 | echo This component is now configured. 22 | echo . 23 | echo To build the component library (if requested) and example(s), 24 | echo run qmake and your make or nmake command. 25 | echo . 26 | echo To remove or reconfigure, run make (nmake) distclean. 27 | echo . 28 | 29 | :PrintUsage 30 | echo Usage: configure.bat [-library] 31 | echo . 32 | echo -library: Build the component as a dynamic library (DLL). Default is to 33 | echo include the component source directly in the application. 34 | echo A DLL may be preferable for technical or licensing (LGPL) reasons. 35 | echo . 36 | goto EOF 37 | 38 | 39 | :EOF 40 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/images/qt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juhovh/shairplay/096b61ad14c90169f438e690d096e3fcf87e504e/AirTV-Qt/qtsingleapplication/doc/html/images/qt-logo.png -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | Single Application 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

Single Application
16 |

17 | 18 |

Description

19 |

The QtSingleApplication component provides support for applications that can be only started once per user.

20 |

For some applications it is useful or even critical that they are started only once by any user. Future attempts to start the application should activate any already running instance, and possibly perform requested actions, e.g. loading a file, in that instance.

21 |

The QtSingleApplication class provides an interface to detect a running instance, and to send command strings to that instance. For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui.

22 | 23 |

Classes

24 | 28 | 29 |

Examples

30 | 35 | 36 |

Tested platforms

37 |
    38 |
  • Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005
  • 39 |
  • Qt 4.4, 4.5 / Linux / gcc
  • 40 |
  • Qt 4.4, 4.5 / MacOS X 10.5 / gcc
  • 41 |
42 |


43 | 44 | 45 | 46 | 47 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
48 | 49 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/qtsingleapplication-obsolete.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | Obsolete Members for QtSingleApplication 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

Obsolete Members for QtSingleApplication

16 |

The following class members are obsolete. They are provided to keep old source code working. We strongly advise against using them in new code.

17 |

18 |

Public Functions

19 | 20 | 21 |
void initialize ( bool dummy = true )   (obsolete)
22 |
23 |

Member Function Documentation

24 |

void QtSingleApplication::initialize ( bool dummy = true )

25 |


26 | 27 | 28 | 29 | 30 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
31 | 32 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/qtsingleapplication.dcf: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | QtSingleApplication 6 | activateWindow 7 | activationWindow 8 | id 9 | isRunning 10 | messageReceived 11 | sendMessage 12 | setActivationWindow 13 |
14 |
15 |
16 |
17 | QtSingleCoreApplication 18 | id 19 | isRunning 20 | messageReceived 21 | sendMessage 22 |
23 |
24 |
25 |
26 |
27 | A non-GUI example 28 |
29 |
30 | A Trivial Example 31 |
32 |
33 | Loading Documents 34 |
35 |
36 | Single Application 37 |
38 |
39 |
40 | 41 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/qtsingleapplication.qhp: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.nokia.qtsolutions.qtsingleapplication_head 4 | qdoc 5 | 6 | qt 7 | solutions 8 | qtsingleapplication 9 | 10 | 11 | qt 12 | solutions 13 | qtsingleapplication 14 | 15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | qtsingleapplication.html 44 | index.html 45 | qtsingleapplication-example-trivial.html 46 | qtsinglecoreapplication.html 47 | qtsingleapplication-example-loader.html 48 | qtsinglecoreapplication-example-console.html 49 | classic.css 50 | images/qt-logo.png 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/images/qt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/juhovh/shairplay/096b61ad14c90169f438e690d096e3fcf87e504e/AirTV-Qt/qtsingleapplication/doc/images/qt-logo.png -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/index.qdoc: -------------------------------------------------------------------------------- 1 | /*! 2 | \page index.html 3 | \title Single Application 4 | 5 | \section1 Description 6 | 7 | The QtSingleApplication component provides support 8 | for applications that can be only started once per user. 9 | 10 | 11 | 12 | For some applications it is useful or even critical that they are started 13 | only once by any user. Future attempts to start the application should 14 | activate any already running instance, and possibly perform requested 15 | actions, e.g. loading a file, in that instance. 16 | 17 | The QtSingleApplication class provides an interface to detect a running 18 | instance, and to send command strings to that instance. 19 | For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui. 20 | 21 | 22 | 23 | 24 | \section1 Classes 25 | \list 26 | \i QtSingleApplication \i QtSingleCoreApplication\endlist 27 | 28 | \section1 Examples 29 | \list 30 | \i \link qtsingleapplication-example-trivial.html A Trivial Example \endlink \i \link qtsingleapplication-example-loader.html Loading Documents \endlink \i \link qtsinglecoreapplication-example-console.html A Non-GUI Example \endlink \endlist 31 | 32 | 33 | 34 | 35 | 36 | 37 | \section1 Tested platforms 38 | \list 39 | \i Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005 40 | \i Qt 4.4, 4.5 / Linux / gcc 41 | \i Qt 4.4, 4.5 / MacOS X 10.5 / gcc 42 | \endlist 43 | 44 | 45 | 46 | 47 | */ -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/console/console.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console 3 | SOURCES += main.cpp 4 | include(../../src/qtsinglecoreapplication.pri) 5 | QT -= gui 6 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/console/console.qdoc: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | /*! \page qtsinglecoreapplication-example-console.html 41 | \title A non-GUI example 42 | 43 | This example shows how to use the single-application functionality 44 | in a console application. It does not require the \c QtGui library 45 | at all. 46 | 47 | The only differences from the GUI application usage demonstrated 48 | in the other examples are: 49 | 50 | 1) The \c.pro file should include \c qtsinglecoreapplication.pri 51 | instead of \c qtsingleapplication.pri 52 | 53 | 2) The class name is \c QtSingleCoreApplication instead of \c 54 | QtSingleApplication. 55 | 56 | 3) No calls are made regarding window activation, for obvious reasons. 57 | 58 | console.pro: 59 | \quotefile console/console.pro 60 | 61 | main.cpp: 62 | \quotefile console/main.cpp 63 | 64 | */ 65 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/console/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | 41 | #include "qtsinglecoreapplication.h" 42 | #include 43 | 44 | 45 | void report(const QString& msg) 46 | { 47 | qDebug("[%i] %s", (int)QCoreApplication::applicationPid(), qPrintable(msg)); 48 | } 49 | 50 | class MainClass : public QObject 51 | { 52 | Q_OBJECT 53 | public: 54 | MainClass() 55 | : QObject() 56 | {} 57 | 58 | public slots: 59 | void handleMessage(const QString& message) 60 | { 61 | report( "Message received: \"" + message + "\""); 62 | } 63 | }; 64 | 65 | int main(int argc, char **argv) 66 | { 67 | report("Starting up"); 68 | 69 | QtSingleCoreApplication app(argc, argv); 70 | 71 | if (app.isRunning()) { 72 | QString msg(QString("Hi master, I am %1.").arg(QCoreApplication::applicationPid())); 73 | bool sentok = app.sendMessage(msg, 2000); 74 | QString rep("Another instance is running, so I will exit."); 75 | rep += sentok ? " Message sent ok." : " Message sending failed; the other instance may be frozen."; 76 | report(rep); 77 | return 0; 78 | } else { 79 | report("No other instance is running; so I will."); 80 | MainClass mainObj; 81 | QObject::connect(&app, SIGNAL(messageReceived(const QString&)), 82 | &mainObj, SLOT(handleMessage(const QString&))); 83 | return app.exec(); 84 | } 85 | } 86 | 87 | 88 | #include "main.moc" 89 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/examples.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | SUBDIRS = trivial \ 3 | loader \ 4 | console 5 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/file1.qsl: -------------------------------------------------------------------------------- 1 | File 1 2 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/file2.qsl: -------------------------------------------------------------------------------- 1 | File 2 2 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/loader.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | include(../../src/qtsingleapplication.pri) 4 | 5 | SOURCES += main.cpp 6 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/loader.qdoc: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | /*! \page qtsingleapplication-example-loader.html 41 | \title Loading Documents 42 | 43 | The application in this example loads or prints the documents 44 | passed as commandline parameters to further instances of this 45 | application. 46 | 47 | \quotefromfile loader/main.cpp 48 | \printuntil }; 49 | The user interface in this application is a QMainWindow subclass 50 | with a QMdiArea as the central widget. It implements a slot 51 | \c handleMessage() that will be connected to the messageReceived() 52 | signal of the QtSingleApplication class. 53 | 54 | \printuntil } 55 | The MainWindow constructor creates a minimal user interface. 56 | 57 | \printto case Print: 58 | The handleMessage() slot interprets the message passed in as a 59 | filename that can be prepended with \e /print to indicate that 60 | the file should just be printed rather than loaded. 61 | 62 | \printto #include 63 | Loading the file will also activate the window. 64 | 65 | \printto mw 66 | The \c main entry point function creates a QtSingleApplication 67 | object, and creates a message to send to a running instance 68 | of the application. If the message was sent successfully the 69 | process exits immediately. 70 | 71 | \printuntil } 72 | If the message could not be sent the application starts up. Note 73 | that \c false is passed to the call to setActivationWindow() to 74 | prevent automatic activation for every message received, e.g. when 75 | the application should just print a file. Instead, the message 76 | handling function determines whether activation is requested, and 77 | signals that by emitting the needToShow() signal. This is then 78 | simply connected directly to QtSingleApplication's 79 | activateWindow() slot. 80 | */ 81 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | class MainWindow : public QMainWindow 50 | { 51 | Q_OBJECT 52 | public: 53 | MainWindow(); 54 | 55 | public slots: 56 | void handleMessage(const QString& message); 57 | 58 | signals: 59 | void needToShow(); 60 | 61 | private: 62 | QMdiArea *workspace; 63 | }; 64 | 65 | MainWindow::MainWindow() 66 | { 67 | workspace = new QMdiArea(this); 68 | 69 | setCentralWidget(workspace); 70 | } 71 | 72 | void MainWindow::handleMessage(const QString& message) 73 | { 74 | enum Action { 75 | Nothing, 76 | Open, 77 | Print 78 | } action; 79 | 80 | action = Nothing; 81 | QString filename = message; 82 | if (message.toLower().startsWith("/print ")) { 83 | filename = filename.mid(7); 84 | action = Print; 85 | } else if (!message.isEmpty()) { 86 | action = Open; 87 | } 88 | if (action == Nothing) { 89 | emit needToShow(); 90 | return; 91 | } 92 | 93 | QFile file(filename); 94 | QString contents; 95 | if (file.open(QIODevice::ReadOnly)) 96 | contents = file.readAll(); 97 | else 98 | contents = "[[Error: Could not load file " + filename + "]]"; 99 | 100 | QTextEdit *view = new QTextEdit; 101 | view->setPlainText(contents); 102 | 103 | switch(action) { 104 | case Print: 105 | { 106 | QPrinter printer; 107 | view->print(&printer); 108 | delete view; 109 | } 110 | break; 111 | 112 | case Open: 113 | { 114 | workspace->addSubWindow(view); 115 | view->setWindowTitle(message); 116 | view->show(); 117 | emit needToShow(); 118 | } 119 | break; 120 | default: 121 | break; 122 | }; 123 | } 124 | 125 | #include "main.moc" 126 | 127 | int main(int argc, char **argv) 128 | { 129 | QtSingleApplication instance("File loader QtSingleApplication example", argc, argv); 130 | QString message; 131 | for (int a = 1; a < argc; ++a) { 132 | message += argv[a]; 133 | if (a < argc-1) 134 | message += " "; 135 | } 136 | 137 | if (instance.sendMessage(message)) 138 | return 0; 139 | 140 | MainWindow mw; 141 | mw.handleMessage(message); 142 | mw.show(); 143 | 144 | QObject::connect(&instance, SIGNAL(messageReceived(const QString&)), 145 | &mw, SLOT(handleMessage(const QString&))); 146 | 147 | instance.setActivationWindow(&mw, false); 148 | QObject::connect(&mw, SIGNAL(needToShow()), &instance, SLOT(activateWindow())); 149 | 150 | return instance.exec(); 151 | } 152 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/trivial/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #include 41 | #include 42 | 43 | class TextEdit : public QTextEdit 44 | { 45 | Q_OBJECT 46 | public: 47 | TextEdit(QWidget *parent = 0) 48 | : QTextEdit(parent) 49 | {} 50 | public slots: 51 | void append(const QString &str) 52 | { 53 | QTextEdit::append(str); 54 | } 55 | }; 56 | 57 | #include "main.moc" 58 | 59 | 60 | 61 | int main(int argc, char **argv) 62 | { 63 | QtSingleApplication instance(argc, argv); 64 | if (instance.sendMessage("Wake up!")) 65 | return 0; 66 | 67 | TextEdit logview; 68 | logview.setReadOnly(true); 69 | logview.show(); 70 | 71 | instance.setActivationWindow(&logview); 72 | 73 | QObject::connect(&instance, SIGNAL(messageReceived(const QString&)), 74 | &logview, SLOT(append(const QString&))); 75 | 76 | return instance.exec(); 77 | } 78 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/trivial/trivial.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | include(../../src/qtsingleapplication.pri) 4 | 5 | SOURCES += main.cpp 6 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/trivial/trivial.qdoc: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | /*! \page qtsingleapplication-example-trivial.html 41 | \title A Trivial Example 42 | 43 | The application in this example has a log-view that displays 44 | messages sent by further instances of the same application. 45 | 46 | The example demonstrates the use of the QtSingleApplication 47 | class to detect and communicate with a running instance of 48 | the application using the sendMessage() API. The messageReceived() 49 | signal is used to display received messages in a QTextEdit log. 50 | 51 | \quotefromfile trivial/main.cpp 52 | \printuntil instance 53 | The example has only the \c main entry point function. 54 | A QtSingleApplication object is created immediately. 55 | 56 | \printuntil return 57 | If another instance of this application is already running, 58 | sendMessage() will succeed, and this instance just exits 59 | immediately. 60 | 61 | \printuntil show() 62 | Otherwise the instance continues as normal and creates the 63 | user interface. 64 | 65 | \printuntil return instance.exec(); 66 | The \c logview object is also set as the application's activation 67 | window. Every time a message is received, the window will be raised 68 | and activated automatically. 69 | 70 | The messageReceived() signal is also connected to the QTextEdit's 71 | append() slot. Every message received from further instances of 72 | this application will be displayed in the log. 73 | 74 | Finally the event loop is entered. 75 | */ 76 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/qtsingleapplication.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE=subdirs 2 | CONFIG += ordered 3 | include(common.pri) 4 | qtsingleapplication-uselib:SUBDIRS=buildlib 5 | SUBDIRS+=examples 6 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/QtLockedFile: -------------------------------------------------------------------------------- 1 | #include "qtlockedfile.h" 2 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/QtSingleApplication: -------------------------------------------------------------------------------- 1 | #include "qtsingleapplication.h" 2 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtlocalpeer.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #ifndef QTLOCALPEER_H 41 | #define QTLOCALPEER_H 42 | 43 | #include 44 | #include 45 | #include 46 | 47 | #include "qtlockedfile.h" 48 | 49 | class QtLocalPeer : public QObject 50 | { 51 | Q_OBJECT 52 | 53 | public: 54 | QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); 55 | bool isClient(); 56 | bool sendMessage(const QString &message, int timeout); 57 | QString applicationId() const 58 | { return id; } 59 | 60 | Q_SIGNALS: 61 | void messageReceived(const QString &message); 62 | 63 | protected Q_SLOTS: 64 | void receiveConnection(); 65 | 66 | protected: 67 | QString id; 68 | QString socketName; 69 | QLocalServer* server; 70 | QtLP_Private::QtLockedFile lockFile; 71 | 72 | private: 73 | static const char* ack; 74 | }; 75 | 76 | #endif // QTLOCALPEER_H 77 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtlockedfile.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #ifndef QTLOCKEDFILE_H 41 | #define QTLOCKEDFILE_H 42 | 43 | #include 44 | #ifdef Q_OS_WIN 45 | #include 46 | #endif 47 | 48 | #if defined(Q_WS_WIN) 49 | # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) 50 | # define QT_QTLOCKEDFILE_EXPORT 51 | # elif defined(QT_QTLOCKEDFILE_IMPORT) 52 | # if defined(QT_QTLOCKEDFILE_EXPORT) 53 | # undef QT_QTLOCKEDFILE_EXPORT 54 | # endif 55 | # define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) 56 | # elif defined(QT_QTLOCKEDFILE_EXPORT) 57 | # undef QT_QTLOCKEDFILE_EXPORT 58 | # define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) 59 | # endif 60 | #else 61 | # define QT_QTLOCKEDFILE_EXPORT 62 | #endif 63 | 64 | namespace QtLP_Private { 65 | 66 | class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile 67 | { 68 | public: 69 | enum LockMode { NoLock = 0, ReadLock, WriteLock }; 70 | 71 | QtLockedFile(); 72 | QtLockedFile(const QString &name); 73 | ~QtLockedFile(); 74 | 75 | bool open(OpenMode mode); 76 | 77 | bool lock(LockMode mode, bool block = true); 78 | bool unlock(); 79 | bool isLocked() const; 80 | LockMode lockMode() const; 81 | 82 | private: 83 | #ifdef Q_OS_WIN 84 | Qt::HANDLE wmutex; 85 | Qt::HANDLE rmutex; 86 | QVector rmutexes; 87 | QString mutexname; 88 | 89 | Qt::HANDLE getMutexHandle(int idx, bool doCreate); 90 | bool waitMutex(Qt::HANDLE mutex, bool doBlock); 91 | 92 | #endif 93 | LockMode m_lock_mode; 94 | }; 95 | } 96 | #endif 97 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtlockedfile_unix.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "qtlockedfile.h" 46 | 47 | bool QtLockedFile::lock(LockMode mode, bool block) 48 | { 49 | if (!isOpen()) { 50 | qWarning("QtLockedFile::lock(): file is not opened"); 51 | return false; 52 | } 53 | 54 | if (mode == NoLock) 55 | return unlock(); 56 | 57 | if (mode == m_lock_mode) 58 | return true; 59 | 60 | if (m_lock_mode != NoLock) 61 | unlock(); 62 | 63 | struct flock fl; 64 | fl.l_whence = SEEK_SET; 65 | fl.l_start = 0; 66 | fl.l_len = 0; 67 | fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; 68 | int cmd = block ? F_SETLKW : F_SETLK; 69 | int ret = fcntl(handle(), cmd, &fl); 70 | 71 | if (ret == -1) { 72 | if (errno != EINTR && errno != EAGAIN) 73 | qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); 74 | return false; 75 | } 76 | 77 | 78 | m_lock_mode = mode; 79 | return true; 80 | } 81 | 82 | 83 | bool QtLockedFile::unlock() 84 | { 85 | if (!isOpen()) { 86 | qWarning("QtLockedFile::unlock(): file is not opened"); 87 | return false; 88 | } 89 | 90 | if (!isLocked()) 91 | return true; 92 | 93 | struct flock fl; 94 | fl.l_whence = SEEK_SET; 95 | fl.l_start = 0; 96 | fl.l_len = 0; 97 | fl.l_type = F_UNLCK; 98 | int ret = fcntl(handle(), F_SETLKW, &fl); 99 | 100 | if (ret == -1) { 101 | qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); 102 | return false; 103 | } 104 | 105 | m_lock_mode = NoLock; 106 | return true; 107 | } 108 | 109 | QtLockedFile::~QtLockedFile() 110 | { 111 | if (isOpen()) 112 | unlock(); 113 | } 114 | 115 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtsingleapplication.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #ifndef QTSINGLEAPPLICATION_H 41 | #define QTSINGLEAPPLICATION_H 42 | 43 | #include 44 | 45 | class QtLocalPeer; 46 | 47 | #if defined(Q_WS_WIN) 48 | # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) 49 | # define QT_QTSINGLEAPPLICATION_EXPORT 50 | # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) 51 | # if defined(QT_QTSINGLEAPPLICATION_EXPORT) 52 | # undef QT_QTSINGLEAPPLICATION_EXPORT 53 | # endif 54 | # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) 55 | # elif defined(QT_QTSINGLEAPPLICATION_EXPORT) 56 | # undef QT_QTSINGLEAPPLICATION_EXPORT 57 | # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) 58 | # endif 59 | #else 60 | # define QT_QTSINGLEAPPLICATION_EXPORT 61 | #endif 62 | 63 | class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication 64 | { 65 | Q_OBJECT 66 | 67 | public: 68 | QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); 69 | QtSingleApplication(const QString &id, int &argc, char **argv); 70 | QtSingleApplication(int &argc, char **argv, Type type); 71 | #if defined(Q_WS_X11) 72 | QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); 73 | QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); 74 | QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); 75 | #endif 76 | 77 | bool isRunning(); 78 | QString id() const; 79 | 80 | void setActivationWindow(QWidget* aw, bool activateOnMessage = true); 81 | QWidget* activationWindow() const; 82 | 83 | // Obsolete: 84 | void initialize(bool dummy = true) 85 | { isRunning(); Q_UNUSED(dummy) } 86 | 87 | public Q_SLOTS: 88 | bool sendMessage(const QString &message, int timeout = 5000); 89 | void activateWindow(); 90 | 91 | 92 | Q_SIGNALS: 93 | void messageReceived(const QString &message); 94 | 95 | 96 | private: 97 | void sysInit(const QString &appId = QString()); 98 | QtLocalPeer *peer; 99 | QWidget *actWin; 100 | }; 101 | 102 | #endif // QTSINGLEAPPLICATION_H 103 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtsingleapplication.pri: -------------------------------------------------------------------------------- 1 | include(../common.pri) 2 | INCLUDEPATH += $$PWD 3 | DEPENDPATH += $$PWD 4 | QT *= network 5 | 6 | qtsingleapplication-uselib:!qtsingleapplication-buildlib { 7 | LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME 8 | } else { 9 | SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp 10 | HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h 11 | } 12 | 13 | win32 { 14 | contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT 15 | else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT 16 | } 17 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtsinglecoreapplication.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #ifndef QTSINGLECOREAPPLICATION_H 41 | #define QTSINGLECOREAPPLICATION_H 42 | 43 | #include 44 | 45 | class QtLocalPeer; 46 | 47 | class QtSingleCoreApplication : public QCoreApplication 48 | { 49 | Q_OBJECT 50 | 51 | public: 52 | QtSingleCoreApplication(int &argc, char **argv); 53 | QtSingleCoreApplication(const QString &id, int &argc, char **argv); 54 | 55 | bool isRunning(); 56 | QString id() const; 57 | 58 | public Q_SLOTS: 59 | bool sendMessage(const QString &message, int timeout = 5000); 60 | 61 | 62 | Q_SIGNALS: 63 | void messageReceived(const QString &message); 64 | 65 | 66 | private: 67 | QtLocalPeer* peer; 68 | }; 69 | 70 | #endif // QTSINGLECOREAPPLICATION_H 71 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtsinglecoreapplication.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h 4 | SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp 5 | 6 | QT *= network 7 | 8 | win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { 9 | DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Following licenses apply: 2 | 3 | src/lib/alac/* - MIT License 4 | src/lib/crypto/* - New BSD License 5 | src/lib/http_parser.* - MIT License 6 | src/lib/* - LGPLv2.1+ License 7 | src/bindings/* - MIT License 8 | src/* - MIT License 9 | AirTV-Qt/* - LGPLv2.1+ License 10 | 11 | Also the following files are used, although not necessary: 12 | 13 | AirTV-Qt/qtsingleapplication/src/* - New BSD License 14 | 15 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = include src 2 | 3 | ACLOCAL_AMFLAGS = -I m4 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Shairplay 2 | ========= 3 | Free portable AirPlay server implementation similar to [ShairPort](https://github.com/abrasive/shairport). 4 | 5 | Currently only AirPort Express emulation is supported. 6 | 7 | Disclaimer 8 | ---------- 9 | All the resources in this repository are written using only freely available 10 | information from the internet. The code and related resources are meant for 11 | educational purposes only. It is the responsibility of the user to make sure 12 | all local laws are adhered to. 13 | 14 | Installation 15 | ------------ 16 | 17 | First you need to install some dependencies, for example on Ubuntu you would 18 | write: 19 | ``` 20 | sudo apt-get install autoconf automake libtool 21 | sudo apt-get install libltdl-dev libao-dev libavahi-compat-libdnssd-dev 22 | sudo apt-get install avahi-daemon 23 | ``` 24 | 25 | ``` 26 | ./autogen.sh 27 | ./configure 28 | make 29 | sudo make install 30 | ``` 31 | 32 | Notice that libao is required in order to install the shairplay binary, 33 | otherwise only the library is compiled and installed. 34 | 35 | ### Fairplay handshake support 36 | 37 | The library has experimental support for handling fairplay handshake (used in 38 | for example screen mirroring) using a playfair library that is licensed under 39 | GPLv3. This can be enabled by adding ```--with-playfair``` to the 40 | ```./configure``` command above. 41 | 42 | Usage 43 | ----- 44 | 45 | Check available options with ```shairplay --help```: 46 | 47 | ``` 48 | Usage: shairplay [OPTION...] 49 | 50 | -a, --apname=AirPort Sets Airport name 51 | -p, --password=secret Sets password 52 | -o, --server_port=5000 Sets port for RAOP service 53 | --ao_driver=driver Sets the ao driver (optional) 54 | --hwaddr=address Sets the MAC address, useful if running multuple instances 55 | --ao_devicename=devicename Sets the ao device name (optional) 56 | --ao_deviceid=id Sets the ao device id (optional) 57 | -h, --help This help 58 | ``` 59 | 60 | Start the server with ```shairplay```, if you are connected to a Wi-Fi the 61 | server should show as an AirPort Express on your iOS devices and Mac OS X 62 | computers in the same network. 63 | 64 | Notice that you need to have the airport.key file in your working directory when 65 | starting the shairplay service. It is not included in the binary for possible 66 | legal reasons. 67 | 68 | Multiple Instances 69 | ------------------ 70 | 71 | Shairplay advertises over mDNS in the form 485D607CEE22@Dining Room Speakers where 485D607CEE22 is a MAC address. This is hardcoded to a nonsense value, which is not a problem so long as it's unique. However, if you run multiple Shairplay instances, iOS devices will only recognize one of them. To fix this, supply the --hwaddr option with different values on each device. 72 | 73 | Related software 74 | ---------------- 75 | 76 | * [ShairPort](https://github.com/abrasive/shairport), original AirPort Express emulator 77 | * [ALAC](http://craz.net/programs/itunes/alac.html), ALAC decoder by David Hammerton 78 | 79 | Description 80 | ----------- 81 | 82 | Short description about what each file in the main library does: 83 | 84 | ``` 85 | src/lib/base64.* - base64 encoder/decoder 86 | src/lib/dnssd.* - dnssd helper functions 87 | src/lib/http_parser.* - HTTP parser from joyent (nginx fork) 88 | src/lib/http_request.* - Request parser that uses http_parser 89 | src/lib/http_response.* - Extremely simple HTTP response serializer 90 | src/lib/httpd.* - Generic HTTP/RTSP server 91 | src/lib/logger.* - Logging related functions 92 | src/lib/netutils.* - Mostly socket related code 93 | src/lib/raop.* - Main RAOP handler, handles all RTSP stuff 94 | src/lib/raop_rtp.* - Handles the RAOP RTP related stuff (UDP/TCP) 95 | src/lib/raop_buffer.* - Parses and buffers RAOP packets, resend logic here 96 | src/lib/rsakey.* - Decrypts and parses the RSA key to bigints 97 | src/lib/rsapem.* - Converts the RSA PEM key to DER encoded bytes 98 | src/lib/sdp.* - Extremely simple RAOP specific SDP parser 99 | src/lib/utils.* - Utils for reading a file and handling strings 100 | ``` 101 | 102 | Short description about what each file in the Qt application does: 103 | 104 | ``` 105 | AirTV-Qt/main.cpp - Initializes the application 106 | AirTV-Qt/mainapplication.cpp - Creates the tray icon and starts RAOP 107 | AirTV-Qt/raopservice.cpp - Handles all communication with the library 108 | AirTV-Qt/raopcallbackhandler.cpp - Converts C callbacks to Qt callbacks 109 | AirTV-Qt/audiooutput.cpp - Takes care of the actual audio output 110 | ``` 111 | 112 | -------------------------------------------------------------------------------- /airport.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEA59dE8qLieItsH1WgjrcFRKj6eUWqi+bGLOX1HL3U3GhC/j0Qg90u3sG/1CUt 3 | wC5vOYvfDmFI6oSFXi5ELabWJmT2dKHzBJKa3k9ok+8t9ucRqMd6DZHJ2YCCLlDRKSKv6kDqnw4U 4 | wPdpOMXziC/AMj3Z/lUVX1G7WSHCAWKf1zNS1eLvqr+boEjXuBOitnZ/bDzPHrTOZz0Dew0uowxf 5 | /+sG+NCK3eQJVxqcaJ/vEHKIVd2M+5qL71yJQ+87X6oV3eaYvt3zWZYD6z5vYTcrtij2VZ9Zmni/ 6 | UAaHqn9JdsBWLUEpVviYnhimNVvYFZeCXg/IdTQ+x4IRdiXNv5hEewIDAQABAoIBAQDl8Axy9XfW 7 | BLmkzkEiqoSwF0PsmVrPzH9KsnwLGH+QZlvjWd8SWYGN7u1507HvhF5N3drJoVU3O14nDY4TFQAa 8 | LlJ9VM35AApXaLyY1ERrN7u9ALKd2LUwYhM7Km539O4yUFYikE2nIPscEsA5ltpxOgUGCY7b7ez5 9 | NtD6nL1ZKauw7aNXmVAvmJTcuPxWmoktF3gDJKK2wxZuNGcJE0uFQEG4Z3BrWP7yoNuSK3dii2jm 10 | lpPHr0O/KnPQtzI3eguhe0TwUem/eYSdyzMyVx/YpwkzwtYL3sR5k0o9rKQLtvLzfAqdBxBurciz 11 | aaA/L0HIgAmOit1GJA2saMxTVPNhAoGBAPfgv1oeZxgxmotiCcMXFEQEWflzhWYTsXrhUIuz5jFu 12 | a39GLS99ZEErhLdrwj8rDDViRVJ5skOp9zFvlYAHs0xh92ji1E7V/ysnKBfsMrPkk5KSKPrnjndM 13 | oPdevWnVkgJ5jxFuNgxkOLMuG9i53B4yMvDTCRiIPMQ++N2iLDaRAoGBAO9v//mU8eVkQaoANf0Z 14 | oMjW8CN4xwWA2cSEIHkd9AfFkftuv8oyLDCG3ZAf0vrhrrtkrfa7ef+AUb69DNggq4mHQAYBp7L+ 15 | k5DKzJrKuO0r+R0YbY9pZD1+/g9dVt91d6LQNepUE/yY2PP5CNoFmjedpLHMOPFdVgqDzDFxU8hL 16 | AoGBANDrr7xAJbqBjHVwIzQ4To9pb4BNeqDndk5Qe7fT3+/H1njGaC0/rXE0Qb7q5ySgnsCb3DvA 17 | cJyRM9SJ7OKlGt0FMSdJD5KG0XPIpAVNwgpXXH5MDJg09KHeh0kXo+QA6viFBi21y340NonnEfdf 18 | 54PX4ZGS/Xac1UK+pLkBB+zRAoGAf0AY3H3qKS2lMEI4bzEFoHeK3G895pDaK3TFBVmD7fV0Zhov 19 | 17fegFPMwOII8MisYm9ZfT2Z0s5Ro3s5rkt+nvLAdfC/PYPKzTLalpGSwomSNYJcB9HNMlmhkGzc 20 | 1JnLYT4iyUyx6pcZBmCd8bD0iwY/FzcgNDaUmbX9+XDvRA0CgYEAkE7pIPlE71qvfJQgoA9em0gI 21 | LAuE4Pu13aKiJnfft7hIjbK+5kyb3TysZvoyDnb3HOKvInK7vXbKuU4ISgxB2bB3HcYzQMGsz1qJ 22 | 2gG0N5hvJpzwwhbhXqFKA4zaaSrw622wDniAK5MlIE0tIAKKP4yxNGjoD2QYjhBGuhvkWKY= 23 | -----END RSA PRIVATE KEY----- 24 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | autoreconf -vif 4 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.61) 5 | AC_INIT([shairplay], [0.9.0], [juhovh@iki.fi]) 6 | AC_CONFIG_MACRO_DIR([m4]) 7 | AC_CONFIG_SRCDIR([src/shairplay.c]) 8 | AC_CONFIG_HEADER([config.h]) 9 | AM_INIT_AUTOMAKE([foreign]) 10 | 11 | # Checks for programs. 12 | AC_PROG_CC 13 | AC_LIBTOOL_WIN32_DLL 14 | AC_PROG_LIBTOOL 15 | 16 | # Checks for libraries. 17 | LT_LIB_M 18 | LT_LIB_DLLOAD 19 | 20 | # Checks for header files. 21 | AC_HEADER_STDC 22 | if test yes = "$libltdl_cv_func_dlopen" || test yes = "$libltdl_cv_lib_dl_dlopen" 23 | then 24 | AC_CHECK_HEADERS([dns_sd.h], [], 25 | [AC_MSG_ERROR([Could not find dns_sd.h header, please install libavahi-compat-libdnssd-dev or equivalent.])]) 26 | fi 27 | 28 | # Checks for typedefs, structures, and compiler characteristics. 29 | 30 | # Checks for library functions. 31 | AC_CHECK_LIB([socket],[connect]) 32 | AC_CHECK_LIB([pthread],[pthread_create]) 33 | 34 | # Custom check for os, similar to webkit 35 | AC_MSG_CHECKING([for native Win32]) 36 | case "$host" in 37 | *-*-mingw*) 38 | os_win32=yes 39 | ;; 40 | *) 41 | os_win32=no 42 | ;; 43 | esac 44 | AC_MSG_RESULT([$os_win32]) 45 | 46 | case "$host" in 47 | *-*-linux*) 48 | os_linux=yes 49 | ;; 50 | *-*-freebsd*) 51 | os_freebsd=yes 52 | ;; 53 | *-*-darwin*) 54 | os_darwin=yes 55 | ;; 56 | esac 57 | 58 | # OS conditionals 59 | AM_CONDITIONAL([OS_WIN32], [test x"$os_win32" = x"yes"]) 60 | AM_CONDITIONAL([OS_UNIX], [test x"$os_win32" = x"no"]) 61 | AM_CONDITIONAL([OS_LINUX], [test x"$os_linux" = x"yes"]) 62 | AM_CONDITIONAL([OS_DARWIN], [test x"$os_darwin" = x"yes"]) 63 | AM_CONDITIONAL([OS_FREEBSD], [test x"$os_freebsd" = x"yes"]) 64 | 65 | # Custom check for libao 66 | PKG_CHECK_MODULES([libao], [ao >= 1.1.0], [have_libao=1], [have_libao=0]) 67 | AM_CONDITIONAL([HAVE_LIBAO], [test "$have_libao" -eq 1]) 68 | AM_COND_IF(HAVE_LIBAO, 69 | [AC_MSG_NOTICE([libao audio library found: Building both shairplay binary and libshairplay library.])], 70 | [AC_MSG_WARN([libao audio library not found: Building shairplay library only.])]) 71 | 72 | # Optional playfair support 73 | AC_ARG_WITH([playfair], 74 | AS_HELP_STRING([--with-playfair], [Build with playfair support])) 75 | AM_CONDITIONAL([WITH_PLAYFAIR], [test x"$with_playfair" = x"yes"]) 76 | AM_COND_IF([WITH_PLAYFAIR], 77 | [AC_DEFINE([HAVE_FAIRPLAY], [1], 78 | [Define if you have the libdl library or equivalent.])]) 79 | 80 | 81 | AC_CONFIG_FILES( 82 | [Makefile] 83 | [include/Makefile] 84 | [src/Makefile] 85 | [src/lib/Makefile] 86 | [src/lib/alac/Makefile] 87 | [src/lib/crypto/Makefile] 88 | [src/lib/curve25519/Makefile] 89 | [src/lib/ed25519/Makefile] 90 | [src/lib/playfair/Makefile] 91 | ) 92 | AC_OUTPUT 93 | -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | nobase_include_HEADERS = shairplay/dnssd.h shairplay/raop.h 2 | -------------------------------------------------------------------------------- /include/shairplay/dnssd.h: -------------------------------------------------------------------------------- 1 | #ifndef DNSSD_H 2 | #define DNSSD_H 3 | 4 | #if defined(WIN32) && defined(DLL_EXPORT) 5 | # define DNSSD_API __declspec(dllexport) 6 | #else 7 | # define DNSSD_API 8 | #endif 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #define DNSSD_ERROR_NOERROR 0 15 | #define DNSSD_ERROR_HWADDRLEN 1 16 | #define DNSSD_ERROR_OUTOFMEM 2 17 | #define DNSSD_ERROR_LIBNOTFOUND 3 18 | #define DNSSD_ERROR_PROCNOTFOUND 4 19 | 20 | typedef struct dnssd_s dnssd_t; 21 | 22 | DNSSD_API dnssd_t *dnssd_init(int *error); 23 | 24 | DNSSD_API int dnssd_register_raop(dnssd_t *dnssd, const char *name, unsigned short port, const char *hwaddr, int hwaddrlen, int password); 25 | DNSSD_API int dnssd_register_airplay(dnssd_t *dnssd, const char *name, unsigned short port, const char *hwaddr, int hwaddrlen); 26 | 27 | DNSSD_API void dnssd_unregister_raop(dnssd_t *dnssd); 28 | DNSSD_API void dnssd_unregister_airplay(dnssd_t *dnssd); 29 | 30 | DNSSD_API void dnssd_destroy(dnssd_t *dnssd); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | #endif 36 | -------------------------------------------------------------------------------- /include/shairplay/raop.h: -------------------------------------------------------------------------------- 1 | #ifndef RAOP_H 2 | #define RAOP_H 3 | 4 | #if defined (WIN32) && defined(DLL_EXPORT) 5 | # define RAOP_API __declspec(dllexport) 6 | #else 7 | # define RAOP_API 8 | #endif 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | 15 | /* Define syslog style log levels */ 16 | #define RAOP_LOG_EMERG 0 /* system is unusable */ 17 | #define RAOP_LOG_ALERT 1 /* action must be taken immediately */ 18 | #define RAOP_LOG_CRIT 2 /* critical conditions */ 19 | #define RAOP_LOG_ERR 3 /* error conditions */ 20 | #define RAOP_LOG_WARNING 4 /* warning conditions */ 21 | #define RAOP_LOG_NOTICE 5 /* normal but significant condition */ 22 | #define RAOP_LOG_INFO 6 /* informational */ 23 | #define RAOP_LOG_DEBUG 7 /* debug-level messages */ 24 | 25 | 26 | typedef struct raop_s raop_t; 27 | 28 | typedef void (*raop_log_callback_t)(void *cls, int level, const char *msg); 29 | 30 | struct raop_callbacks_s { 31 | void* cls; 32 | 33 | /* Compulsory callback functions */ 34 | void* (*audio_init)(void *cls, int bits, int channels, int samplerate); 35 | void (*audio_process)(void *cls, void *session, const void *buffer, int buflen); 36 | void (*audio_destroy)(void *cls, void *session); 37 | 38 | /* Optional but recommended callback functions */ 39 | void (*audio_flush)(void *cls, void *session); 40 | void (*audio_set_volume)(void *cls, void *session, float volume); 41 | void (*audio_set_metadata)(void *cls, void *session, const void *buffer, int buflen); 42 | void (*audio_set_coverart)(void *cls, void *session, const void *buffer, int buflen); 43 | void (*audio_remote_control_id)(void *cls, const char *dacp_id, const char *active_remote_header); 44 | void (*audio_set_progress)(void *cls, void *session, unsigned int start, unsigned int curr, unsigned int end); 45 | }; 46 | typedef struct raop_callbacks_s raop_callbacks_t; 47 | 48 | RAOP_API raop_t *raop_init(int max_clients, raop_callbacks_t *callbacks, const char *pemkey, int *error); 49 | RAOP_API raop_t *raop_init_from_keyfile(int max_clients, raop_callbacks_t *callbacks, const char *keyfile, int *error); 50 | 51 | RAOP_API void raop_set_log_level(raop_t *raop, int level); 52 | RAOP_API void raop_set_log_callback(raop_t *raop, raop_log_callback_t callback, void *cls); 53 | 54 | RAOP_API int raop_start(raop_t *raop, unsigned short *port, const char *hwaddr, int hwaddrlen, const char *password); 55 | RAOP_API int raop_is_running(raop_t *raop); 56 | RAOP_API void raop_stop(raop_t *raop); 57 | 58 | RAOP_API void raop_destroy(raop_t *raop); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | #endif 64 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib 2 | 3 | AM_CPPFLAGS = -I$(top_srcdir)/include 4 | 5 | if HAVE_LIBAO 6 | bin_PROGRAMS = shairplay 7 | shairplay_SOURCES = shairplay.c 8 | shairplay_LDADD = lib/libshairplay.la 9 | shairplay_CFLAGS = 10 | shairplay_LDFLAGS = -static-libtool-libs 11 | 12 | shairplay_CFLAGS += $(libao_CFLAGS) 13 | shairplay_LDADD += $(libao_LIBS) 14 | endif 15 | -------------------------------------------------------------------------------- /src/bindings/qt4/dnssdservice.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "dnssdservice.h" 25 | 26 | DnssdService::DnssdService(QObject *parent) : 27 | QObject(parent) 28 | { 29 | } 30 | 31 | bool DnssdService::init() 32 | { 33 | int error; 34 | m_dnssd = dnssd_init(&error); 35 | if (!m_dnssd) { 36 | return false; 37 | } 38 | return true; 39 | } 40 | 41 | DnssdService::~DnssdService() 42 | { 43 | dnssd_destroy(m_dnssd); 44 | } 45 | 46 | void DnssdService::registerRaop(const QString & name, quint16 port, const QByteArray & hwaddr) 47 | { 48 | dnssd_register_raop(m_dnssd, name.toUtf8().data(), port, hwaddr.data(), hwaddr.size(), 0); 49 | } 50 | 51 | void DnssdService::unregisterRaop() 52 | { 53 | dnssd_unregister_raop(m_dnssd); 54 | } 55 | 56 | void DnssdService::registerAirplay(const QString &name, quint16 port, const QByteArray &hwaddr) 57 | { 58 | dnssd_register_airplay(m_dnssd, name.toUtf8().data(), port, hwaddr.data(), hwaddr.size()); 59 | } 60 | 61 | void DnssdService::unregisterAirplay() 62 | { 63 | dnssd_unregister_airplay(m_dnssd); 64 | } 65 | -------------------------------------------------------------------------------- /src/bindings/qt4/dnssdservice.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef DNSSDSERVICE_H 25 | #define DNSSDSERVICE_H 26 | 27 | #include 28 | 29 | #include 30 | 31 | class DnssdService : public QObject 32 | { 33 | Q_OBJECT 34 | public: 35 | explicit DnssdService(QObject *parent = 0); 36 | ~DnssdService(); 37 | 38 | bool init(); 39 | 40 | void registerRaop(const QString & name, quint16 port, const QByteArray & hwaddr); 41 | void unregisterRaop(); 42 | 43 | void registerAirplay(const QString & name, quint16 port, const QByteArray & hwaddr); 44 | void unregisterAirplay(); 45 | 46 | private: 47 | dnssd_t * m_dnssd; 48 | 49 | signals: 50 | 51 | public slots: 52 | 53 | }; 54 | 55 | #endif // DNSSDSERVICE_H 56 | -------------------------------------------------------------------------------- /src/bindings/qt4/raopcallbackhandler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "raopcallbackhandler.h" 25 | 26 | RaopCallbackHandler::RaopCallbackHandler(QObject *parent) : 27 | QObject(parent) 28 | { 29 | } 30 | 31 | void RaopCallbackHandler::init(RaopAudioHandler *callbacks) 32 | { 33 | m_callbacks = callbacks; 34 | } 35 | 36 | void RaopCallbackHandler::audioInit(void *session, int bits, int channels, int samplerate) 37 | { 38 | void **retval = (void**)session; 39 | if (m_callbacks) { 40 | *retval = m_callbacks->audioInit(bits, channels, samplerate); 41 | } 42 | } 43 | 44 | void RaopCallbackHandler::audioProcess(void *session, void *buffer, int buflen) 45 | { 46 | if (m_callbacks) { 47 | m_callbacks->audioProcess(session, QByteArray((const char *)buffer, buflen)); 48 | } 49 | } 50 | 51 | void RaopCallbackHandler::audioDestroy(void *session) 52 | { 53 | if (m_callbacks) { 54 | m_callbacks->audioDestroy(session); 55 | } 56 | } 57 | 58 | void RaopCallbackHandler::audioFlush(void *session) 59 | { 60 | if (m_callbacks) { 61 | m_callbacks->audioFlush(session); 62 | } 63 | } 64 | 65 | void RaopCallbackHandler::audioSetVolume(void *session, float volume) 66 | { 67 | if (m_callbacks) { 68 | m_callbacks->audioSetVolume(session, volume); 69 | } 70 | } 71 | 72 | void RaopCallbackHandler::audioSetMetadata(void *session, void *buffer, int buflen) 73 | { 74 | if (m_callbacks) { 75 | m_callbacks->audioSetMetadata(session, QByteArray((const char *)buffer, buflen)); 76 | } 77 | } 78 | 79 | void RaopCallbackHandler::audioSetCoverart(void *session, void *buffer, int buflen) 80 | { 81 | if (m_callbacks) { 82 | m_callbacks->audioSetCoverart(session, QByteArray((const char *)buffer, buflen)); 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/bindings/qt4/raopcallbackhandler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef RAOPCALLBACKHANDLER_H 25 | #define RAOPCALLBACKHANDLER_H 26 | 27 | #include 28 | 29 | #include "raopcallbacks.h" 30 | 31 | class RaopCallbackHandler : public QObject 32 | { 33 | Q_OBJECT 34 | public: 35 | explicit RaopCallbackHandler(QObject *parent = 0); 36 | void init(RaopAudioHandler *callbacks); 37 | 38 | private: 39 | RaopAudioHandler * m_callbacks; 40 | 41 | signals: 42 | 43 | public slots: 44 | void audioInit(void *session, int bits, int channels, int samplerate); 45 | void audioProcess(void *session, void *buffer, int buflen); 46 | void audioDestroy(void *session); 47 | void audioFlush(void *session); 48 | void audioSetVolume(void *session, float volume); 49 | void audioSetMetadata(void *session, void *buffer, int buflen); 50 | void audioSetCoverart(void *session, void *buffer, int buflen); 51 | }; 52 | 53 | #endif // RAOPCALLBACKHANDLER_H 54 | -------------------------------------------------------------------------------- /src/bindings/qt4/raopcallbacks.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef RAOPCALLBACKS_H 25 | #define RAOPCALLBACKS_H 26 | 27 | #include 28 | 29 | class RaopLogHandler : public QObject 30 | { 31 | Q_OBJECT 32 | public: 33 | explicit RaopLogHandler(QObject *parent = 0) : QObject(parent) {} 34 | 35 | virtual void logCallback(int level, const char *msg) = 0; 36 | }; 37 | 38 | class RaopAudioHandler : public QObject 39 | { 40 | Q_OBJECT 41 | public: 42 | explicit RaopAudioHandler(QObject *parent = 0) : QObject(parent) {} 43 | 44 | virtual void *audioInit(int bits, int channels, int samplerate) = 0; 45 | virtual void audioProcess(void *session, const QByteArray & buffer) = 0; 46 | virtual void audioDestroy(void *session) = 0; 47 | 48 | virtual void audioFlush(void *session) { Q_UNUSED(session) } 49 | virtual void audioSetVolume(void *session, float volume) { Q_UNUSED(session) Q_UNUSED(volume) } 50 | virtual void audioSetMetadata(void *session, const QByteArray & buffer) { Q_UNUSED(session) Q_UNUSED(buffer) } 51 | virtual void audioSetCoverart(void *session, const QByteArray & buffer) { Q_UNUSED(session) Q_UNUSED(buffer) } 52 | }; 53 | 54 | #endif // RAOPCALLBACKS_H 55 | -------------------------------------------------------------------------------- /src/bindings/qt4/raopservice.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef RAOPSERVICE_H 25 | #define RAOPSERVICE_H 26 | 27 | #include 28 | 29 | #include 30 | 31 | #include "raopcallbacks.h" 32 | 33 | class RaopService : public QObject 34 | { 35 | Q_OBJECT 36 | public: 37 | explicit RaopService(QObject *parent = 0); 38 | ~RaopService(); 39 | 40 | bool init(int max_clients, RaopAudioHandler *callbacks); 41 | void setLogLevel(int level); 42 | void setLogHandler(RaopLogHandler *logger); 43 | bool start(quint16 port, const QByteArray & hwaddr); 44 | bool isRunning(); 45 | void stop(); 46 | 47 | private: 48 | raop_t * m_raop; 49 | 50 | signals: 51 | 52 | public slots: 53 | 54 | }; 55 | 56 | #endif // RAOPSERVICE_H 57 | -------------------------------------------------------------------------------- /src/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | if WITH_PLAYFAIR 2 | PLAYFAIR_SUBDIR = playfair 3 | PLAYFAIR_LIBADD = playfair/libplayfair.la 4 | FAIRPLAY_SOURCE = fairplay_playfair.c 5 | else 6 | FAIRPLAY_SOURCE = fairplay_dummy.c 7 | endif 8 | 9 | SUBDIRS = crypto alac curve25519 ed25519 $(PLAYFAIR_SUBDIR) 10 | 11 | AM_CPPFLAGS = -I$(top_srcdir)/include/shairplay 12 | 13 | lib_LTLIBRARIES = libshairplay.la 14 | libshairplay_la_SOURCES = base64.c base64.h digest.c digest.h dnssd.c dnssdint.h http_parser.c http_parser.h http_request.c http_request.h http_response.c http_response.h httpd.c httpd.h logger.c logger.h netutils.c netutils.h raop.c raop_buffer.c raop_buffer.h raop_rtp.c raop_rtp.h rsakey.c rsakey.h rsapem.c rsapem.h sdp.c sdp.h aes_ctr.c aes_ctr.h pairing.c pairing.h utils.c utils.h $(FAIRPLAY_SOURCE) fairplay.h plist.c plist.h compat.h memalign.h sockets.h threads.h 15 | libshairplay_la_CPPFLAGS = $(AM_CPPFLAGS) 16 | 17 | # This library depends on 3rd party libraries 18 | libshairplay_la_LIBADD = crypto/libcrypto.la alac/libalac.la curve25519/libcurve25519.la ed25519/libed25519.la $(PLAYFAIR_LIBADD) 19 | libshairplay_la_LDFLAGS = -no-undefined -version-info 0:0:0 20 | 21 | ### Update -version-info above with the following rules 22 | # 1. Start with version information of ‘0:0:0’ for each libtool library. 23 | # 2. Update the version information only immediately before a public release of 24 | # your software. More frequent updates are unnecessary, and only guarantee 25 | # that the current interface number gets larger faster. 26 | # 3. If the library source code has changed at all since the last update, then 27 | # increment revision (‘c:r:a’ becomes ‘c:r+1:a’). 28 | # 4. If any interfaces have been added, removed, or changed since the last 29 | # update, increment current, and set revision to 0. 30 | # 5. If any interfaces have been added since the last public release, then 31 | # increment age. 32 | # 6. If any interfaces have been removed or changed since the last public 33 | # release, then set age to 0. 34 | ### 35 | 36 | libshairplay_la_LIBADD += $(LIBADD_DLOPEN) 37 | libshairplay_la_LIBADD += $(LIBM) 38 | 39 | if OS_WIN32 40 | libshairplay_la_CPPFLAGS += -DDLL_EXPORT 41 | libshairplay_la_LDFLAGS += -lws2_32 -lwinmm 42 | else 43 | libshairplay_la_LDFLAGS += -export-symbols-regex '^(raop|dnssd)' 44 | endif 45 | -------------------------------------------------------------------------------- /src/lib/aes_ctr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2018 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include "aes_ctr.h" 19 | 20 | static void 21 | ctr128_inc(uint8_t *counter) 22 | { 23 | uint32_t n = 16, c = 1; 24 | 25 | do { 26 | --n; 27 | c += counter[n]; 28 | counter[n] = (uint8_t) c; 29 | c >>= 8; 30 | } while (n); 31 | } 32 | 33 | void 34 | AES_ctr_set_key(AES_CTR_CTX *ctx, const uint8_t *key, const uint8_t *nonce, AES_MODE mode) 35 | { 36 | assert(ctx); 37 | 38 | /* Setting IV as nonce, but it will be overridden in encrypt */ 39 | AES_set_key(&ctx->aes_ctx, key, nonce, mode); 40 | memcpy(ctx->counter, nonce, AES_BLOCKSIZE); 41 | memset(ctx->state, 0, AES_BLOCKSIZE); 42 | ctx->available = 0; 43 | } 44 | 45 | void 46 | AES_ctr_encrypt(AES_CTR_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) 47 | { 48 | unsigned char block[16]; 49 | int msgidx, i; 50 | 51 | assert(ctx); 52 | assert(msg); 53 | assert(out); 54 | 55 | msgidx = 0; 56 | while (msgidx < length) { 57 | if (ctx->available == 0) { 58 | /* Generate a new block into state if we have no bytes */ 59 | memset(ctx->aes_ctx.iv, 0, AES_IV_SIZE); 60 | AES_cbc_encrypt(&ctx->aes_ctx, ctx->counter, ctx->state, AES_BLOCKSIZE); 61 | ctx->available = AES_BLOCKSIZE; 62 | ctr128_inc(ctx->counter); 63 | } 64 | for (i=0; iavailable && msgidxstate[AES_BLOCKSIZE-ctx->available+i]; 66 | } 67 | ctx->available -= i; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/lib/aes_ctr.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2018 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef AES_CTR_H 16 | #define AES_CTR_H 17 | 18 | #include 19 | #include "crypto/crypto.h" 20 | 21 | typedef struct aes_ctr_key_st { 22 | AES_CTX aes_ctx; 23 | uint8_t counter[AES_BLOCKSIZE]; 24 | uint8_t state[AES_BLOCKSIZE]; 25 | uint8_t available; 26 | } AES_CTR_CTX; 27 | 28 | void AES_ctr_set_key(AES_CTR_CTX *ctx, const uint8_t *key, const uint8_t *nonce, AES_MODE mode); 29 | void AES_ctr_encrypt(AES_CTR_CTX *ctx, const uint8_t *msg, uint8_t *out, int length); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/lib/alac/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LTLIBRARIES = libalac.la 2 | libalac_la_SOURCES = alac.c alac.h stdint_win.h 3 | -------------------------------------------------------------------------------- /src/lib/alac/alac.h: -------------------------------------------------------------------------------- 1 | #ifndef __ALAC__DECOMP_H 2 | #define __ALAC__DECOMP_H 3 | 4 | #include 5 | 6 | typedef struct alac_file alac_file; 7 | 8 | alac_file *alac_create(int samplesize, int numchannels); 9 | void alac_decode_frame(alac_file *alac, 10 | unsigned char *inbuffer, 11 | void *outbuffer, int *outputsize); 12 | void alac_set_info(alac_file *alac, char *inputbuffer); 13 | void alac_allocate_buffers(alac_file *alac); 14 | void alac_free(alac_file *alac); 15 | 16 | struct alac_file 17 | { 18 | unsigned char *input_buffer; 19 | int input_buffer_bitaccumulator; /* used so we can do arbitary 20 | bit reads */ 21 | 22 | int samplesize; 23 | int numchannels; 24 | int bytespersample; 25 | 26 | 27 | /* buffers */ 28 | int32_t *predicterror_buffer_a; 29 | int32_t *predicterror_buffer_b; 30 | 31 | int32_t *outputsamples_buffer_a; 32 | int32_t *outputsamples_buffer_b; 33 | 34 | int32_t *uncompressed_bytes_buffer_a; 35 | int32_t *uncompressed_bytes_buffer_b; 36 | 37 | 38 | 39 | /* stuff from setinfo */ 40 | uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max samples per frame? */ 41 | uint8_t setinfo_7a; /* 0x00 */ 42 | uint8_t setinfo_sample_size; /* 0x10 */ 43 | uint8_t setinfo_rice_historymult; /* 0x28 */ 44 | uint8_t setinfo_rice_initialhistory; /* 0x0a */ 45 | uint8_t setinfo_rice_kmodifier; /* 0x0e */ 46 | uint8_t setinfo_7f; /* 0x02 */ 47 | uint16_t setinfo_80; /* 0x00ff */ 48 | uint32_t setinfo_82; /* 0x000020e7 */ /* max sample size?? */ 49 | uint32_t setinfo_86; /* 0x00069fe4 */ /* bit rate (avarge)?? */ 50 | uint32_t setinfo_8a_rate; /* 0x0000ac44 */ 51 | /* end setinfo stuff */ 52 | 53 | }; 54 | 55 | 56 | #endif /* __ALAC__DECOMP_H */ 57 | 58 | -------------------------------------------------------------------------------- /src/lib/alac/stdint_win.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ALAC_STDINT_WIN_H__ 3 | #define ALAC_STDINT_WIN_H__ 4 | 5 | typedef signed char int8_t; 6 | typedef signed short int16_t; 7 | typedef signed int int32_t; 8 | typedef signed __int64 int64_t; 9 | typedef unsigned char uint8_t; 10 | typedef unsigned short uint16_t; 11 | typedef unsigned int uint32_t; 12 | typedef unsigned __int64 uint64_t; 13 | 14 | #endif // ALAC_STDINT_WIN_H__ -------------------------------------------------------------------------------- /src/lib/base64.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef BASE64_H 16 | #define BASE64_H 17 | 18 | typedef struct base64_s base64_t; 19 | 20 | base64_t *base64_init(const char *charlist, int use_padding, int skip_spaces); 21 | 22 | int base64_encoded_length(base64_t *base64, int srclen); 23 | 24 | int base64_encode(base64_t *base64, char *dst, const unsigned char *src, int srclen); 25 | int base64_decode(base64_t *base64, unsigned char **dst, const char *src, int srclen); 26 | 27 | void base64_destroy(base64_t *base64); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/lib/compat.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef COMPAT_H 16 | #define COMPAT_H 17 | 18 | #if defined(WIN32) 19 | #include 20 | #include 21 | #ifndef snprintf 22 | #define snprintf _snprintf 23 | #endif 24 | #else 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #endif 36 | 37 | #include "memalign.h" 38 | #include "sockets.h" 39 | #include "threads.h" 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/lib/crypto/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LTLIBRARIES = libcrypto.la 2 | libcrypto_la_SOURCES = bigint.c bigint.h bigint_impl.h aes.c hmac.c md5.c rc4.c sha1.c crypto.h os_port.h config.h 3 | 4 | -------------------------------------------------------------------------------- /src/lib/crypto/bigint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007, Cameron Rich 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * * Neither the name of the axTLS project nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef BIGINT_HEADER 32 | #define BIGINT_HEADER 33 | 34 | #include "crypto.h" 35 | 36 | BI_CTX *bi_initialize(void); 37 | void bi_terminate(BI_CTX *ctx); 38 | void bi_permanent(bigint *bi); 39 | void bi_depermanent(bigint *bi); 40 | void bi_clear_cache(BI_CTX *ctx); 41 | void bi_free(BI_CTX *ctx, bigint *bi); 42 | bigint *bi_copy(bigint *bi); 43 | bigint *bi_clone(BI_CTX *ctx, const bigint *bi); 44 | void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size); 45 | bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len); 46 | bigint *int_to_bi(BI_CTX *ctx, comp i); 47 | 48 | /* the functions that actually do something interesting */ 49 | bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib); 50 | bigint *bi_subtract(BI_CTX *ctx, bigint *bia, 51 | bigint *bib, int *is_negative); 52 | bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod); 53 | bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib); 54 | bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp); 55 | bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp); 56 | int bi_compare(bigint *bia, bigint *bib); 57 | void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset); 58 | void bi_free_mod(BI_CTX *ctx, int mod_offset); 59 | 60 | #ifdef CONFIG_SSL_FULL_MODE 61 | void bi_print(const char *label, bigint *bi); 62 | bigint *bi_str_import(BI_CTX *ctx, const char *data); 63 | #endif 64 | 65 | /** 66 | * @def bi_mod 67 | * Find the residue of B. bi_set_mod() must be called before hand. 68 | */ 69 | #define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1) 70 | 71 | /** 72 | * bi_residue() is technically the same as bi_mod(), but it uses the 73 | * appropriate reduction technique (which is bi_mod() when doing classical 74 | * reduction). 75 | */ 76 | #if defined(CONFIG_BIGINT_MONTGOMERY) 77 | #define bi_residue(A, B) bi_mont(A, B) 78 | bigint *bi_mont(BI_CTX *ctx, bigint *bixy); 79 | #elif defined(CONFIG_BIGINT_BARRETT) 80 | #define bi_residue(A, B) bi_barrett(A, B) 81 | bigint *bi_barrett(BI_CTX *ctx, bigint *bi); 82 | #else /* if defined(CONFIG_BIGINT_CLASSICAL) */ 83 | #define bi_residue(A, B) bi_mod(A, B) 84 | #endif 85 | 86 | #ifdef CONFIG_BIGINT_SQUARE 87 | bigint *bi_square(BI_CTX *ctx, bigint *bi); 88 | #else 89 | #define bi_square(A, B) bi_multiply(A, bi_copy(B), B) 90 | #endif 91 | 92 | #ifdef CONFIG_BIGINT_CRT 93 | bigint *bi_crt(BI_CTX *ctx, bigint *bi, 94 | bigint *dP, bigint *dQ, 95 | bigint *p, bigint *q, 96 | bigint *qInv); 97 | #endif 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/lib/crypto/config.h: -------------------------------------------------------------------------------- 1 | 2 | #define CONFIG_BIGINT_BARRETT 1 3 | #define CONFIG_BIGINT_CRT 1 4 | #define CONFIG_BIGINT_SQUARE 1 5 | #define CONFIG_BIGINT_32BIT 1 6 | 7 | -------------------------------------------------------------------------------- /src/lib/crypto/hmac.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007, Cameron Rich 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * * Neither the name of the axTLS project nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | /** 32 | * HMAC implementation - This code was originally taken from RFC2104 33 | * See http://www.ietf.org/rfc/rfc2104.txt and 34 | * http://www.faqs.org/rfcs/rfc2202.html 35 | */ 36 | 37 | #include 38 | #include "os_port.h" 39 | #include "crypto.h" 40 | 41 | /** 42 | * Perform HMAC-MD5 43 | * NOTE: does not handle keys larger than the block size. 44 | */ 45 | void hmac_md5(const uint8_t *msg, int length, const uint8_t *key, 46 | int key_len, uint8_t *digest) 47 | { 48 | MD5_CTX context; 49 | uint8_t k_ipad[64]; 50 | uint8_t k_opad[64]; 51 | int i; 52 | 53 | memset(k_ipad, 0, sizeof k_ipad); 54 | memset(k_opad, 0, sizeof k_opad); 55 | memcpy(k_ipad, key, key_len); 56 | memcpy(k_opad, key, key_len); 57 | 58 | for (i = 0; i < 64; i++) 59 | { 60 | k_ipad[i] ^= 0x36; 61 | k_opad[i] ^= 0x5c; 62 | } 63 | 64 | MD5_Init(&context); 65 | MD5_Update(&context, k_ipad, 64); 66 | MD5_Update(&context, msg, length); 67 | MD5_Final(digest, &context); 68 | MD5_Init(&context); 69 | MD5_Update(&context, k_opad, 64); 70 | MD5_Update(&context, digest, MD5_SIZE); 71 | MD5_Final(digest, &context); 72 | } 73 | 74 | /** 75 | * Perform HMAC-SHA1 76 | * NOTE: does not handle keys larger than the block size. 77 | */ 78 | void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, 79 | int key_len, uint8_t *digest) 80 | { 81 | SHA1_CTX context; 82 | uint8_t k_ipad[64]; 83 | uint8_t k_opad[64]; 84 | int i; 85 | 86 | memset(k_ipad, 0, sizeof k_ipad); 87 | memset(k_opad, 0, sizeof k_opad); 88 | memcpy(k_ipad, key, key_len); 89 | memcpy(k_opad, key, key_len); 90 | 91 | for (i = 0; i < 64; i++) 92 | { 93 | k_ipad[i] ^= 0x36; 94 | k_opad[i] ^= 0x5c; 95 | } 96 | 97 | SHA1_Init(&context); 98 | SHA1_Update(&context, k_ipad, 64); 99 | SHA1_Update(&context, msg, length); 100 | SHA1_Final(digest, &context); 101 | SHA1_Init(&context); 102 | SHA1_Update(&context, k_opad, 64); 103 | SHA1_Update(&context, digest, SHA1_SIZE); 104 | SHA1_Final(digest, &context); 105 | } 106 | -------------------------------------------------------------------------------- /src/lib/crypto/rc4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007, Cameron Rich 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * * Neither the name of the axTLS project nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | /** 32 | * An implementation of the RC4/ARC4 algorithm. 33 | * Originally written by Christophe Devine. 34 | */ 35 | 36 | #include 37 | #include "os_port.h" 38 | #include "crypto.h" 39 | 40 | /** 41 | * Get ready for an encrypt/decrypt operation 42 | */ 43 | void RC4_setup(RC4_CTX *ctx, const uint8_t *key, int length) 44 | { 45 | int i, j = 0, k = 0, a; 46 | uint8_t *m; 47 | 48 | ctx->x = 0; 49 | ctx->y = 0; 50 | m = ctx->m; 51 | 52 | for (i = 0; i < 256; i++) 53 | m[i] = i; 54 | 55 | for (i = 0; i < 256; i++) 56 | { 57 | a = m[i]; 58 | j = (uint8_t)(j + a + key[k]); 59 | m[i] = m[j]; 60 | m[j] = a; 61 | 62 | if (++k >= length) 63 | k = 0; 64 | } 65 | } 66 | 67 | /** 68 | * Perform the encrypt/decrypt operation (can use it for either since 69 | * this is a stream cipher). 70 | * NOTE: *msg and *out must be the same pointer (performance tweak) 71 | */ 72 | void RC4_crypt(RC4_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) 73 | { 74 | int i; 75 | uint8_t *m, x, y, a, b; 76 | 77 | x = ctx->x; 78 | y = ctx->y; 79 | m = ctx->m; 80 | 81 | for (i = 0; i < length; i++) 82 | { 83 | a = m[++x]; 84 | y += a; 85 | m[x] = b = m[y]; 86 | m[y] = a; 87 | out[i] ^= m[(uint8_t)(a + b)]; 88 | } 89 | 90 | ctx->x = x; 91 | ctx->y = y; 92 | } 93 | -------------------------------------------------------------------------------- /src/lib/curve25519/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LTLIBRARIES = libcurve25519.la 2 | libcurve25519_la_SOURCES = curve25519-donna.c 3 | -------------------------------------------------------------------------------- /src/lib/curve25519/curve25519.h: -------------------------------------------------------------------------------- 1 | #ifndef CURVE25519_DONNA_H 2 | #define CURVE25519_DONNA_H 3 | 4 | static const unsigned char kCurve25519BasePoint[32] = { 9 }; 5 | 6 | int curve25519_donna(unsigned char *mypublic, const unsigned char *secret, const unsigned char *basepoint); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/lib/digest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "compat.h" 7 | #include "utils.h" 8 | #include "crypto/crypto.h" 9 | 10 | void 11 | digest_md5_to_hex(const unsigned char *md5buf, char *md5hex) 12 | { 13 | int i; 14 | for (i=0; i>4; 16 | md5hex[i] = (val<10) ? '0'+val : 'a'+(val-10); 17 | } 18 | } 19 | 20 | void 21 | digest_get_response(const char *username, const char *realm, 22 | const char *password, const char *nonce, 23 | const char *method, const char *uri, 24 | char *response) 25 | { 26 | MD5_CTX md5ctx; 27 | unsigned char md5buf[MD5_SIZE]; 28 | char md5hex[MD5_SIZE*2]; 29 | 30 | /* Calculate first inner MD5 hash */ 31 | MD5_Init(&md5ctx); 32 | MD5_Update(&md5ctx, (const unsigned char *)username, strlen(username)); 33 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 34 | MD5_Update(&md5ctx, (const unsigned char *)realm, strlen(realm)); 35 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 36 | MD5_Update(&md5ctx, (const unsigned char *)password, strlen(password)); 37 | MD5_Final(md5buf, &md5ctx); 38 | digest_md5_to_hex(md5buf, md5hex); 39 | 40 | /* Calculate second inner MD5 hash */ 41 | MD5_Init(&md5ctx); 42 | MD5_Update(&md5ctx, (const unsigned char *)method, strlen(method)); 43 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 44 | MD5_Update(&md5ctx, (const unsigned char *)uri, strlen(uri)); 45 | MD5_Final(md5buf, &md5ctx); 46 | 47 | /* Calculate outer MD5 hash */ 48 | MD5_Init(&md5ctx); 49 | MD5_Update(&md5ctx, (const unsigned char *)md5hex, sizeof(md5hex)); 50 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 51 | MD5_Update(&md5ctx, (const unsigned char *)nonce, strlen(nonce)); 52 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 53 | digest_md5_to_hex(md5buf, md5hex); 54 | MD5_Update(&md5ctx, (const unsigned char *)md5hex, sizeof(md5hex)); 55 | MD5_Final(md5buf, &md5ctx); 56 | 57 | /* Store the final result to response */ 58 | digest_md5_to_hex(md5buf, response); 59 | } 60 | 61 | void 62 | digest_generate_nonce(char *result, int resultlen) 63 | { 64 | MD5_CTX md5ctx; 65 | unsigned char md5buf[MD5_SIZE]; 66 | char md5hex[MD5_SIZE*2]; 67 | unsigned int time; 68 | 69 | SYSTEM_GET_TIME(time); 70 | 71 | MD5_Init(&md5ctx); 72 | MD5_Update(&md5ctx, (unsigned char *)&time, sizeof(time)); 73 | MD5_Final(md5buf, &md5ctx); 74 | digest_md5_to_hex(md5buf, md5hex); 75 | 76 | memset(result, 0, resultlen); 77 | strncpy(result, md5hex, resultlen-1); 78 | } 79 | 80 | int 81 | digest_is_valid(const char *our_realm, const char *password, 82 | const char *our_nonce, const char *method, 83 | const char *our_uri, const char *authorization) 84 | { 85 | char *auth; 86 | char *current; 87 | char *value; 88 | int success; 89 | 90 | /* Get values from authorization */ 91 | char *username = NULL; 92 | char *realm = NULL; 93 | char *nonce = NULL; 94 | char *uri = NULL; 95 | char *response = NULL; 96 | 97 | /* Buffer for our response */ 98 | char our_response[MD5_SIZE*2+1]; 99 | 100 | if (!authorization) { 101 | return 0; 102 | } 103 | current = auth = strdup(authorization); 104 | if (!auth) { 105 | return 0; 106 | } 107 | 108 | /* Check that the type is digest */ 109 | if (strncmp("Digest", current, 6)) { 110 | free(auth); 111 | return 0; 112 | } 113 | current += 6; 114 | 115 | while ((value = utils_strsep(¤t, ",")) != NULL) { 116 | char *first, *last; 117 | 118 | /* Find first and last characters */ 119 | first = value; 120 | last = value+strlen(value)-1; 121 | 122 | /* Trim spaces from the value */ 123 | while (*first == ' ' && first < last) first++; 124 | while (*last == ' ' && last > first) last--; 125 | 126 | /* Validate the last character */ 127 | if (*last != '"') continue; 128 | else *last = '\0'; 129 | 130 | /* Store value if it is relevant */ 131 | if (!strncmp("username=\"", first, 10)) { 132 | username = first+10; 133 | } else if (!strncmp("realm=\"", first, 7)) { 134 | realm = first+7; 135 | } else if (!strncmp("nonce=\"", first, 7)) { 136 | nonce = first+7; 137 | } else if (!strncmp("uri=\"", first, 5)) { 138 | uri = first+5; 139 | } else if (!strncmp("response=\"", first, 10)) { 140 | response = first+10; 141 | } 142 | } 143 | 144 | if (!username || !realm || !nonce || !uri || !response) { 145 | free(auth); 146 | return 0; 147 | } 148 | if (strcmp(realm, our_realm) || strcmp(nonce, our_nonce) || strcmp(uri, our_uri)) { 149 | free(auth); 150 | return 0; 151 | } 152 | 153 | /* Calculate our response */ 154 | memset(our_response, 0, sizeof(our_response)); 155 | digest_get_response(username, realm, password, nonce, 156 | method, uri, our_response); 157 | success = !strcmp(response, our_response); 158 | free(auth); 159 | 160 | return success; 161 | } 162 | 163 | 164 | -------------------------------------------------------------------------------- /src/lib/digest.h: -------------------------------------------------------------------------------- 1 | #ifndef DIGEST_H 2 | #define DIGEST_H 3 | 4 | void digest_generate_nonce(char *result, int resultlen); 5 | int digest_is_valid(const char *our_realm, const char *password, 6 | const char *our_nonce, const char *method, 7 | const char *our_uri, const char *authorization); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/lib/dnssdint.h: -------------------------------------------------------------------------------- 1 | #ifndef DNSSDINT_H 2 | #define DNSSDINT_H 3 | 4 | #define RAOP_TXTVERS "1" 5 | #define RAOP_CH "2" /* Audio channels: 2 */ 6 | #define RAOP_CN "0,1" /* Audio codec: PCM, ALAC */ 7 | #define RAOP_ET "0,1" /* Encryption type: none, RSA */ 8 | #define RAOP_SV "false" 9 | #define RAOP_DA "true" 10 | #define RAOP_SR "44100" 11 | #define RAOP_SS "16" /* Sample size: 16 */ 12 | #define RAOP_VN "3" 13 | #define RAOP_TP "TCP,UDP" 14 | #define RAOP_MD "0,1,2" /* Metadata: text, artwork, progress */ 15 | #define RAOP_SM "false" 16 | #define RAOP_EK "1" 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/lib/ed25519/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LTLIBRARIES = libed25519.la 2 | libed25519_la_SOURCES = add_scalar.c fe.c ge.c keypair.c sc.c seed.c sha512.c sign.c verify.c 3 | 4 | -------------------------------------------------------------------------------- /src/lib/ed25519/add_scalar.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "ge.h" 3 | #include "sc.h" 4 | #include "sha512.h" 5 | 6 | 7 | /* see http://crypto.stackexchange.com/a/6215/4697 */ 8 | void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) { 9 | const unsigned char SC_1[32] = {1}; /* scalar with value 1 */ 10 | 11 | unsigned char n[32]; 12 | ge_p3 nB; 13 | ge_p1p1 A_p1p1; 14 | ge_p3 A; 15 | ge_p3 public_key_unpacked; 16 | ge_cached T; 17 | 18 | sha512_context hash; 19 | unsigned char hashbuf[64]; 20 | 21 | int i; 22 | 23 | /* copy the scalar and clear highest bit */ 24 | for (i = 0; i < 31; ++i) { 25 | n[i] = scalar[i]; 26 | } 27 | n[31] = scalar[31] & 127; 28 | 29 | /* private key: a = n + t */ 30 | if (private_key) { 31 | sc_muladd(private_key, SC_1, n, private_key); 32 | 33 | // https://github.com/orlp/ed25519/issues/3 34 | sha512_init(&hash); 35 | sha512_update(&hash, private_key + 32, 32); 36 | sha512_update(&hash, scalar, 32); 37 | sha512_final(&hash, hashbuf); 38 | for (i = 0; i < 32; ++i) { 39 | private_key[32 + i] = hashbuf[i]; 40 | } 41 | } 42 | 43 | /* public key: A = nB + T */ 44 | if (public_key) { 45 | /* if we know the private key we don't need a point addition, which is faster */ 46 | /* using a "timing attack" you could find out wether or not we know the private 47 | key, but this information seems rather useless - if this is important pass 48 | public_key and private_key seperately in 2 function calls */ 49 | if (private_key) { 50 | ge_scalarmult_base(&A, private_key); 51 | } else { 52 | /* unpack public key into T */ 53 | ge_frombytes_negate_vartime(&public_key_unpacked, public_key); 54 | fe_neg(public_key_unpacked.X, public_key_unpacked.X); /* undo negate */ 55 | fe_neg(public_key_unpacked.T, public_key_unpacked.T); /* undo negate */ 56 | ge_p3_to_cached(&T, &public_key_unpacked); 57 | 58 | /* calculate n*B */ 59 | ge_scalarmult_base(&nB, n); 60 | 61 | /* A = n*B + T */ 62 | ge_add(&A_p1p1, &nB, &T); 63 | ge_p1p1_to_p3(&A, &A_p1p1); 64 | } 65 | 66 | /* pack public key */ 67 | ge_p3_tobytes(public_key, &A); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/lib/ed25519/ed25519.h: -------------------------------------------------------------------------------- 1 | #ifndef ED25519_H 2 | #define ED25519_H 3 | 4 | #include 5 | 6 | #if defined(_WIN32) 7 | #if defined(ED25519_BUILD_DLL) 8 | #define ED25519_DECLSPEC __declspec(dllexport) 9 | #elif defined(ED25519_DLL) 10 | #define ED25519_DECLSPEC __declspec(dllimport) 11 | #else 12 | #define ED25519_DECLSPEC 13 | #endif 14 | #else 15 | #define ED25519_DECLSPEC 16 | #endif 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #ifndef ED25519_NO_SEED 24 | int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); 25 | #endif 26 | 27 | void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); 28 | void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); 29 | int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); 30 | void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); 31 | void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); 32 | 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/lib/ed25519/fe.h: -------------------------------------------------------------------------------- 1 | #ifndef FE_H 2 | #define FE_H 3 | 4 | #include "fixedint.h" 5 | 6 | 7 | /* 8 | fe means field element. 9 | Here the field is \Z/(2^255-19). 10 | An element t, entries t[0]...t[9], represents the integer 11 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. 12 | Bounds on each t[i] vary depending on context. 13 | */ 14 | 15 | 16 | typedef int32_t fe[10]; 17 | 18 | 19 | void fe_0(fe h); 20 | void fe_1(fe h); 21 | 22 | void fe_frombytes(fe h, const unsigned char *s); 23 | void fe_tobytes(unsigned char *s, const fe h); 24 | 25 | void fe_copy(fe h, const fe f); 26 | int fe_isnegative(const fe f); 27 | int fe_isnonzero(const fe f); 28 | void fe_cmov(fe f, const fe g, unsigned int b); 29 | void fe_cswap(fe f, fe g, unsigned int b); 30 | 31 | void fe_neg(fe h, const fe f); 32 | void fe_add(fe h, const fe f, const fe g); 33 | void fe_invert(fe out, const fe z); 34 | void fe_sq(fe h, const fe f); 35 | void fe_sq2(fe h, const fe f); 36 | void fe_mul(fe h, const fe f, const fe g); 37 | void fe_mul121666(fe h, fe f); 38 | void fe_pow22523(fe out, const fe z); 39 | void fe_sub(fe h, const fe f, const fe g); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/lib/ed25519/fixedint.h: -------------------------------------------------------------------------------- 1 | /* 2 | Portable header to provide the 32 and 64 bits type. 3 | 4 | Not a compatible replacement for , do not blindly use it as such. 5 | */ 6 | 7 | #if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED) 8 | #include 9 | #define FIXEDINT_H_INCLUDED 10 | 11 | #if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C) 12 | #include 13 | #define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) 14 | #endif 15 | #endif 16 | 17 | 18 | #ifndef FIXEDINT_H_INCLUDED 19 | #define FIXEDINT_H_INCLUDED 20 | 21 | #include 22 | 23 | /* (u)int32_t */ 24 | #ifndef uint32_t 25 | #if (ULONG_MAX == 0xffffffffUL) 26 | typedef unsigned long uint32_t; 27 | #elif (UINT_MAX == 0xffffffffUL) 28 | typedef unsigned int uint32_t; 29 | #elif (USHRT_MAX == 0xffffffffUL) 30 | typedef unsigned short uint32_t; 31 | #endif 32 | #endif 33 | 34 | 35 | #ifndef int32_t 36 | #if (LONG_MAX == 0x7fffffffL) 37 | typedef signed long int32_t; 38 | #elif (INT_MAX == 0x7fffffffL) 39 | typedef signed int int32_t; 40 | #elif (SHRT_MAX == 0x7fffffffL) 41 | typedef signed short int32_t; 42 | #endif 43 | #endif 44 | 45 | 46 | /* (u)int64_t */ 47 | #if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L) 48 | typedef long long int64_t; 49 | typedef unsigned long long uint64_t; 50 | 51 | #define UINT64_C(v) v ##ULL 52 | #define INT64_C(v) v ##LL 53 | #elif defined(__GNUC__) 54 | __extension__ typedef long long int64_t; 55 | __extension__ typedef unsigned long long uint64_t; 56 | 57 | #define UINT64_C(v) v ##ULL 58 | #define INT64_C(v) v ##LL 59 | #elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC) 60 | typedef long long int64_t; 61 | typedef unsigned long long uint64_t; 62 | 63 | #define UINT64_C(v) v ##ULL 64 | #define INT64_C(v) v ##LL 65 | #elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC) 66 | typedef __int64 int64_t; 67 | typedef unsigned __int64 uint64_t; 68 | 69 | #define UINT64_C(v) v ##UI64 70 | #define INT64_C(v) v ##I64 71 | #endif 72 | #endif 73 | -------------------------------------------------------------------------------- /src/lib/ed25519/ge.h: -------------------------------------------------------------------------------- 1 | #ifndef GE_H 2 | #define GE_H 3 | 4 | #include "fe.h" 5 | 6 | 7 | /* 8 | ge means group element. 9 | 10 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 11 | satisfying -x^2 + y^2 = 1 + d x^2y^2 12 | where d = -121665/121666. 13 | 14 | Representations: 15 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 16 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 17 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 18 | ge_precomp (Duif): (y+x,y-x,2dxy) 19 | */ 20 | 21 | typedef struct { 22 | fe X; 23 | fe Y; 24 | fe Z; 25 | } ge_p2; 26 | 27 | typedef struct { 28 | fe X; 29 | fe Y; 30 | fe Z; 31 | fe T; 32 | } ge_p3; 33 | 34 | typedef struct { 35 | fe X; 36 | fe Y; 37 | fe Z; 38 | fe T; 39 | } ge_p1p1; 40 | 41 | typedef struct { 42 | fe yplusx; 43 | fe yminusx; 44 | fe xy2d; 45 | } ge_precomp; 46 | 47 | typedef struct { 48 | fe YplusX; 49 | fe YminusX; 50 | fe Z; 51 | fe T2d; 52 | } ge_cached; 53 | 54 | void ge_p3_tobytes(unsigned char *s, const ge_p3 *h); 55 | void ge_tobytes(unsigned char *s, const ge_p2 *h); 56 | int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s); 57 | 58 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 59 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 60 | void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); 61 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 62 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 63 | void ge_scalarmult_base(ge_p3 *h, const unsigned char *a); 64 | 65 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); 66 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); 67 | void ge_p2_0(ge_p2 *h); 68 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p); 69 | void ge_p3_0(ge_p3 *h); 70 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p); 71 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); 72 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/lib/ed25519/key_exchange.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "fe.h" 3 | 4 | void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) { 5 | unsigned char e[32]; 6 | unsigned int i; 7 | 8 | fe x1; 9 | fe x2; 10 | fe z2; 11 | fe x3; 12 | fe z3; 13 | fe tmp0; 14 | fe tmp1; 15 | 16 | int pos; 17 | unsigned int swap; 18 | unsigned int b; 19 | 20 | /* copy the private key and make sure it's valid */ 21 | for (i = 0; i < 32; ++i) { 22 | e[i] = private_key[i]; 23 | } 24 | 25 | e[0] &= 248; 26 | e[31] &= 63; 27 | e[31] |= 64; 28 | 29 | /* unpack the public key and convert edwards to montgomery */ 30 | /* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */ 31 | fe_frombytes(x1, public_key); 32 | fe_1(tmp1); 33 | fe_add(tmp0, x1, tmp1); 34 | fe_sub(tmp1, tmp1, x1); 35 | fe_invert(tmp1, tmp1); 36 | fe_mul(x1, tmp0, tmp1); 37 | 38 | fe_1(x2); 39 | fe_0(z2); 40 | fe_copy(x3, x1); 41 | fe_1(z3); 42 | 43 | swap = 0; 44 | for (pos = 254; pos >= 0; --pos) { 45 | b = e[pos / 8] >> (pos & 7); 46 | b &= 1; 47 | swap ^= b; 48 | fe_cswap(x2, x3, swap); 49 | fe_cswap(z2, z3, swap); 50 | swap = b; 51 | 52 | /* from montgomery.h */ 53 | fe_sub(tmp0, x3, z3); 54 | fe_sub(tmp1, x2, z2); 55 | fe_add(x2, x2, z2); 56 | fe_add(z2, x3, z3); 57 | fe_mul(z3, tmp0, x2); 58 | fe_mul(z2, z2, tmp1); 59 | fe_sq(tmp0, tmp1); 60 | fe_sq(tmp1, x2); 61 | fe_add(x3, z3, z2); 62 | fe_sub(z2, z3, z2); 63 | fe_mul(x2, tmp1, tmp0); 64 | fe_sub(tmp1, tmp1, tmp0); 65 | fe_sq(z2, z2); 66 | fe_mul121666(z3, tmp1); 67 | fe_sq(x3, x3); 68 | fe_add(tmp0, tmp0, z3); 69 | fe_mul(z3, x1, z2); 70 | fe_mul(z2, tmp1, tmp0); 71 | } 72 | 73 | fe_cswap(x2, x3, swap); 74 | fe_cswap(z2, z3, swap); 75 | 76 | fe_invert(z2, z2); 77 | fe_mul(x2, x2, z2); 78 | fe_tobytes(shared_secret, x2); 79 | } 80 | -------------------------------------------------------------------------------- /src/lib/ed25519/keypair.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | 5 | 6 | void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) { 7 | ge_p3 A; 8 | 9 | sha512(seed, 32, private_key); 10 | private_key[0] &= 248; 11 | private_key[31] &= 63; 12 | private_key[31] |= 64; 13 | 14 | ge_scalarmult_base(&A, private_key); 15 | ge_p3_tobytes(public_key, &A); 16 | } 17 | -------------------------------------------------------------------------------- /src/lib/ed25519/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Orson Peters 2 | 3 | This software is provided 'as-is', without any express or implied warranty. In no event will the 4 | authors be held liable for any damages arising from the use of this software. 5 | 6 | Permission is granted to anyone to use this software for any purpose, including commercial 7 | applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the 10 | original software. If you use this software in a product, an acknowledgment in the product 11 | documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 14 | being the original software. 15 | 16 | 3. This notice may not be removed or altered from any source distribution. 17 | -------------------------------------------------------------------------------- /src/lib/ed25519/sc.h: -------------------------------------------------------------------------------- 1 | #ifndef SC_H 2 | #define SC_H 3 | 4 | /* 5 | The set of scalars is \Z/l 6 | where l = 2^252 + 27742317777372353535851937790883648493. 7 | */ 8 | 9 | void sc_reduce(unsigned char *s); 10 | void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/lib/ed25519/seed.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | 3 | #ifndef ED25519_NO_SEED 4 | 5 | #ifdef _WIN32 6 | #include 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | int ed25519_create_seed(unsigned char *seed) { 13 | #ifdef _WIN32 14 | HCRYPTPROV prov; 15 | 16 | if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 17 | return 1; 18 | } 19 | 20 | if (!CryptGenRandom(prov, 32, seed)) { 21 | CryptReleaseContext(prov, 0); 22 | return 1; 23 | } 24 | 25 | CryptReleaseContext(prov, 0); 26 | #else 27 | FILE *f = fopen("/dev/urandom", "rb"); 28 | 29 | if (f == NULL) { 30 | return 1; 31 | } 32 | 33 | fread(seed, 1, 32, f); 34 | fclose(f); 35 | #endif 36 | 37 | return 0; 38 | } 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/lib/ed25519/sha512.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA512_H 2 | #define SHA512_H 3 | 4 | #include 5 | 6 | #include "fixedint.h" 7 | 8 | /* state */ 9 | typedef struct sha512_context_ { 10 | uint64_t length, state[8]; 11 | size_t curlen; 12 | unsigned char buf[128]; 13 | } sha512_context; 14 | 15 | 16 | int sha512_init(sha512_context * md); 17 | int sha512_final(sha512_context * md, unsigned char *out); 18 | int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen); 19 | int sha512(const unsigned char *message, size_t message_len, unsigned char *out); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/lib/ed25519/sign.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | #include "sc.h" 5 | 6 | 7 | void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { 8 | sha512_context hash; 9 | unsigned char hram[64]; 10 | unsigned char r[64]; 11 | ge_p3 R; 12 | 13 | 14 | sha512_init(&hash); 15 | sha512_update(&hash, private_key + 32, 32); 16 | sha512_update(&hash, message, message_len); 17 | sha512_final(&hash, r); 18 | 19 | sc_reduce(r); 20 | ge_scalarmult_base(&R, r); 21 | ge_p3_tobytes(signature, &R); 22 | 23 | sha512_init(&hash); 24 | sha512_update(&hash, signature, 32); 25 | sha512_update(&hash, public_key, 32); 26 | sha512_update(&hash, message, message_len); 27 | sha512_final(&hash, hram); 28 | 29 | sc_reduce(hram); 30 | sc_muladd(signature + 32, hram, private_key, r); 31 | } 32 | -------------------------------------------------------------------------------- /src/lib/ed25519/verify.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha512.h" 3 | #include "ge.h" 4 | #include "sc.h" 5 | 6 | static int consttime_equal(const unsigned char *x, const unsigned char *y) { 7 | unsigned char r = 0; 8 | 9 | r = x[0] ^ y[0]; 10 | #define F(i) r |= x[i] ^ y[i] 11 | F(1); 12 | F(2); 13 | F(3); 14 | F(4); 15 | F(5); 16 | F(6); 17 | F(7); 18 | F(8); 19 | F(9); 20 | F(10); 21 | F(11); 22 | F(12); 23 | F(13); 24 | F(14); 25 | F(15); 26 | F(16); 27 | F(17); 28 | F(18); 29 | F(19); 30 | F(20); 31 | F(21); 32 | F(22); 33 | F(23); 34 | F(24); 35 | F(25); 36 | F(26); 37 | F(27); 38 | F(28); 39 | F(29); 40 | F(30); 41 | F(31); 42 | #undef F 43 | 44 | return !r; 45 | } 46 | 47 | int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) { 48 | unsigned char h[64]; 49 | unsigned char checker[32]; 50 | sha512_context hash; 51 | ge_p3 A; 52 | ge_p2 R; 53 | 54 | if (signature[63] & 224) { 55 | return 0; 56 | } 57 | 58 | if (ge_frombytes_negate_vartime(&A, public_key) != 0) { 59 | return 0; 60 | } 61 | 62 | sha512_init(&hash); 63 | sha512_update(&hash, signature, 32); 64 | sha512_update(&hash, public_key, 32); 65 | sha512_update(&hash, message, message_len); 66 | sha512_final(&hash, h); 67 | 68 | sc_reduce(h); 69 | ge_double_scalarmult_vartime(&R, h, &A, signature + 32); 70 | ge_tobytes(checker, &R); 71 | 72 | if (!consttime_equal(checker, signature)) { 73 | return 0; 74 | } 75 | 76 | return 1; 77 | } 78 | -------------------------------------------------------------------------------- /src/lib/fairplay.h: -------------------------------------------------------------------------------- 1 | #ifndef FAIRPLAY_H 2 | #define FAIRPLAY_H 3 | 4 | #include "logger.h" 5 | 6 | typedef struct fairplay_s fairplay_t; 7 | 8 | fairplay_t *fairplay_init(logger_t *logger); 9 | int fairplay_setup(fairplay_t *fp, const unsigned char req[16], unsigned char res[142]); 10 | int fairplay_handshake(fairplay_t *fp, const unsigned char req[164], unsigned char res[32]); 11 | int fairplay_decrypt(fairplay_t *fp, const unsigned char input[72], unsigned char output[16]); 12 | void fairplay_destroy(fairplay_t *fp); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/lib/fairplay_dummy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "fairplay.h" 4 | 5 | struct fairplay_s { 6 | }; 7 | 8 | fairplay_t * 9 | fairplay_init(logger_t *logger) 10 | { 11 | /* NULL would mean failure so let's use any number */ 12 | return (void *) 42; 13 | } 14 | 15 | int 16 | fairplay_setup(fairplay_t *fp, const unsigned char req[16], unsigned char res[142]) 17 | { 18 | return -1; 19 | } 20 | 21 | int 22 | fairplay_handshake(fairplay_t *fp, const unsigned char req[164], unsigned char res[32]) 23 | { 24 | return -1; 25 | } 26 | 27 | int 28 | fairplay_decrypt(fairplay_t *fp, const unsigned char input[72], unsigned char output[16]) 29 | { 30 | return -1; 31 | } 32 | 33 | void 34 | fairplay_destroy(fairplay_t *fp) 35 | { 36 | } 37 | -------------------------------------------------------------------------------- /src/lib/fairplay_playfair.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "fairplay.h" 6 | #include "playfair/playfair.h" 7 | 8 | char reply_message[4][142] = {{0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x00,0x0f,0x9f,0x3f,0x9e,0x0a,0x25,0x21,0xdb,0xdf,0x31,0x2a,0xb2,0xbf,0xb2,0x9e,0x8d,0x23,0x2b,0x63,0x76,0xa8,0xc8,0x18,0x70,0x1d,0x22,0xae,0x93,0xd8,0x27,0x37,0xfe,0xaf,0x9d,0xb4,0xfd,0xf4,0x1c,0x2d,0xba,0x9d,0x1f,0x49,0xca,0xaa,0xbf,0x65,0x91,0xac,0x1f,0x7b,0xc6,0xf7,0xe0,0x66,0x3d,0x21,0xaf,0xe0,0x15,0x65,0x95,0x3e,0xab,0x81,0xf4,0x18,0xce,0xed,0x09,0x5a,0xdb,0x7c,0x3d,0x0e,0x25,0x49,0x09,0xa7,0x98,0x31,0xd4,0x9c,0x39,0x82,0x97,0x34,0x34,0xfa,0xcb,0x42,0xc6,0x3a,0x1c,0xd9,0x11,0xa6,0xfe,0x94,0x1a,0x8a,0x6d,0x4a,0x74,0x3b,0x46,0xc3,0xa7,0x64,0x9e,0x44,0xc7,0x89,0x55,0xe4,0x9d,0x81,0x55,0x00,0x95,0x49,0xc4,0xe2,0xf7,0xa3,0xf6,0xd5,0xba}, 9 | {0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x01,0xcf,0x32,0xa2,0x57,0x14,0xb2,0x52,0x4f,0x8a,0xa0,0xad,0x7a,0xf1,0x64,0xe3,0x7b,0xcf,0x44,0x24,0xe2,0x00,0x04,0x7e,0xfc,0x0a,0xd6,0x7a,0xfc,0xd9,0x5d,0xed,0x1c,0x27,0x30,0xbb,0x59,0x1b,0x96,0x2e,0xd6,0x3a,0x9c,0x4d,0xed,0x88,0xba,0x8f,0xc7,0x8d,0xe6,0x4d,0x91,0xcc,0xfd,0x5c,0x7b,0x56,0xda,0x88,0xe3,0x1f,0x5c,0xce,0xaf,0xc7,0x43,0x19,0x95,0xa0,0x16,0x65,0xa5,0x4e,0x19,0x39,0xd2,0x5b,0x94,0xdb,0x64,0xb9,0xe4,0x5d,0x8d,0x06,0x3e,0x1e,0x6a,0xf0,0x7e,0x96,0x56,0x16,0x2b,0x0e,0xfa,0x40,0x42,0x75,0xea,0x5a,0x44,0xd9,0x59,0x1c,0x72,0x56,0xb9,0xfb,0xe6,0x51,0x38,0x98,0xb8,0x02,0x27,0x72,0x19,0x88,0x57,0x16,0x50,0x94,0x2a,0xd9,0x46,0x68,0x8a}, 10 | {0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x02,0xc1,0x69,0xa3,0x52,0xee,0xed,0x35,0xb1,0x8c,0xdd,0x9c,0x58,0xd6,0x4f,0x16,0xc1,0x51,0x9a,0x89,0xeb,0x53,0x17,0xbd,0x0d,0x43,0x36,0xcd,0x68,0xf6,0x38,0xff,0x9d,0x01,0x6a,0x5b,0x52,0xb7,0xfa,0x92,0x16,0xb2,0xb6,0x54,0x82,0xc7,0x84,0x44,0x11,0x81,0x21,0xa2,0xc7,0xfe,0xd8,0x3d,0xb7,0x11,0x9e,0x91,0x82,0xaa,0xd7,0xd1,0x8c,0x70,0x63,0xe2,0xa4,0x57,0x55,0x59,0x10,0xaf,0x9e,0x0e,0xfc,0x76,0x34,0x7d,0x16,0x40,0x43,0x80,0x7f,0x58,0x1e,0xe4,0xfb,0xe4,0x2c,0xa9,0xde,0xdc,0x1b,0x5e,0xb2,0xa3,0xaa,0x3d,0x2e,0xcd,0x59,0xe7,0xee,0xe7,0x0b,0x36,0x29,0xf2,0x2a,0xfd,0x16,0x1d,0x87,0x73,0x53,0xdd,0xb9,0x9a,0xdc,0x8e,0x07,0x00,0x6e,0x56,0xf8,0x50,0xce}, 11 | {0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x03,0x90,0x01,0xe1,0x72,0x7e,0x0f,0x57,0xf9,0xf5,0x88,0x0d,0xb1,0x04,0xa6,0x25,0x7a,0x23,0xf5,0xcf,0xff,0x1a,0xbb,0xe1,0xe9,0x30,0x45,0x25,0x1a,0xfb,0x97,0xeb,0x9f,0xc0,0x01,0x1e,0xbe,0x0f,0x3a,0x81,0xdf,0x5b,0x69,0x1d,0x76,0xac,0xb2,0xf7,0xa5,0xc7,0x08,0xe3,0xd3,0x28,0xf5,0x6b,0xb3,0x9d,0xbd,0xe5,0xf2,0x9c,0x8a,0x17,0xf4,0x81,0x48,0x7e,0x3a,0xe8,0x63,0xc6,0x78,0x32,0x54,0x22,0xe6,0xf7,0x8e,0x16,0x6d,0x18,0xaa,0x7f,0xd6,0x36,0x25,0x8b,0xce,0x28,0x72,0x6f,0x66,0x1f,0x73,0x88,0x93,0xce,0x44,0x31,0x1e,0x4b,0xe6,0xc0,0x53,0x51,0x93,0xe5,0xef,0x72,0xe8,0x68,0x62,0x33,0x72,0x9c,0x22,0x7d,0x82,0x0c,0x99,0x94,0x45,0xd8,0x92,0x46,0xc8,0xc3,0x59}}; 12 | 13 | char fp_header[] = {0x46, 0x50, 0x4c, 0x59, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14}; 14 | 15 | struct fairplay_s { 16 | logger_t *logger; 17 | 18 | unsigned char keymsg[164]; 19 | unsigned int keymsglen; 20 | }; 21 | 22 | fairplay_t * 23 | fairplay_init(logger_t *logger) 24 | { 25 | fairplay_t *fp; 26 | 27 | fp = calloc(1, sizeof(fairplay_t)); 28 | if (!fp) { 29 | return NULL; 30 | } 31 | fp->logger = logger; 32 | 33 | return fp; 34 | } 35 | 36 | int 37 | fairplay_setup(fairplay_t *fp, const unsigned char req[16], unsigned char res[142]) 38 | { 39 | int mode; 40 | 41 | assert(fp); 42 | 43 | if (req[4] != 0x03) { 44 | /* Unsupported fairplay version */ 45 | return -1; 46 | } 47 | 48 | mode = req[14]; 49 | memcpy(res, reply_message[mode], 142); 50 | fp->keymsglen = 0; 51 | return 0; 52 | } 53 | 54 | int 55 | fairplay_handshake(fairplay_t *fp, const unsigned char req[164], unsigned char res[32]) 56 | { 57 | assert(fp); 58 | 59 | if (req[4] != 0x03) { 60 | /* Unsupported fairplay version */ 61 | return -1; 62 | } 63 | 64 | memcpy(fp->keymsg, req, 164); 65 | fp->keymsglen = 164; 66 | 67 | memcpy(res, fp_header, 12); 68 | memcpy(res + 12, req + 144, 20); 69 | return 0; 70 | } 71 | 72 | int 73 | fairplay_decrypt(fairplay_t *fp, const unsigned char input[72], unsigned char output[16]) 74 | { 75 | if (fp->keymsglen != 164) { 76 | return -1; 77 | } 78 | 79 | playfair_decrypt(fp->keymsg, (unsigned char *) input, output); 80 | return 0; 81 | } 82 | 83 | void 84 | fairplay_destroy(fairplay_t *fp) 85 | { 86 | free(fp); 87 | } 88 | -------------------------------------------------------------------------------- /src/lib/global.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBAL_H 2 | #define GLOBAL_H 3 | 4 | #define GLOBAL_FEATURES 0x7 5 | #define GLOBAL_MODEL "AppleTV2,1" 6 | #define GLOBAL_VERSION "130.14" 7 | 8 | #define MAX_HWADDR_LEN 6 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/lib/http_request.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef HTTP_REQUEST_H 16 | #define HTTP_REQUEST_H 17 | 18 | typedef struct http_request_s http_request_t; 19 | 20 | 21 | http_request_t *http_request_init(void); 22 | 23 | int http_request_add_data(http_request_t *request, const char *data, int datalen); 24 | int http_request_is_complete(http_request_t *request); 25 | int http_request_has_error(http_request_t *request); 26 | 27 | const char *http_request_get_error_name(http_request_t *request); 28 | const char *http_request_get_error_description(http_request_t *request); 29 | const char *http_request_get_method(http_request_t *request); 30 | const char *http_request_get_url(http_request_t *request); 31 | const char *http_request_get_header(http_request_t *request, const char *name); 32 | const char *http_request_get_data(http_request_t *request, int *datalen); 33 | 34 | void http_request_destroy(http_request_t *request); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/lib/http_response.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "http_response.h" 21 | #include "compat.h" 22 | 23 | struct http_response_s { 24 | int complete; 25 | int disconnect; 26 | 27 | char *data; 28 | int data_size; 29 | int data_length; 30 | }; 31 | 32 | 33 | static void 34 | http_response_add_data(http_response_t *response, const char *data, int datalen) 35 | { 36 | int newdatasize; 37 | 38 | assert(response); 39 | assert(data); 40 | assert(datalen > 0); 41 | 42 | newdatasize = response->data_size; 43 | while (response->data_size+datalen > newdatasize) { 44 | newdatasize *= 2; 45 | } 46 | if (newdatasize != response->data_size) { 47 | response->data = realloc(response->data, newdatasize); 48 | assert(response->data); 49 | } 50 | memcpy(response->data+response->data_length, data, datalen); 51 | response->data_length += datalen; 52 | } 53 | 54 | http_response_t * 55 | http_response_init(const char *protocol, int code, const char *message) 56 | { 57 | http_response_t *response; 58 | char codestr[4]; 59 | 60 | assert(code >= 100 && code < 1000); 61 | 62 | /* Convert code into string */ 63 | memset(codestr, 0, sizeof(codestr)); 64 | snprintf(codestr, sizeof(codestr), "%u", code); 65 | 66 | response = calloc(1, sizeof(http_response_t)); 67 | if (!response) { 68 | return NULL; 69 | } 70 | 71 | /* Allocate response data */ 72 | response->data_size = 1024; 73 | response->data = malloc(response->data_size); 74 | if (!response->data) { 75 | free(response); 76 | return NULL; 77 | } 78 | 79 | /* Add first line of response to the data array */ 80 | http_response_add_data(response, protocol, strlen(protocol)); 81 | http_response_add_data(response, " ", 1); 82 | http_response_add_data(response, codestr, strlen(codestr)); 83 | http_response_add_data(response, " ", 1); 84 | http_response_add_data(response, message, strlen(message)); 85 | http_response_add_data(response, "\r\n", 2); 86 | 87 | return response; 88 | } 89 | 90 | void 91 | http_response_destroy(http_response_t *response) 92 | { 93 | if (response) { 94 | free(response->data); 95 | free(response); 96 | } 97 | } 98 | 99 | void 100 | http_response_add_header(http_response_t *response, const char *name, const char *value) 101 | { 102 | assert(response); 103 | assert(name); 104 | assert(value); 105 | 106 | http_response_add_data(response, name, strlen(name)); 107 | http_response_add_data(response, ": ", 2); 108 | http_response_add_data(response, value, strlen(value)); 109 | http_response_add_data(response, "\r\n", 2); 110 | } 111 | 112 | void 113 | http_response_finish(http_response_t *response, const char *data, int datalen) 114 | { 115 | assert(response); 116 | assert(datalen==0 || (data && datalen > 0)); 117 | 118 | if (data && datalen > 0) { 119 | const char *hdrname = "Content-Length"; 120 | char hdrvalue[16]; 121 | 122 | memset(hdrvalue, 0, sizeof(hdrvalue)); 123 | snprintf(hdrvalue, sizeof(hdrvalue)-1, "%d", datalen); 124 | 125 | /* Add Content-Length header first */ 126 | http_response_add_data(response, hdrname, strlen(hdrname)); 127 | http_response_add_data(response, ": ", 2); 128 | http_response_add_data(response, hdrvalue, strlen(hdrvalue)); 129 | http_response_add_data(response, "\r\n\r\n", 4); 130 | 131 | /* Add data to the end of response */ 132 | http_response_add_data(response, data, datalen); 133 | } else { 134 | /* Add extra end of line after headers */ 135 | http_response_add_data(response, "\r\n", 2); 136 | } 137 | response->complete = 1; 138 | } 139 | 140 | void 141 | http_response_set_disconnect(http_response_t *response, int disconnect) 142 | { 143 | assert(response); 144 | 145 | response->disconnect = !!disconnect; 146 | } 147 | 148 | int 149 | http_response_get_disconnect(http_response_t *response) 150 | { 151 | assert(response); 152 | 153 | return response->disconnect; 154 | } 155 | 156 | const char * 157 | http_response_get_data(http_response_t *response, int *datalen) 158 | { 159 | assert(response); 160 | assert(datalen); 161 | assert(response->complete); 162 | 163 | *datalen = response->data_length; 164 | return response->data; 165 | } 166 | -------------------------------------------------------------------------------- /src/lib/http_response.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef HTTP_RESPONSE_H 16 | #define HTTP_RESPONSE_H 17 | 18 | typedef struct http_response_s http_response_t; 19 | 20 | http_response_t *http_response_init(const char *protocol, int code, const char *message); 21 | 22 | void http_response_add_header(http_response_t *response, const char *name, const char *value); 23 | void http_response_finish(http_response_t *response, const char *data, int datalen); 24 | 25 | void http_response_set_disconnect(http_response_t *response, int disconnect); 26 | int http_response_get_disconnect(http_response_t *response); 27 | 28 | const char *http_response_get_data(http_response_t *response, int *datalen); 29 | 30 | void http_response_destroy(http_response_t *response); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/lib/httpd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef HTTPD_H 16 | #define HTTPD_H 17 | 18 | #include "logger.h" 19 | #include "http_request.h" 20 | #include "http_response.h" 21 | 22 | typedef struct httpd_s httpd_t; 23 | 24 | struct httpd_callbacks_s { 25 | void* opaque; 26 | void* (*conn_init)(void *opaque, unsigned char *local, int locallen, unsigned char *remote, int remotelen); 27 | void (*conn_request)(void *ptr, http_request_t *request, http_response_t **response); 28 | void (*conn_destroy)(void *ptr); 29 | }; 30 | typedef struct httpd_callbacks_s httpd_callbacks_t; 31 | 32 | 33 | httpd_t *httpd_init(logger_t *logger, httpd_callbacks_t *callbacks, int max_connections); 34 | 35 | int httpd_is_running(httpd_t *httpd); 36 | 37 | int httpd_start(httpd_t *httpd, unsigned short *port); 38 | void httpd_stop(httpd_t *httpd); 39 | 40 | void httpd_destroy(httpd_t *httpd); 41 | 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/lib/logger.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "logger.h" 21 | #include "compat.h" 22 | 23 | struct logger_s { 24 | mutex_handle_t lvl_mutex; 25 | mutex_handle_t cb_mutex; 26 | 27 | int level; 28 | void *cls; 29 | logger_callback_t callback; 30 | }; 31 | 32 | logger_t * 33 | logger_init() 34 | { 35 | logger_t *logger = calloc(1, sizeof(logger_t)); 36 | assert(logger); 37 | 38 | MUTEX_CREATE(logger->lvl_mutex); 39 | MUTEX_CREATE(logger->cb_mutex); 40 | 41 | logger->level = LOGGER_WARNING; 42 | logger->callback = NULL; 43 | return logger; 44 | } 45 | 46 | void 47 | logger_destroy(logger_t *logger) 48 | { 49 | MUTEX_DESTROY(logger->lvl_mutex); 50 | MUTEX_DESTROY(logger->cb_mutex); 51 | free(logger); 52 | } 53 | 54 | void 55 | logger_set_level(logger_t *logger, int level) 56 | { 57 | assert(logger); 58 | 59 | MUTEX_LOCK(logger->lvl_mutex); 60 | logger->level = level; 61 | MUTEX_UNLOCK(logger->lvl_mutex); 62 | } 63 | 64 | void 65 | logger_set_callback(logger_t *logger, logger_callback_t callback, void *cls) 66 | { 67 | assert(logger); 68 | 69 | MUTEX_LOCK(logger->cb_mutex); 70 | logger->cls = cls; 71 | logger->callback = callback; 72 | MUTEX_UNLOCK(logger->cb_mutex); 73 | } 74 | 75 | static char * 76 | logger_utf8_to_local(const char *str) 77 | { 78 | char *ret = NULL; 79 | 80 | /* FIXME: This is only implemented on Windows for now */ 81 | #if defined(_WIN32) || defined(_WIN64) 82 | int wclen, mblen; 83 | WCHAR *wcstr; 84 | BOOL failed; 85 | 86 | wclen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); 87 | wcstr = malloc(sizeof(WCHAR) * wclen); 88 | MultiByteToWideChar(CP_UTF8, 0, str, -1, wcstr, wclen); 89 | 90 | mblen = WideCharToMultiByte(CP_ACP, 0, wcstr, wclen, NULL, 0, NULL, &failed); 91 | if (failed) { 92 | /* Invalid characters in input, conversion failed */ 93 | free(wcstr); 94 | return NULL; 95 | } 96 | 97 | ret = malloc(sizeof(CHAR) * mblen); 98 | WideCharToMultiByte(CP_ACP, 0, wcstr, wclen, ret, mblen, NULL, NULL); 99 | free(wcstr); 100 | #endif 101 | 102 | return ret; 103 | } 104 | 105 | void 106 | logger_log(logger_t *logger, int level, const char *fmt, ...) 107 | { 108 | char buffer[4096]; 109 | va_list ap; 110 | 111 | MUTEX_LOCK(logger->lvl_mutex); 112 | if (level > logger->level) { 113 | MUTEX_UNLOCK(logger->lvl_mutex); 114 | return; 115 | } 116 | MUTEX_UNLOCK(logger->lvl_mutex); 117 | 118 | buffer[sizeof(buffer)-1] = '\0'; 119 | va_start(ap, fmt); 120 | vsnprintf(buffer, sizeof(buffer)-1, fmt, ap); 121 | va_end(ap); 122 | 123 | MUTEX_LOCK(logger->cb_mutex); 124 | if (logger->callback) { 125 | logger->callback(logger->cls, level, buffer); 126 | MUTEX_UNLOCK(logger->cb_mutex); 127 | } else { 128 | char *local; 129 | MUTEX_UNLOCK(logger->cb_mutex); 130 | local = logger_utf8_to_local(buffer); 131 | if (local) { 132 | fprintf(stderr, "%s\n", local); 133 | free(local); 134 | } else { 135 | fprintf(stderr, "%s\n", buffer); 136 | } 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /src/lib/logger.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef LOGGER_H 16 | #define LOGGER_H 17 | 18 | /* Define syslog style log levels */ 19 | #define LOGGER_EMERG 0 /* system is unusable */ 20 | #define LOGGER_ALERT 1 /* action must be taken immediately */ 21 | #define LOGGER_CRIT 2 /* critical conditions */ 22 | #define LOGGER_ERR 3 /* error conditions */ 23 | #define LOGGER_WARNING 4 /* warning conditions */ 24 | #define LOGGER_NOTICE 5 /* normal but significant condition */ 25 | #define LOGGER_INFO 6 /* informational */ 26 | #define LOGGER_DEBUG 7 /* debug-level messages */ 27 | 28 | typedef void (*logger_callback_t)(void *cls, int level, const char *msg); 29 | 30 | typedef struct logger_s logger_t; 31 | 32 | logger_t *logger_init(); 33 | void logger_destroy(logger_t *logger); 34 | 35 | void logger_set_level(logger_t *logger, int level); 36 | void logger_set_callback(logger_t *logger, logger_callback_t callback, void *cls); 37 | 38 | void logger_log(logger_t *logger, int level, const char *fmt, ...); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/lib/memalign.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef MEMALIGN_H 16 | #define MEMALIGN_H 17 | 18 | #if defined(WIN32) 19 | 20 | #define SYSTEM_GET_PAGESIZE(ret) do {\ 21 | SYSTEM_INFO si;\ 22 | GetSystemInfo(&si);\ 23 | ret = si.dwPageSize;\ 24 | } while(0) 25 | #define SYSTEM_GET_TIME(ret) ret = timeGetTime() 26 | 27 | #define ALIGNED_MALLOC(memptr, alignment, size) do {\ 28 | char *ptr = malloc(sizeof(void*) + (size) + (alignment)-1);\ 29 | memptr = NULL;\ 30 | if (ptr) {\ 31 | size_t ptrval = (size_t)ptr + sizeof(void*) + (alignment)-1;\ 32 | ptrval = ptrval / (alignment) * (alignment);\ 33 | memptr = (void *)ptrval;\ 34 | *(((void **)memptr)-1) = ptr;\ 35 | }\ 36 | } while(0) 37 | #define ALIGNED_FREE(memptr) free(*(((void **)memptr)-1)) 38 | 39 | #else 40 | 41 | #define SYSTEM_GET_PAGESIZE(ret) ret = sysconf(_SC_PAGESIZE) 42 | #define SYSTEM_GET_TIME(ret) do {\ 43 | struct timeval tv;\ 44 | gettimeofday(&tv, NULL);\ 45 | ret = (unsigned int)(tv.tv_sec*1000 + tv.tv_usec/1000);\ 46 | } while(0) 47 | 48 | #define ALIGNED_MALLOC(memptr, alignment, size) if (posix_memalign((void **)&memptr, alignment, size)) memptr = NULL 49 | #define ALIGNED_FREE(memptr) free(memptr) 50 | 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/lib/netutils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef NETUTILS_H 16 | #define NETUTILS_H 17 | 18 | int netutils_init(); 19 | void netutils_cleanup(); 20 | 21 | int netutils_init_socket(unsigned short *port, int use_ipv6, int use_udp); 22 | unsigned char *netutils_get_address(void *sockaddr, int *length); 23 | int netutils_parse_address(int family, const char *src, void *dst, int dstlen); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/lib/pairing.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2018 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef PAIRING_H 16 | #define PAIRING_H 17 | 18 | typedef struct pairing_s pairing_t; 19 | typedef struct pairing_session_s pairing_session_t; 20 | 21 | pairing_t *pairing_init_generate(); 22 | pairing_t *pairing_init_seed(const unsigned char seed[32]); 23 | void pairing_get_public_key(pairing_t *pairing, unsigned char public_key[32]); 24 | 25 | pairing_session_t *pairing_session_init(pairing_t *pairing); 26 | int pairing_session_handshake(pairing_session_t *session, const unsigned char ecdh_key[32], const unsigned char ed_key[32]); 27 | int pairing_session_get_public_key(pairing_session_t *session, unsigned char ecdh_key[32]); 28 | int pairing_session_get_signature(pairing_session_t *session, unsigned char signature[64]); 29 | int pairing_session_finish(pairing_session_t *session, const unsigned char signature[64]); 30 | int pairing_session_derive_key(pairing_session_t *session, const unsigned char *seed, unsigned int seedlen, unsigned char *buf, unsigned int buflen); 31 | void pairing_session_destroy(pairing_session_t *session); 32 | 33 | void pairing_destroy(pairing_t *pairing); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/lib/playfair/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LTLIBRARIES = libplayfair.la 2 | libplayfair_la_SOURCES = playfair.c playfair.h omg_hax.c omg_hax.h hand_garble.c modified_md5.c sap_hash.c 3 | -------------------------------------------------------------------------------- /src/lib/playfair/modified_md5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define printf(...) (void)0; 8 | 9 | int shift[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 10 | 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 11 | 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 12 | 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}; 13 | 14 | uint32_t F(uint32_t B, uint32_t C, uint32_t D) 15 | { 16 | return (B & C) | (~B & D); 17 | } 18 | 19 | uint32_t G(uint32_t B, uint32_t C, uint32_t D) 20 | { 21 | return (B & D) | (C & ~D); 22 | } 23 | 24 | uint32_t H(uint32_t B, uint32_t C, uint32_t D) 25 | { 26 | return B ^ C ^ D; 27 | } 28 | 29 | uint32_t I(uint32_t B, uint32_t C, uint32_t D) 30 | { 31 | return C ^ (B | ~D); 32 | } 33 | 34 | 35 | uint32_t rol(uint32_t input, int count) 36 | { 37 | return ((input << count) & 0xffffffff) | (input & 0xffffffff) >> (32-count); 38 | } 39 | 40 | void swap(uint32_t* a, uint32_t* b) 41 | { 42 | printf("%08x <-> %08x\n", *a, *b); 43 | uint32_t c = *a; 44 | *a = *b; 45 | *b = c; 46 | } 47 | 48 | void modified_md5(unsigned char* originalblockIn, unsigned char* keyIn, unsigned char* keyOut) 49 | { 50 | unsigned char blockIn[64]; 51 | uint32_t* block_words = (uint32_t*)blockIn; 52 | uint32_t* key_words = (uint32_t*)keyIn; 53 | uint32_t* out_words = (uint32_t*)keyOut; 54 | uint32_t A, B, C, D, Z, tmp; 55 | int i; 56 | 57 | memcpy(blockIn, originalblockIn, 64); 58 | 59 | // Each cycle does something like this: 60 | A = key_words[0]; 61 | B = key_words[1]; 62 | C = key_words[2]; 63 | D = key_words[3]; 64 | for (i = 0; i < 64; i++) 65 | { 66 | uint32_t input; 67 | int j; 68 | if (i < 16) 69 | j = i; 70 | else if (i < 32) 71 | j = (5*i + 1) % 16; 72 | else if (i < 48) 73 | j = (3*i + 5) % 16; 74 | else if (i < 64) 75 | j = 7*i % 16; 76 | 77 | input = blockIn[4*j] << 24 | blockIn[4*j+1] << 16 | blockIn[4*j+2] << 8 | blockIn[4*j+3]; 78 | printf("Key = %08x\n", A); 79 | Z = A + input + (int)(long long)((1LL << 32) * fabs(sin(i + 1))); 80 | if (i < 16) 81 | Z = rol(Z + F(B,C,D), shift[i]); 82 | else if (i < 32) 83 | Z = rol(Z + G(B,C,D), shift[i]); 84 | else if (i < 48) 85 | Z = rol(Z + H(B,C,D), shift[i]); 86 | else if (i < 64) 87 | Z = rol(Z + I(B,C,D), shift[i]); 88 | if (i == 63) 89 | printf("Ror is %08x\n", Z); 90 | printf("Output of round %d: %08X + %08X = %08X (shift %d, constant %08X)\n", i, Z, B, Z+B, shift[i], (int)(long long)((1LL << 32) * fabs(sin(i + 1)))); 91 | Z = Z + B; 92 | tmp = D; 93 | D = C; 94 | C = B; 95 | B = Z; 96 | A = tmp; 97 | if (i == 31) 98 | { 99 | // swapsies 100 | swap(&block_words[A & 15], &block_words[B & 15]); 101 | swap(&block_words[C & 15], &block_words[D & 15]); 102 | swap(&block_words[(A & (15<<4))>>4], &block_words[(B & (15<<4))>>4]); 103 | swap(&block_words[(A & (15<<8))>>8], &block_words[(B & (15<<8))>>8]); 104 | swap(&block_words[(A & (15<<12))>>12], &block_words[(B & (15<<12))>>12]); 105 | } 106 | } 107 | printf("%08X %08X %08X %08X\n", A, B, C, D); 108 | // Now we can actually compute the output 109 | printf("Out:\n"); 110 | printf("%08x + %08x = %08x\n", key_words[0], A, key_words[0] + A); 111 | printf("%08x + %08x = %08x\n", key_words[1], B, key_words[1] + B); 112 | printf("%08x + %08x = %08x\n", key_words[2], C, key_words[2] + C); 113 | printf("%08x + %08x = %08x\n", key_words[3], D, key_words[3] + D); 114 | out_words[0] = key_words[0] + A; 115 | out_words[1] = key_words[1] + B; 116 | out_words[2] = key_words[2] + C; 117 | out_words[3] = key_words[3] + D; 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/lib/playfair/playfair.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "playfair.h" 4 | 5 | void generate_key_schedule(unsigned char* key_material, uint32_t key_schedule[11][4]); 6 | void generate_session_key(unsigned char* oldSap, unsigned char* messageIn, unsigned char* sessionKey); 7 | void cycle(unsigned char* block, uint32_t key_schedule[11][4]); 8 | void z_xor(unsigned char* in, unsigned char* out, int blocks); 9 | void x_xor(unsigned char* in, unsigned char* out, int blocks); 10 | 11 | extern unsigned char default_sap[]; 12 | 13 | void playfair_decrypt(unsigned char* message3, unsigned char* cipherText, unsigned char* keyOut) 14 | { 15 | unsigned char* chunk1 = &cipherText[16]; 16 | unsigned char* chunk2 = &cipherText[56]; 17 | int i; 18 | unsigned char blockIn[16]; 19 | unsigned char sapKey[16]; 20 | uint32_t key_schedule[11][4]; 21 | generate_session_key(default_sap, message3, sapKey); 22 | generate_key_schedule(sapKey, key_schedule); 23 | z_xor(chunk2, blockIn, 1); 24 | cycle(blockIn, key_schedule); 25 | for (i = 0; i < 16; i++) { 26 | keyOut[i] = blockIn[i] ^ chunk1[i]; 27 | } 28 | x_xor(keyOut, keyOut, 1); 29 | z_xor(keyOut, keyOut, 1); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/lib/playfair/playfair.h: -------------------------------------------------------------------------------- 1 | #ifndef PLAYFAIR_H 2 | #define PLAYFAIR_H 3 | 4 | void playfair_decrypt(unsigned char* message3, unsigned char* cipherText, unsigned char* keyOut); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/lib/playfair/sap_hash.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define printf(...) (void)0; 6 | 7 | void garble(unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*); 8 | 9 | unsigned char rol8(unsigned char input, int count) 10 | { 11 | return ((input << count) & 0xff) | (input & 0xff) >> (8-count); 12 | } 13 | 14 | uint32_t rol8x(unsigned char input, int count) 15 | { 16 | return ((input << count)) | (input) >> (8-count); 17 | } 18 | 19 | 20 | void sap_hash(unsigned char* blockIn, unsigned char* keyOut) 21 | { 22 | uint32_t* block_words = (uint32_t*)blockIn; 23 | uint32_t* out_words = (uint32_t*)keyOut; 24 | unsigned char buffer0[20] = {0x96, 0x5F, 0xC6, 0x53, 0xF8, 0x46, 0xCC, 0x18, 0xDF, 0xBE, 0xB2, 0xF8, 0x38, 0xD7, 0xEC, 0x22, 0x03, 0xD1, 0x20, 0x8F}; 25 | unsigned char buffer1[210]; 26 | unsigned char buffer2[35] = {0x43, 0x54, 0x62, 0x7A, 0x18, 0xC3, 0xD6, 0xB3, 0x9A, 0x56, 0xF6, 0x1C, 0x14, 0x3F, 0x0C, 0x1D, 0x3B, 0x36, 0x83, 0xB1, 0x39, 0x51, 0x4A, 0xAA, 0x09, 0x3E, 0xFE, 0x44, 0xAF, 0xDE, 0xC3, 0x20, 0x9D, 0x42, 0x3A}; 27 | unsigned char buffer3[132]; 28 | unsigned char buffer4[21] = {0xED, 0x25, 0xD1, 0xBB, 0xBC, 0x27, 0x9F, 0x02, 0xA2, 0xA9, 0x11, 0x00, 0x0C, 0xB3, 0x52, 0xC0, 0xBD, 0xE3, 0x1B, 0x49, 0xC7}; 29 | int i0_index[11] = {18, 22, 23, 0, 5, 19, 32, 31, 10, 21, 30}; 30 | uint8_t w,x,y,z; 31 | int i, j; 32 | 33 | // Load the input into the buffer 34 | for (i = 0; i < 210; i++) 35 | { 36 | // We need to swap the byte order around so it is the right endianness 37 | uint32_t in_word = block_words[((i % 64)>>2)]; 38 | uint32_t in_byte = (in_word >> ((3-(i % 4)) << 3)) & 0xff; 39 | buffer1[i] = in_byte; 40 | } 41 | // Next a scrambling 42 | for (i = 0; i < 840; i++) 43 | { 44 | // We have to do unsigned, 32-bit modulo, or we get the wrong indices 45 | x = buffer1[((i-155) & 0xffffffff) % 210]; 46 | y = buffer1[((i-57) & 0xffffffff) % 210]; 47 | z = buffer1[((i-13) & 0xffffffff) % 210]; 48 | w = buffer1[(i & 0xffffffff) % 210]; 49 | buffer1[i % 210] = (rol8(y, 5) + (rol8(z, 3) ^ w) - rol8(x,7)) & 0xff; 50 | } 51 | printf("Garbling...\n"); 52 | // I have no idea what this is doing (yet), but it gives the right output 53 | garble(buffer0, buffer1, buffer2, buffer3, buffer4); 54 | 55 | // Fill the output with 0xE1 56 | for (i = 0; i < 16; i++) 57 | keyOut[i] = 0xE1; 58 | 59 | // Now we use all the buffers we have calculated to grind out the output. First buffer3 60 | for (i = 0; i < 11; i++) 61 | { 62 | // Note that this is addition (mod 255) and not XOR 63 | // Also note that we only use certain indices 64 | // And that index 3 is hard-coded to be 0x3d (Maybe we can hack this up by changing buffer3[0] to be 0xdc? 65 | if (i == 3) 66 | keyOut[i] = 0x3d; 67 | else 68 | keyOut[i] = ((keyOut[i] + buffer3[i0_index[i] * 4]) & 0xff); 69 | } 70 | 71 | // Then buffer0 72 | for (i = 0; i < 20; i++) 73 | keyOut[i % 16] ^= buffer0[i]; 74 | 75 | // Then buffer2 76 | for (i = 0; i < 35; i++) 77 | keyOut[i % 16] ^= buffer2[i]; 78 | 79 | // Do buffer1 80 | for (i = 0; i < 210; i++) 81 | keyOut[(i % 16)] ^= buffer1[i]; 82 | 83 | 84 | // Now we do a kind of reverse-scramble 85 | for (j = 0; j < 16; j++) 86 | { 87 | for (i = 0; i < 16; i++) 88 | { 89 | x = keyOut[((i-7) & 0xffffffff) % 16]; 90 | y = keyOut[i % 16]; 91 | z = keyOut[((i-37) & 0xffffffff) % 16]; 92 | w = keyOut[((i-177) & 0xffffffff) % 16]; 93 | keyOut[i] = rol8(x, 1) ^ y ^ rol8(z, 6) ^ rol8(w, 5); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/lib/plist.h: -------------------------------------------------------------------------------- 1 | #ifndef PLIST_H 2 | #define PLIST_H 3 | 4 | #if defined(_WIN32) && defined(_MSC_VER) 5 | typedef signed __int8 int8_t; 6 | typedef unsigned __int8 uint8_t; 7 | typedef __int16 int16_t; 8 | typedef unsigned __int16 uint16_t; 9 | typedef __int32 int32_t; 10 | typedef unsigned __int32 uint32_t; 11 | typedef __int64 int64_t; 12 | typedef unsigned __int64 uint64_t; 13 | #else 14 | #include 15 | #endif 16 | 17 | #define PLIST_TYPE_PRIMITIVE 0x00 18 | #define PLIST_TYPE_INTEGER 0x10 19 | #define PLIST_TYPE_REAL 0x20 20 | #define PLIST_TYPE_DATA 0x40 21 | #define PLIST_TYPE_STRING 0x50 22 | #define PLIST_TYPE_ARRAY 0xA0 23 | #define PLIST_TYPE_DICT 0xD0 24 | 25 | #define PLIST_PRIMITIVE_TRUE 0x08 26 | #define PLIST_PRIMITIVE_FALSE 0x09 27 | 28 | typedef struct plist_object_s plist_object_t; 29 | 30 | plist_object_t *plist_object_true(); 31 | plist_object_t *plist_object_false(); 32 | plist_object_t *plist_object_integer(uint64_t value); 33 | plist_object_t *plist_object_real(double value); 34 | plist_object_t *plist_object_data(const uint8_t *value, uint32_t valuelen); 35 | plist_object_t *plist_object_string(const char *value); 36 | plist_object_t *plist_object_array(uint32_t size, ...); 37 | plist_object_t *plist_object_dict(uint32_t size, ...); 38 | 39 | uint8_t plist_object_get_type(plist_object_t *object); 40 | int plist_object_primitive_get_value(plist_object_t *object, uint8_t *value); 41 | int plist_object_integer_get_value(plist_object_t *object, int64_t *value); 42 | int plist_object_real_get_value(plist_object_t *object, double *value); 43 | int plist_object_data_get_value(plist_object_t *object, const uint8_t **value, uint32_t *valuelen); 44 | int plist_object_string_get_value(plist_object_t *object, const char **value); 45 | const plist_object_t *plist_object_array_get_value(plist_object_t *object, uint32_t idx); 46 | const plist_object_t *plist_object_dict_get_value(plist_object_t *object, const char *key); 47 | 48 | plist_object_t *plist_object_from_bplist(const uint8_t *data, uint32_t datalen); 49 | int plist_object_to_bplist(plist_object_t *object, uint8_t **data, uint32_t *datalen); 50 | 51 | void plist_object_destroy(plist_object_t *object); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/lib/raop_buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef RAOP_BUFFER_H 16 | #define RAOP_BUFFER_H 17 | 18 | typedef struct raop_buffer_s raop_buffer_t; 19 | 20 | /* From ALACMagicCookieDescription.txt at http://http://alac.macosforge.org/ */ 21 | typedef struct { 22 | unsigned int frameLength; 23 | unsigned char compatibleVersion; 24 | unsigned char bitDepth; 25 | unsigned char pb; 26 | unsigned char mb; 27 | unsigned char kb; 28 | unsigned char numChannels; 29 | unsigned short maxRun; 30 | unsigned int maxFrameBytes; 31 | unsigned int avgBitRate; 32 | unsigned int sampleRate; 33 | } ALACSpecificConfig; 34 | 35 | typedef int (*raop_resend_cb_t)(void *opaque, unsigned short seqno, unsigned short count); 36 | 37 | raop_buffer_t *raop_buffer_init(const char *rtpmap, 38 | const char *fmtp, 39 | const unsigned char *aeskey, 40 | const unsigned char *aesiv); 41 | 42 | const ALACSpecificConfig *raop_buffer_get_config(raop_buffer_t *raop_buffer); 43 | int raop_buffer_queue(raop_buffer_t *raop_buffer, unsigned char *data, unsigned short datalen, int use_seqnum); 44 | const void *raop_buffer_dequeue(raop_buffer_t *raop_buffer, int *length, int no_resend); 45 | void raop_buffer_handle_resends(raop_buffer_t *raop_buffer, raop_resend_cb_t resend_cb, void *opaque); 46 | void raop_buffer_flush(raop_buffer_t *raop_buffer, int next_seq); 47 | 48 | void raop_buffer_destroy(raop_buffer_t *raop_buffer); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/lib/raop_rtp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef RAOP_RTP_H 16 | #define RAOP_RTP_H 17 | 18 | /* For raop_callbacks_t */ 19 | #include "raop.h" 20 | #include "logger.h" 21 | 22 | #define RAOP_AESKEY_LEN 16 23 | #define RAOP_AESIV_LEN 16 24 | #define RAOP_PACKET_LEN 32768 25 | 26 | typedef struct raop_rtp_s raop_rtp_t; 27 | 28 | raop_rtp_t *raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote, 29 | const char *rtpmap, const char *fmtp, 30 | const unsigned char *aeskey, const unsigned char *aesiv); 31 | void raop_rtp_start(raop_rtp_t *raop_rtp, int use_udp, unsigned short control_rport, unsigned short timing_rport, 32 | unsigned short *control_lport, unsigned short *timing_lport, unsigned short *data_lport); 33 | void raop_rtp_set_volume(raop_rtp_t *raop_rtp, float volume); 34 | void raop_rtp_set_metadata(raop_rtp_t *raop_rtp, const char *data, int datalen); 35 | void raop_rtp_set_coverart(raop_rtp_t *raop_rtp, const char *data, int datalen); 36 | void raop_rtp_remote_control_id(raop_rtp_t *raop_rtp, const char *dacp_id, const char *active_remote_header); 37 | void raop_rtp_set_progress(raop_rtp_t *raop_rtp, unsigned int start, unsigned int curr, unsigned int end); 38 | void raop_rtp_flush(raop_rtp_t *raop_rtp, int next_seq); 39 | void raop_rtp_stop(raop_rtp_t *raop_rtp); 40 | void raop_rtp_destroy(raop_rtp_t *raop_rtp); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/lib/rsakey.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef RSAKEY_H 16 | #define RSAKEY_H 17 | 18 | typedef struct rsakey_s rsakey_t; 19 | 20 | rsakey_t *rsakey_init(const unsigned char *modulus, int mod_len, 21 | const unsigned char *pub_exp, int pub_len, 22 | const unsigned char *priv_exp, int priv_len, 23 | const unsigned char *p, int p_len, 24 | const unsigned char *q, int q_len, 25 | const unsigned char *dP, int dP_len, 26 | const unsigned char *dQ, int dQ_len, 27 | const unsigned char *qInv, int qInv_len); 28 | rsakey_t *rsakey_init_pem(const char *pemstr); 29 | 30 | int rsakey_sign(rsakey_t *rsakey, char *dst, int dstlen, const char *b64digest, 31 | unsigned char *ipaddr, int ipaddrlen, 32 | unsigned char *hwaddr, int hwaddrlen); 33 | 34 | int rsakey_decrypt(rsakey_t *rsakey, unsigned char *dst, int dstlen, const char *b64input); 35 | int rsakey_decode(rsakey_t *rsakey, unsigned char *dst, int dstlen, const char *b64input); 36 | 37 | void rsakey_destroy(rsakey_t *rsakey); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/lib/rsapem.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "rsapem.h" 21 | #include "base64.h" 22 | 23 | #define RSAPRIVHEADER "-----BEGIN RSA PRIVATE KEY-----" 24 | #define RSAPRIVFOOTER "-----END RSA PRIVATE KEY-----" 25 | 26 | struct rsapem_s { 27 | unsigned char *data; 28 | unsigned int datalen; 29 | unsigned int datapos; 30 | }; 31 | 32 | rsapem_t * 33 | rsapem_init(const char *pemstr) 34 | { 35 | rsapem_t *rsapem=NULL; 36 | const char *header; 37 | const char *footer; 38 | base64_t *b64dec; 39 | unsigned char *data; 40 | int datalen; 41 | 42 | header = strstr(pemstr, RSAPRIVHEADER); 43 | footer = strstr(pemstr, RSAPRIVFOOTER); 44 | if (!header || !footer) { 45 | return NULL; 46 | } 47 | 48 | 49 | /* Base64 decode the whole input excluding header and footer */ 50 | b64dec = base64_init(NULL, 0, 1); 51 | datalen = base64_decode(b64dec, &data, pemstr+sizeof(RSAPRIVHEADER), 52 | (footer-header)-sizeof(RSAPRIVHEADER)); 53 | base64_destroy(b64dec); 54 | b64dec = NULL; 55 | 56 | if (datalen < 0) { 57 | return NULL; 58 | } 59 | 60 | #ifdef RSAPEM_DEBUG 61 | { 62 | int i; 63 | printf("Decoded output:\n"); 64 | for (i=0; idata = data; 88 | rsapem->datalen = datalen; 89 | rsapem->datapos = 4; 90 | 91 | data = NULL; 92 | datalen = rsapem_read_vector(rsapem, &data); 93 | if (datalen != 1 && data[0] != 0x00) { 94 | free(data); 95 | rsapem_destroy(rsapem); 96 | return NULL; 97 | } 98 | free(data); 99 | return rsapem; 100 | } 101 | 102 | void 103 | rsapem_destroy(rsapem_t *rsapem) 104 | { 105 | if (rsapem) { 106 | free(rsapem->data); 107 | free(rsapem); 108 | } 109 | } 110 | 111 | int 112 | rsapem_read_vector(rsapem_t *rsapem, unsigned char **data) 113 | { 114 | unsigned int length; 115 | unsigned char *ptr; 116 | 117 | if (rsapem->datalen-rsapem->datapos < 2) { 118 | return -1; 119 | } 120 | if (rsapem->data[rsapem->datapos] != 0x02) { 121 | return -2; 122 | } 123 | 124 | /* Read vector length */ 125 | length = rsapem->data[rsapem->datapos+1]; 126 | if (length <= 0x80) { 127 | rsapem->datapos += 2; 128 | } else if (length == 0x81) { 129 | if (rsapem->datalen-rsapem->datapos < 3) { 130 | return -3; 131 | } 132 | length = rsapem->data[rsapem->datapos+2]; 133 | rsapem->datapos += 3; 134 | } else if (length == 0x82) { 135 | if (rsapem->datalen-rsapem->datapos < 4) { 136 | return -3; 137 | } 138 | length = (rsapem->data[rsapem->datapos+2] << 8) | 139 | rsapem->data[rsapem->datapos+3]; 140 | rsapem->datapos += 4; 141 | } else { 142 | return -3; 143 | } 144 | 145 | /* Check that we have enough data available */ 146 | if (rsapem->datalen-rsapem->datapos < length) { 147 | return -4; 148 | } 149 | 150 | /* Allocate data buffer and read bytes */ 151 | ptr = malloc(length); 152 | if (!ptr) { 153 | return -5; 154 | } 155 | memcpy(ptr, rsapem->data+rsapem->datapos, length); 156 | rsapem->datapos += length; 157 | 158 | /* Return buffer and length */ 159 | *data = ptr; 160 | return length; 161 | } 162 | 163 | -------------------------------------------------------------------------------- /src/lib/rsapem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef RSAPEM_H 16 | #define RSAPEM_H 17 | 18 | typedef struct rsapem_s rsapem_t; 19 | 20 | rsapem_t *rsapem_init(const char *pemstr); 21 | int rsapem_read_vector(rsapem_t *rsapem, unsigned char **data); 22 | void rsapem_destroy(rsapem_t *rsapem); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/lib/sdp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "sdp.h" 20 | 21 | struct sdp_s { 22 | char *data; 23 | 24 | /* Actual SDP records */ 25 | const char *version; 26 | const char *origin; 27 | const char *connection; 28 | const char *session; 29 | const char *time; 30 | const char *media; 31 | 32 | /* Additional SDP records */ 33 | const char *rtpmap; 34 | const char *fmtp; 35 | const char *rsaaeskey; 36 | const char *fpaeskey; 37 | const char *aesiv; 38 | const char *min_latency; 39 | }; 40 | 41 | static void 42 | parse_sdp_line(sdp_t *sdp, char *line) 43 | { 44 | int len = strlen(line); 45 | if (len < 2 || line[1] != '=') { 46 | return; 47 | } 48 | 49 | switch (line[0]) { 50 | case 'v': 51 | sdp->version = &line[2]; 52 | break; 53 | case 'o': 54 | sdp->origin = &line[2]; 55 | break; 56 | case 's': 57 | sdp->session = &line[2]; 58 | break; 59 | case 'c': 60 | sdp->connection = &line[2]; 61 | break; 62 | case 't': 63 | sdp->time = &line[2]; 64 | break; 65 | case 'm': 66 | sdp->media = &line[2]; 67 | break; 68 | case 'a': 69 | { 70 | char *key; 71 | char *value; 72 | 73 | /* Parse key and value */ 74 | key = &line[2]; 75 | value = strstr(line, ":"); 76 | if (!value) break; 77 | *(value++) = '\0'; 78 | 79 | if (!strcmp(key, "rtpmap") && !sdp->rtpmap) { 80 | sdp->rtpmap = value; 81 | } else if (!strcmp(key, "fmtp") && !sdp->fmtp) { 82 | sdp->fmtp = value; 83 | } else if (!strcmp(key, "rsaaeskey")) { 84 | sdp->rsaaeskey = value; 85 | } else if (!strcmp(key, "fpaeskey")) { 86 | sdp->fpaeskey = value; 87 | } else if (!strcmp(key, "aesiv")) { 88 | sdp->aesiv = value; 89 | } else if (!strcmp(key, "min-latency")) { 90 | sdp->min_latency = value; 91 | } 92 | break; 93 | } 94 | } 95 | } 96 | 97 | static void 98 | parse_sdp_data(sdp_t *sdp) 99 | { 100 | int pos, len; 101 | 102 | pos = 0; 103 | len = strlen(sdp->data); 104 | while (pos < len) { 105 | int lfpos; 106 | 107 | /* Find newline in string */ 108 | for (lfpos=pos; sdp->data[lfpos]; lfpos++) { 109 | if (sdp->data[lfpos] == '\n') { 110 | break; 111 | } 112 | } 113 | if (sdp->data[lfpos] != '\n') { 114 | break; 115 | } 116 | 117 | /* Replace newline with '\0' and parse line */ 118 | sdp->data[lfpos] = '\0'; 119 | if (lfpos > pos && sdp->data[lfpos-1] == '\r') { 120 | sdp->data[lfpos-1] = '\0'; 121 | } 122 | parse_sdp_line(sdp, sdp->data+pos); 123 | pos = lfpos+1; 124 | } 125 | } 126 | 127 | sdp_t * 128 | sdp_init(const char *sdpdata, int sdpdatalen) 129 | { 130 | sdp_t *sdp; 131 | 132 | sdp = calloc(1, sizeof(sdp_t)); 133 | if (!sdp) { 134 | return NULL; 135 | } 136 | 137 | /* Allocate data buffer */ 138 | sdp->data = malloc(sdpdatalen+1); 139 | if (!sdp->data) { 140 | free(sdp); 141 | return NULL; 142 | } 143 | memcpy(sdp->data, sdpdata, sdpdatalen); 144 | sdp->data[sdpdatalen] = '\0'; 145 | parse_sdp_data(sdp); 146 | return sdp; 147 | } 148 | 149 | void 150 | sdp_destroy(sdp_t *sdp) 151 | { 152 | if (sdp) { 153 | free(sdp->data); 154 | free(sdp); 155 | } 156 | } 157 | 158 | const char * 159 | sdp_get_version(sdp_t *sdp) 160 | { 161 | assert(sdp); 162 | 163 | return sdp->version; 164 | } 165 | 166 | const char * 167 | sdp_get_origin(sdp_t *sdp) 168 | { 169 | assert(sdp); 170 | 171 | return sdp->origin; 172 | } 173 | 174 | const char * 175 | sdp_get_session(sdp_t *sdp) 176 | { 177 | assert(sdp); 178 | 179 | return sdp->session; 180 | } 181 | 182 | const char * 183 | sdp_get_connection(sdp_t *sdp) 184 | { 185 | assert(sdp); 186 | 187 | return sdp->connection; 188 | } 189 | 190 | const char * 191 | sdp_get_time(sdp_t *sdp) 192 | { 193 | assert(sdp); 194 | 195 | return sdp->time; 196 | } 197 | 198 | const char * 199 | sdp_get_media(sdp_t *sdp) 200 | { 201 | assert(sdp); 202 | 203 | return sdp->media; 204 | } 205 | 206 | const char * 207 | sdp_get_rtpmap(sdp_t *sdp) 208 | { 209 | assert(sdp); 210 | 211 | return sdp->rtpmap; 212 | } 213 | 214 | const char * 215 | sdp_get_fmtp(sdp_t *sdp) 216 | { 217 | assert(sdp); 218 | 219 | return sdp->fmtp; 220 | } 221 | 222 | const char * 223 | sdp_get_rsaaeskey(sdp_t *sdp) 224 | { 225 | assert(sdp); 226 | 227 | return sdp->rsaaeskey; 228 | } 229 | 230 | const char * 231 | sdp_get_fpaeskey(sdp_t *sdp) 232 | { 233 | assert(sdp); 234 | 235 | return sdp->fpaeskey; 236 | } 237 | 238 | const char * 239 | sdp_get_aesiv(sdp_t *sdp) 240 | { 241 | assert(sdp); 242 | 243 | return sdp->aesiv; 244 | } 245 | 246 | const char * 247 | sdp_get_min_latency(sdp_t *sdp) 248 | { 249 | assert(sdp); 250 | 251 | return sdp->min_latency; 252 | } 253 | 254 | -------------------------------------------------------------------------------- /src/lib/sdp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef SDP_H 16 | #define SDP_H 17 | 18 | typedef struct sdp_s sdp_t; 19 | 20 | sdp_t *sdp_init(const char *sdpdata, int sdpdatalen); 21 | 22 | const char *sdp_get_version(sdp_t *sdp); 23 | const char *sdp_get_origin(sdp_t *sdp); 24 | const char *sdp_get_session(sdp_t *sdp); 25 | const char *sdp_get_connection(sdp_t *sdp); 26 | const char *sdp_get_time(sdp_t *sdp); 27 | const char *sdp_get_media(sdp_t *sdp); 28 | const char *sdp_get_rtpmap(sdp_t *sdp); 29 | const char *sdp_get_fmtp(sdp_t *sdp); 30 | const char *sdp_get_rsaaeskey(sdp_t *sdp); 31 | const char *sdp_get_fpaeskey(sdp_t *sdp); 32 | const char *sdp_get_aesiv(sdp_t *sdp); 33 | const char *sdp_get_min_latency(sdp_t *sdp); 34 | 35 | void sdp_destroy(sdp_t *sdp); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/lib/sockets.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef SOCKETS_H 16 | #define SOCKETS_H 17 | 18 | #if defined(WIN32) 19 | typedef int socklen_t; 20 | 21 | #ifndef SHUT_RD 22 | # define SHUT_RD SD_RECEIVE 23 | #endif 24 | #ifndef SHUT_WR 25 | # define SHUT_WR SD_SEND 26 | #endif 27 | #ifndef SHUT_RDWR 28 | # define SHUT_RDWR SD_BOTH 29 | #endif 30 | 31 | #define SOCKET_GET_ERROR() WSAGetLastError() 32 | #define SOCKET_SET_ERROR(value) WSASetLastError(value) 33 | #define SOCKET_ERRORNAME(name) WSA##name 34 | 35 | #define WSAEAGAIN WSAEWOULDBLOCK 36 | #define WSAENOMEM WSA_NOT_ENOUGH_MEMORY 37 | 38 | #else 39 | 40 | #define closesocket close 41 | #define ioctlsocket ioctl 42 | 43 | #define SOCKET_GET_ERROR() (errno) 44 | #define SOCKET_SET_ERROR(value) (errno = (value)) 45 | #define SOCKET_ERRORNAME(name) name 46 | 47 | #endif 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/lib/threads.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef THREADS_H 16 | #define THREADS_H 17 | 18 | #if defined(WIN32) 19 | #include 20 | 21 | #define sleepms(x) Sleep(x) 22 | 23 | typedef HANDLE thread_handle_t; 24 | 25 | #define THREAD_RETVAL DWORD WINAPI 26 | #define THREAD_CREATE(handle, func, arg) \ 27 | handle = CreateThread(NULL, 0, func, arg, 0, NULL) 28 | #define THREAD_JOIN(handle) do { WaitForSingleObject(handle, INFINITE); CloseHandle(handle); } while(0) 29 | 30 | typedef HANDLE mutex_handle_t; 31 | 32 | #define MUTEX_CREATE(handle) handle = CreateMutex(NULL, FALSE, NULL) 33 | #define MUTEX_LOCK(handle) WaitForSingleObject(handle, INFINITE) 34 | #define MUTEX_UNLOCK(handle) ReleaseMutex(handle) 35 | #define MUTEX_DESTROY(handle) CloseHandle(handle) 36 | 37 | #else /* Use pthread library */ 38 | 39 | #include 40 | #include 41 | 42 | #define sleepms(x) usleep((x)*1000) 43 | 44 | typedef pthread_t thread_handle_t; 45 | 46 | #define THREAD_RETVAL void * 47 | #define THREAD_CREATE(handle, func, arg) \ 48 | if (pthread_create(&(handle), NULL, func, arg)) handle = 0 49 | #define THREAD_JOIN(handle) pthread_join(handle, NULL) 50 | 51 | typedef pthread_mutex_t mutex_handle_t; 52 | 53 | #define MUTEX_CREATE(handle) pthread_mutex_init(&(handle), NULL) 54 | #define MUTEX_LOCK(handle) pthread_mutex_lock(&(handle)) 55 | #define MUTEX_UNLOCK(handle) pthread_mutex_unlock(&(handle)) 56 | #define MUTEX_DESTROY(handle) pthread_mutex_destroy(&(handle)) 57 | 58 | #endif 59 | 60 | #endif /* THREADS_H */ 61 | -------------------------------------------------------------------------------- /src/lib/utils.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | char * 20 | utils_strsep(char **stringp, const char *delim) 21 | { 22 | char *original; 23 | char *strptr; 24 | 25 | if (*stringp == NULL) { 26 | return NULL; 27 | } 28 | 29 | original = *stringp; 30 | strptr = strstr(*stringp, delim); 31 | if (strptr == NULL) { 32 | *stringp = NULL; 33 | return original; 34 | } 35 | *strptr = '\0'; 36 | *stringp = strptr+strlen(delim); 37 | return original; 38 | } 39 | 40 | int 41 | utils_read_file(char **dst, const char *filename) 42 | { 43 | FILE *stream; 44 | int filesize; 45 | char *buffer; 46 | int read_bytes; 47 | 48 | /* Open stream for reading */ 49 | stream = fopen(filename, "rb"); 50 | if (!stream) { 51 | return -1; 52 | } 53 | 54 | /* Find out file size */ 55 | fseek(stream, 0, SEEK_END); 56 | filesize = ftell(stream); 57 | fseek(stream, 0, SEEK_SET); 58 | 59 | /* Allocate one extra byte for zero */ 60 | buffer = malloc(filesize+1); 61 | if (!buffer) { 62 | fclose(stream); 63 | return -2; 64 | } 65 | 66 | /* Read data in a loop to buffer */ 67 | read_bytes = 0; 68 | do { 69 | int ret = fread(buffer+read_bytes, 1, 70 | filesize-read_bytes, stream); 71 | if (ret == 0) { 72 | break; 73 | } 74 | read_bytes += ret; 75 | } while (read_bytes < filesize); 76 | 77 | /* Add final null byte and close stream */ 78 | buffer[read_bytes] = '\0'; 79 | fclose(stream); 80 | 81 | /* If read didn't finish, return error */ 82 | if (read_bytes != filesize) { 83 | free(buffer); 84 | return -3; 85 | } 86 | 87 | /* Return buffer */ 88 | *dst = buffer; 89 | return filesize; 90 | } 91 | 92 | int 93 | utils_hwaddr_raop(char *str, int strlen, const char *hwaddr, int hwaddrlen) 94 | { 95 | int i,j; 96 | 97 | /* Check that our string is long enough */ 98 | if (strlen == 0 || strlen < 2*hwaddrlen+1) 99 | return -1; 100 | 101 | /* Convert hardware address to hex string */ 102 | for (i=0,j=0; i>4) & 0x0f; 104 | int lo = hwaddr[i] & 0x0f; 105 | 106 | if (hi < 10) str[j++] = '0' + hi; 107 | else str[j++] = 'A' + hi-10; 108 | if (lo < 10) str[j++] = '0' + lo; 109 | else str[j++] = 'A' + lo-10; 110 | } 111 | 112 | /* Add string terminator */ 113 | str[j++] = '\0'; 114 | return j; 115 | } 116 | 117 | int 118 | utils_hwaddr_airplay(char *str, int strlen, const char *hwaddr, int hwaddrlen) 119 | { 120 | int i,j; 121 | 122 | /* Check that our string is long enough */ 123 | if (strlen == 0 || strlen < 2*hwaddrlen+hwaddrlen) 124 | return -1; 125 | 126 | /* Convert hardware address to hex string */ 127 | for (i=0,j=0; i>4) & 0x0f; 129 | int lo = hwaddr[i] & 0x0f; 130 | 131 | if (hi < 10) str[j++] = '0' + hi; 132 | else str[j++] = 'a' + hi-10; 133 | if (lo < 10) str[j++] = '0' + lo; 134 | else str[j++] = 'a' + lo-10; 135 | 136 | str[j++] = ':'; 137 | } 138 | 139 | /* Add string terminator */ 140 | if (j != 0) j--; 141 | str[j++] = '\0'; 142 | return j; 143 | } 144 | 145 | -------------------------------------------------------------------------------- /src/lib/utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef UTILS_H 16 | #define UTILS_H 17 | 18 | char *utils_strsep(char **stringp, const char *delim); 19 | int utils_read_file(char **dst, const char *pemstr); 20 | int utils_hwaddr_raop(char *str, int strlen, const char *hwaddr, int hwaddrlen); 21 | int utils_hwaddr_airplay(char *str, int strlen, const char *hwaddr, int hwaddrlen); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/test/dnssd_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "dnssd.h" 6 | #include "compat.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | const char hwaddr[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB }; 12 | dnssd_t *dnssd; 13 | 14 | 15 | #ifdef WIN32 16 | WORD wVersionRequested; 17 | WSADATA wsaData; 18 | 19 | wVersionRequested = MAKEWORD(2, 2); 20 | if (WSAStartup(wVersionRequested, &wsaData) != 0) { 21 | return -1; 22 | } 23 | if (LOBYTE(wsaData.wVersion) != 2 || 24 | HIBYTE(wsaData.wVersion) != 2) { 25 | return -1; 26 | } 27 | #endif 28 | 29 | dnssd = dnssd_init(NULL); 30 | if (!dnssd) { 31 | printf("Failed to init dnssd\n"); 32 | return -1; 33 | } 34 | dnssd_register_raop(dnssd, "Test", 5000, hwaddr, sizeof(hwaddr)); 35 | dnssd_register_airplay(dnssd, "Test", 6000, hwaddr, sizeof(hwaddr)); 36 | 37 | sleepms(60000); 38 | 39 | dnssd_unregister_raop(dnssd); 40 | dnssd_unregister_airplay(dnssd); 41 | dnssd_destroy(dnssd); 42 | 43 | #ifdef WIN32 44 | WSACleanup(); 45 | #endif 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /src/test/dnssd_test.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "dnssd.h" 7 | #include "compat.h" 8 | 9 | int 10 | main(int argc, char *argv[]) 11 | { 12 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 13 | const char hwaddr[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB }; 14 | dnssd_t *dnssd; 15 | 16 | dnssd = dnssd_init(NULL); 17 | if (!dnssd) { 18 | printf("Failed to init dnssd\n"); 19 | return -1; 20 | } 21 | dnssd_register_raop(dnssd, "Test", 5000, hwaddr, sizeof(hwaddr)); 22 | dnssd_register_airplay(dnssd, "Test", 6000, hwaddr, sizeof(hwaddr)); 23 | 24 | sleepms(60000); 25 | 26 | dnssd_unregister_raop(dnssd); 27 | dnssd_unregister_airplay(dnssd); 28 | dnssd_destroy(dnssd); 29 | [pool release]; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /src/test/example.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Starts the AirPlay server (name "FakePort") and dumps the received contents 3 | * to files: 4 | * - audio.pcm : decoded audio content 5 | * - metadata.bin : meta data 6 | * - covertart.jpg : cover art 7 | * 8 | * Requires avahi-daemon to run. Also requires file "airplay.key" in the same directory. 9 | * 10 | * Compile with: gcc -o example -g -I../../include/shairplay example.c -lshairplay 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef WIN32 18 | #include 19 | #endif 20 | 21 | #include "dnssd.h" 22 | #include "raop.h" 23 | 24 | static int running; 25 | 26 | #ifndef WIN32 27 | 28 | #include 29 | static void 30 | signal_handler(int sig) 31 | { 32 | switch (sig) { 33 | case SIGINT: 34 | case SIGTERM: 35 | running = 0; 36 | break; 37 | } 38 | } 39 | static void 40 | init_signals(void) 41 | { 42 | struct sigaction sigact; 43 | 44 | sigact.sa_handler = signal_handler; 45 | sigemptyset(&sigact.sa_mask); 46 | sigact.sa_flags = 0; 47 | sigaction(SIGINT, &sigact, NULL); 48 | sigaction(SIGTERM, &sigact, NULL); 49 | } 50 | 51 | #endif 52 | 53 | static void * 54 | audio_init(void *cls, int bits, int channels, int samplerate) 55 | { 56 | return fopen("audio.pcm", "wb"); 57 | } 58 | 59 | static void 60 | audio_set_volume(void *cls, void *session, float volume) 61 | { 62 | printf("Setting volume to %f\n", volume); 63 | } 64 | 65 | static void 66 | audio_set_metadata(void *cls, void *session, const void *buffer, int buflen) 67 | { 68 | int orig = buflen; 69 | FILE *file = fopen("metadata.bin", "wb"); 70 | while (buflen > 0) { 71 | buflen -= fwrite(buffer+orig-buflen, 1, buflen, file); 72 | } 73 | fclose(file); 74 | printf("Metadata of length %d saved as metadata.bin\n", orig); 75 | } 76 | 77 | static void 78 | audio_set_coverart(void *cls, void *session, const void *buffer, int buflen) 79 | { 80 | int orig = buflen; 81 | FILE *file = fopen("coverart.jpg", "wb"); 82 | while (buflen > 0) { 83 | buflen -= fwrite(buffer+orig-buflen, 1, buflen, file); 84 | } 85 | fclose(file); 86 | printf("Coverart of length %d saved as coverart.jpg\n", orig); 87 | } 88 | 89 | static void 90 | audio_process(void *cls, void *session, const void *buffer, int buflen) 91 | { 92 | int orig = buflen; 93 | while (buflen > 0) { 94 | buflen -= fwrite(buffer+orig-buflen, 1, buflen, session); 95 | } 96 | } 97 | 98 | static void 99 | audio_flush(void *cls, void *session) 100 | { 101 | printf("Flushing audio\n"); 102 | } 103 | 104 | static void 105 | audio_destroy(void *cls, void *session) 106 | { 107 | fclose(session); 108 | } 109 | 110 | static void 111 | raop_log_callback(void *cls, int level, const char *msg) 112 | { 113 | printf("RAOP LOG(%d): %s\n", level, msg); 114 | } 115 | 116 | int 117 | main(int argc, char *argv[]) 118 | { 119 | const char *name = "FakePort"; 120 | unsigned short raop_port = 5000; 121 | const char hwaddr[] = { 0x48, 0x5d, 0x60, 0x7c, 0xee, 0x22 }; 122 | 123 | dnssd_t *dnssd; 124 | raop_t *raop; 125 | raop_callbacks_t raop_cbs; 126 | 127 | int error; 128 | 129 | raop_cbs.cls = NULL; 130 | raop_cbs.audio_init = audio_init; 131 | raop_cbs.audio_set_volume = audio_set_volume; 132 | raop_cbs.audio_set_metadata = audio_set_metadata; 133 | raop_cbs.audio_set_coverart = audio_set_coverart; 134 | raop_cbs.audio_process = audio_process; 135 | raop_cbs.audio_flush = audio_flush; 136 | raop_cbs.audio_destroy = audio_destroy; 137 | 138 | raop = raop_init_from_keyfile(10, &raop_cbs, "airport.key", NULL); 139 | if (raop == NULL) { 140 | fprintf(stderr, "Could not initialize the RAOP service (airport.key missing?)\n"); 141 | return -1; 142 | } 143 | 144 | raop_set_log_level(raop, RAOP_LOG_DEBUG); 145 | raop_set_log_callback(raop, &raop_log_callback, NULL); 146 | raop_start(raop, &raop_port, hwaddr, sizeof(hwaddr), NULL); 147 | 148 | error = 0; 149 | dnssd = dnssd_init(&error); 150 | if (error) { 151 | fprintf(stderr, "ERROR: Could not initialize dnssd library!\n"); 152 | fprintf(stderr, "------------------------------------------\n"); 153 | fprintf(stderr, "You could try the following resolutions based on your OS:\n"); 154 | fprintf(stderr, "Windows: Try installing http://support.apple.com/kb/DL999\n"); 155 | fprintf(stderr, "Debian/Ubuntu: Try installing libavahi-compat-libdnssd-dev package\n"); 156 | raop_destroy(raop); 157 | return -1; 158 | } 159 | 160 | dnssd_register_raop(dnssd, name, raop_port, hwaddr, sizeof(hwaddr), 1); 161 | 162 | printf("Startup complete... Kill with Ctrl+C\n"); 163 | 164 | running = 1; 165 | while (running != 0) { 166 | #ifndef WIN32 167 | sleep(1); 168 | #else 169 | Sleep(1000); 170 | #endif 171 | } 172 | 173 | dnssd_unregister_raop(dnssd); 174 | dnssd_destroy(dnssd); 175 | 176 | raop_stop(raop); 177 | raop_destroy(raop); 178 | 179 | return 0; 180 | } 181 | 182 | -------------------------------------------------------------------------------- /src/test/test.py: -------------------------------------------------------------------------------- 1 | import time 2 | from struct import * 3 | from Shairplay import * 4 | 5 | hwaddr = pack('BBBBBB', 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB) 6 | class SampleCallbacks(RaopCallbacks): 7 | def audio_init(self, bits, channels, samplerate): 8 | print "Initializing", bits, channels, samplerate 9 | def audio_process(self, session, buffer): 10 | print "Processing", + len(buffer), "bytes of audio" 11 | def audio_destroy(self, session): 12 | print "Destroying" 13 | def audio_set_volume(self, session, volume): 14 | print "Set volume to", volume 15 | def audio_set_metadata(self, session, metadata): 16 | print "Got", len(metadata), "bytes of metadata" 17 | def audio_set_coverart(self, session, coverart): 18 | print "Got", len(coverart), "bytes of coverart" 19 | 20 | shairplay = LoadShairplay(".") 21 | callbacks = SampleCallbacks() 22 | 23 | def log_callback(level, message): 24 | print "Level", level, ":", message 25 | 26 | raop = RaopService(shairplay, 10, callbacks) 27 | raop.set_log_level(RaopLogLevel.DEBUG) 28 | raop.set_log_callback(log_callback) 29 | port = raop.start(5000, hwaddr) 30 | 31 | dnssd = DnssdService(shairplay) 32 | dnssd.register_raop("RAOP test", port, hwaddr) 33 | 34 | time.sleep(50) 35 | 36 | dnssd.unregister_raop() 37 | raop.stop() 38 | 39 | del dnssd 40 | del raop 41 | 42 | --------------------------------------------------------------------------------