passenger 5.3.4 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (283) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +69 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/README.md +2 -1
  5. data/Rakefile +0 -5
  6. data/build/agent.rb +6 -3
  7. data/build/cxx_tests.rb +28 -19
  8. data/build/integration_tests.rb +6 -2
  9. data/build/misc.rb +2 -1
  10. data/build/packaging.rb +2 -0
  11. data/build/support/cplusplus.rb +2 -2
  12. data/build/support/cxx_dependency_map.rb +2651 -2189
  13. data/dev/colorize-logs +272 -0
  14. data/dev/show-latest-crashlog-dir +27 -0
  15. data/resources/templates/standalone/http.erb +2 -0
  16. data/resources/templates/standalone/server.erb +1 -0
  17. data/src/agent/AgentMain.cpp +4 -0
  18. data/src/agent/Core/AdminPanelConnector.h +6 -6
  19. data/src/agent/Core/ApiServer.h +4 -4
  20. data/src/agent/Core/ApplicationPool/BasicProcessInfo.h +2 -2
  21. data/src/agent/Core/ApplicationPool/Context.h +5 -1
  22. data/src/agent/Core/ApplicationPool/Group/InternalUtils.cpp +2 -2
  23. data/src/agent/Core/ApplicationPool/Group/LifetimeAndBasics.cpp +5 -0
  24. data/src/agent/Core/ApplicationPool/Group/Miscellaneous.cpp +2 -1
  25. data/src/agent/Core/ApplicationPool/Group/OutOfBandWork.cpp +3 -3
  26. data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +1 -1
  27. data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +13 -20
  28. data/src/agent/Core/ApplicationPool/Group.h +4 -2
  29. data/src/agent/Core/ApplicationPool/Implementation.cpp +5 -5
  30. data/src/agent/Core/ApplicationPool/Options.h +42 -38
  31. data/src/agent/Core/ApplicationPool/Pool/GroupUtils.cpp +2 -1
  32. data/src/agent/Core/ApplicationPool/Pool.h +4 -4
  33. data/src/agent/Core/ApplicationPool/Process.h +13 -15
  34. data/src/agent/Core/ApplicationPool/Socket.h +5 -5
  35. data/src/agent/Core/ApplicationPool/TestSession.h +3 -3
  36. data/src/agent/Core/Config.h +50 -10
  37. data/src/agent/Core/ConfigChange.cpp +13 -1
  38. data/src/agent/Core/Controller/Config.h +41 -17
  39. data/src/agent/Core/Controller/ForwardResponse.cpp +4 -0
  40. data/src/agent/Core/Controller/InitRequest.cpp +14 -8
  41. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +5 -0
  42. data/src/agent/Core/Controller/SendRequest.cpp +9 -9
  43. data/src/agent/Core/Controller/TurboCaching.h +2 -2
  44. data/src/agent/Core/Controller.h +7 -5
  45. data/src/agent/Core/CoreMain.cpp +204 -60
  46. data/src/agent/Core/OptionParser.h +20 -3
  47. data/src/agent/Core/ResponseCache.h +3 -3
  48. data/src/agent/Core/SecurityUpdateChecker.h +4 -2
  49. data/src/agent/Core/SpawningKit/Config/AutoGeneratedCode.h +1 -1
  50. data/src/agent/Core/SpawningKit/Config.h +3 -2
  51. data/src/agent/Core/SpawningKit/Context.h +8 -2
  52. data/src/agent/Core/SpawningKit/DirectSpawner.h +4 -4
  53. data/src/agent/Core/SpawningKit/DummySpawner.h +3 -3
  54. data/src/agent/Core/SpawningKit/ErrorRenderer.h +1 -1
  55. data/src/agent/Core/SpawningKit/Exceptions.h +21 -14
  56. data/src/agent/Core/SpawningKit/Factory.h +1 -1
  57. data/src/agent/Core/SpawningKit/Handshake/BackgroundIOCapturer.h +1 -1
  58. data/src/agent/Core/SpawningKit/Handshake/Perform.h +14 -2
  59. data/src/agent/Core/SpawningKit/Handshake/Prepare.h +3 -3
  60. data/src/agent/Core/SpawningKit/Handshake/WorkDir.h +1 -1
  61. data/src/agent/Core/SpawningKit/Journey.h +4 -5
  62. data/src/agent/Core/SpawningKit/PipeWatcher.h +1 -1
  63. data/src/agent/Core/SpawningKit/README.md +34 -17
  64. data/src/agent/Core/SpawningKit/Result/AutoGeneratedCode.h +1 -1
  65. data/src/agent/Core/SpawningKit/Result.h +20 -8
  66. data/src/agent/Core/SpawningKit/SmartSpawner.h +7 -7
  67. data/src/agent/Core/SpawningKit/Spawner.h +25 -8
  68. data/src/agent/Core/SpawningKit/UserSwitchingRules.h +17 -7
  69. data/src/agent/Core/TelemetryCollector.h +681 -0
  70. data/src/agent/ExecHelper/ExecHelperMain.cpp +1 -1
  71. data/src/agent/FileReadHelper/FileReadHelperMain.cpp +198 -0
  72. data/src/agent/README.md +1 -1
  73. data/src/agent/Shared/ApiAccountUtils.h +1 -1
  74. data/src/agent/Shared/ApiServerUtils.h +3 -3
  75. data/src/agent/Shared/ApplicationPoolApiKey.h +2 -2
  76. data/src/agent/Shared/Fundamentals/AbortHandler.cpp +324 -98
  77. data/src/agent/Shared/Fundamentals/AbortHandler.h +31 -4
  78. data/src/agent/Shared/Fundamentals/Initialization.cpp +4 -5
  79. data/src/agent/Shared/Fundamentals/Initialization.h +9 -1
  80. data/src/agent/SpawnEnvSetupper/SpawnEnvSetupperMain.cpp +1 -1
  81. data/src/agent/SystemMetrics/SystemMetricsMain.cpp +4 -3
  82. data/src/agent/TempDirToucher/TempDirToucherMain.cpp +3 -3
  83. data/src/agent/Watchdog/ApiServer.h +3 -3
  84. data/src/agent/Watchdog/Config.h +24 -5
  85. data/src/agent/Watchdog/CoreWatcher.cpp +2 -2
  86. data/src/agent/Watchdog/WatchdogMain.cpp +97 -28
  87. data/src/apache2_module/Config.cpp +14 -14
  88. data/src/apache2_module/Config.h +8 -16
  89. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +510 -481
  90. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp.cxxcodebuilder +39 -17
  91. data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +5 -0
  92. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +69 -1
  93. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp.cxxcodebuilder +31 -1
  94. data/src/apache2_module/ConfigGeneral/Common.h +45 -0
  95. data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp +17 -1
  96. data/src/apache2_module/DirConfig/AutoGeneratedCreateFunction.cpp.cxxcodebuilder +16 -1
  97. data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp +19 -5
  98. data/src/apache2_module/DirConfig/AutoGeneratedHeaderSerialization.cpp.cxxcodebuilder +26 -9
  99. data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp +19 -1
  100. data/src/apache2_module/DirConfig/AutoGeneratedManifestGeneration.cpp.cxxcodebuilder +10 -1
  101. data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp +14 -1
  102. data/src/apache2_module/DirConfig/AutoGeneratedMergeFunction.cpp.cxxcodebuilder +11 -1
  103. data/src/apache2_module/DirConfig/AutoGeneratedStruct.h +36 -1
  104. data/src/apache2_module/DirConfig/AutoGeneratedStruct.h.cxxcodebuilder +34 -1
  105. data/src/apache2_module/DirectoryMapper.h +36 -37
  106. data/src/apache2_module/Hooks.cpp +27 -8
  107. data/src/apache2_module/ServerConfig/AutoGeneratedManifestGeneration.cpp +20 -0
  108. data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h +48 -1
  109. data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h.cxxcodebuilder +36 -1
  110. data/src/cxx_supportlib/{Utils → Algorithms}/Hasher.cpp +2 -2
  111. data/src/cxx_supportlib/{Utils → Algorithms}/Hasher.h +4 -4
  112. data/src/cxx_supportlib/AppLocalConfigFileUtils.h +148 -0
  113. data/src/cxx_supportlib/AppTypeDetector/CBindings.cpp +147 -0
  114. data/src/cxx_supportlib/AppTypeDetector/CBindings.h +75 -0
  115. data/src/cxx_supportlib/{AppTypes.h → AppTypeDetector/Detector.h} +92 -131
  116. data/src/cxx_supportlib/ConfigKit/README.md +90 -2
  117. data/src/cxx_supportlib/ConfigKit/Schema.h +60 -15
  118. data/src/cxx_supportlib/ConfigKit/Store.h +129 -5
  119. data/src/cxx_supportlib/Constants.h +1 -1
  120. data/src/cxx_supportlib/{Utils → DataStructures}/HashMap.h +4 -4
  121. data/src/cxx_supportlib/DataStructures/HashedStaticString.h +5 -5
  122. data/src/cxx_supportlib/DataStructures/LString.h +3 -3
  123. data/src/cxx_supportlib/{Utils → DataStructures}/StringMap.h +36 -36
  124. data/src/cxx_supportlib/FileTools/FileManip.cpp +1 -1
  125. data/src/cxx_supportlib/FileTools/PathManip.cpp +2 -2
  126. data/src/cxx_supportlib/FileTools/PathSecurityCheck.cpp +1 -1
  127. data/src/cxx_supportlib/Hooks.h +2 -2
  128. data/src/cxx_supportlib/{Utils → IOTools}/BufferedIO.h +5 -5
  129. data/src/cxx_supportlib/{Utils → IOTools}/IOUtils.cpp +4 -3
  130. data/src/cxx_supportlib/{Utils → IOTools}/IOUtils.h +3 -3
  131. data/src/cxx_supportlib/{Utils → IOTools}/MessageIO.h +7 -7
  132. data/src/cxx_supportlib/{MessageReadersWriters.h → IOTools/MessageSerialization.h} +5 -5
  133. data/src/cxx_supportlib/InstanceDirectory.h +4 -4
  134. data/src/cxx_supportlib/Integrations/LibevJsonUtils.h +3 -3
  135. data/src/cxx_supportlib/{Utils → JsonTools}/JsonUtils.h +5 -5
  136. data/src/cxx_supportlib/LoggingKit/Context.h +2 -2
  137. data/src/cxx_supportlib/LoggingKit/Implementation.cpp +3 -3
  138. data/src/cxx_supportlib/MemoryKit/mbuf.cpp +2 -2
  139. data/src/cxx_supportlib/ProcessManagement/Ruby.cpp +3 -3
  140. data/src/cxx_supportlib/ProcessManagement/Ruby.h +7 -2
  141. data/src/cxx_supportlib/ProcessManagement/Spawn.cpp +19 -12
  142. data/src/cxx_supportlib/ProcessManagement/Spawn.h +21 -2
  143. data/src/cxx_supportlib/ProcessManagement/Utils.h +10 -0
  144. data/src/cxx_supportlib/RandomGenerator.h +2 -2
  145. data/src/cxx_supportlib/ResourceLocator.h +1 -1
  146. data/src/cxx_supportlib/{Crypto.cpp → SecurityKit/Crypto.cpp} +4 -4
  147. data/src/cxx_supportlib/{Crypto.h → SecurityKit/Crypto.h} +4 -4
  148. data/src/cxx_supportlib/{Utils → SecurityKit}/MemZeroGuard.h +0 -0
  149. data/src/cxx_supportlib/ServerKit/AcceptLoadBalancer.h +2 -2
  150. data/src/cxx_supportlib/ServerKit/Channel.h +1 -1
  151. data/src/cxx_supportlib/ServerKit/ClientRef.h +17 -7
  152. data/src/cxx_supportlib/ServerKit/Context.h +2 -2
  153. data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +1 -1
  154. data/src/cxx_supportlib/ServerKit/HttpHeaderParser.h +3 -3
  155. data/src/cxx_supportlib/ServerKit/HttpHeaderParserState.h +2 -2
  156. data/src/cxx_supportlib/ServerKit/HttpRequestRef.h +17 -7
  157. data/src/cxx_supportlib/ServerKit/HttpServer.h +16 -10
  158. data/src/cxx_supportlib/ServerKit/Server.h +3 -4
  159. data/src/cxx_supportlib/{Utils → StrIntTools}/DateParsing.h +5 -5
  160. data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtils.cpp +3 -3
  161. data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtils.h +0 -0
  162. data/src/cxx_supportlib/{Utils → StrIntTools}/StrIntUtilsNoStrictAliasing.cpp +12 -12
  163. data/src/cxx_supportlib/{Utils → StrIntTools}/StringScanning.h +5 -5
  164. data/src/cxx_supportlib/{Utils → StrIntTools}/Template.h +30 -5
  165. data/src/cxx_supportlib/SystemTools/ContainerHelpers.h +88 -0
  166. data/src/cxx_supportlib/{Utils → SystemTools}/ProcessMetricsCollector.h +15 -12
  167. data/src/cxx_supportlib/{Utils → SystemTools}/SystemMetricsCollector.h +3 -3
  168. data/src/cxx_supportlib/{Utils → SystemTools}/SystemTime.cpp +1 -1
  169. data/src/cxx_supportlib/{Utils → SystemTools}/SystemTime.h +0 -0
  170. data/src/cxx_supportlib/SystemTools/UserDatabase.h +1 -1
  171. data/src/cxx_supportlib/Utils/CachedFileStat.hpp +3 -3
  172. data/src/cxx_supportlib/Utils/Curl.h +2 -2
  173. data/src/cxx_supportlib/Utils/FileChangeChecker.h +2 -2
  174. data/src/cxx_supportlib/Utils/MessagePassing.h +1 -1
  175. data/src/cxx_supportlib/Utils/SpeedMeter.h +2 -2
  176. data/src/cxx_supportlib/Utils/Timer.h +2 -2
  177. data/src/cxx_supportlib/Utils/VariantMap.h +3 -3
  178. data/src/cxx_supportlib/Utils.cpp +2 -2
  179. data/src/cxx_supportlib/WatchdogLauncher.h +3 -3
  180. data/src/cxx_supportlib/WebSocketCommandReverseServer.h +1 -1
  181. data/src/cxx_supportlib/WrapperRegistry/CBindings.cpp +85 -0
  182. data/src/cxx_supportlib/{Utils/MemoryBarrier.h → WrapperRegistry/CBindings.h} +30 -27
  183. data/src/cxx_supportlib/WrapperRegistry/Entry.h +112 -0
  184. data/src/cxx_supportlib/WrapperRegistry/README.md +37 -0
  185. data/src/cxx_supportlib/WrapperRegistry/Registry.h +309 -0
  186. data/src/cxx_supportlib/vendor-modified/psg_sysqueue.h +3 -0
  187. data/src/helper-scripts/download_binaries/extconf.rb +6 -2
  188. data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +32 -0
  189. data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +12 -0
  190. data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +36 -0
  191. data/src/nginx_module/Configuration.c +23 -3
  192. data/src/nginx_module/ContentHandler.c +331 -32
  193. data/src/nginx_module/ContentHandler.h +8 -3
  194. data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +10 -0
  195. data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +27 -0
  196. data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +3 -0
  197. data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +7 -0
  198. data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c +11 -0
  199. data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c +23 -0
  200. data/src/nginx_module/MainConfig/AutoGeneratedStruct.h +8 -0
  201. data/src/nginx_module/config +2 -1
  202. data/src/nginx_module/ngx_http_passenger_module.c +9 -3
  203. data/src/nginx_module/ngx_http_passenger_module.h +10 -3
  204. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +19 -0
  205. data/src/ruby_supportlib/phusion_passenger/common_library.rb +19 -16
  206. data/src/ruby_supportlib/phusion_passenger/config/agent_compiler.rb +4 -4
  207. data/src/ruby_supportlib/phusion_passenger/config/download_agent_command.rb +6 -2
  208. data/src/ruby_supportlib/phusion_passenger/config/download_nginx_engine_command.rb +6 -2
  209. data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +1 -1
  210. data/src/ruby_supportlib/phusion_passenger/message_channel.rb +2 -2
  211. data/src/ruby_supportlib/phusion_passenger/native_support.rb +7 -3
  212. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +29 -0
  213. data/src/ruby_supportlib/phusion_passenger/packaging.rb +20 -19
  214. data/src/ruby_supportlib/phusion_passenger/platform_info/apache.rb +22 -4
  215. data/src/ruby_supportlib/phusion_passenger/platform_info/ruby.rb +33 -13
  216. data/src/ruby_supportlib/phusion_passenger/standalone/app_finder.rb +1 -0
  217. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +22 -2
  218. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +4 -1
  219. data/src/ruby_supportlib/phusion_passenger.rb +7 -5
  220. data/src/schema_printer/SchemaPrinterMain.cpp +2 -0
  221. metadata +40 -89
  222. data/.editorconfig +0 -134
  223. data/CODE_OF_CONDUCT.md +0 -52
  224. data/dev/boost-patches/0001-Patch-boost-thread-so-that-oxt-thread-can-use-it.patch +0 -48
  225. data/dev/boost-patches/0002-Make-boost-thread_interrupted-derive-from-oxt-tracab.patch +0 -33
  226. data/dev/boost-patches/0003-Disable-a-Clang-pragma-to-prevent-warnings-on-OS-X.patch +0 -25
  227. data/dev/ci/README.md +0 -134
  228. data/dev/ci/lib/functions.sh +0 -129
  229. data/dev/ci/lib/set-container-envvars.sh +0 -53
  230. data/dev/ci/lib/setup-container.sh +0 -46
  231. data/dev/ci/run-tests-natively +0 -24
  232. data/dev/ci/run-tests-with-docker +0 -42
  233. data/dev/ci/scripts/debug-console-wrapper.sh +0 -29
  234. data/dev/ci/scripts/docker-entrypoint-stage2.sh +0 -17
  235. data/dev/ci/scripts/docker-entrypoint.sh +0 -17
  236. data/dev/ci/scripts/inituidgid +0 -17
  237. data/dev/ci/scripts/run-tests-natively-stage2.sh +0 -17
  238. data/dev/ci/scripts/setup-host-natively.sh +0 -11
  239. data/dev/ci/setup-host +0 -56
  240. data/dev/ci/tests/apache2/run +0 -6
  241. data/dev/ci/tests/apache2/setup +0 -4
  242. data/dev/ci/tests/binaries/Jenkinsfile +0 -105
  243. data/dev/ci/tests/binaries/build-linux +0 -38
  244. data/dev/ci/tests/binaries/build-macos +0 -40
  245. data/dev/ci/tests/binaries/prepare-macos +0 -38
  246. data/dev/ci/tests/binaries/test-linux +0 -45
  247. data/dev/ci/tests/binaries/test-macos +0 -38
  248. data/dev/ci/tests/cxx/run +0 -9
  249. data/dev/ci/tests/cxx/setup +0 -4
  250. data/dev/ci/tests/debian/Jenkinsfile +0 -89
  251. data/dev/ci/tests/debian/run +0 -60
  252. data/dev/ci/tests/nginx/run +0 -5
  253. data/dev/ci/tests/nginx/setup +0 -4
  254. data/dev/ci/tests/nginx-dynamic/run +0 -20
  255. data/dev/ci/tests/nginx-dynamic/setup +0 -4
  256. data/dev/ci/tests/nodejs/run +0 -4
  257. data/dev/ci/tests/nodejs/setup +0 -4
  258. data/dev/ci/tests/rpm/Jenkinsfile +0 -68
  259. data/dev/ci/tests/rpm/run +0 -63
  260. data/dev/ci/tests/ruby/run +0 -4
  261. data/dev/ci/tests/ruby/setup +0 -4
  262. data/dev/ci/tests/source-packaging/run +0 -4
  263. data/dev/ci/tests/source-packaging/setup +0 -4
  264. data/dev/ci/tests/standalone/run +0 -4
  265. data/dev/ci/tests/standalone/setup +0 -4
  266. data/dev/configkit-schemas/index.json +0 -1748
  267. data/dev/configkit-schemas/update_schema_inline_comments.rb +0 -118
  268. data/dev/rack.test/config.ru +0 -5
  269. data/dev/rack.test/public/asset.txt +0 -1
  270. data/dev/vagrant/apache_default_site.conf +0 -35
  271. data/dev/vagrant/apache_passenger.conf +0 -5
  272. data/dev/vagrant/apache_passenger.load +0 -1
  273. data/dev/vagrant/apache_ports.conf +0 -24
  274. data/dev/vagrant/apache_rack_test.conf +0 -9
  275. data/dev/vagrant/bashrc +0 -23
  276. data/dev/vagrant/nginx.conf +0 -39
  277. data/dev/vagrant/nginx_rakefile +0 -33
  278. data/dev/vagrant/nginx_start +0 -32
  279. data/dev/vagrant/provision.sh +0 -117
  280. data/dev/vagrant/sudoers.conf +0 -5
  281. data/resources/templates/error_renderer/.editorconfig +0 -19
  282. data/src/cxx_supportlib/AppTypes.cpp +0 -109
  283. data/src/cxx_supportlib/vendor-modified/SmallVector.h +0 -653
@@ -0,0 +1,681 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2018 Phusion Holding B.V.
4
+ *
5
+ * "Passenger", "Phusion Passenger" and "Union Station" are registered
6
+ * trademarks of Phusion Holding B.V.
7
+ *
8
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ * of this software and associated documentation files (the "Software"), to deal
10
+ * in the Software without restriction, including without limitation the rights
11
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ * copies of the Software, and to permit persons to whom the Software is
13
+ * furnished to do so, subject to the following conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be included in
16
+ * all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ * THE SOFTWARE.
25
+ */
26
+ #ifndef _PASSENGER_TELEMETRY_COLLECTOR_H_
27
+ #define _PASSENGER_TELEMETRY_COLLECTOR_H_
28
+
29
+ #include <string>
30
+ #include <vector>
31
+ #include <limits>
32
+ #include <cstddef>
33
+ #include <cstdlib>
34
+ #include <cassert>
35
+
36
+ #include <boost/cstdint.hpp>
37
+ #include <boost/bind.hpp>
38
+ #include <oxt/thread.hpp>
39
+ #include <oxt/backtrace.hpp>
40
+
41
+ #include <curl/curl.h>
42
+
43
+ #include <Constants.h>
44
+ #include <Exceptions.h>
45
+ #include <Core/Controller.h>
46
+ #include <LoggingKit/LoggingKit.h>
47
+ #include <ConfigKit/ConfigKit.h>
48
+ #include <Utils/Curl.h>
49
+ #include <StrIntTools/StrIntUtils.h>
50
+
51
+ namespace Passenger {
52
+ namespace Core {
53
+
54
+ using namespace std;
55
+
56
+
57
+ class TelemetryCollector {
58
+ public:
59
+ /*
60
+ * BEGIN ConfigKit schema: Passenger::Core::TelemetryCollector::Schema
61
+ * (do not edit: following text is automatically generated
62
+ * by 'rake configkit_schemas_inline_comments')
63
+ *
64
+ * ca_certificate_path string - -
65
+ * debug_curl boolean - default(false)
66
+ * disabled boolean - default(false)
67
+ * final_run_timeout unsigned integer - default(5)
68
+ * first_interval unsigned integer - default(7200)
69
+ * interval unsigned integer - default(21600)
70
+ * interval_jitter unsigned integer - default(7200)
71
+ * proxy_url string - -
72
+ * timeout unsigned integer - default(180)
73
+ * url string - default("https://anontelemetry.phusionpassenger.com/v1/collect.json")
74
+ * verify_server boolean - default(true)
75
+ *
76
+ * END
77
+ */
78
+ class Schema: public ConfigKit::Schema {
79
+ private:
80
+ static void validateProxyUrl(const ConfigKit::Store &config, vector<ConfigKit::Error> &errors) {
81
+ if (config["proxy_url"].isNull()) {
82
+ return;
83
+ }
84
+ if (config["proxy_url"].asString().empty()) {
85
+ errors.push_back(ConfigKit::Error("'{{proxy_url}}', if specified, may not be empty"));
86
+ return;
87
+ }
88
+
89
+ try {
90
+ prepareCurlProxy(config["proxy_url"].asString());
91
+ } catch (const ArgumentException &e) {
92
+ errors.push_back(ConfigKit::Error(
93
+ P_STATIC_STRING("'{{proxy_url}}': ")
94
+ + e.what()));
95
+ }
96
+ }
97
+
98
+ public:
99
+ Schema() {
100
+ using namespace ConfigKit;
101
+
102
+ add("disabled", BOOL_TYPE, OPTIONAL, false);
103
+ add("url", STRING_TYPE, OPTIONAL, "https://anontelemetry.phusionpassenger.com/v1/collect.json");
104
+ // Should be in the form: scheme://user:password@proxy_host:proxy_port
105
+ add("proxy_url", STRING_TYPE, OPTIONAL);
106
+ add("ca_certificate_path", STRING_TYPE, OPTIONAL);
107
+ add("verify_server", BOOL_TYPE, OPTIONAL, true);
108
+ add("first_interval", UINT_TYPE, OPTIONAL, 2 * 60 * 60);
109
+ add("interval", UINT_TYPE, OPTIONAL, 6 * 60 * 60);
110
+ add("interval_jitter", UINT_TYPE, OPTIONAL, 2 * 60 * 60);
111
+ add("debug_curl", BOOL_TYPE, OPTIONAL, false);
112
+ add("timeout", UINT_TYPE, OPTIONAL, 180);
113
+ add("final_run_timeout", UINT_TYPE, OPTIONAL, 5);
114
+
115
+ addValidator(validateProxyUrl);
116
+
117
+ finalize();
118
+ }
119
+ };
120
+
121
+ struct ConfigRealization {
122
+ CurlProxyInfo proxyInfo;
123
+ string url;
124
+ string caCertificatePath;
125
+
126
+ ConfigRealization(const ConfigKit::Store &config)
127
+ : proxyInfo(prepareCurlProxy(config["proxy_url"].asString())),
128
+ url(config["url"].asString()),
129
+ caCertificatePath(config["ca_certificate_path"].asString())
130
+ { }
131
+
132
+ void swap(ConfigRealization &other) BOOST_NOEXCEPT_OR_NOTHROW {
133
+ proxyInfo.swap(other.proxyInfo);
134
+ url.swap(other.url);
135
+ caCertificatePath.swap(other.caCertificatePath);
136
+ }
137
+ };
138
+
139
+ struct ConfigChangeRequest {
140
+ boost::scoped_ptr<ConfigKit::Store> config;
141
+ boost::scoped_ptr<ConfigRealization> configRlz;
142
+ };
143
+
144
+ struct TelemetryData {
145
+ vector<boost::uint64_t> requestsHandled;
146
+ MonotonicTimeUsec timestamp;
147
+ };
148
+
149
+ private:
150
+ /*
151
+ * Since the telemetry collector runs in a separate thread,
152
+ * and the configuration can change while the collector is active,
153
+ * we make a copy of the current configuration at the beginning
154
+ * of each collection cycle.
155
+ */
156
+ struct SessionState {
157
+ ConfigKit::Store config;
158
+ ConfigRealization configRlz;
159
+
160
+ SessionState(const ConfigKit::Store &currentConfig,
161
+ const ConfigRealization &currentConfigRlz)
162
+ : config(currentConfig),
163
+ configRlz(currentConfigRlz)
164
+ { }
165
+ };
166
+
167
+ mutable boost::mutex configSyncher;
168
+ ConfigKit::Store config;
169
+ ConfigRealization configRlz;
170
+ TelemetryData lastTelemetryData;
171
+ oxt::thread *collectorThread;
172
+
173
+ void threadMain() {
174
+ TRACE_POINT();
175
+
176
+ {
177
+ // Sleep for a short while to allow interruption during the Apache integration
178
+ // double startup procedure, this prevents running the update check twice
179
+ boost::unique_lock<boost::mutex> l(configSyncher);
180
+ ConfigKit::Store config(this->config);
181
+ l.unlock();
182
+
183
+ unsigned int backoffSec = config["first_interval"].asUInt()
184
+ + calculateIntervalJitter(config);
185
+ P_DEBUG("Next anonymous telemetry collection in " <<
186
+ distanceOfTimeInWords(SystemTime::get() + backoffSec));
187
+ boost::this_thread::sleep_for(boost::chrono::seconds(backoffSec));
188
+ }
189
+
190
+ while (!boost::this_thread::interruption_requested()) {
191
+ UPDATE_TRACE_POINT();
192
+ unsigned int backoffSec = 0;
193
+ try {
194
+ backoffSec = runOneCycle();
195
+ } catch (const oxt::tracable_exception &e) {
196
+ P_ERROR(e.what() << "\n" << e.backtrace());
197
+ }
198
+
199
+ if (backoffSec == 0) {
200
+ boost::unique_lock<boost::mutex> l(configSyncher);
201
+ backoffSec = config["interval"].asUInt()
202
+ + calculateIntervalJitter(config);
203
+ }
204
+
205
+ UPDATE_TRACE_POINT();
206
+ P_DEBUG("Next anonymous telemetry collection in "
207
+ << distanceOfTimeInWords(SystemTime::get() + backoffSec));
208
+ boost::this_thread::sleep_for(boost::chrono::seconds(backoffSec));
209
+ }
210
+ }
211
+
212
+ static unsigned int calculateIntervalJitter(const ConfigKit::Store &config) {
213
+ unsigned int jitter = config["interval_jitter"].asUInt();
214
+ if (jitter == 0) {
215
+ return 0;
216
+ } else {
217
+ return std::rand() % jitter;
218
+ }
219
+ }
220
+
221
+ // Virtual to allow mocking in unit tests.
222
+ virtual TelemetryData collectTelemetryData(bool isFinalRun) const {
223
+ TRACE_POINT();
224
+ TelemetryData tmData;
225
+ unsigned int counter = 0;
226
+ boost::mutex syncher;
227
+ boost::condition_variable cond;
228
+
229
+ tmData.requestsHandled.resize(controllers.size(), 0);
230
+
231
+ UPDATE_TRACE_POINT();
232
+ for (unsigned int i = 0; i < controllers.size(); i++) {
233
+ if (isFinalRun) {
234
+ inspectController(&tmData, controllers[i], i, &counter,
235
+ &syncher, &cond);
236
+ } else {
237
+ controllers[i]->getContext()->libev->runLater(boost::bind(
238
+ &TelemetryCollector::inspectController, this, &tmData,
239
+ controllers[i], i, &counter, &syncher, &cond));
240
+ }
241
+ }
242
+
243
+ UPDATE_TRACE_POINT();
244
+ {
245
+ boost::unique_lock<boost::mutex> l(syncher);
246
+ while (counter != controllers.size()) {
247
+ cond.wait(l);
248
+ }
249
+ }
250
+
251
+ tmData.timestamp = SystemTime::getMonotonicUsecWithGranularity
252
+ <SystemTime::GRAN_1SEC>();
253
+ return tmData;
254
+ }
255
+
256
+ void inspectController(TelemetryData *tmData, Controller *controller,
257
+ unsigned int index, unsigned int *counter, boost::mutex *syncher,
258
+ boost::condition_variable *cond) const
259
+ {
260
+ boost::unique_lock<boost::mutex> l(*syncher);
261
+ tmData->requestsHandled[index] = controller->totalRequestsBegun;
262
+ (*counter)++;
263
+ cond->notify_one();
264
+ }
265
+
266
+ string createRequestBody(const TelemetryData &tmData) const {
267
+ Json::Value doc;
268
+ boost::uint64_t totalRequestsHandled = 0;
269
+
270
+ P_ASSERT_EQ(tmData.requestsHandled.size(),
271
+ lastTelemetryData.requestsHandled.size());
272
+
273
+ for (unsigned int i = 0; i < tmData.requestsHandled.size(); i++) {
274
+ if (tmData.requestsHandled[i] >= lastTelemetryData.requestsHandled[i]) {
275
+ totalRequestsHandled += tmData.requestsHandled[i]
276
+ - lastTelemetryData.requestsHandled[i];
277
+ } else {
278
+ // Counter overflowed
279
+ totalRequestsHandled += std::numeric_limits<boost::uint64_t>::max()
280
+ - lastTelemetryData.requestsHandled[i]
281
+ + 1
282
+ + tmData.requestsHandled[i];
283
+ }
284
+ }
285
+
286
+ doc["requests_handled"] = (Json::UInt64) totalRequestsHandled;
287
+ doc["begin_time"] = (Json::UInt64) monoTimeToRealTime(
288
+ lastTelemetryData.timestamp);
289
+ doc["end_time"] = (Json::UInt64) monoTimeToRealTime(
290
+ tmData.timestamp);
291
+ doc["version"] = PASSENGER_VERSION;
292
+ #ifdef PASSENGER_IS_ENTERPRISE
293
+ doc["edition"] = "enterprise";
294
+ #else
295
+ doc["edition"] = "oss";
296
+ #endif
297
+
298
+ return doc.toStyledString();
299
+ }
300
+
301
+ static time_t monoTimeToRealTime(MonotonicTimeUsec monoTime) {
302
+ MonotonicTimeUsec monoNow = SystemTime::getMonotonicUsecWithGranularity
303
+ <SystemTime::GRAN_1SEC>();
304
+ unsigned long long realNow = SystemTime::getUsec();
305
+ MonotonicTimeUsec diff;
306
+
307
+ if (monoNow >= monoTime) {
308
+ diff = monoNow - monoTime;
309
+ return (realNow - diff) / 1000000;
310
+ } else {
311
+ diff = monoTime - monoNow;
312
+ return (realNow + diff) / 1000000;
313
+ }
314
+ }
315
+
316
+ static CURL *prepareCurlRequest(SessionState &sessionState, bool isFinalRun,
317
+ struct curl_slist **headers, char *lastErrorMessage,
318
+ const string &requestBody, string &responseData)
319
+ {
320
+ CURL *curl;
321
+ CURLcode code;
322
+
323
+ curl = curl_easy_init();
324
+ if (curl == NULL) {
325
+ P_ERROR("Error initializing libcurl");
326
+ return NULL;
327
+ }
328
+
329
+ code = curl_easy_setopt(curl, CURLOPT_VERBOSE,
330
+ sessionState.config["debug_curl"].asBool() ? 1L : 0L);
331
+ if (code != CURLE_OK) {
332
+ goto error;
333
+ }
334
+
335
+ code = setCurlDefaultCaInfo(curl);
336
+ if (code != CURLE_OK) {
337
+ goto error;
338
+ }
339
+
340
+ code = setCurlProxy(curl, sessionState.configRlz.proxyInfo);
341
+ if (code != CURLE_OK) {
342
+ goto error;
343
+ }
344
+
345
+ code = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
346
+ if (code != CURLE_OK) {
347
+ goto error;
348
+ }
349
+
350
+ code = curl_easy_setopt(curl, CURLOPT_URL,
351
+ sessionState.configRlz.url.c_str());
352
+ if (code != CURLE_OK) {
353
+ goto error;
354
+ }
355
+
356
+ code = curl_easy_setopt(curl, CURLOPT_HTTPGET, 0);
357
+ if (code != CURLE_OK) {
358
+ goto error;
359
+ }
360
+
361
+ code = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestBody.c_str());
362
+ if (code != CURLE_OK) {
363
+ goto error;
364
+ }
365
+
366
+ code = curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, requestBody.length());
367
+ if (code != CURLE_OK) {
368
+ goto error;
369
+ }
370
+
371
+ *headers = curl_slist_append(NULL, "Content-Type: application/json");
372
+ code = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, *headers);
373
+ if (code != CURLE_OK) {
374
+ goto error;
375
+ }
376
+
377
+ if (!sessionState.configRlz.caCertificatePath.empty()) {
378
+ code = curl_easy_setopt(curl, CURLOPT_CAINFO,
379
+ sessionState.configRlz.caCertificatePath.c_str());
380
+ if (code != CURLE_OK) {
381
+ goto error;
382
+ }
383
+ }
384
+
385
+ if (sessionState.config["verify_server"].asBool()) {
386
+ // These should be on by default, but make sure.
387
+ code = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
388
+ if (code != CURLE_OK) {
389
+ goto error;
390
+ }
391
+ code = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
392
+ if (code != CURLE_OK) {
393
+ goto error;
394
+ }
395
+ } else {
396
+ code = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
397
+ if (code != CURLE_OK) {
398
+ goto error;
399
+ }
400
+ code = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
401
+ if (code != CURLE_OK) {
402
+ goto error;
403
+ }
404
+ }
405
+
406
+ code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, lastErrorMessage);
407
+ if (code != CURLE_OK) {
408
+ goto error;
409
+ }
410
+ code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receiveResponseBytes);
411
+ if (code != CURLE_OK) {
412
+ goto error;
413
+ }
414
+ code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);
415
+ if (code != CURLE_OK) {
416
+ goto error;
417
+ }
418
+
419
+ // setopt failure(s) below don't abort the check.
420
+ if (isFinalRun) {
421
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT,
422
+ sessionState.config["final_run_timeout"].asUInt());
423
+ } else {
424
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT,
425
+ sessionState.config["timeout"].asUInt());
426
+ }
427
+
428
+ return curl;
429
+
430
+ error:
431
+ curl_easy_cleanup(curl);
432
+ curl_slist_free_all(*headers);
433
+ P_ERROR("Error setting libcurl handle parameters: " << curl_easy_strerror(code));
434
+ return NULL;
435
+ }
436
+
437
+ static size_t receiveResponseBytes(void *buffer, size_t size,
438
+ size_t nmemb, void *userData)
439
+ {
440
+ string *responseData = (string *) userData;
441
+ responseData->append((const char *) buffer, size * nmemb);
442
+ return size * nmemb;
443
+ }
444
+
445
+ // Virtual to allow mocking in unit tests.
446
+ virtual CURLcode performCurlAction(CURL *curl, const char *lastErrorMessage,
447
+ const string &_requestBody, // only used by unit tests
448
+ string &_responseData, // only used by unit tests
449
+ long &responseCode)
450
+ {
451
+ TRACE_POINT();
452
+ CURLcode code = curl_easy_perform(curl);
453
+ if (code != CURLE_OK) {
454
+ P_ERROR("Error contacting anonymous telemetry server: "
455
+ << lastErrorMessage);
456
+ return code;
457
+ }
458
+
459
+ code = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
460
+ if (code != CURLE_OK) {
461
+ P_ERROR("Error querying libcurl handle for HTTP response code: "
462
+ << curl_easy_strerror(code));
463
+ return code;
464
+ }
465
+
466
+ return CURLE_OK;
467
+ }
468
+
469
+ static bool responseCodeSupported(long code) {
470
+ return code == 200 || code == 400 || code == 422 || code == 500;
471
+ }
472
+
473
+ static bool parseResponseBody(const string &responseData, Json::Value &jsonBody) {
474
+ Json::Reader reader;
475
+ if (reader.parse(responseData, jsonBody, false)) {
476
+ return true;
477
+ } else {
478
+ P_ERROR("Error in anonymous telemetry server response:"
479
+ " JSON response parse error: " << reader.getFormattedErrorMessages()
480
+ << "; data: \"" << cEscapeString(responseData) << "\"");
481
+ return false;
482
+ }
483
+ }
484
+
485
+ static bool validateResponseBody(const Json::Value &jsonBody) {
486
+ if (!jsonBody.isObject()) {
487
+ P_ERROR("Error in anonymous telemetry server response:"
488
+ " JSON response is not an object (data: "
489
+ << stringifyJson(jsonBody) << ")");
490
+ return false;
491
+ }
492
+ if (!jsonBody.isMember("data_processed")) {
493
+ P_ERROR("Error in anonymous telemetry server response:"
494
+ " JSON response must contain a 'data_processed' field (data: "
495
+ << stringifyJson(jsonBody) << ")");
496
+ return false;
497
+ }
498
+ if (!jsonBody["data_processed"].isBool()) {
499
+ P_ERROR("Error in anonymous telemetry server response:"
500
+ " 'data_processed' field must be a boolean (data: "
501
+ << stringifyJson(jsonBody) << ")");
502
+ return false;
503
+ }
504
+ if (jsonBody.isMember("backoff") && !jsonBody["backoff"].isUInt()) {
505
+ P_ERROR("Error in anonymous telemetry server response:"
506
+ " 'backoff' field must be an unsigned integer (data: "
507
+ << stringifyJson(jsonBody) << ")");
508
+ return false;
509
+ }
510
+ if (jsonBody.isMember("log_message") && !jsonBody["log_message"].isString()) {
511
+ P_ERROR("Error in anonymous telemetry server response:"
512
+ " 'log_message' field must be a string (data: "
513
+ << stringifyJson(jsonBody) << ")");
514
+ return false;
515
+ }
516
+ return true;
517
+ }
518
+
519
+ unsigned int handleResponseBody(const TelemetryData &tmData,
520
+ const Json::Value &jsonBody)
521
+ {
522
+ unsigned int backoffSec = 0;
523
+
524
+ if (jsonBody["data_processed"].asBool()) {
525
+ lastTelemetryData = tmData;
526
+ }
527
+ if (jsonBody.isMember("backoff")) {
528
+ backoffSec = jsonBody["backoff"].asUInt();
529
+ }
530
+ if (jsonBody.isMember("log_message")) {
531
+ P_NOTICE("Message from " PROGRAM_AUTHOR ": " << jsonBody["log_message"].asString());
532
+ }
533
+
534
+ return backoffSec;
535
+ }
536
+
537
+ public:
538
+ // Dependencies
539
+ vector<Controller *> controllers;
540
+
541
+ TelemetryCollector(const Schema &schema,
542
+ const Json::Value &initialConfig = Json::Value(),
543
+ const ConfigKit::Translator &translator = ConfigKit::DummyTranslator())
544
+ : config(schema, initialConfig, translator),
545
+ configRlz(config),
546
+ collectorThread(NULL)
547
+ { }
548
+
549
+ virtual ~TelemetryCollector() {
550
+ stop();
551
+ }
552
+
553
+ void initialize() {
554
+ if (controllers.empty()) {
555
+ throw RuntimeException("controllers must be initialized");
556
+ }
557
+ lastTelemetryData.requestsHandled.resize(controllers.size(), 0);
558
+ lastTelemetryData.timestamp =
559
+ SystemTime::getMonotonicUsecWithGranularity<SystemTime::GRAN_1SEC>();
560
+ }
561
+
562
+ void start() {
563
+ assert(!lastTelemetryData.requestsHandled.empty());
564
+ collectorThread = new oxt::thread(
565
+ boost::bind(&TelemetryCollector::threadMain, this),
566
+ "Telemetry collector",
567
+ 1024 * 512
568
+ );
569
+ }
570
+
571
+ void stop() {
572
+ if (collectorThread != NULL) {
573
+ collectorThread->interrupt_and_join();
574
+ delete collectorThread;
575
+ collectorThread = NULL;
576
+ }
577
+ }
578
+
579
+ unsigned int runOneCycle(bool isFinalRun = false) {
580
+ TRACE_POINT();
581
+ boost::unique_lock<boost::mutex> l(configSyncher);
582
+ SessionState sessionState(config, configRlz);
583
+ l.unlock();
584
+
585
+ if (sessionState.config["disabled"].asBool()) {
586
+ P_DEBUG("Telemetry collector disabled; not sending anonymous telemetry data");
587
+ return 0;
588
+ }
589
+
590
+ UPDATE_TRACE_POINT();
591
+ TelemetryData tmData = collectTelemetryData(isFinalRun);
592
+
593
+ UPDATE_TRACE_POINT();
594
+ CURL *curl = NULL;
595
+ CURLcode code;
596
+ struct curl_slist *headers = NULL;
597
+ string requestBody = createRequestBody(tmData);
598
+ string responseData;
599
+ char lastErrorMessage[CURL_ERROR_SIZE] = "unknown error";
600
+ Json::Value jsonBody;
601
+
602
+ curl = prepareCurlRequest(sessionState, isFinalRun, &headers,
603
+ lastErrorMessage, requestBody, responseData);
604
+ if (curl == NULL) {
605
+ // Error message already printed
606
+ goto error;
607
+ }
608
+
609
+ P_INFO("Sending anonymous telemetry data to " PROGRAM_AUTHOR);
610
+ P_DEBUG("Telemetry server URL is: " << sessionState.configRlz.url);
611
+ P_DEBUG("Telemetry data to be sent is: " << requestBody);
612
+
613
+ UPDATE_TRACE_POINT();
614
+ long responseCode;
615
+ code = performCurlAction(curl, lastErrorMessage, requestBody,
616
+ responseData, responseCode);
617
+ if (code != CURLE_OK) {
618
+ // Error message already printed
619
+ goto error;
620
+ }
621
+
622
+ UPDATE_TRACE_POINT();
623
+ P_DEBUG("Response from telemetry server: status=" << responseCode
624
+ << ", body=" << responseData);
625
+
626
+ if (!responseCodeSupported(responseCode)) {
627
+ P_ERROR("Error from anonymous telemetry server:"
628
+ " response status not supported: " << responseCode);
629
+ goto error;
630
+ }
631
+
632
+ if (!parseResponseBody(responseData, jsonBody)
633
+ || !validateResponseBody(jsonBody))
634
+ {
635
+ // Error message already printed
636
+ goto error;
637
+ }
638
+
639
+ curl_slist_free_all(headers);
640
+ curl_easy_cleanup(curl);
641
+
642
+ return handleResponseBody(tmData, jsonBody);
643
+
644
+ error:
645
+ curl_slist_free_all(headers);
646
+ if (curl != NULL) {
647
+ curl_easy_cleanup(curl);
648
+ }
649
+ return 0;
650
+ }
651
+
652
+ bool prepareConfigChange(const Json::Value &updates,
653
+ vector<ConfigKit::Error> &errors, ConfigChangeRequest &req)
654
+ {
655
+ {
656
+ boost::lock_guard<boost::mutex> l(configSyncher);
657
+ req.config.reset(new ConfigKit::Store(config, updates, errors));
658
+ }
659
+ if (errors.empty()) {
660
+ req.configRlz.reset(new ConfigRealization(*req.config));
661
+ }
662
+ return errors.empty();
663
+ }
664
+
665
+ void commitConfigChange(ConfigChangeRequest &req) BOOST_NOEXCEPT_OR_NOTHROW {
666
+ boost::lock_guard<boost::mutex> l(configSyncher);
667
+ config.swap(*req.config);
668
+ configRlz.swap(*req.configRlz);
669
+ }
670
+
671
+ Json::Value inspectConfig() const {
672
+ boost::lock_guard<boost::mutex> l(configSyncher);
673
+ return config.inspect();
674
+ }
675
+ };
676
+
677
+
678
+ } // namespace Core
679
+ } // namespace Passenger
680
+
681
+ #endif /* _PASSENGER_TELEMETRY_COLLECTOR_H_ */
@@ -40,7 +40,7 @@
40
40
  #include <Constants.h>
41
41
  #include <ProcessManagement/Utils.h>
42
42
  #include <Utils/OptionParsing.h>
43
- #include <Utils/StrIntUtils.h>
43
+ #include <StrIntTools/StrIntUtils.h>
44
44
 
45
45
  namespace Passenger {
46
46
  namespace ExecHelper {