From 529adbfaf6c94bcc9ba649813b05ce322085bbb8 Mon Sep 17 00:00:00 2001
From: Gijs Peskens <gijs@peskens.net>
Date: Tue, 20 Sep 2022 15:40:08 +0200
Subject: [PATCH] Add building via meson, remove outdated options

Co-authored-by: Thulinma <jaron@vietors.com>
Change-Id: I2a620c8d98aca7203f6742c66c3f82afe91b5c3c
---
 CMakeLists.txt                     |  34 +------
 Doxyfile.in                        |   4 +-
 generated/meson.build              |  46 +++++++++
 lib/config.cpp                     |  11 +-
 lib/meson.build                    | 136 +++++++++++++++++++++++++
 lib/urireader.cpp                  |  12 +--
 lsp/meson.build                    |  26 +++++
 meson.build                        | 158 +++++++++++++++++++++++++++++
 meson_options.txt                  |  27 +++++
 mist/meson.build                   |   6 ++
 src/analysers/meson.build          |  40 ++++++++
 src/controller/controller_limits.h |   8 --
 src/controller/meson.build         |  22 ++++
 src/input/meson.build              |  86 ++++++++++++++++
 src/make_html.cpp                  |  40 ++++++++
 src/meson.build                    |  17 ++++
 src/output/meson.build             | 133 ++++++++++++++++++++++++
 src/process/meson.build            |  50 +++++++++
 src/relaccxsampler.cpp             |  21 ----
 src/utils/meson.build              |  29 ++++++
 test/downloader.cpp                |   7 +-
 test/json.cpp                      |   1 +
 test/meson.build                   |  23 +++++
 23 files changed, 855 insertions(+), 82 deletions(-)
 create mode 100644 generated/meson.build
 create mode 100644 lib/meson.build
 create mode 100644 lsp/meson.build
 create mode 100644 meson.build
 create mode 100644 meson_options.txt
 create mode 100644 mist/meson.build
 create mode 100644 src/analysers/meson.build
 create mode 100644 src/controller/meson.build
 create mode 100644 src/input/meson.build
 create mode 100644 src/make_html.cpp
 create mode 100644 src/meson.build
 create mode 100644 src/output/meson.build
 create mode 100644 src/process/meson.build
 delete mode 100644 src/relaccxsampler.cpp
 create mode 100644 src/utils/meson.build
 create mode 100644 test/meson.build

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 38afbb72..a1bcf1ed 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,12 +78,6 @@ if (FILLER_DATA AND SHARED_SECRET AND SUPER_SECRET)
 add_definitions(-DFILLER_DATA="${FILLER_DATA}" -DSHARED_SECRET="${SHARED_SECRET}" -DSUPER_SECRET="${SUPER_SECRET}")#LTS
 endif()
 
-option(GEOIP "Enable GeoIP capabilities (deprecated)")
-if (GEOIP)
-  add_definitions(-DGEOIP=1)
-  message("GeoIP is turned ON")
-endif()
-
 option(NOSSL "Disable SSL/TLS support")
 if (NOT NOSSL)
   add_definitions(-DSSL=1)
@@ -104,21 +98,11 @@ if (NOT NOUPDATE)
   add_definitions(-DUPDATER=1)
 endif()
 
-option(PERPETUAL "Disable the licensing system")
-if (NOT PERPETUAL)
-  add_definitions(-DLICENSING=1)
-endif()
-
 option(NOAUTH "Disable API authentication entirely (insecure!)")
 if (NOAUTH)
   add_definitions(-DNOAUTH=1)
 endif()
 
-option(KILLONEXIT "Kill all processes on exit, ensuring nothing is running anymore (disables rolling restart/update support)")
-if (KILLONEXIT)
-  add_definitions(-DKILLONEXIT=true)
-endif()
-
 if (DEFINED UDP_API_HOST )
   add_definitions(-DUDP_API_HOST=${UDP_API_HOST})
 endif()
@@ -140,11 +124,6 @@ if (WITH_THREADNAMES)
   add_definitions(-DWITH_THREADNAMES=1)
 endif()
 
-option(NOCRASHCHECK "Disables the crash check in the controller stats and input userpages. Prevents killing processes that are stalled/stuck.")
-if (NOCRASHCHECK)
-  add_definitions(-DNOCRASHCHECK=1)
-endif()
-
 if (DEFINED STATS_DELAY)
   add_definitions(-DSTATS_DELAY=${STATS_DELAY})
 endif()
@@ -690,6 +669,8 @@ install(
 ########################################
 find_package(Doxygen)
 if(DOXYGEN_FOUND)
+  set(DOXY_LAYOUT "${SOURCE_DIR}/DoxygenLayout.xml")
+  set(INPUT_DIRS "${SOURCE_DIR}/src ${SOURCE_DIR}/lib")
   configure_file(${SOURCE_DIR}/Doxyfile.in ${BINARY_DIR}/Doxyfile @ONLY)
   add_custom_target( docs
     ${DOXYGEN_EXECUTABLE} ${BINARY_DIR}/Doxyfile
@@ -731,17 +712,6 @@ else()
   endif()
 endif()
 
-########################################
-# RelAccX Sampler                      #
-########################################
-  add_executable(RelAccXSampler
-    src/relaccxsampler.cpp
-    ${BINARY_DIR}/mist/.headers
-  )
-  target_link_libraries(RelAccXSampler
-    mist 
-  )
-
 ########################################
 # Embed Code                           #
 ########################################
diff --git a/Doxyfile.in b/Doxyfile.in
index ca69803f..66279ed6 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -672,7 +672,7 @@ FILE_VERSION_FILTER    =
 # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
 # tag is left empty.
 
-LAYOUT_FILE = DoxygenLayout.xml
+LAYOUT_FILE = "@DOXY_LAYOUT@"
 
 # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
 # the reference definitions. This must be a list of .bib files. The .bib
@@ -754,7 +754,7 @@ WARN_LOGFILE           =
 # spaces.
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = .
+INPUT                  = @INPUT_DIRS@
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/generated/meson.build b/generated/meson.build
new file mode 100644
index 00000000..7180c0d7
--- /dev/null
+++ b/generated/meson.build
@@ -0,0 +1,46 @@
+
+# Utilities that we use to generate source files
+sourcery = executable('sourcery', '../src/sourcery.cpp', native: true)
+make_html = executable('make_html', '../src/make_html.cpp', native: true)
+
+# If requested, use local versions instead of building our own
+if get_option('LOCAL_GENERATORS')
+  make_html = find_program('make_html', required:true, native:true, dirs: [meson.project_source_root()])
+  sourcery = find_program('sourcery', required:true, native:true, dirs: [meson.project_source_root()])
+endif
+
+gen_html = custom_target('gen_html', output: 'server.html', input: html_files, command: [make_html, '@OUTPUT@', '@INPUT@'])
+
+embed_files = [
+    {'infile': '../embed/min/player.js',                'variable': 'player_js',         'outfile': 'player.js.h'},
+    {'infile': '../embed/min/wrappers/html5.js',        'variable': 'html5_js',          'outfile': 'html5.js.h'},
+    {'infile': '../embed/min/wrappers/flash_strobe.js', 'variable': 'flash_strobe_js',   'outfile': 'flash_strobe.js.h'},
+    {'infile': '../embed/min/wrappers/dashjs.js',       'variable': 'dash_js',           'outfile': 'dashjs.js.h'},
+    {'infile': '../embed/min/wrappers/videojs.js',      'variable': 'video_js',          'outfile': 'videojs.js.h'},
+    {'infile': '../embed/min/wrappers/webrtc.js',       'variable': 'webrtc_js',         'outfile': 'webrtc.js.h'},
+    {'infile': '../embed/min/wrappers/mews.js',         'variable': 'mews_js',           'outfile': 'mews.js.h'},
+    {'infile': '../embed/min/wrappers/flv.js',          'variable': 'flv_js',            'outfile': 'flv.js.h'},
+    {'infile': '../embed/min/wrappers/hlsjs.js',        'variable': 'hlsjs_js',          'outfile': 'hlsjs.js.h'},
+    {'infile': '../embed/min/wrappers/rawws.js',        'variable': 'rawws_js',          'outfile': 'rawws.js.h'},
+    {'infile': '../embed/players/dash.js.license.js',   'variable': 'player_dash_lic_js','outfile': 'player_dash_lic.js.h'},
+    {'infile': '../embed/players/dash.all.min.js',      'variable': 'player_dash_js',    'outfile': 'player_dash.js.h'},
+    {'infile': '../embed/players/video.min.js',         'variable': 'player_video_js',   'outfile': 'player_video.js.h'},
+    {'infile': '../embed/players/webrtc.js',            'variable': 'player_webrtc_js',  'outfile': 'player_webrtc.js.h'},
+    {'infile': '../embed/players/flv.min.js',           'variable': 'player_flv_js',     'outfile': 'player_flv.js.h'},
+    {'infile': '../embed/players/hls.js',               'variable': 'player_hlsjs_js',   'outfile': 'player_hlsjs.js.h'},
+    {'infile': '../embed/players/libde265.min.js',      'variable': 'player_libde265_js','outfile': 'player_libde265.js.h'},
+    {'infile': '../embed/min/skins/default.css',        'variable': 'skin_default_css',  'outfile': 'skin_default.css.h'},
+    {'infile': '../embed/min/skins/dev.css',            'variable': 'skin_dev_css',      'outfile': 'skin_dev.css.h'},
+    {'infile': '../embed/skins/video-js.css',           'variable': 'skin_videojs_css',  'outfile': 'skin_videojs.css.h'},
+    {'infile': '../src/output/noffmpeg.jpg',            'variable': 'noffmpeg',          'outfile': 'noffmpeg.h'},
+    {'infile': '../src/output/noh264.jpg',              'variable': 'noh264',            'outfile': 'noh264.h'},
+]
+
+embed_tgts = []
+
+foreach e : embed_files
+  embed_tgts += custom_target('embed_'+e.get('outfile'), output: e.get('outfile'), input: e.get('infile'), command: [sourcery, '@INPUT@', e.get('variable'), '@OUTPUT@'])
+endforeach
+
+
+server_html = custom_target('embed_server.html', output: 'server.html.h', input: gen_html, command: [sourcery, '@INPUT@', 'server_html', '@OUTPUT@'])
diff --git a/lib/config.cpp b/lib/config.cpp
index f75b1e36..df7895e3 100644
--- a/lib/config.cpp
+++ b/lib/config.cpp
@@ -309,10 +309,6 @@ bool Util::Config::parseArgs(int &argc, char **&argv){
     case 'h':
     case '?': printHelp(std::cout);
     case 'v': std::cout << "Version: " PACKAGE_VERSION ", release " RELEASE << std::endl;
-#ifdef NOCRASHCHECK
-      std::cout << "- Flag: No crash check. Will not attempt to detect and kill crashed processes."
-                << std::endl;
-#endif
 #ifndef SHM_ENABLED
       std::cout << "- Flag: Shared memory disabled. Will use shared files in stead of shared "
                    "memory as IPC method."
@@ -331,7 +327,7 @@ bool Util::Config::parseArgs(int &argc, char **&argv){
       }
 #endif
 #ifndef SSL
-      std::cout << "- Flag: SSL support disabled. HTTPS/RTMPS are unavailable." << std::endl;
+      std::cout << "- Flag: SSL support disabled. HTTPS/RTMPS/WebRTC/WebSockets are either unavailable or may not function fully." << std::endl;
 #endif
 /*LTS-START*/
 #ifndef UPDATER
@@ -344,11 +340,6 @@ bool Util::Config::parseArgs(int &argc, char **&argv){
                    "account first. Make sure access to API port isn't public!"
                 << std::endl;
 #endif
-#ifdef KILLONEXIT
-      std::cout << "- Flag: Kill on exit. All binaries will forcibly shut down all their children "
-                   "on exit. Rolling restart support is disabled."
-                << std::endl;
-#endif
 #ifdef STATS_DELAY
       if (STATS_DELAY != 15){
         std::cout << "- Setting: Stats delay " << STATS_DELAY << ". Statistics of viewer counts are delayed by "
diff --git a/lib/meson.build b/lib/meson.build
new file mode 100644
index 00000000..03f95028
--- /dev/null
+++ b/lib/meson.build
@@ -0,0 +1,136 @@
+
+headers = [
+  'adts.h',
+  'amf.h',
+  'auth.h',
+  'encode.h',
+  'bitfields.h',
+  'bitstream.h',
+  'certificate.h',
+  'checksum.h',
+  'cmaf.h',
+  'comms.h',
+  'config.h',
+  'defines.h',
+  'dtls_srtp_handshake.h',
+  'dtsc.h',
+  'encryption.h',
+  'flv_tag.h',
+  'h264.h',
+  'h265.h',
+  'hls_support.h',
+  'http_parser.h',
+  'downloader.h',
+  'json.h',
+  'langcodes.h',
+  'mp4_adobe.h',
+  'mp4_dash.h',
+  'mp4_encryption.h',
+  'mp4_generic.h',
+  'mp4.h',
+  'mp4_ms.h',
+  'mpeg.h',
+  'nal.h',
+  'ogg.h',
+  'procs.h',
+  'rtmpchunks.h',
+  'rtp_fec.h',
+  'rtp.h',
+  'sdp.h',
+  'sdp_media.h',
+  'shared_memory.h',
+  'socket.h',
+  'srtp.h',
+  'stream.h',
+  'stun.h',
+  'theora.h',
+  'timing.h',
+  'tinythread.h',
+  'ts_packet.h',
+  'ts_stream.h',
+  'util.h',
+  'vorbis.h',
+  'triggers.h',
+  'opus.h',
+  'riff.h',
+  'ebml.h',
+  'ebml_socketglue.h',
+  'websocket.h',
+  'url.h',
+  'urireader.h',
+]
+
+if have_srt 
+  headers += 'socket_srt.h'
+endif
+
+install_headers(headers, subdir: 'mist')
+
+extra_code = []
+
+if usessl
+  extra_code += ['dtls_srtp_handshake.cpp', 'stun.cpp', 'certificate.cpp', 'encryption.cpp', 'srtp.cpp',]
+endif
+
+libmist = library('mist',
+  'adts.cpp',
+  'amf.cpp',
+  'auth.cpp',
+  'encode.cpp',
+  'bitfields.cpp',
+  'bitstream.cpp',
+  'cmaf.cpp',
+  'comms.cpp',
+  'config.cpp',
+  'dtsc.cpp',
+  'flv_tag.cpp',
+  'h264.cpp',
+  'h265.cpp',
+  'hls_support.cpp',
+  'http_parser.cpp',
+  'downloader.cpp',
+  'json.cpp',
+  'langcodes.cpp',
+  'mp4_adobe.cpp',
+  'mp4.cpp',
+  'mp4_dash.cpp',
+  'mp4_encryption.cpp',
+  'mp4_generic.cpp',
+  'mp4_ms.cpp',
+  'mpeg.cpp',
+  'nal.cpp',
+  'ogg.cpp',
+  'procs.cpp',
+  'rtmpchunks.cpp',
+  'rtp_fec.cpp',
+  'rtp.cpp',
+  'sdp.cpp',
+  'sdp_media.cpp',
+  'shared_memory.cpp',
+  'socket.cpp',
+  'stream.cpp',
+  'theora.cpp',
+  'timing.cpp',
+  'tinythread.cpp',
+  'ts_packet.cpp',
+  'ts_stream.cpp',
+  'util.cpp',
+  'vorbis.cpp',
+  'triggers.cpp',
+  'opus.cpp',
+  'riff.cpp',
+  'ebml.cpp',
+  'ebml_socketglue.cpp',
+  'url.cpp',
+  'urireader.cpp',
+  'websocket.cpp',
+  extra_code,
+  include_directories: incroot,
+  dependencies: ssl_deps,
+  install: true,
+)
+
+if have_srt
+  libmist_srt = library('mist_srt', 'socket_srt.cpp', include_directories: incroot, link_with: libmist, dependencies: libsrt, install: true)
+endif
+
diff --git a/lib/urireader.cpp b/lib/urireader.cpp
index 78f9c75a..bc690980 100644
--- a/lib/urireader.cpp
+++ b/lib/urireader.cpp
@@ -11,7 +11,7 @@
 
 namespace HTTP{
 
-#ifndef NOSSL
+#ifdef SSL
   inline bool s3CalculateSignature(std::string& signature, const std::string method, const std::string date, const std::string& requestPath, const std::string& accessKey, const std::string& secret) {
     std::string toSign = method + "\n\n\n" + date + "\n" + requestPath;
     unsigned char signatureBytes[MBEDTLS_MD_MAX_SIZE];
@@ -32,11 +32,11 @@ namespace HTTP{
     signature = "AWS " + accessKey + ":" + base64encoded;
     return true;
   }
-#endif // ifndef NOSSL
+#endif // ifdef SSL
 
 
   inline HTTP::URL injectHeaders(const HTTP::URL& url, const std::string & method, HTTP::Downloader & downer) {
-#ifndef NOSSL
+#ifdef SSL
     // Input url == s3+https://s3_key:secret@storage.googleapis.com/alexk-dms-upload-test/testvideo.ts
     // Transform to: 
     // url=https://storage.googleapis.com/alexk-dms-upload-test/testvideo.ts
@@ -61,7 +61,7 @@ namespace HTTP{
       }
       return newUrl;
     }
-#endif // ifndef NOSSL
+#endif // ifdef SSL
     return url;
   }
 
@@ -154,7 +154,7 @@ namespace HTTP{
     }
 
     // prepare for s3 and http
-#ifndef NOSSL
+#ifdef SSL
     // In case of s3 URI we prepare HTTP request with AWS authorization and rely on HTTP logic below
     if (myURI.protocol == "s3+https" || myURI.protocol == "s3+http"){
       // Check fallback to global credentials in env vars
@@ -177,7 +177,7 @@ namespace HTTP{
       myURI = injectHeaders(originalUrl, "", downer);
       // Do not return, continue to HTTP case
     }
-#endif // ifndef NOSSL
+#endif // ifdef SSL
 
     // HTTP, stream or regular download?
     if (myURI.protocol == "http" || myURI.protocol == "https"){
diff --git a/lsp/meson.build b/lsp/meson.build
new file mode 100644
index 00000000..e5a6b36a
--- /dev/null
+++ b/lsp/meson.build
@@ -0,0 +1,26 @@
+minified = files('minified.js')
+
+if get_option('LSP_MINIFY')
+    java = find_program('java', required: true)
+
+    closure_compiler = files('closure-compiler.jar')
+
+    minified = custom_target('lsp_gen_minified',output: 'minified.js', input: ['plugins/md5.js', 'plugins/cattablesort.js', 'mist.js'], command: [java, '-jar', closure_compiler, '--warning_level', 'QUIET', '@INPUT@'], capture: true)
+endif
+
+html_list = ['header.html',
+     'main.css',
+     'footer.html',
+     'plugins/jquery.js',
+     'plugins/jquery.flot.min.js',
+     'plugins/jquery.flot.time.min.js',
+     'plugins/jquery.qrcode.min.js',
+    ]
+
+html_files = files(html_list)
+html_files += minified
+
+if not get_option('NOGA')
+    html_files += files('analytics.js')
+endif
+
diff --git a/meson.build b/meson.build
new file mode 100644
index 00000000..fbb69aee
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,158 @@
+project('mistserver', 'cpp', default_options: ['cpp_std=gnu++03'])
+add_project_arguments(['-funsigned-char', '-D_LARGEFILE_SOURCE','-Wno-sign-compare', '-Wparentheses', '-Wno-non-virtual-dtor', '-Wno-strict-aliasing'], language: 'cpp')
+
+# Ensures the "mist" directory is in the include path
+incroot = include_directories('.')
+
+# Sets the RELEASE, if not set externally
+release = get_option('RELEASE')
+if release.contains('DEFAULT')
+    release = 'Generic_'+target_machine.cpu_family()
+endif
+release = release.strip()
+
+# Grab version number from git, if available
+# Falls back to a file called "VERSION" or the string "Unknown" otherwise
+rv = run_command('git', 'describe', '--tags', check: false)
+version = rv.stdout().strip()
+if rv.returncode() != 0
+  fs = import('fs') 
+  if fs.is_file('VERSION')
+    version = fs.read('VERSION').strip()
+  else 
+    version = 'Unknown'
+  endif
+endif
+
+# Handle all options
+string_opt = '-D@0@="@1@"'
+int_opt = '-D@0@=@1@'
+
+option_defines = [
+    string_opt.format('APPNAME', get_option('APPNAME')),
+    int_opt.format('DEBUG', get_option('DEBUG')),
+    string_opt.format('RELEASE' ,release),
+    string_opt.format('PACKAGE_VERSION' ,version),
+    int_opt.format('SHM_DATASIZE', get_option('DATASIZE')),
+    int_opt.format('STAT_CUTOFF', get_option('STAT_CUTOFF')),
+    int_opt.format('STATS_DELAY', get_option('STATS_DELAY')),
+    string_opt.format('UDP_API_HOST' ,get_option('UDP_API_HOST')),
+    int_opt.format('UDP_API_PORT', get_option('UDP_API_PORT')),
+]
+
+if not get_option('NOSHM')
+  option_defines += '-DSHM_ENABLED=1'
+else
+  message('Shared memory use is turned OFF')
+endif
+
+usessl = true
+if get_option('NOSSL')
+  message('SSL/TLS support is turned OFF')
+  usessl = false
+else
+  option_defines += '-DSSL=1'
+endif
+
+if not get_option('NOUPDATE')
+  option_defines += '-DUPDATER=1'
+endif
+
+if get_option('NOAUTH')
+  option_defines += '-DNOAUTH=1'
+endif
+
+if not get_option('DISKSERIAL').contains('DEFAULT')
+  option_defines += string_opt.format('DISKSERIAL',get_option('DISKSERIAL'))
+endif
+
+if not get_option('FILLER_DATA').contains('DEFAULT')
+  option_defines += string_opt.format('FILLER_DATA',get_option('FILLER_DATA'))
+endif
+
+if not get_option('SHARED_SECRET').contains('DEFAULT')
+  option_defines += string_opt.format('SHARED_SECRET',get_option('SHARED_SECRET'))
+endif
+
+if get_option('WITH_THREADNAMES')
+  option_defines += '-DWITH_THREADNAMES=1'
+endif
+
+if get_option('NOLLHLS')
+  option_defines += '-DNOLLHLS=1'
+endif
+
+add_project_arguments(option_defines, language: 'cpp')
+
+# End of options
+
+message('Building release @0@ for version @1@ @ debug level @2@'.format(release, version, get_option('DEBUG')))
+
+# Set dependencies
+
+ssl_deps = []
+
+libsrt = false
+if not get_option('NOSRT')
+  libsrt = dependency('srt', required: false)
+endif
+have_srt = not get_option('NOSRT') and libsrt.found()
+
+librist = false
+if not get_option('NORIST')
+  librist = dependency('librist', required: false)
+endif
+have_librist = not get_option('NORIST') and librist.found()
+
+if usessl
+  ccpp = meson.get_compiler('cpp')
+  mbedtls = ccpp.find_library('mbedtls')
+  mbedx509 = ccpp.find_library('mbedx509')
+  mbedcrypto = ccpp.find_library('mbedcrypto')
+  srtp2 = dependency('libsrtp2')
+  ssl_deps = [mbedtls, mbedx509, mbedcrypto, srtp2]
+endif
+
+# Set build targets
+
+executables = []
+
+# Web sources
+subdir('lsp')
+subdir('generated')
+
+# libmist
+subdir('lib')
+subdir('mist')
+
+# Binaries
+subdir('src')
+subdir('test')
+
+exec_tgts = []
+
+## This makes sure all (installable) executables are build in top level directory
+## Done because MistController expects its binaries to all be in the same directory
+foreach exec : executables
+  exec_tgts += executable(
+    exec.get('name'),
+    exec.get('sources'),
+    link_with: exec.get('link'),
+    dependencies: exec.get('deps'),
+    cpp_args: exec.get('defines'),
+    install: true,
+  )
+endforeach
+
+# Docs
+doxygen = find_program('doxygen', required: false)
+if doxygen.found()
+  doxyfile = configure_file(output: 'Doxyfile', input: 'Doxyfile.in', configuration: {
+    'PACKAGE_VERSION': version,
+    'RELEASE' : release,
+    'DOXY_LAYOUT': meson.project_source_root() + '/DoxygenLayout.xml',
+    'INPUT_DIRS': meson.project_source_root() + '/src ' + meson.project_source_root() + '/lib',
+  })
+  run_target('docs', command: [doxygen, doxyfile])
+endif
+
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 00000000..45c408bd
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,27 @@
+option('NOSHM', description: 'Disabled shared memory (falling back to shared temporary files)', type : 'boolean', value : false)
+option('NOSSL', description: 'Disable SSL/TLS support', type : 'boolean', value : false)
+option('NOUPDATE', description: 'Disable the updater', type : 'boolean', value : false)
+option('NOAUTH', description: 'Disable API authentication entirely (insecure!)', type : 'boolean', value : false)
+option('WITH_THREADNAMES', description: 'Enable fancy names for threads (not supported on all platforms)', type : 'boolean', value : false)
+option('NOLLHLS', description: 'Disable LLHLS support (falling back to plain HLS)', type : 'boolean', value : false)
+option('FILLER_DATA', description: 'Data used to as filler data in various protocols that use/need it', type: 'string', value: 'DEFAULT')
+option('SHARED_SECRET', description: '"Secret" string used to ask for customer-specific binaries from the update server', type: 'string', value: 'DEFAULT')
+option('UDP_API_HOST', description: 'Hostname the internal UDP API listens on', type: 'string', value: 'localhost')
+option('UDP_API_PORT', description: 'Port the internal UDP API listens on', type: 'integer', value: 4242)
+option('DISKSERIAL', description: 'Lock application to given disk serial number', type: 'string', value: 'DEFAULT')
+option('STATS_DELAY', description: 'Delay to apply to statistics, used to consistently handle segmented protocols', type: 'integer', value: 15)
+option('APPNAME', description: 'Name of the application', type: 'string', value: 'MistServer')
+option('DATASIZE', description: 'Size in mebibytes for live stream data pages', type: 'integer', value: 40)
+option('STAT_CUTOFF', description: 'Time in seconds that statistics history is kept in memory for', type: 'integer', value: 600)
+option('NORIST', description: 'Disable building RIST support, regardless of library being present (by default RIST is enabled if libraries are installed)', type : 'boolean', value : false)
+option('NOSRT', description: 'Disable building SRT support, regardless of library being present (by default SRT is enabled if libraries are installed)', type : 'boolean', value : false)
+option('RELEASE', description: 'Release string used in the reported version information', type: 'string', value: 'DEFAULT')
+option('DEBUG', description: 'Default debug level. Recommended value for development is 4, recommended value for production is 3', type: 'integer', value: 4)
+option('NOGA', description: 'Disables Google Analytics entirely in the LSP', type: 'boolean', value: false)
+option('LOAD_BALANCE', description: 'Build the load balancer (WIP)', type: 'boolean', value: false)
+option('WITH_AV', description: 'Build a generic libav-based input (not distributable!)', type: 'boolean', value: false)
+option('WITH_JPG', description: 'Build JPG thumbnailer output support (WIP)', type: 'boolean', value: false)
+option('WITH_SANITY', description: 'Enable MistOutSanityCheck output for testing purposes', type: 'boolean', value: false)
+option('LSP_MINIFY', description: 'Try to minify LSP JS via java closure-compiler, generally not needed unless changing JS code as a minified version is part of the repository already', type: 'boolean', value: false)
+option('LOCAL_GENERATORS', description: 'Attempts to find a locally-installed version of sourcery and make_html, instead of compiling it', type: 'boolean', value: false)
+
diff --git a/mist/meson.build b/mist/meson.build
new file mode 100644
index 00000000..67d9f98b
--- /dev/null
+++ b/mist/meson.build
@@ -0,0 +1,6 @@
+header_tgts = []
+
+foreach header : headers
+  header_tgts += custom_target('copy'+header, input: join_paths('../lib', header), output: header, command: ['cp', '@INPUT@', '@OUTPUT@'])
+endforeach
+
diff --git a/src/analysers/meson.build b/src/analysers/meson.build
new file mode 100644
index 00000000..9ca82f61
--- /dev/null
+++ b/src/analysers/meson.build
@@ -0,0 +1,40 @@
+
+analysers = [
+    {'name': 'RTMP', 'format': 'rtmp'},
+    {'name': 'FLV', 'format': 'flv'},
+    {'name': 'DTSC', 'format': 'dtsc'},
+    {'name': 'OGG', 'format': 'ogg'},
+    {'name': 'EBML', 'format': 'ebml'},
+    {'name': 'TS', 'format': 'ts'},
+    {'name': 'MP4', 'format': 'mp4'},
+    {'name': 'H264', 'format': 'h264'},
+    {'name': 'HLS', 'format': 'hls'},
+    {'name': 'RIFF', 'format': 'riff'},
+    {'name': 'RTSP', 'format': 'rtsp'},
+]
+
+foreach analyser : analysers
+  executables += { 'name': 'MistAnalyser'+analyser.get('name'),
+                 'sources' : [
+                    files('mist_analyse.cpp',
+                          'analyser.cpp',
+                          'analyser_'+analyser.get('format')+'.cpp'),
+                    header_tgts,
+                 ],
+                 'link': libmist,
+                 'defines': [
+                    string_opt.format('ANALYSERHEADER', 'analyser_'+analyser.get('format')+'.h'),
+                    '-DANALYSERTYPE=Analyser'+analyser.get('name')
+                 ],
+                 'deps': []
+                }
+endforeach
+
+executables += {
+  'name': 'MistTranslateH264', 
+  'sources' : [files('h264_translate.cpp'),  header_tgts],
+  'link': libmist, 
+  'defines': [],
+  'deps' : []
+}
+
diff --git a/src/controller/controller_limits.h b/src/controller/controller_limits.h
index 9b912868..427e27ec 100644
--- a/src/controller/controller_limits.h
+++ b/src/controller/controller_limits.h
@@ -3,14 +3,6 @@
 #include <mist/json.h>
 #include <string>
 
-/*LTS-START*/
-#ifdef GEOIP
-#include <GeoIP.h>
-#define GEOIPV4 "/usr/share/GeoIP/GeoIP.dat"
-#define GEOIPV6 "/usr/share/GeoIP/GeoIPv6.dat"
-#endif
-/*LTS-END*/
-
 namespace Controller{
   void checkStreamLimits(std::string streamName, long long currentKbps, long long connectedUsers);
   void checkServerLimits();
diff --git a/src/controller/meson.build b/src/controller/meson.build
new file mode 100644
index 00000000..682f424b
--- /dev/null
+++ b/src/controller/meson.build
@@ -0,0 +1,22 @@
+
+executables += {
+  'name': 'MistController', 
+  'sources' : [
+    files( 'controller.cpp',
+           'controller_updater.cpp',
+           'controller_streams.cpp',
+           'controller_storage.cpp',
+           'controller_connectors.cpp',
+           'controller_statistics.cpp',
+           'controller_limits.cpp',
+           'controller_capabilities.cpp',
+           'controller_uplink.cpp',
+           'controller_api.cpp',
+           'controller_push.cpp'),
+    header_tgts,
+    server_html],
+  'link': libmist, 
+  'defines': [],
+  'deps' : []
+}
+
diff --git a/src/input/meson.build b/src/input/meson.build
new file mode 100644
index 00000000..eb0de5e9
--- /dev/null
+++ b/src/input/meson.build
@@ -0,0 +1,86 @@
+inputs = [
+    {'name' : 'HLS', 'format' : 'hls'},
+    {'name' : 'DTSC', 'format' : 'dtsc'},
+    {'name' : 'MP3', 'format' : 'mp3'},
+    {'name' : 'FLV', 'format' : 'flv'},
+    {'name' : 'OGG', 'format' : 'ogg'},
+    {'name' : 'Buffer', 'format' : 'buffer'},
+    {'name' : 'H264', 'format' : 'h264'},
+    {'name' : 'EBML', 'format' : 'ebml'},
+    {'name' : 'ISMV', 'format' : 'ismv'},
+    {'name' : 'MP4', 'format' : 'mp4'},
+    {'name' : 'TS', 'format' : 'ts'},
+    {'name' : 'Folder', 'format' : 'folder'},
+    {'name' : 'Playlist', 'format' : 'playlist'},
+    {'name' : 'Balancer', 'format' : 'balancer'},
+    {'name' : 'RTSP', 'format' : 'rtsp'},
+    {'name' : 'SRT', 'format' : 'srt'},
+    {'name' : 'SDP', 'format' : 'sdp'},
+    {'name' : 'AAC', 'format' : 'aac'},
+]
+
+#Referenced by process targets
+input_ebml_cpp = files('input_ebml.cpp')
+input_cpp = files('input.cpp')
+
+if have_librist
+  inputs += {'name' : 'TSRIST', 'format' : 'tsrist', 'extra' : 'with_rist'}
+endif
+
+if have_srt
+  inputs += {'name' : 'TSSRT', 'format' : 'tssrt', 'extra' : 'with_srt'}
+endif
+
+av_libs = []
+
+if get_option('WITH_AV')
+  inputs += {'name' : 'AV', 'format' : 'av'}
+  av_libs = [
+    dependency('libavformat'),
+    dependency('libavcodec'),
+    dependency('libavutil'),
+  ]
+endif
+
+inputs_tgts = []
+
+foreach input : inputs
+  link_libs = [libmist]
+  deps = []
+
+  if input.has_key('extra')
+    if input.get('extra').contains('with_rist')
+      deps += librist
+    endif
+    if input.get('extra').contains('with_srt')
+      link_libs += libmist_srt
+      deps += libsrt
+    endif
+  endif
+  if input.get('name').contains('AV')
+    deps += av_libs
+  endif
+  if input.get('name').contains('HLS')
+    deps += ssl_deps
+  endif
+
+  executables += {
+    'name' : 'MistIn'+input.get('name'),
+    'sources' : [
+      files(
+        'mist_in.cpp',
+        'input.cpp',
+        'input_'+input.get('format')+'.cpp',
+      ),
+      io_cpp,
+      header_tgts
+    ],
+    'link' : link_libs,
+    'deps' : deps,
+    'inc': [],
+    'defines': [
+      string_opt.format('INPUTTYPE', 'input_'+input.get('format')+'.h')
+    ]
+  }
+endforeach
+
diff --git a/src/make_html.cpp b/src/make_html.cpp
new file mode 100644
index 00000000..014b7b7d
--- /dev/null
+++ b/src/make_html.cpp
@@ -0,0 +1,40 @@
+#include <cstdlib>
+#include <ios>
+#include <iostream>
+#include <fstream>
+#include <ostream>
+
+int main(int argc, char* argv[]) {
+    if (argc < 6) {
+        std::cerr << "ERROR EXPECTED MORE FILES" << std::endl;
+        return 1;
+    }
+
+    std::ofstream output(argv[1]);
+
+    std::ifstream header(argv[2]);
+    std::ifstream css(argv[3]);
+    std::ifstream footer(argv[4]);
+
+    if (!header.is_open() || !css.is_open() || !footer.is_open()) {
+        std::cerr << "ERROR Couldn't open file" << std::endl;
+        return 1;
+    }
+
+    output << header.rdbuf();
+    output << "<script>";
+    for (int i = 5; i < argc; i++) {
+        std::ifstream script(argv[i]);
+        if (!script.is_open()) {
+            std::cerr << "ERROR Couldn't open file" << std::endl;
+            return 1;
+        }
+        output << script.rdbuf();
+    }
+    output << "</script>";
+    output << "<style>" << css.rdbuf() << "</style>";
+    output << footer.rdbuf();
+    std::flush(output);
+    return 0;
+}
+
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 00000000..3d9147e2
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,17 @@
+io_cpp = files('io.cpp')
+
+subdir('analysers')
+subdir('utils')
+subdir('input')
+subdir('output')
+subdir('process')
+subdir('controller')
+
+executables += {
+  'name': 'MistSession',
+  'sources' : [files('session.cpp'),  header_tgts],
+  'link': libmist,
+  'defines': [],
+  'deps' : []
+}
+
diff --git a/src/output/meson.build b/src/output/meson.build
new file mode 100644
index 00000000..b741e3c6
--- /dev/null
+++ b/src/output/meson.build
@@ -0,0 +1,133 @@
+outputs = [
+    {'name' : 'RTMP',              'format' : 'rtmp'},
+    {'name' : 'DTSC',              'format' : 'dtsc'},
+    {'name' : 'OGG',               'format' : 'ogg',                'extra': ['http']},
+    {'name' : 'FLV',               'format' : 'flv',                'extra': ['http'] },
+    {'name' : 'HTTPMinimalServer', 'format' : 'http_minimalserver', 'extra': ['http']},
+    {'name' : 'MP4',               'format' : 'mp4',                'extra': ['http']},
+    {'name' : 'AAC',               'format' : 'aac',                'extra': ['http']},
+    {'name' : 'MP3',               'format' : 'mp3',                'extra': ['http']},
+    {'name' : 'H264',              'format' : 'h264',               'extra': ['http']},
+    {'name' : 'HDS',               'format' : 'hds',                'extra': ['http']},
+    {'name' : 'SRT',               'format' : 'srt',                'extra': ['http']},
+    {'name' : 'JSON',              'format' : 'json',               'extra': ['http']},
+    {'name' : 'TS',                'format' : 'ts',                 'extra': ['ts']},
+    {'name' : 'HTTPTS',            'format' : 'httpts',             'extra': ['http', 'ts']},
+    {'name' : 'HLS',               'format' : 'hls',                'extra': ['http', 'ts']},
+    {'name' : 'CMAF',              'format' : 'cmaf',               'extra': ['http']},
+    {'name' : 'EBML',              'format' : 'ebml',               'extra': ['http']},
+    {'name' : 'RTSP',              'format' : 'rtsp'},
+    {'name' : 'WAV',               'format' : 'wav',                'extra': ['http']},
+    {'name' : 'SDP',               'format' : 'sdp',                'extra': ['http']},
+]
+
+if usessl 
+  outputs += [
+    {'name' : 'HTTPS', 'format' : 'https'},
+    {'name' : 'WebRTC', 'format' : 'webrtc', 'extra': ['http','jpg']}
+  ]
+endif
+
+if have_librist
+  outputs += {'name' : 'TSRIST', 'format' : 'tsrist', 'extra': ['ts', 'debased', 'with_rist']}
+endif
+
+if have_srt
+  outputs += {'name' : 'TSSRT', 'format' : 'tssrt', 'extra': ['ts', 'debased', 'with_srt']}
+endif
+
+if get_option('WITH_JPG')
+  outputs += {'name' : 'JPG', 'format' : 'jpg', 'extra': ['http','jpg']}
+endif
+
+if get_option('WITH_SANITY')
+  outputs += {'name' : 'SanityCheck', 'format' : 'sanitycheck'}
+endif
+
+#Referenced by targets in process
+output_ebml_cpp = files('output_ebml.cpp')
+output_http_cpp = files('output_http.cpp')
+output_ts_base_cpp = files('output_ts_base.cpp')
+output_cpp = files('output.cpp')
+
+outputs_tgts = []
+
+foreach output : outputs 
+  link_libs = [libmist]
+  deps = []
+  base = files('mist_out.cpp')
+  tsBaseClass = 'Output'
+  extra_tgt_dep = []
+
+  sources = [
+    files('output.cpp',
+    'output_'+output.get('format')+'.cpp'),
+    io_cpp
+  ]
+
+  if output.has_key('extra')
+    extra = output.get('extra')
+    if not extra.contains('debased')
+      sources += base
+    endif
+    if extra.contains('http')
+      sources += files('output_http.cpp')
+      if extra.contains('ts')
+        tsBaseClass = 'HTTPOutput'
+      endif
+    endif
+    if extra.contains('jpg')
+      extra_tgt_dep = embed_tgts
+    endif
+    if extra.contains('ts')
+      sources += files('output_ts_base.cpp')
+    endif
+    if extra.contains('with_rist')
+      deps += librist
+    endif
+    if extra.contains('with_srt')
+      link_libs += libmist_srt
+      deps += libsrt
+    endif
+  else
+    sources += base
+  endif
+  if output.get('name').contains('HTTPS')
+    deps += ssl_deps
+  endif
+
+  executables += {
+    'name': 'MistOut'+output.get('name'),
+    'sources' : [
+      sources,
+      extra_tgt_dep,
+      header_tgts
+    ],
+    'link' : link_libs,
+    'deps' : deps,
+    'defines' : [
+      string_opt.format('OUTPUTTYPE', 'output_'+output.get('format')+'.h'),
+      '-DTS_BASECLASS='+tsBaseClass
+    ]
+  }
+endforeach
+
+executables += {
+  'name' : 'MistOutHTTP',
+  'sources' : [
+    files(
+      'mist_out.cpp',
+      'output.cpp',
+      'output_http.cpp',
+      'output_http_internal.cpp',
+    ),
+    io_cpp,
+    header_tgts,
+    embed_tgts,
+  ],
+  'link' : libmist,
+  'defines' :[
+    string_opt.format('OUTPUTTYPE', 'output_http_internal.h')
+  ],
+  'deps' : []
+}
diff --git a/src/process/meson.build b/src/process/meson.build
new file mode 100644
index 00000000..d36e9fa9
--- /dev/null
+++ b/src/process/meson.build
@@ -0,0 +1,50 @@
+process_common = static_library('mist_process_common',
+                            output_ebml_cpp,
+                            input_ebml_cpp,
+                            input_cpp,
+                            output_http_cpp,
+                            output_cpp,
+                            io_cpp,
+                            header_tgts,
+                            include_directories: incroot,
+                            install: false,
+)
+
+executables += {
+    'name' : 'MistProcFFMPEG',
+    'sources' : [
+        files('process_ffmpeg.cpp'),
+        header_tgts
+    ],
+    'link' : [libmist, process_common],
+    'deps' :[],
+    'defines': [],
+}
+
+executables += {
+    'name' : 'MistProcMKVExec',
+    'sources' : [
+        files('process_exec.cpp'),
+        header_tgts
+    ],
+    'link' : [libmist, process_common],
+    'deps' :[],
+    'defines': [],
+}
+
+executables += {
+    'name' : 'MistProcLivepeer',
+    'sources' : [
+        files('process_livepeer.cpp'),
+        input_cpp,
+        output_http_cpp,
+        output_ts_base_cpp,
+        output_cpp,
+        io_cpp,
+        header_tgts
+    ],
+    'link' : [libmist],
+    'deps' :[],
+    'defines': [],
+}
+
diff --git a/src/relaccxsampler.cpp b/src/relaccxsampler.cpp
deleted file mode 100644
index 59f61c6c..00000000
--- a/src/relaccxsampler.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <mist/defines.h>
-#include <mist/util.h>
-
-#include <iostream>
-
-int main(){
-  char storage[5000000]; // 5mb
-  Util::RelAccX tmp(storage, false);
-
-  tmp.addField("vod", RAX_UINT);
-  tmp.addField("live", RAX_UINT);
-  tmp.addField("source", RAX_STRING, 512);
-  tmp.addField("bufferwindow", RAX_64UINT);
-  tmp.addField("bootmsoffset", RAX_64UINT);
-  tmp.setRCount(1);
-  tmp.setReady();
-
-  std::cout << tmp.toPrettyString() << std::endl;
-
-  return 0;
-}
diff --git a/src/utils/meson.build b/src/utils/meson.build
new file mode 100644
index 00000000..c69275aa
--- /dev/null
+++ b/src/utils/meson.build
@@ -0,0 +1,29 @@
+
+utils = [
+#    {'name': 'Stats',   'file': 'stats'},
+    {'name': 'META',    'file': 'meta'},
+    {'name': 'RAX',     'file': 'rax'},
+    {'name': 'AMF',     'file': 'amf'},
+    {'name': 'Certbot', 'file': 'certbot'},
+    {'name': 'Nuke',    'file': 'nuke'},
+]
+
+if get_option('LOAD_BALANCE')
+  utils += {'name': 'Load', 'file': 'load'}
+endif
+
+utils_tgts = []
+
+foreach util : utils
+  executables += {
+    'name': 'MistUtil'+util.get('name'),
+    'sources' : [
+      files('util_'+util.get('file')+'.cpp'),
+      header_tgts
+    ],
+    'link' : libmist,
+    'deps' : [],
+    'defines' :[],
+  }
+endforeach
+
diff --git a/test/downloader.cpp b/test/downloader.cpp
index c0ad0817..ab348ffa 100644
--- a/test/downloader.cpp
+++ b/test/downloader.cpp
@@ -18,8 +18,9 @@ int main(int argc, char **argv){
   HTTP::URL url(argv[1]);
   if (d.get(url, 10, callback)){
     std::cerr << "Download success!" << std::endl;
-  }else{
-    std::cerr << "Download fail!" << std::endl;
+    return 0;
   }
-  return 0;
+  std::cerr << "Download fail!" << std::endl;
+  return 1;
 }
+
diff --git a/test/json.cpp b/test/json.cpp
index fb504a4a..ff103827 100644
--- a/test/json.cpp
+++ b/test/json.cpp
@@ -11,3 +11,4 @@ int main(int argc, char **argv){
   std::cout << J.toPrettyString() << std::endl;
   return 0;
 }
+
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 00000000..0f678f2d
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,23 @@
+
+# Testing binaries that are not unit tests, but intended for manual use
+
+urltest = executable('urltest', 'url.cpp', include_directories: incroot, link_with: libmist)
+logtest = executable('logtest', 'log.cpp', include_directories: incroot, link_with: libmist)
+downloadertest = executable('downloadertest', 'downloader.cpp', include_directories: incroot, link_with: libmist)
+urireadertest = executable('urireadertest', 'urireader.cpp', include_directories: incroot, link_with: libmist, dependencies: ssl_deps)
+jsontest = executable('jsontest', 'json.cpp', include_directories: incroot, link_with: libmist)
+resolvetest = executable('resolvetest', 'resolve.cpp', include_directories: incroot, link_with: libmist, dependencies: ssl_deps)
+streamstatustest = executable('streamstatustest', 'status.cpp', include_directories: incroot, link_with: libmist)
+websockettest = executable('websockettest', 'websocket.cpp', include_directories: incroot, link_with: libmist)
+
+# Actual unit tests
+
+dtsc_sizing_test = executable('dtsc_sizing_test', 'dtsc_sizing.cpp', include_directories: incroot, link_with: libmist)
+test('DTSC Sizing Test', dtsc_sizing_test)
+
+bitwritertest = executable('bitwritertest', 'bitwriter.cpp', include_directories: incroot, link_with: libmist)
+test('bitWriter Test', bitwritertest)
+
+#abst_test = executable('abst_test', 'abst_test.cpp', include_directories: incroot, link_with: libmist)
+#test('MP4::ABST Test', abst_test)
+