passenger 5.0.21 → 5.0.22

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (203) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +38 -2
  5. data/CONTRIBUTORS +3 -0
  6. data/README.md +5 -1
  7. data/bin/passenger-status +2 -7
  8. data/build/agent.rb +2 -0
  9. data/build/cxx_dependency_map.rb +1464 -162
  10. data/build/node_tests.rb +1 -1
  11. data/build/packaging.rb +1 -1
  12. data/dev/ci/run_travis.sh +1 -1
  13. data/dev/vagrant/provision.sh +1 -1
  14. data/npm-shrinkwrap.json +635 -125
  15. data/package.json +1 -1
  16. data/resources/templates/standalone/config.erb +33 -161
  17. data/resources/templates/standalone/global.erb +15 -0
  18. data/resources/templates/standalone/http.erb +40 -0
  19. data/resources/templates/standalone/mass_deployment_default_server.erb +11 -0
  20. data/resources/templates/standalone/rails_asset_pipeline.erb +22 -0
  21. data/resources/templates/standalone/server.erb +58 -0
  22. data/src/agent/Core/ApiServer.h +37 -32
  23. data/src/agent/Core/ApplicationPool/BasicGroupInfo.h +1 -1
  24. data/src/agent/Core/ApplicationPool/BasicProcessInfo.h +6 -0
  25. data/src/agent/Core/ApplicationPool/Common.h +1 -1
  26. data/src/agent/Core/ApplicationPool/Group/OutOfBandWork.cpp +1 -1
  27. data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +4 -0
  28. data/src/agent/Core/ApplicationPool/Implementation.cpp +2 -2
  29. data/src/agent/Core/ApplicationPool/Options.h +18 -1
  30. data/src/agent/Core/ApplicationPool/Pool.h +1 -1
  31. data/src/agent/Core/ApplicationPool/Pool/AnalyticsCollection.cpp +6 -6
  32. data/src/agent/Core/ApplicationPool/Pool/GeneralUtils.cpp +3 -3
  33. data/src/agent/Core/ApplicationPool/Pool/InitializationAndShutdown.cpp +1 -1
  34. data/src/agent/Core/ApplicationPool/Pool/Miscellaneous.cpp +6 -0
  35. data/src/agent/Core/ApplicationPool/Process.h +6 -1
  36. data/src/agent/Core/ApplicationPool/Socket.h +9 -12
  37. data/src/agent/Core/Controller.h +422 -0
  38. data/src/agent/Core/{RequestHandler → Controller}/AppResponse.h +2 -0
  39. data/src/agent/Core/{RequestHandler → Controller}/BufferBody.cpp +27 -5
  40. data/src/agent/Core/{RequestHandler → Controller}/CheckoutSession.cpp +61 -31
  41. data/src/agent/Core/{RequestHandler → Controller}/Client.h +5 -2
  42. data/src/agent/Core/{RequestHandler → Controller}/ForwardResponse.cpp +93 -42
  43. data/src/agent/Core/{RequestHandler → Controller}/Hooks.cpp +107 -60
  44. data/src/agent/Core/Controller/Implementation.cpp +38 -0
  45. data/src/agent/Core/{RequestHandler → Controller}/InitRequest.cpp +134 -80
  46. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +165 -0
  47. data/src/agent/Core/{RequestHandler/Utils.cpp → Controller/InternalUtils.cpp} +49 -32
  48. data/src/agent/Core/Controller/Miscellaneous.cpp +116 -0
  49. data/src/agent/Core/{RequestHandler → Controller}/Request.h +6 -4
  50. data/src/agent/Core/{RequestHandler → Controller}/SendRequest.cpp +205 -130
  51. data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +161 -0
  52. data/src/agent/Core/{RequestHandler → Controller}/TurboCaching.h +3 -0
  53. data/src/agent/Core/CoreMain.cpp +62 -51
  54. data/src/agent/Core/OptionParser.h +24 -0
  55. data/src/agent/Core/ResponseCache.h +5 -5
  56. data/src/agent/Core/SpawningKit/Config.h +2 -2
  57. data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -1
  58. data/src/agent/Core/UnionStation/{Core.h → Context.h} +14 -18
  59. data/src/agent/Core/UnionStation/StopwatchLog.h +3 -2
  60. data/src/agent/Core/UnionStation/Transaction.h +7 -7
  61. data/src/agent/Shared/ApiServerUtils.h +9 -1
  62. data/src/agent/UstRouter/ApiServer.h +5 -2
  63. data/src/agent/UstRouter/Controller.h +27 -9
  64. data/src/agent/UstRouter/UstRouterMain.cpp +1 -0
  65. data/src/agent/Watchdog/ApiServer.h +5 -2
  66. data/src/apache2_module/ConfigurationCommands.cpp +7 -0
  67. data/src/apache2_module/ConfigurationFields.hpp +2 -0
  68. data/src/apache2_module/ConfigurationSetters.cpp +24 -0
  69. data/src/apache2_module/CreateDirConfig.cpp +1 -0
  70. data/src/apache2_module/Hooks.cpp +6 -5
  71. data/src/apache2_module/MergeDirConfig.cpp +7 -0
  72. data/src/apache2_module/SetHeaders.cpp +5 -0
  73. data/src/cxx_supportlib/Constants.h +5 -3
  74. data/src/cxx_supportlib/SafeLibev.h +2 -1
  75. data/src/cxx_supportlib/UnionStationFilterSupport.h +2 -1
  76. data/src/cxx_supportlib/Utils/ReleaseableScopedPointer.h +70 -0
  77. data/src/cxx_supportlib/vendor-modified/boost/libs/regex/src/regex_raw_buffer.cpp +6 -6
  78. data/src/helper-scripts/node-loader.js +59 -0
  79. data/src/nginx_module/CacheLocationConfig.c +48 -0
  80. data/src/nginx_module/ConfigurationCommands.c +20 -0
  81. data/src/nginx_module/ConfigurationFields.h +4 -0
  82. data/src/nginx_module/CreateLocationConfig.c +8 -0
  83. data/src/nginx_module/MergeLocationConfig.c +12 -0
  84. data/src/nodejs_supportlib/phusion_passenger/log_express.js +106 -0
  85. data/src/nodejs_supportlib/phusion_passenger/log_mongodb.js +203 -0
  86. data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +227 -0
  87. data/src/nodejs_supportlib/phusion_passenger/ustrouter_connector.js +446 -0
  88. data/src/nodejs_supportlib/vendor-copy/codify/codify.js +44 -0
  89. data/src/nodejs_supportlib/vendor-copy/codify/package.json +29 -0
  90. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/context.js +200 -0
  91. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/glue.js +488 -0
  92. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/index.js +407 -0
  93. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/node_modules/shimmer/index.js +90 -0
  94. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/node_modules/shimmer/package.json +40 -0
  95. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/async-listener/package.json +54 -0
  96. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/listener.js +160 -0
  97. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/node_modules/shimmer/index.js +90 -0
  98. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/node_modules/shimmer/package.json +40 -0
  99. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/node_modules/emitter-listener/package.json +46 -0
  100. data/src/nodejs_supportlib/vendor-copy/continuation-local-storage/package.json +56 -0
  101. data/src/nodejs_supportlib/vendor-copy/network-byte-order/lib/index.js +102 -0
  102. data/src/nodejs_supportlib/vendor-copy/network-byte-order/package.json +51 -0
  103. data/src/nodejs_supportlib/vendor-copy/winston/LICENSE +19 -0
  104. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston.js +165 -0
  105. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/common.js +483 -0
  106. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config.js +62 -0
  107. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/cli-config.js +35 -0
  108. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/npm-config.js +27 -0
  109. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/config/syslog-config.js +31 -0
  110. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/container.js +127 -0
  111. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/exception.js +56 -0
  112. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/logger.js +701 -0
  113. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports.js +34 -0
  114. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/console.js +128 -0
  115. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/daily-rotate-file.js +601 -0
  116. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/file.js +675 -0
  117. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/http.js +232 -0
  118. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/memory.js +89 -0
  119. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/transport.js +135 -0
  120. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/transports/webhook.js +146 -0
  121. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/LICENSE +19 -0
  122. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/lib/async.js +1283 -0
  123. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/package.json +66 -0
  124. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/async/support/sync-package-managers.js +53 -0
  125. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/MIT-LICENSE.txt +23 -0
  126. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/colors.js +176 -0
  127. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/custom/trap.js +45 -0
  128. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/custom/zalgo.js +104 -0
  129. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/extendStringPrototype.js +118 -0
  130. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/index.js +12 -0
  131. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/america.js +12 -0
  132. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/rainbow.js +13 -0
  133. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/random.js +8 -0
  134. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/maps/zebra.js +5 -0
  135. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/styles.js +77 -0
  136. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/lib/system/supports-colors.js +61 -0
  137. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/package.json +35 -0
  138. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/safe.js +9 -0
  139. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/colors/themes/generic-logging.js +12 -0
  140. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/cycle/cycle.js +170 -0
  141. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/cycle/package.json +30 -0
  142. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/LICENSE +20 -0
  143. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/lib/eyes.js +236 -0
  144. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/eyes/package.json +42 -0
  145. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/LICENSE.md +11 -0
  146. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/isstream.js +27 -0
  147. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/isstream/package.json +42 -0
  148. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/LICENSE +19 -0
  149. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/lib/pkginfo.js +136 -0
  150. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/pkginfo/package.json +56 -0
  151. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/License +19 -0
  152. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/lib/stack-trace.js +111 -0
  153. data/src/nodejs_supportlib/vendor-copy/winston/node_modules/stack-trace/package.json +33 -0
  154. data/src/nodejs_supportlib/vendor-copy/winston/package.json +87 -0
  155. data/src/ruby_supportlib/phusion_passenger.rb +3 -4
  156. data/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb +19 -2
  157. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +8 -0
  158. data/src/ruby_supportlib/phusion_passenger/config/list_instances_command.rb +2 -6
  159. data/src/ruby_supportlib/phusion_passenger/config/reopen_logs_command.rb +13 -0
  160. data/src/ruby_supportlib/phusion_passenger/config/restart_app_command.rb +3 -0
  161. data/src/ruby_supportlib/phusion_passenger/config/utils.rb +9 -7
  162. data/src/ruby_supportlib/phusion_passenger/config/validate_install_command.rb +8 -1
  163. data/src/ruby_supportlib/phusion_passenger/constants.rb +3 -1
  164. data/src/ruby_supportlib/phusion_passenger/native_support.rb +20 -4
  165. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +8 -0
  166. data/src/ruby_supportlib/phusion_passenger/packaging.rb +1 -0
  167. data/src/ruby_supportlib/phusion_passenger/platform_info/apache_detector.rb +1 -1
  168. data/src/ruby_supportlib/phusion_passenger/platform_info/operating_system.rb +11 -4
  169. data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +1 -1
  170. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +647 -0
  171. data/src/ruby_supportlib/phusion_passenger/standalone/config_utils.rb +229 -15
  172. data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +35 -323
  173. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +36 -12
  174. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +123 -14
  175. data/src/ruby_supportlib/phusion_passenger/standalone/status_command.rb +32 -17
  176. data/src/ruby_supportlib/phusion_passenger/standalone/stop_command.rb +32 -21
  177. data/src/ruby_supportlib/phusion_passenger/standalone/version_command.rb +5 -5
  178. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/README.md +2 -2
  179. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/Rakefile +5 -1
  180. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +68 -24
  181. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/api.rb +9 -1
  182. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/context.rb +9 -7
  183. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter.rb +3 -2
  184. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/request_reporter/basics.rb +8 -5
  185. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/simple_json.rb +395 -0
  186. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/transaction.rb +10 -7
  187. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/utils.rb +14 -0
  188. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/version_data.rb +2 -2
  189. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml +4 -2
  190. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.example +2 -2
  191. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis +2 -2
  192. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis-with-sudo +16 -0
  193. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Gemfile +1 -1
  194. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/Gemfile.lock +2 -2
  195. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/README.md +1 -1
  196. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails.rb +44 -17
  197. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/active_support_cache_subscriber.rb +16 -7
  198. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/lib/union_station_hooks_rails/version_data.rb +2 -2
  199. data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_rails/union_station_hooks_rails.gemspec +1 -1
  200. metadata +99 -16
  201. metadata.gz.asc +7 -7
  202. data/resources/oss-binaries.phusionpassenger.com.crt +0 -248
  203. data/src/agent/Core/RequestHandler.h +0 -471
@@ -0,0 +1,446 @@
1
+ /*
2
+ * Phusion Passenger - https://www.phusionpassenger.com/
3
+ * Copyright (c) 2010-2015 Phusion
4
+ *
5
+ * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in
15
+ * all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ * THE SOFTWARE.
24
+ */
25
+
26
+ var log;
27
+ var net = require('net');
28
+ var os = require('os');
29
+ var nbo = require('vendor-copy/network-byte-order');
30
+ var codify = require('vendor-copy/codify');
31
+
32
+ var ustRouterAddress; // will normally be a unix sock, although there is a default standalone = "tcp://127.0.0.1:9344";
33
+ var ustRouterPort; // if not a unix sock
34
+ var ustRouterUser;
35
+ var ustRouterPass;
36
+ var ustGatewayKey;
37
+
38
+ var appGroupName;
39
+
40
+ var routerConn;
41
+ var routerState;
42
+ // -1: disabled (not initialized or unrecoverable error, won't try to reconnect without new init)
43
+ // 0: disconnected, ready to (re)try connect
44
+ // 1: awaiting connect
45
+ // 2: awaiting version
46
+ // 3: awaiting auth OK
47
+ // 4: awaiting init OK
48
+ // 5: idle / ready to send
49
+ // 6: awaiting openTransaction OK
50
+ // 7: awaiting closeTransaction OK
51
+
52
+ var pendingTxnBuf;
53
+ var pendingTxnBufMaxLength;
54
+ var connTimeoutMs;
55
+ var autoRetryAfterMs;
56
+
57
+ setDefaults();
58
+ function setDefaults() {
59
+ routerState = -1;
60
+ pendingTxnBuf = [];
61
+ pendingTxnBufMaxLength = 5000;
62
+ connTimeoutMs = 10000;
63
+ autoRetryAfterMs = 30000;
64
+ }
65
+
66
+ // Call to initiate a connection with the UstRouter. If called with incomplete parameters the connector will just be
67
+ // disabled (isEnabled() will return false) and no further actions will be taken. If the connection fails, it is auto-retried
68
+ // whenever logToUstTransaction(..) is called.
69
+ exports.init = function(logger, routerAddress, routerUser, routerPass, gatewayKey, groupName) {
70
+ log = logger;
71
+ if (routerState > 0) {
72
+ log.warn("Trying to init when routerState > 0! (ignoring)");
73
+ return;
74
+ }
75
+
76
+ routerState = -1;
77
+ ustRouterAddress = routerAddress;
78
+ ustRouterUser = routerUser;
79
+ ustRouterPass = routerPass;
80
+ ustGatewayKey = gatewayKey;
81
+ appGroupName = groupName;
82
+
83
+ if (ustRouterAddress) {
84
+ if (ustRouterAddress.indexOf("unix:") == 0) {
85
+ // createConnection doesn't understand the "unix:" prefix, but it does understand the path that follows.
86
+ ustRouterAddress = ustRouterAddress.substring(5);
87
+ } else if (ustRouterAddress.indexOf("tcp://") == 0) {
88
+ var hostAndPort = ustRouterAddress.substring(6).split(':');
89
+ ustRouterAddress = hostAndPort[0];
90
+ ustRouterPort = hostAndPort[1];
91
+ }
92
+ }
93
+ log.debug("initialize ustrouter_connector with [routerAddress:" + ustRouterAddress + "] " +
94
+ (ustRouterPort ? "[ustRouterPort:" + ustRouterPort + "] " : "") + "[user:" + ustRouterUser + "] [pass:" +
95
+ ustRouterPass + "] [key:" + ustGatewayKey + "] [app:" + appGroupName + "]");
96
+
97
+ if (!ustRouterAddress || !ustRouterUser || !ustRouterPass || !ustGatewayKey || !appGroupName) {
98
+ log.verbose("Union Station logging disabled (incomplete configuration).");
99
+ return;
100
+ }
101
+
102
+ changeState(0, "Init approved");
103
+
104
+ beginConnection();
105
+ }
106
+
107
+ exports.finit = function() {
108
+ resetState("finit()");
109
+ }
110
+
111
+ exports.isEnabled = function() {
112
+ return routerState >= 0;
113
+ }
114
+
115
+ function beginConnection() {
116
+ changeState(1);
117
+
118
+ setWatchdog(connTimeoutMs); // Watchdog for the entire connect-to-ustRouter process.
119
+
120
+ if (ustRouterPort) {
121
+ routerConn = net.createConnection(ustRouterPort, ustRouterAddress);
122
+ } else {
123
+ routerConn = net.createConnection(ustRouterAddress);
124
+ }
125
+
126
+ routerConn.on("connect", onConnect);
127
+ routerConn.on("error", onError);
128
+ routerConn.on("end", onEnd);
129
+ routerConn.on("data", onData);
130
+ }
131
+
132
+ function onConnect() {
133
+ changeState(2);
134
+ }
135
+
136
+ function onError(e) {
137
+ if (routerState == 1) {
138
+ log.error("Unable to connect to UstRouter at [" + ustRouterAddress +"], will auto-retry.");
139
+ } else {
140
+ // could be called when e.g. a write fails
141
+ log.error("Uncategorized error in UstRouter connection: " + e + ", will auto-retry.");
142
+ }
143
+ resetState("onError");
144
+ }
145
+
146
+ function onEnd() {
147
+ // e.g. when connection dies
148
+ resetState("onEnd");
149
+ }
150
+
151
+ function getWallclockMicrosec() {
152
+ // for lack of a more accurate clock
153
+ return new Date().getTime() * 1000;
154
+ }
155
+
156
+ function LogTransaction(cat) {
157
+ this.timestamp = getWallclockMicrosec();
158
+ this.category = cat;
159
+ this.txnId = "";
160
+ this.logBuf = [];
161
+ this.state = 0; // 0: untouched, 1: open sent, 2: close sent
162
+ }
163
+
164
+ function findLastPendingTxnForId(txnId) {
165
+ for (i = pendingTxnBuf.length - 1; i >= 0; i--) {
166
+ if (pendingTxnBuf[i].txnId == txnId) {
167
+ return pendingTxnBuf[i];
168
+ }
169
+ }
170
+ }
171
+
172
+ exports.deferIfPendingTxns = function(txnId, deferThis, deferFn, deferArgs) {
173
+ var txn = findLastPendingTxnForId(txnId);
174
+
175
+ if (!txn) {
176
+ return deferFn.apply(deferThis, deferArgs);
177
+ } else {
178
+ log.debug("defer response.end() for txn " + txnId);
179
+ txn.deferThis = deferThis;
180
+ txn.deferFn = deferFn;
181
+ txn.deferArgs = deferArgs;
182
+ }
183
+ }
184
+
185
+ // Example categories are "requests", "exceptions". The lineArray is a specific format parsed by Union STation.
186
+ // txnIfContinue is an optional txnId and attaches the log to an existing transaction with the specified txnId.
187
+ // N.B. transactions will be dropped if the outgoing buffer limit is reached.
188
+ exports.logToUstTransaction = function(category, lineArray, txnIfContinue) {
189
+ if (!this.isEnabled()) {
190
+ return;
191
+ }
192
+
193
+ if (pendingTxnBuf.length < pendingTxnBufMaxLength) {
194
+ var logTxn = new LogTransaction(category);
195
+
196
+ if (txnIfContinue) {
197
+ logTxn.txnId = txnIfContinue;
198
+ }
199
+ logTxn.logBuf = lineArray;
200
+
201
+ pendingTxnBuf.push(logTxn);
202
+ } else {
203
+ log.debug("Dropping Union Station log due to outgoing buffer limit (" + pendingTxnBufMaxLength + ") reached");
204
+ }
205
+
206
+ pushPendingData();
207
+ }
208
+
209
+ function verifyOk(rcvString, topic) {
210
+ if ("status" != rcvString[0] || "ok" != rcvString[1]) {
211
+ log.error("Error with " + topic + ": [" + rcvString + "], will auto-retry.");
212
+ resetState("not OK reply");
213
+ return false;
214
+ }
215
+ return true;
216
+ }
217
+
218
+ function pushPendingData() {
219
+ log.debug("pushPendingData");
220
+
221
+ if (routerState == 0) {
222
+ // it disconnected or crashed somehow, reconnect
223
+ beginConnection();
224
+ return;
225
+ } else if (routerState != 5) {
226
+ return; // we're not ready to send
227
+ }
228
+
229
+ // we have an authenticated, active connection; see what we can send
230
+ if (pendingTxnBuf.length == 0) {
231
+ return; // no pending
232
+ }
233
+
234
+ switch (pendingTxnBuf[0].state) {
235
+ case 0:
236
+ // still need to open the txn
237
+ changeState(6); // expect ok/txnid in onData()..
238
+ setWatchdog(connTimeoutMs);
239
+ log.debug("open transaction(" + pendingTxnBuf[0].txnId + ")");
240
+ pendingTxnBuf[0].state = 1;
241
+ writeLenArray(routerConn, "openTransaction\0" + pendingTxnBuf[0].txnId + "\0" + appGroupName + "\0\0" +
242
+ pendingTxnBuf[0].category + "\0" + codify.toCode(pendingTxnBuf[0].timestamp) + "\0" + ustGatewayKey + "\0true\0true\0\0");
243
+ break;
244
+
245
+ case 1:
246
+ // open was sent, still waiting for OK.
247
+ break;
248
+
249
+ case 2:
250
+ // txn is open, log the data & close
251
+ log.debug("log & close transaction(" + pendingTxnBuf[0].txnId + ")");
252
+ txn = pendingTxnBuf.shift();
253
+
254
+ if (txn.deferFn) {
255
+ var moveToTxn = findLastPendingTxnForId(txn.txnId);
256
+ if (!moveToTxn) {
257
+ log.debug("found deferred response.end(), no other queued attachments for txn " + txn.txnId + ", so calling now that it's safe");
258
+ txn.deferFn.apply(txn.deferThis, txn.deferArgs);
259
+ } else {
260
+ log.debug("moving deferred response.end() because there are other relevant attachment(s) for txn " + txn.txnId);
261
+ moveToTxn.deferThis = txn.deferThis;
262
+ moveToTxn.deferFn = txn.deferFn;
263
+ moveToTxn.deferArgs = txn.deferArgs;
264
+ }
265
+ }
266
+
267
+ for (i = 0; i < txn.logBuf.length; i++) {
268
+ writeLenArray(routerConn, "log\0" + txn.txnId + "\0" + codify.toCode(txn.timestamp) + "\0");
269
+ writeLenString(routerConn, txn.logBuf[i]);
270
+ }
271
+
272
+ changeState(7); // expect ok in onData()..
273
+ setWatchdog(connTimeoutMs);
274
+ writeLenArray(routerConn, "closeTransaction\0" + txn.txnId + "\0" + codify.toCode(getWallclockMicrosec()) + "\0true\0");
275
+ log.debug("wrote log and close for " + txn.txnId);
276
+ break;
277
+
278
+ default:
279
+ log.error("Unexpected pendingTxnBuf[0].state " + pendingTxnBuf[0].state + ", discarding it.");
280
+ pendingTxnBuf.shift();
281
+ break;
282
+ }
283
+ }
284
+
285
+ var watchDogId;
286
+
287
+ function onWatchdogTimeout() {
288
+ resetState("onWatchdogTimeout");
289
+ }
290
+
291
+ // Resets the connection if there is no progress in the next timeoutMs.
292
+ function setWatchdog(timeoutMs) {
293
+ if (watchDogId) {
294
+ resetWatchdog();
295
+ }
296
+ watchDogId = setTimeout(onWatchdogTimeout, timeoutMs);
297
+ }
298
+
299
+ function resetWatchdog() {
300
+ if (watchDogId) {
301
+ clearTimeout(watchDogId);
302
+ watchDogId = null;
303
+ }
304
+ }
305
+
306
+ var readBuf = "";
307
+ // N.B. newData may be partial!
308
+ function readLenArray(newData) {
309
+ readBuf += newData;
310
+ log.silly("read: total len = " + readBuf.length);
311
+ log.silly(new Buffer(readBuf).toString("hex"));
312
+ if (readBuf.length < 2) {
313
+ log.silly("need more header data..");
314
+ return null; // expecting at least length bytes
315
+ }
316
+ payloadLen = nbo.ntohs(new Buffer(readBuf), 0);
317
+ log.silly("read: payloadLen = " + payloadLen);
318
+ if (readBuf.length < 2 + payloadLen) {
319
+ log.silly("need more payload data..");
320
+ return null; // not fully read yet
321
+ }
322
+ resultStr = readBuf.substring(2, payloadLen + 2);
323
+ readBuf = readBuf.substring(payloadLen + 2); // keep any bytes read beyond length for next read
324
+
325
+ return resultStr.split("\0");
326
+ }
327
+
328
+ function onData(data) {
329
+ log.silly("onData [" + data + "] (len = " + data.length + ")");
330
+
331
+ rcvString = readLenArray(data);
332
+ if (!rcvString) {
333
+ return;
334
+ }
335
+
336
+ log.silly("got: [" + rcvString + "]");
337
+
338
+ switch (routerState) {
339
+ case 2:
340
+ if ("version" == rcvString[0] && "1" == rcvString[1]) {
341
+ changeState(3);
342
+
343
+ writeLenString(routerConn, ustRouterUser);
344
+ writeLenString(routerConn, ustRouterPass);
345
+ } else {
346
+ log.error("Error with UstRouter version: [" + rcvString + "], will auto-retry.");
347
+ resetState("not OK version reply");
348
+ }
349
+ break;
350
+
351
+ case 3:
352
+ if (verifyOk(rcvString, "UstRouter authentication")) {
353
+ changeState(4);
354
+ writeLenArray(routerConn, "init\0");
355
+ }
356
+ break;
357
+
358
+ case 4:
359
+ if (verifyOk(rcvString, "UstRouter initialization")) {
360
+ resetWatchdog(); // initialization done, lift the watchdog guard
361
+ changeState(5);
362
+ pushPendingData();
363
+ }
364
+ break;
365
+
366
+ case 5:
367
+ log.warn("unexpected data receive state (5)");
368
+ pushPendingData();
369
+ break;
370
+
371
+ case 6:
372
+ resetWatchdog();
373
+ if (verifyOk(rcvString, "UstRouter openTransaction")) {
374
+ pendingTxnBuf[0].state = 2;
375
+ if (pendingTxnBuf[0].txnId.length == 0) {
376
+ log.debug("use rcvd back txnId: " + rcvString[2]);
377
+ pendingTxnBuf[0].txnId = rcvString[2]; // fill in the txn from the UstRouter reply
378
+ }
379
+
380
+ changeState(5);
381
+ pushPendingData();
382
+ }
383
+ break;
384
+
385
+ case 7:
386
+ resetWatchdog();
387
+ if (verifyOk(rcvString, "UstRouter closeTransaction")) {
388
+ changeState(5);
389
+ pushPendingData();
390
+ }
391
+ break;
392
+ }
393
+ }
394
+
395
+ function resetState(reason) {
396
+ changeState(0, reason);
397
+
398
+ // When experiencing a mid-transaction failure (pending transaction state is increased once a transaction open has
399
+ // been sent), we don't really know what the other side remembers about the transaction (e.g. nothing if it crashed).
400
+ // It's even possible that the transaction itself is causing the problem (e.g. invalid category), so we choose to
401
+ // drop it and disconnect. The drop avoids getting stuck on invalid txns and the disconnect cleans up remote resources.
402
+ if (pendingTxnBuf.length > 0 && pendingTxnBuf[0].state != 0) {
403
+ log.debug("Mid-transaction (id: " + pendingTxnBuf[0].txnId + ") failure: drop/skipping Union Station log");
404
+ pendingTxnBuf.shift();
405
+ }
406
+
407
+ // ensure connection is finished and we don't get any outdated triggers
408
+ resetWatchdog();
409
+
410
+ if (routerConn) {
411
+ routerConn.destroy();
412
+ }
413
+
414
+ setTimeout(function() { pushPendingData(); }, autoRetryAfterMs);
415
+ }
416
+
417
+ function changeState(newRouterState, optReason) {
418
+ log.debug("routerState: " + routerState + " -> " + newRouterState + (optReason ? " due to: " + optReason : ""));
419
+
420
+ routerState = newRouterState;
421
+ }
422
+
423
+ function writeLenString(c, str) {
424
+ len = new Buffer(4);
425
+ nbo.htonl(len, 0, str.length);
426
+ c.write(len);
427
+ c.write(str);
428
+ }
429
+
430
+ function writeLenArray(c, str) {
431
+ len = new Buffer(2);
432
+ nbo.htons(len, 0, str.length);
433
+ c.write(len);
434
+ c.write(str);
435
+ }
436
+
437
+ if (process.env.NODE_ENV === 'test') {
438
+ exports.setDefaults = setDefaults;
439
+ exports.pushPendingData = pushPendingData;
440
+
441
+ exports.getRouterState = function() { return routerState; };
442
+ exports.setPendingTxnBufMaxLength = function(val) { pendingTxnBufMaxLength = val; };
443
+ exports.getPendingTxnBuf = function() { return pendingTxnBuf; };
444
+ exports.setConnTimeoutMs = function(val) { connTimeoutMs = val; };
445
+ exports.setAutoRetryAfterMs = function(val) { autoRetryAfterMs = val; };
446
+ }
@@ -0,0 +1,44 @@
1
+ var codify = module.exports = {};
2
+
3
+ // This function accepts numbers from 0-35
4
+ function character(num) {
5
+ if (num < 10) return String(num);
6
+ return String.fromCharCode(num-10+65);
7
+ }
8
+
9
+ /*
10
+ * Generate an alphanumeric (base-36) code from an integer
11
+ */
12
+ codify.toCode = function(val, minSize) {
13
+ minSize = minSize || 1;
14
+ var code = '';
15
+ while (val >= 1) {
16
+ var remainder = val % 36;
17
+ val = Math.floor(val / 36);
18
+ code = character(remainder)+code;
19
+ }
20
+ while (code.length < minSize) {
21
+ code = '0'+code;
22
+ }
23
+ return code;
24
+ };
25
+
26
+ var digits = {};
27
+ for (var i = 0; i < 10; i++) {
28
+ digits[String(i)] = i;
29
+ }
30
+ for (i = 0; i < 26; i++) {
31
+ digits[String.fromCharCode(i+65)] = i+10;
32
+ }
33
+
34
+ /*
35
+ * Convert an alphanumeric (base-36) code to an integer
36
+ */
37
+ codify.toInt = function(code) {
38
+ var calculated = 0;
39
+ for (var i =0; i < code.length; i++) {
40
+ var num = digits[code.charAt(i)];
41
+ calculated += Math.pow(36, code.length-i-1)*num;
42
+ }
43
+ return calculated;
44
+ };