passenger 3.0.0 → 3.0.1

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 (538) hide show
  1. data/DEVELOPERS.TXT +9 -6
  2. data/NEWS +50 -0
  3. data/Rakefile +2 -1
  4. data/bin/passenger-install-apache2-module +4 -4
  5. data/bin/passenger-install-nginx-module +1 -1
  6. data/bin/passenger-make-enterprisey +1 -1
  7. data/build/agents.rb +26 -19
  8. data/build/apache2.rb +49 -46
  9. data/build/basics.rb +37 -13
  10. data/build/common_library.rb +134 -64
  11. data/build/config.rb +18 -11
  12. data/build/cplusplus_support.rb +4 -0
  13. data/build/cxx_tests.rb +26 -12
  14. data/build/documentation.rb +18 -11
  15. data/build/integration_tests.rb +18 -11
  16. data/build/misc.rb +18 -11
  17. data/build/nginx.rb +27 -19
  18. data/build/oxt_tests.rb +18 -11
  19. data/build/packaging.rb +45 -37
  20. data/build/rpm.rb +98 -0
  21. data/build/ruby_extension.rb +19 -13
  22. data/build/ruby_tests.rb +19 -12
  23. data/build/test_basics.rb +23 -11
  24. data/debian/README.Debian +15 -0
  25. data/debian/changelog +185 -0
  26. data/debian/control +47 -19
  27. data/debian/copyright +20 -0
  28. data/debian/libapache2-mod-passenger.install +1 -0
  29. data/debian/libapache2-mod-passenger.postinst +36 -0
  30. data/debian/libapache2-mod-passenger.prerm +15 -0
  31. data/debian/passenger-common.install +4 -0
  32. data/debian/passenger.conf +4 -0
  33. data/debian/passenger.load +1 -0
  34. data/debian/rules +37 -0
  35. data/debian/watch +3 -0
  36. data/{misc → dev}/copy_boost_headers.rb +3 -0
  37. data/{misc → dev}/find_owner_pipe_leaks.rb +0 -0
  38. data/{misc → dev}/render_error_pages.rb +0 -0
  39. data/doc/Users guide Apache.html +39 -1
  40. data/doc/Users guide Apache.txt +40 -0
  41. data/doc/Users guide Nginx.html +1 -1
  42. data/doc/Users guide Standalone.html +1 -1
  43. data/doc/cxxapi/Constants_8h_source.html +1 -1
  44. data/doc/cxxapi/DirectoryMapper_8h_source.html +6 -22
  45. data/doc/cxxapi/EventedClient_8h_source.html +572 -468
  46. data/doc/cxxapi/Exceptions_8h_source.html +142 -129
  47. data/doc/cxxapi/FileDescriptor_8h_source.html +263 -199
  48. data/doc/cxxapi/MessageChannel_8h_source.html +686 -770
  49. data/doc/cxxapi/MessageServer_8h_source.html +1 -1
  50. data/doc/cxxapi/PoolOptions_8h_source.html +79 -78
  51. data/doc/cxxapi/ResourceLocator_8h_source.html +105 -55
  52. data/doc/cxxapi/SafeLibev_8h_source.html +180 -0
  53. data/doc/cxxapi/ServerInstanceDir_8h_source.html +114 -110
  54. data/doc/cxxapi/Session_8h_source.html +1 -1
  55. data/doc/cxxapi/SpawnManager_8h_source.html +208 -208
  56. data/doc/cxxapi/StaticString_8h_source.html +258 -183
  57. data/doc/cxxapi/Utils_8h_source.html +71 -54
  58. data/doc/cxxapi/annotated.html +3 -0
  59. data/doc/cxxapi/classAgentWatcher.html +2 -2
  60. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +0 -1
  61. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +0 -27
  62. data/doc/cxxapi/classPassenger_1_1EventedClient-members.html +5 -0
  63. data/doc/cxxapi/classPassenger_1_1EventedClient.html +102 -7
  64. data/doc/cxxapi/classPassenger_1_1FileDescriptor-members.html +2 -1
  65. data/doc/cxxapi/classPassenger_1_1FileDescriptor.html +34 -8
  66. data/doc/cxxapi/classPassenger_1_1FileDescriptorPair-members.html +36 -0
  67. data/doc/cxxapi/classPassenger_1_1FileDescriptorPair.html +52 -0
  68. data/doc/cxxapi/classPassenger_1_1MessageChannel-members.html +0 -3
  69. data/doc/cxxapi/classPassenger_1_1MessageChannel.html +0 -120
  70. data/doc/cxxapi/classPassenger_1_1SafeLibev-members.html +36 -0
  71. data/doc/cxxapi/classPassenger_1_1SafeLibev.html +51 -0
  72. data/doc/cxxapi/classPassenger_1_1SpawnException-members.html +1 -0
  73. data/doc/cxxapi/classPassenger_1_1SpawnException.html +22 -0
  74. data/doc/cxxapi/classes.html +14 -14
  75. data/doc/cxxapi/files.html +2 -0
  76. data/doc/cxxapi/functions_0x63.html +6 -3
  77. data/doc/cxxapi/functions_0x64.html +9 -2
  78. data/doc/cxxapi/functions_0x67.html +6 -9
  79. data/doc/cxxapi/functions_0x69.html +3 -0
  80. data/doc/cxxapi/functions_0x77.html +8 -8
  81. data/doc/cxxapi/functions_eval.html +6 -0
  82. data/doc/cxxapi/functions_func.html +18 -17
  83. data/doc/cxxapi/functions_vars.html +8 -0
  84. data/doc/cxxapi/graph_legend.png +0 -0
  85. data/doc/cxxapi/group__Core.png +0 -0
  86. data/doc/cxxapi/group__Hooks.png +0 -0
  87. data/doc/cxxapi/hierarchy.html +3 -0
  88. data/doc/cxxapi/inherit__graph__14.map +1 -1
  89. data/doc/cxxapi/inherit__graph__14.md5 +1 -1
  90. data/doc/cxxapi/inherit__graph__14.png +0 -0
  91. data/doc/cxxapi/inherit__graph__15.map +1 -3
  92. data/doc/cxxapi/inherit__graph__15.md5 +1 -1
  93. data/doc/cxxapi/inherit__graph__15.png +0 -0
  94. data/doc/cxxapi/inherit__graph__16.map +3 -1
  95. data/doc/cxxapi/inherit__graph__16.md5 +1 -1
  96. data/doc/cxxapi/inherit__graph__16.png +0 -0
  97. data/doc/cxxapi/inherit__graph__17.map +1 -1
  98. data/doc/cxxapi/inherit__graph__17.md5 +1 -1
  99. data/doc/cxxapi/inherit__graph__17.png +0 -0
  100. data/doc/cxxapi/inherit__graph__18.map +1 -2
  101. data/doc/cxxapi/inherit__graph__18.md5 +1 -1
  102. data/doc/cxxapi/inherit__graph__18.png +0 -0
  103. data/doc/cxxapi/inherit__graph__19.map +2 -1
  104. data/doc/cxxapi/inherit__graph__19.md5 +1 -1
  105. data/doc/cxxapi/inherit__graph__19.png +0 -0
  106. data/doc/cxxapi/inherit__graph__20.map +1 -1
  107. data/doc/cxxapi/inherit__graph__20.md5 +1 -1
  108. data/doc/cxxapi/inherit__graph__20.png +0 -0
  109. data/doc/cxxapi/inherit__graph__21.map +1 -1
  110. data/doc/cxxapi/inherit__graph__21.md5 +1 -1
  111. data/doc/cxxapi/inherit__graph__21.png +0 -0
  112. data/doc/cxxapi/inherit__graph__22.map +1 -1
  113. data/doc/cxxapi/inherit__graph__22.md5 +1 -1
  114. data/doc/cxxapi/inherit__graph__22.png +0 -0
  115. data/doc/cxxapi/inherit__graph__23.map +1 -1
  116. data/doc/cxxapi/inherit__graph__23.md5 +1 -1
  117. data/doc/cxxapi/inherit__graph__23.png +0 -0
  118. data/doc/cxxapi/inherit__graph__24.map +1 -1
  119. data/doc/cxxapi/inherit__graph__24.md5 +1 -1
  120. data/doc/cxxapi/inherit__graph__24.png +0 -0
  121. data/doc/cxxapi/inherit__graph__25.map +1 -1
  122. data/doc/cxxapi/inherit__graph__25.md5 +1 -1
  123. data/doc/cxxapi/inherit__graph__25.png +0 -0
  124. data/doc/cxxapi/inherit__graph__26.map +1 -1
  125. data/doc/cxxapi/inherit__graph__26.md5 +1 -1
  126. data/doc/cxxapi/inherit__graph__26.png +0 -0
  127. data/doc/cxxapi/inherit__graph__27.map +1 -1
  128. data/doc/cxxapi/inherit__graph__27.md5 +1 -1
  129. data/doc/cxxapi/inherit__graph__27.png +0 -0
  130. data/doc/cxxapi/inherit__graph__28.map +1 -2
  131. data/doc/cxxapi/inherit__graph__28.md5 +1 -1
  132. data/doc/cxxapi/inherit__graph__28.png +0 -0
  133. data/doc/cxxapi/inherit__graph__29.map +1 -1
  134. data/doc/cxxapi/inherit__graph__29.md5 +1 -1
  135. data/doc/cxxapi/inherit__graph__29.png +0 -0
  136. data/doc/cxxapi/inherit__graph__30.map +1 -1
  137. data/doc/cxxapi/inherit__graph__30.md5 +1 -1
  138. data/doc/cxxapi/inherit__graph__30.png +0 -0
  139. data/doc/cxxapi/inherit__graph__31.map +2 -1
  140. data/doc/cxxapi/inherit__graph__31.md5 +1 -1
  141. data/doc/cxxapi/inherit__graph__31.png +0 -0
  142. data/doc/cxxapi/inherit__graph__32.map +1 -3
  143. data/doc/cxxapi/inherit__graph__32.md5 +1 -1
  144. data/doc/cxxapi/inherit__graph__32.png +0 -0
  145. data/doc/cxxapi/inherit__graph__33.map +1 -1
  146. data/doc/cxxapi/inherit__graph__33.md5 +1 -1
  147. data/doc/cxxapi/inherit__graph__33.png +0 -0
  148. data/doc/cxxapi/inherit__graph__34.map +1 -1
  149. data/doc/cxxapi/inherit__graph__34.md5 +1 -1
  150. data/doc/cxxapi/inherit__graph__34.png +0 -0
  151. data/doc/cxxapi/inherit__graph__35.map +3 -1
  152. data/doc/cxxapi/inherit__graph__35.md5 +1 -1
  153. data/doc/cxxapi/inherit__graph__35.png +0 -0
  154. data/doc/cxxapi/inherit__graph__36.map +1 -1
  155. data/doc/cxxapi/inherit__graph__36.md5 +1 -1
  156. data/doc/cxxapi/inherit__graph__36.png +0 -0
  157. data/doc/cxxapi/inherit__graph__37.map +1 -1
  158. data/doc/cxxapi/inherit__graph__37.md5 +1 -1
  159. data/doc/cxxapi/inherit__graph__37.png +0 -0
  160. data/doc/cxxapi/inherit__graph__38.map +3 -1
  161. data/doc/cxxapi/inherit__graph__38.md5 +1 -1
  162. data/doc/cxxapi/inherit__graph__38.png +0 -0
  163. data/doc/cxxapi/inherit__graph__39.map +3 -1
  164. data/doc/cxxapi/inherit__graph__39.md5 +1 -1
  165. data/doc/cxxapi/inherit__graph__39.png +0 -0
  166. data/doc/cxxapi/inherits.html +33 -24
  167. data/doc/cxxapi/namespacePassenger.html +52 -0
  168. data/doc/cxxapi/namespacemembers.html +6 -0
  169. data/doc/cxxapi/namespacemembers_func.html +6 -0
  170. data/doc/cxxapi/tree.html +8 -0
  171. data/ext/apache2/Configuration.cpp +30 -8
  172. data/ext/apache2/Configuration.hpp +15 -14
  173. data/ext/apache2/DirectoryMapper.h +0 -16
  174. data/ext/apache2/Hooks.cpp +30 -29
  175. data/ext/boost/algorithm/string/detail/case_conv.hpp +6 -6
  176. data/ext/boost/algorithm/string/detail/find_format.hpp +14 -4
  177. data/ext/boost/algorithm/string/detail/find_format_all.hpp +13 -3
  178. data/ext/boost/algorithm/string/detail/find_format_store.hpp +11 -0
  179. data/ext/boost/algorithm/string/erase.hpp +2 -2
  180. data/ext/boost/bind/placeholders.hpp +2 -2
  181. data/ext/boost/concept/detail/backward_compatibility.hpp +16 -0
  182. data/ext/boost/concept/detail/general.hpp +15 -6
  183. data/ext/boost/concept/detail/has_constraints.hpp +5 -3
  184. data/ext/boost/concept/usage.hpp +5 -4
  185. data/ext/boost/concept_check.hpp +10 -1
  186. data/ext/boost/config/abi/borland_prefix.hpp +1 -1
  187. data/ext/boost/config/auto_link.hpp +68 -21
  188. data/ext/boost/config/compiler/borland.hpp +11 -3
  189. data/ext/boost/config/compiler/clang.hpp +62 -0
  190. data/ext/boost/config/compiler/codegear.hpp +21 -7
  191. data/ext/boost/config/compiler/common_edg.hpp +4 -2
  192. data/ext/boost/config/compiler/digitalmars.hpp +1 -1
  193. data/ext/boost/config/compiler/gcc.hpp +46 -7
  194. data/ext/boost/config/compiler/gcc_xml.hpp +25 -0
  195. data/ext/boost/config/compiler/intel.hpp +23 -0
  196. data/ext/boost/config/compiler/kai.hpp +1 -1
  197. data/ext/boost/config/compiler/metrowerks.hpp +1 -1
  198. data/ext/boost/config/compiler/nvcc.hpp +86 -0
  199. data/ext/boost/config/compiler/pgi.hpp +18 -3
  200. data/ext/boost/config/compiler/sunpro_cc.hpp +19 -5
  201. data/ext/boost/config/compiler/vacpp.hpp +8 -0
  202. data/ext/boost/config/compiler/visualc.hpp +27 -11
  203. data/ext/boost/config/platform/cygwin.hpp +0 -3
  204. data/ext/boost/config/platform/symbian.hpp +94 -0
  205. data/ext/boost/config/platform/win32.hpp +8 -1
  206. data/ext/boost/config/select_compiler_config.hpp +10 -0
  207. data/ext/boost/config/select_platform_config.hpp +4 -0
  208. data/ext/boost/config/stdlib/dinkumware.hpp +11 -1
  209. data/ext/boost/config/stdlib/libcomo.hpp +1 -0
  210. data/ext/boost/config/stdlib/libstdcpp3.hpp +1 -0
  211. data/ext/boost/config/stdlib/modena.hpp +1 -0
  212. data/ext/boost/config/stdlib/msl.hpp +1 -0
  213. data/ext/boost/config/stdlib/roguewave.hpp +1 -0
  214. data/ext/boost/config/stdlib/sgi.hpp +1 -0
  215. data/ext/boost/config/stdlib/stlport.hpp +1 -0
  216. data/ext/boost/config/stdlib/vacpp.hpp +1 -0
  217. data/ext/boost/config/suffix.hpp +40 -2
  218. data/ext/boost/cstdint.hpp +36 -7
  219. data/ext/boost/date_time/gregorian/conversion.hpp +4 -2
  220. data/ext/boost/date_time/microsec_time_clock.hpp +7 -7
  221. data/ext/boost/date_time/posix_time/conversion.hpp +4 -2
  222. data/ext/boost/date_time/time_facet.hpp +43 -4
  223. data/ext/boost/detail/endian.hpp +5 -2
  224. data/ext/boost/detail/lcast_precision.hpp +2 -2
  225. data/ext/boost/detail/sp_typeinfo.hpp +1 -1
  226. data/ext/boost/detail/workaround.hpp +5 -0
  227. data/ext/boost/exception/detail/error_info_impl.hpp +3 -3
  228. data/ext/boost/exception/detail/exception_ptr.hpp +76 -135
  229. data/ext/boost/exception/detail/is_output_streamable.hpp +15 -2
  230. data/ext/boost/exception/detail/type_info.hpp +9 -5
  231. data/ext/boost/exception/diagnostic_information.hpp +5 -3
  232. data/ext/boost/exception/exception.hpp +60 -46
  233. data/ext/boost/exception/info.hpp +47 -14
  234. data/ext/boost/function/function_base.hpp +4 -4
  235. data/ext/boost/integer.hpp +4 -0
  236. data/ext/boost/integer_fwd.hpp +9 -3
  237. data/ext/boost/iterator/iterator_concepts.hpp +284 -0
  238. data/ext/boost/iterator/transform_iterator.hpp +0 -1
  239. data/ext/boost/make_shared.hpp +17 -0
  240. data/ext/boost/mpl/aux_/config/has_xxx.hpp +4 -3
  241. data/ext/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp +2 -6
  242. data/ext/boost/mpl/aux_/template_arity.hpp +4 -4
  243. data/ext/boost/mpl/eval_if.hpp +3 -3
  244. data/ext/boost/mpl/has_xxx.hpp +369 -3
  245. data/ext/boost/optional/optional.hpp +3 -1
  246. data/ext/boost/optional/optional_fwd.hpp +1 -1
  247. data/ext/boost/preprocessor/repetition/enum_trailing_params.hpp +38 -0
  248. data/ext/boost/range/algorithm/equal.hpp +188 -0
  249. data/ext/boost/range/as_literal.hpp +15 -15
  250. data/ext/boost/range/concepts.hpp +331 -0
  251. data/ext/boost/range/const_iterator.hpp +7 -4
  252. data/ext/boost/range/detail/extract_optional_type.hpp +52 -0
  253. data/ext/boost/range/detail/implementation_help.hpp +7 -7
  254. data/ext/boost/range/detail/misc_concept.hpp +33 -0
  255. data/ext/boost/range/iterator.hpp +32 -32
  256. data/ext/boost/range/iterator_range.hpp +8 -651
  257. data/ext/boost/range/iterator_range_core.hpp +542 -0
  258. data/ext/boost/range/iterator_range_io.hpp +93 -0
  259. data/ext/boost/range/mutable_iterator.hpp +7 -4
  260. data/ext/boost/range/size.hpp +1 -1
  261. data/ext/boost/range/size_type.hpp +2 -1
  262. data/ext/boost/shared_array.hpp +19 -0
  263. data/ext/boost/smart_ptr/detail/sp_convertible.hpp +2 -2
  264. data/ext/boost/smart_ptr/detail/yield_k.hpp +1 -1
  265. data/ext/boost/smart_ptr/make_shared.hpp +508 -0
  266. data/ext/boost/smart_ptr/shared_array.hpp +147 -0
  267. data/ext/boost/src/pthread/thread.cpp +16 -21
  268. data/ext/boost/src/pthread/timeconv.inl +7 -4
  269. data/ext/boost/thread/barrier.hpp +2 -1
  270. data/ext/boost/thread/detail/config.hpp +7 -1
  271. data/ext/boost/thread/detail/platform.hpp +1 -1
  272. data/ext/boost/thread/detail/thread.hpp +62 -18
  273. data/ext/boost/thread/detail/thread_group.hpp +5 -2
  274. data/ext/boost/thread/detail/tss_hooks.hpp +8 -25
  275. data/ext/boost/thread/future.hpp +45 -34
  276. data/ext/boost/thread/locks.hpp +184 -55
  277. data/ext/boost/thread/pthread/condition_variable.hpp +7 -7
  278. data/ext/boost/thread/pthread/condition_variable_fwd.hpp +4 -2
  279. data/ext/boost/thread/pthread/mutex.hpp +29 -17
  280. data/ext/boost/thread/pthread/once.hpp +5 -0
  281. data/ext/boost/thread/pthread/recursive_mutex.hpp +97 -18
  282. data/ext/boost/thread/pthread/shared_mutex.hpp +1 -1
  283. data/ext/boost/thread/pthread/thread_heap_alloc.hpp +1 -1
  284. data/ext/boost/thread/tss.hpp +2 -0
  285. data/ext/boost/throw_exception.hpp +21 -5
  286. data/ext/boost/token_functions.hpp +111 -91
  287. data/ext/boost/type_traits/add_reference.hpp +19 -1
  288. data/ext/boost/type_traits/function_traits.hpp +2 -2
  289. data/ext/boost/type_traits/is_const.hpp +24 -5
  290. data/ext/boost/type_traits/is_convertible.hpp +1 -1
  291. data/ext/boost/type_traits/is_function.hpp +3 -0
  292. data/ext/boost/type_traits/is_lvalue_reference.hpp +118 -0
  293. data/ext/boost/type_traits/is_reference.hpp +8 -81
  294. data/ext/boost/type_traits/is_rvalue_reference.hpp +29 -0
  295. data/ext/boost/type_traits/is_same.hpp +2 -2
  296. data/ext/boost/type_traits/is_volatile.hpp +26 -7
  297. data/ext/boost/type_traits/remove_const.hpp +12 -0
  298. data/ext/boost/type_traits/remove_cv.hpp +23 -1
  299. data/ext/boost/type_traits/remove_reference.hpp +21 -1
  300. data/ext/boost/type_traits/type_with_alignment.hpp +10 -10
  301. data/ext/boost/units/detail/utility.hpp +104 -0
  302. data/ext/boost/utility/compare_pointees.hpp +1 -1
  303. data/ext/common/AgentsStarter.hpp +151 -161
  304. data/ext/common/ApplicationPool/Pool.h +16 -4
  305. data/ext/common/Constants.h +1 -1
  306. data/ext/common/EventedClient.h +130 -26
  307. data/ext/common/Exceptions.h +15 -2
  308. data/ext/common/FileDescriptor.h +76 -12
  309. data/ext/common/IniFile.h +488 -0
  310. data/ext/common/LoggingAgent/LoggingServer.h +2 -2
  311. data/ext/common/LoggingAgent/RemoteSender.h +15 -6
  312. data/ext/common/MessageChannel.h +17 -101
  313. data/ext/common/PoolOptions.h +1 -0
  314. data/ext/common/ResourceLocator.h +78 -28
  315. data/ext/common/SafeLibev.h +149 -0
  316. data/ext/common/ServerInstanceDir.h +11 -7
  317. data/ext/common/Session.h +1 -1
  318. data/ext/common/SpawnManager.h +14 -14
  319. data/ext/common/StaticString.h +75 -0
  320. data/ext/common/Utils.cpp +304 -12
  321. data/ext/common/Utils.h +17 -0
  322. data/ext/common/Utils/BufferedIO.h +196 -0
  323. data/ext/common/Utils/IOUtils.cpp +159 -0
  324. data/ext/common/Utils/IOUtils.h +118 -1
  325. data/ext/common/Utils/ProcessMetricsCollector.h +184 -56
  326. data/ext/common/Utils/StrIntUtils.cpp +45 -11
  327. data/ext/common/Utils/StrIntUtils.h +8 -5
  328. data/ext/common/Utils/Timer.h +22 -0
  329. data/ext/common/Utils/utf8.h +35 -0
  330. data/ext/common/Utils/utf8/checked.h +324 -0
  331. data/ext/common/Utils/utf8/core.h +359 -0
  332. data/ext/common/Utils/utf8/unchecked.h +229 -0
  333. data/ext/common/Watchdog.cpp +52 -85
  334. data/ext/libev/config.h +122 -0
  335. data/ext/nginx/Configuration.c +7 -1
  336. data/ext/nginx/HelperAgent.cpp +16 -18
  337. data/ext/nginx/config +6 -4
  338. data/ext/oxt/system_calls.cpp +10 -0
  339. data/ext/oxt/system_calls.hpp +2 -0
  340. data/lib/phusion_passenger.rb +6 -11
  341. data/lib/phusion_passenger/dependencies.rb +2 -0
  342. data/lib/phusion_passenger/packaging.rb +5 -5
  343. data/lib/phusion_passenger/platform_info.rb +88 -0
  344. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +3 -17
  345. data/lib/phusion_passenger/platform_info/compiler.rb +14 -32
  346. data/lib/phusion_passenger/platform_info/curl.rb +6 -1
  347. data/lib/phusion_passenger/platform_info/operating_system.rb +107 -0
  348. data/lib/phusion_passenger/public_api.rb +2 -2
  349. data/lib/phusion_passenger/rails3_extensions/init.rb +5 -2
  350. data/lib/phusion_passenger/standalone/command.rb +6 -2
  351. data/lib/phusion_passenger/standalone/package_runtime_command.rb +2 -2
  352. data/lib/phusion_passenger/standalone/runtime_installer.rb +17 -5
  353. data/lib/phusion_passenger/standalone/start_command.rb +12 -12
  354. data/lib/phusion_passenger/standalone/stop_command.rb +3 -3
  355. data/lib/phusion_passenger/standalone/utils.rb +6 -2
  356. data/lib/phusion_passenger/templates/standalone/config.erb +37 -5
  357. data/lib/phusion_passenger/utils.rb +4 -7
  358. data/resources/mime.types +73 -0
  359. data/{misc → resources}/union_station_gateway.crt +0 -0
  360. data/test/cxx/BufferedIOTest.cpp +364 -0
  361. data/test/cxx/EventedClientTest.cpp +150 -13
  362. data/test/cxx/IOUtilsTest.cpp +399 -1
  363. data/test/cxx/MessageChannelTest.cpp +5 -120
  364. data/test/cxx/ProcessMetricsCollectorTest.cpp +121 -0
  365. data/test/cxx/StaticStringTest.cpp +134 -0
  366. data/test/cxx/UtilsTest.cpp +16 -46
  367. data/test/stub/rails_apps/2.3/mycook/public/dispatch.cgi +2 -2
  368. data/test/stub/rails_apps/2.3/mycook/public/dispatch.fcgi +1 -1
  369. data/test/stub/rails_apps/2.3/mycook/public/dispatch.rb +1 -1
  370. data/test/stub/rails_apps/3.0/empty/Gemfile.lock +73 -0
  371. data/test/support/allocate_memory.c +14 -0
  372. data/test/support/test_helper.rb +3 -0
  373. metadata +57 -174
  374. data/bin/passenger-stress-test +0 -345
  375. data/debian/postinst +0 -24
  376. data/doc/rdoc/classes/ConditionVariable.html +0 -215
  377. data/doc/rdoc/classes/Exception.html +0 -120
  378. data/doc/rdoc/classes/GC.html +0 -113
  379. data/doc/rdoc/classes/IO.html +0 -221
  380. data/doc/rdoc/classes/PhusionPassenger.html +0 -397
  381. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +0 -180
  382. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +0 -647
  383. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +0 -654
  384. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/InvalidPassword.html +0 -92
  385. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerAlreadyStarted.html +0 -97
  386. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerError.html +0 -96
  387. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/ServerNotStarted.html +0 -97
  388. data/doc/rdoc/classes/PhusionPassenger/AbstractServer/UnknownMessage.html +0 -96
  389. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +0 -619
  390. data/doc/rdoc/classes/PhusionPassenger/AdminTools.html +0 -142
  391. data/doc/rdoc/classes/PhusionPassenger/AdminTools/MemoryStats.html +0 -368
  392. data/doc/rdoc/classes/PhusionPassenger/AdminTools/MemoryStats/Process.html +0 -231
  393. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance.html +0 -588
  394. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/CorruptedDirectoryError.html +0 -92
  395. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/GenerationsAbsentError.html +0 -92
  396. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Group.html +0 -147
  397. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Process.html +0 -279
  398. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/RoleDeniedError.html +0 -92
  399. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/StaleDirectoryError.html +0 -92
  400. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/Stats.html +0 -123
  401. data/doc/rdoc/classes/PhusionPassenger/AdminTools/ServerInstance/UnsupportedGenerationStructureVersionError.html +0 -92
  402. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger.html +0 -341
  403. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/Log.html +0 -294
  404. data/doc/rdoc/classes/PhusionPassenger/AnalyticsLogger/SharedData.html +0 -199
  405. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +0 -155
  406. data/doc/rdoc/classes/PhusionPassenger/AppProcess.html +0 -367
  407. data/doc/rdoc/classes/PhusionPassenger/ClassicRails.html +0 -95
  408. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/ApplicationSpawner.html +0 -351
  409. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/ApplicationSpawner/Error.html +0 -98
  410. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/CGIFixed.html +0 -200
  411. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/FrameworkSpawner.html +0 -410
  412. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/FrameworkSpawner/Error.html +0 -98
  413. data/doc/rdoc/classes/PhusionPassenger/ClassicRails/RequestHandler.html +0 -156
  414. data/doc/rdoc/classes/PhusionPassenger/ClassicRailsExtensions.html +0 -115
  415. data/doc/rdoc/classes/PhusionPassenger/ClassicRailsExtensions/AnalyticsLogging.html +0 -202
  416. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +0 -172
  417. data/doc/rdoc/classes/PhusionPassenger/DebugLogging.html +0 -273
  418. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +0 -145
  419. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +0 -162
  420. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +0 -141
  421. data/doc/rdoc/classes/PhusionPassenger/InvalidPath.html +0 -92
  422. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +0 -673
  423. data/doc/rdoc/classes/PhusionPassenger/MessageChannel/InvalidHashError.html +0 -92
  424. data/doc/rdoc/classes/PhusionPassenger/MessageClient.html +0 -415
  425. data/doc/rdoc/classes/PhusionPassenger/NativeSupportLoader.html +0 -134
  426. data/doc/rdoc/classes/PhusionPassenger/Packaging.html +0 -129
  427. data/doc/rdoc/classes/PhusionPassenger/PlatformInfo.html +0 -1809
  428. data/doc/rdoc/classes/PhusionPassenger/Plugin.html +0 -237
  429. data/doc/rdoc/classes/PhusionPassenger/Rack.html +0 -91
  430. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +0 -312
  431. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner/Error.html +0 -98
  432. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +0 -218
  433. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions.html +0 -114
  434. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging.html +0 -256
  435. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ACExtension.html +0 -139
  436. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ASBenchmarkableExtension.html +0 -118
  437. data/doc/rdoc/classes/PhusionPassenger/Rails3Extensions/AnalyticsLogging/ExceptionLogger.html +0 -135
  438. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +0 -378
  439. data/doc/rdoc/classes/PhusionPassenger/Standalone.html +0 -111
  440. data/doc/rdoc/classes/PhusionPassenger/Standalone/AppFinder.html +0 -252
  441. data/doc/rdoc/classes/PhusionPassenger/Standalone/Command.html +0 -161
  442. data/doc/rdoc/classes/PhusionPassenger/Standalone/ConfigFile.html +0 -368
  443. data/doc/rdoc/classes/PhusionPassenger/Standalone/ConfigFile/DisallowedContextError.html +0 -132
  444. data/doc/rdoc/classes/PhusionPassenger/Standalone/HelpCommand.html +0 -151
  445. data/doc/rdoc/classes/PhusionPassenger/Standalone/Main.html +0 -189
  446. data/doc/rdoc/classes/PhusionPassenger/Standalone/PackageRuntimeCommand.html +0 -177
  447. data/doc/rdoc/classes/PhusionPassenger/Standalone/RuntimeInstaller.html +0 -341
  448. data/doc/rdoc/classes/PhusionPassenger/Standalone/StartCommand.html +0 -203
  449. data/doc/rdoc/classes/PhusionPassenger/Standalone/StatusCommand.html +0 -156
  450. data/doc/rdoc/classes/PhusionPassenger/Standalone/StopCommand.html +0 -168
  451. data/doc/rdoc/classes/PhusionPassenger/Standalone/Utils.html +0 -86
  452. data/doc/rdoc/classes/PhusionPassenger/Standalone/VersionCommand.html +0 -135
  453. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +0 -125
  454. data/doc/rdoc/classes/PhusionPassenger/Utils.html +0 -1550
  455. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher.html +0 -204
  456. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher/DirInfo.html +0 -171
  457. data/doc/rdoc/classes/PhusionPassenger/Utils/FileSystemWatcher/FileInfo.html +0 -140
  458. data/doc/rdoc/classes/PhusionPassenger/Utils/HostsFileParser.html +0 -260
  459. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +0 -169
  460. data/doc/rdoc/classes/PhusionPassenger/Utils/RewindableInput.html +0 -265
  461. data/doc/rdoc/classes/PhusionPassenger/Utils/RewindableInput/Tempfile.html +0 -120
  462. data/doc/rdoc/classes/PhusionPassenger/Utils/UnseekableSocket.html +0 -561
  463. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +0 -140
  464. data/doc/rdoc/classes/PhusionPassenger/WSGI.html +0 -89
  465. data/doc/rdoc/classes/PhusionPassenger/WSGI/ApplicationSpawner.html +0 -182
  466. data/doc/rdoc/classes/Process.html +0 -115
  467. data/doc/rdoc/classes/Signal.html +0 -139
  468. data/doc/rdoc/created.rid +0 -1
  469. data/doc/rdoc/files/DEVELOPERS_TXT.html +0 -276
  470. data/doc/rdoc/files/README.html +0 -157
  471. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +0 -130
  472. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +0 -135
  473. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +0 -126
  474. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +0 -128
  475. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/memory_stats_rb.html +0 -126
  476. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/server_instance_rb.html +0 -132
  477. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +0 -122
  478. data/doc/rdoc/files/lib/phusion_passenger/analytics_logger_rb.html +0 -129
  479. data/doc/rdoc/files/lib/phusion_passenger/app_process_rb.html +0 -127
  480. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/application_spawner_rb.html +0 -141
  481. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/cgi_fixed_rb.html +0 -126
  482. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/framework_spawner_rb.html +0 -146
  483. data/doc/rdoc/files/lib/phusion_passenger/classic_rails/request_handler_rb.html +0 -125
  484. data/doc/rdoc/files/lib/phusion_passenger/classic_rails_extensions/init_rb.html +0 -132
  485. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +0 -126
  486. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +0 -122
  487. data/doc/rdoc/files/lib/phusion_passenger/debug_logging_rb.html +0 -122
  488. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +0 -147
  489. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +0 -122
  490. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +0 -127
  491. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +0 -120
  492. data/doc/rdoc/files/lib/phusion_passenger/message_client_rb.html +0 -127
  493. data/doc/rdoc/files/lib/phusion_passenger/native_support_rb.html +0 -132
  494. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +0 -122
  495. data/doc/rdoc/files/lib/phusion_passenger/platform_info/apache_rb.html +0 -127
  496. data/doc/rdoc/files/lib/phusion_passenger/platform_info/binary_compatibility_rb.html +0 -129
  497. data/doc/rdoc/files/lib/phusion_passenger/platform_info/compiler_rb.html +0 -126
  498. data/doc/rdoc/files/lib/phusion_passenger/platform_info/curl_rb.html +0 -126
  499. data/doc/rdoc/files/lib/phusion_passenger/platform_info/documentation_tools_rb.html +0 -126
  500. data/doc/rdoc/files/lib/phusion_passenger/platform_info/linux_rb.html +0 -126
  501. data/doc/rdoc/files/lib/phusion_passenger/platform_info/operating_system_rb.html +0 -127
  502. data/doc/rdoc/files/lib/phusion_passenger/platform_info/ruby_rb.html +0 -128
  503. data/doc/rdoc/files/lib/phusion_passenger/platform_info/zlib_rb.html +0 -126
  504. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +0 -122
  505. data/doc/rdoc/files/lib/phusion_passenger/plugin_rb.html +0 -127
  506. data/doc/rdoc/files/lib/phusion_passenger/public_api_rb.html +0 -127
  507. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +0 -137
  508. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +0 -125
  509. data/doc/rdoc/files/lib/phusion_passenger/rails3_extensions/init_rb.html +0 -127
  510. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +0 -122
  511. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +0 -160
  512. data/doc/rdoc/files/lib/phusion_passenger/standalone/app_finder_rb.html +0 -127
  513. data/doc/rdoc/files/lib/phusion_passenger/standalone/command_rb.html +0 -135
  514. data/doc/rdoc/files/lib/phusion_passenger/standalone/config_file_rb.html +0 -126
  515. data/doc/rdoc/files/lib/phusion_passenger/standalone/help_command_rb.html +0 -126
  516. data/doc/rdoc/files/lib/phusion_passenger/standalone/main_rb.html +0 -126
  517. data/doc/rdoc/files/lib/phusion_passenger/standalone/package_runtime_command_rb.html +0 -127
  518. data/doc/rdoc/files/lib/phusion_passenger/standalone/runtime_installer_rb.html +0 -133
  519. data/doc/rdoc/files/lib/phusion_passenger/standalone/start_command_rb.html +0 -136
  520. data/doc/rdoc/files/lib/phusion_passenger/standalone/status_command_rb.html +0 -126
  521. data/doc/rdoc/files/lib/phusion_passenger/standalone/stop_command_rb.html +0 -126
  522. data/doc/rdoc/files/lib/phusion_passenger/standalone/utils_rb.html +0 -126
  523. data/doc/rdoc/files/lib/phusion_passenger/standalone/version_command_rb.html +0 -127
  524. data/doc/rdoc/files/lib/phusion_passenger/utils/file_system_watcher_rb.html +0 -126
  525. data/doc/rdoc/files/lib/phusion_passenger/utils/hosts_file_parser_rb.html +0 -120
  526. data/doc/rdoc/files/lib/phusion_passenger/utils/rewindable_input_rb.html +0 -100
  527. data/doc/rdoc/files/lib/phusion_passenger/utils/tmpdir_rb.html +0 -122
  528. data/doc/rdoc/files/lib/phusion_passenger/utils/unseekable_socket_rb.html +0 -126
  529. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +0 -179
  530. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +0 -132
  531. data/doc/rdoc/fr_class_index.html +0 -138
  532. data/doc/rdoc/fr_file_index.html +0 -108
  533. data/doc/rdoc/fr_method_index.html +0 -430
  534. data/doc/rdoc/index.html +0 -26
  535. data/doc/rdoc/rdoc-style.css +0 -187
  536. data/ext/apache2/LICENSE-CNRI.TXT +0 -79
  537. data/ext/common/Utils/BlockingScalar.h +0 -50
  538. data/ext/common/Utils/FileHandleGuard.h +0 -81
@@ -2049,6 +2049,46 @@ following command to give your Rails application folder that context:
2049
2049
  chcon -R -h -t httpd_sys_content_t /path/to/your/rails/app
2050
2050
  -----------------------------------------------------------
2051
2051
 
2052
+ ==== I've deployed my app on SSL, but the app thinks its not on SSL ====
2053
+
2054
+ Rails and many other frameworks infers whether it's running on SSL through the CGI
2055
+ environment variable `HTTPS`. Apache always sets this variable when on SSL,
2056
+ except when SSL is incorrectly configured.
2057
+
2058
+ Most Apache installations already configure SSL by default on port 443
2059
+ (conf/extra/httpd-ssl.conf). Some people think they can save some typing in
2060
+ subsequent SSL vhost blocks, and omit important options like 'SSLEngine on',
2061
+ like this:
2062
+
2063
+ --------------------------------------
2064
+ # httpd-ssl.conf contains something like:
2065
+ # <VirtualHost _default_:443>
2066
+ # SSLEngine on
2067
+ # ...
2068
+ # </VirtualHost>
2069
+ Include conf/extra/httpd-ssl.conf
2070
+
2071
+ <VirtualHost *:443>
2072
+ ServerName www.example.com
2073
+ DocumentRoot /webapps/example/public
2074
+ </Virtualhost>
2075
+ --------------------------------------
2076
+
2077
+ *This is wrong!* In each SSL vhost block you must re-specify all the SSL options.
2078
+ Otherwise Apache won't properly detect the vhost as an SSL vhost block. Here's
2079
+ the corrected example:
2080
+
2081
+ --------------------------------------
2082
+ Include conf/extra/httpd-ssl.conf
2083
+
2084
+ <VirtualHost *:443>
2085
+ ServerName www.example.com
2086
+ DocumentRoot /webapps/example/public
2087
+ SSLEngine on
2088
+ ...more SSL options here...
2089
+ </Virtualhost>
2090
+ --------------------------------------
2091
+
2052
2092
 
2053
2093
  [[conflicting_apache_modules]]
2054
2094
  === Conflicting Apache modules ===
@@ -3426,7 +3426,7 @@ has no effect.</p></div>
3426
3426
  <div id="footnotes"><hr /></div>
3427
3427
  <div id="footer">
3428
3428
  <div id="footer-text">
3429
- Last updated 2010-10-10 20:52:03 CEST
3429
+ Last updated 2010-12-05 20:52:52 CET
3430
3430
  </div>
3431
3431
  </div>
3432
3432
  </body>
@@ -596,7 +596,7 @@ use the <tt>-p</tt> option, e.g.:</p></div>
596
596
  <div id="footnotes"><hr /></div>
597
597
  <div id="footer">
598
598
  <div id="footer-text">
599
- Last updated 2010-10-01 12:22:34 CEST
599
+ Last updated 2010-12-05 20:52:52 CET
600
600
  </div>
601
601
  </div>
602
602
  </body>
@@ -51,7 +51,7 @@
51
51
  <a name="l00026"></a>00026 <span class="preprocessor"></span><span class="preprocessor">#define _PASSENGER_CONSTANTS_H_</span>
52
52
  <a name="l00027"></a>00027 <span class="preprocessor"></span>
53
53
  <a name="l00028"></a>00028 <span class="comment">/* Don&#39;t forget to update lib/phusion_passenger.rb too. */</span>
54
- <a name="l00029"></a>00029 <span class="preprocessor">#define PASSENGER_VERSION &quot;3.0.0&quot;</span>
54
+ <a name="l00029"></a>00029 <span class="preprocessor">#define PASSENGER_VERSION &quot;3.0.1&quot;</span>
55
55
  <a name="l00030"></a>00030 <span class="preprocessor"></span>
56
56
  <a name="l00031"></a>00031 <span class="preprocessor">#define FEEDBACK_FD 3</span>
57
57
  <a name="l00032"></a>00032 <span class="preprocessor"></span>
@@ -297,28 +297,12 @@
297
297
  <a name="l00272"></a>00272 <span class="keywordflow">return</span> NULL;
298
298
  <a name="l00273"></a>00273 };
299
299
  <a name="l00274"></a>00274 }
300
- <a name="l00275"></a>00275 <span class="comment"></span>
301
- <a name="l00276"></a>00276 <span class="comment"> /**</span>
302
- <a name="l00277"></a>00277 <span class="comment"> * Returns the environment under which the application should be spawned.</span>
303
- <a name="l00278"></a>00278 <span class="comment"> *</span>
304
- <a name="l00279"></a>00279 <span class="comment"> * @throws FileSystemException An error occured while examening the filesystem.</span>
305
- <a name="l00280"></a>00280 <span class="comment"> */</span>
306
- <a name="l00281"></a><a class="code" href="classPassenger_1_1DirectoryMapper.html#af5091e3cef3878e160e5d3b2181d82fb">00281</a> <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code" href="classPassenger_1_1DirectoryMapper.html#af5091e3cef3878e160e5d3b2181d82fb" title="Returns the environment under which the application should be spawned.">getEnvironment</a>() {
307
- <a name="l00282"></a>00282 <span class="keywordflow">switch</span> (<a class="code" href="classPassenger_1_1DirectoryMapper.html#aba438d86ca263972a47540956bf11ec1" title="Returns the application type that&amp;#39;s associated with the HTTP request.">getApplicationType</a>()) {
308
- <a name="l00283"></a>00283 <span class="keywordflow">case</span> RAILS:
309
- <a name="l00284"></a>00284 <span class="keywordflow">return</span> config-&gt;getRailsEnv();
310
- <a name="l00285"></a>00285 <span class="keywordflow">case</span> RACK:
311
- <a name="l00286"></a>00286 <span class="keywordflow">return</span> config-&gt;getRackEnv();
312
- <a name="l00287"></a>00287 <span class="keywordflow">default</span>:
313
- <a name="l00288"></a>00288 <span class="keywordflow">return</span> <span class="stringliteral">&quot;production&quot;</span>;
314
- <a name="l00289"></a>00289 }
315
- <a name="l00290"></a>00290 }
316
- <a name="l00291"></a>00291 };
317
- <a name="l00292"></a>00292
318
- <a name="l00293"></a>00293 } <span class="comment">// namespace Passenger</span>
319
- <a name="l00294"></a>00294
320
- <a name="l00295"></a>00295 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_DIRECTORY_MAPPER_H_ */</span>
321
- <a name="l00296"></a>00296
300
+ <a name="l00275"></a>00275 };
301
+ <a name="l00276"></a>00276
302
+ <a name="l00277"></a>00277 } <span class="comment">// namespace Passenger</span>
303
+ <a name="l00278"></a>00278
304
+ <a name="l00279"></a>00279 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_DIRECTORY_MAPPER_H_ */</span>
305
+ <a name="l00280"></a>00280
322
306
  </pre></div></div>
323
307
  <hr size="1"/><address style="text-align: right;"><small>Generated by&nbsp;
324
308
  <a href="http://www.doxygen.org/index.html">
@@ -148,479 +148,583 @@
148
148
  <a name="l00123"></a>00123 <span class="comment"> * method fails to send all data immediately and EventedClient</span>
149
149
  <a name="l00124"></a>00124 <span class="comment"> * schedules some data to be sent later, when the socket becomes</span>
150
150
  <a name="l00125"></a>00125 <span class="comment"> * readable again. In here we will be watching for read</span>
151
- <a name="l00126"></a>00126 <span class="comment"> * and write events.</span>
152
- <a name="l00127"></a>00127 <span class="comment"> */</span>
153
- <a name="l00128"></a>00128 EC_WRITES_PENDING,
154
- <a name="l00129"></a>00129 <span class="comment"></span>
155
- <a name="l00130"></a>00130 <span class="comment"> /**</span>
156
- <a name="l00131"></a>00131 <span class="comment"> * This state is entered from EC_WRITES_PENDING or from EC_CONNECTED</span>
157
- <a name="l00132"></a>00132 <span class="comment"> * when the write() method fails to send all data immediately, and</span>
158
- <a name="l00133"></a>00133 <span class="comment"> * the amount of data to be scheduled to be sent later is larger</span>
159
- <a name="l00134"></a>00134 <span class="comment"> * than the specified outbox limit. In this state, EventedClient</span>
160
- <a name="l00135"></a>00135 <span class="comment"> * will not watch for read events and will instead concentrate on</span>
161
- <a name="l00136"></a>00136 <span class="comment"> * sending out all pending data before watching read events again.</span>
162
- <a name="l00137"></a>00137 <span class="comment"> * When all pending data has been sent out the system will transition</span>
163
- <a name="l00138"></a>00138 <span class="comment"> * to EC_CONNECTED.</span>
164
- <a name="l00139"></a>00139 <span class="comment"> */</span>
165
- <a name="l00140"></a>00140 EC_TOO_MANY_WRITES_PENDING,
166
- <a name="l00141"></a>00141 <span class="comment"></span>
167
- <a name="l00142"></a>00142 <span class="comment"> /**</span>
168
- <a name="l00143"></a>00143 <span class="comment"> * This state is entered from the EC_WRITES_PENDING or the</span>
169
- <a name="l00144"></a>00144 <span class="comment"> * EC_TOO_MANY_WRITES_PENDING state when disconnect() is called.</span>
170
- <a name="l00145"></a>00145 <span class="comment"> * It means that we want to close the connection as soon as all</span>
171
- <a name="l00146"></a>00146 <span class="comment"> * pending outgoing data has been sent. As soon as that happens</span>
172
- <a name="l00147"></a>00147 <span class="comment"> * it&#39;ll transition to EC_DISCONNECTED. In this state no further</span>
173
- <a name="l00148"></a>00148 <span class="comment"> * I/O should be allowed.</span>
174
- <a name="l00149"></a>00149 <span class="comment"> */</span>
175
- <a name="l00150"></a>00150 EC_DISCONNECTING_WITH_WRITES_PENDING,
176
- <a name="l00151"></a>00151 <span class="comment"></span>
177
- <a name="l00152"></a>00152 <span class="comment"> /**</span>
178
- <a name="l00153"></a>00153 <span class="comment"> * Final state. Client connection has been closed. No</span>
179
- <a name="l00154"></a>00154 <span class="comment"> * I/O with the client is possible.</span>
180
- <a name="l00155"></a>00155 <span class="comment"> */</span>
181
- <a name="l00156"></a>00156 EC_DISCONNECTED
182
- <a name="l00157"></a>00157 } state;
183
- <a name="l00158"></a>00158 <span class="comment"></span>
184
- <a name="l00159"></a>00159 <span class="comment"> /** A libev watcher on for watching read events on &lt;tt&gt;fd&lt;/tt&gt;. */</span>
185
- <a name="l00160"></a>00160 ev::io readWatcher;<span class="comment"></span>
186
- <a name="l00161"></a>00161 <span class="comment"> /** A libev watcher on for watching write events on &lt;tt&gt;fd&lt;/tt&gt;. */</span>
187
- <a name="l00162"></a>00162 ev::io writeWatcher;<span class="comment"></span>
188
- <a name="l00163"></a>00163 <span class="comment"> /** Storage for data that could not be sent out immediately. */</span>
189
- <a name="l00164"></a>00164 <span class="keywordtype">string</span> outbox;
190
- <a name="l00165"></a>00165 <span class="keywordtype">int</span> refcount;
191
- <a name="l00166"></a>00166 <span class="keywordtype">bool</span> m_notifyReads;
192
- <a name="l00167"></a>00167 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> outboxLimit;
193
- <a name="l00168"></a>00168
194
- <a name="l00169"></a>00169 <span class="keywordtype">void</span> _onReadable(ev::io &amp;w, <span class="keywordtype">int</span> revents) {
195
- <a name="l00170"></a>00170 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a155988f311fba920bef3031f3d9b6f6a" title="Called when the file descriptor becomes readable and read notifications are enabled...">onReadable</a>);
196
- <a name="l00171"></a>00171 }
197
- <a name="l00172"></a>00172
198
- <a name="l00173"></a>00173 <span class="keywordtype">void</span> onWritable(ev::io &amp;w, <span class="keywordtype">int</span> revents) {
199
- <a name="l00174"></a>00174 assert(state != EC_DISCONNECTED);
200
- <a name="l00175"></a>00175
201
- <a name="l00176"></a>00176 this_thread::disable_interruption di;
202
- <a name="l00177"></a>00177 this_thread::disable_syscall_interruption dsi;
203
- <a name="l00178"></a>00178 <span class="keywordtype">size_t</span> sent = 0;
204
- <a name="l00179"></a>00179 <span class="keywordtype">bool</span> done = outbox.empty();
205
- <a name="l00180"></a>00180
206
- <a name="l00181"></a>00181 <span class="keywordflow">while</span> (!done) {
207
- <a name="l00182"></a>00182 ssize_t ret = syscalls::write(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>,
208
- <a name="l00183"></a>00183 outbox.data() + sent,
209
- <a name="l00184"></a>00184 outbox.size() - sent);
210
- <a name="l00185"></a>00185 <span class="keywordflow">if</span> (ret == -1) {
211
- <a name="l00186"></a>00186 <span class="keywordflow">if</span> (errno != EAGAIN) {
212
- <a name="l00187"></a>00187 <span class="keywordtype">int</span> e = errno;
213
- <a name="l00188"></a>00188 <a class="code" href="classPassenger_1_1EventedClient.html#a5b1a3011165ea9a47f6fe668a5010a20" title="Disconnects the client.">disconnect</a>(<span class="keyword">true</span>);
214
- <a name="l00189"></a>00189 emitSystemErrorEvent(<span class="stringliteral">&quot;Cannot write data to client&quot;</span>, e);
215
- <a name="l00190"></a>00190 <span class="keywordflow">return</span>;
216
- <a name="l00191"></a>00191 }
217
- <a name="l00192"></a>00192 done = <span class="keyword">true</span>;
218
- <a name="l00193"></a>00193 } <span class="keywordflow">else</span> {
219
- <a name="l00194"></a>00194 sent += ret;
220
- <a name="l00195"></a>00195 done = sent == outbox.size();
221
- <a name="l00196"></a>00196 }
222
- <a name="l00197"></a>00197 }
223
- <a name="l00198"></a>00198 <span class="keywordflow">if</span> (sent &gt; 0) {
224
- <a name="l00199"></a>00199 outbox.erase(0, sent);
225
- <a name="l00200"></a>00200 }
151
+ <a name="l00126"></a>00126 <span class="comment"> * and write events. Once all data has been sent out the system</span>
152
+ <a name="l00127"></a>00127 <span class="comment"> * will transition back to EC_CONNECTED.</span>
153
+ <a name="l00128"></a>00128 <span class="comment"> */</span>
154
+ <a name="l00129"></a>00129 EC_WRITES_PENDING,
155
+ <a name="l00130"></a>00130 <span class="comment"></span>
156
+ <a name="l00131"></a>00131 <span class="comment"> /**</span>
157
+ <a name="l00132"></a>00132 <span class="comment"> * This state is entered from EC_WRITES_PENDING or from EC_CONNECTED</span>
158
+ <a name="l00133"></a>00133 <span class="comment"> * when the write() method fails to send all data immediately, and</span>
159
+ <a name="l00134"></a>00134 <span class="comment"> * the amount of data to be scheduled to be sent later is larger</span>
160
+ <a name="l00135"></a>00135 <span class="comment"> * than the specified outbox limit. In this state, EventedClient</span>
161
+ <a name="l00136"></a>00136 <span class="comment"> * will not watch for read events and will instead concentrate on</span>
162
+ <a name="l00137"></a>00137 <span class="comment"> * sending out all pending data before watching read events again.</span>
163
+ <a name="l00138"></a>00138 <span class="comment"> * When all pending data has been sent out the system will transition</span>
164
+ <a name="l00139"></a>00139 <span class="comment"> * to EC_CONNECTED.</span>
165
+ <a name="l00140"></a>00140 <span class="comment"> */</span>
166
+ <a name="l00141"></a>00141 EC_TOO_MANY_WRITES_PENDING,
167
+ <a name="l00142"></a>00142 <span class="comment"></span>
168
+ <a name="l00143"></a>00143 <span class="comment"> /**</span>
169
+ <a name="l00144"></a>00144 <span class="comment"> * This state is like EC_CONNECTED, but indicates that the write</span>
170
+ <a name="l00145"></a>00145 <span class="comment"> * side of the connection has been closed. In this state write()</span>
171
+ <a name="l00146"></a>00146 <span class="comment"> * calls won&#39;t have any effect.</span>
172
+ <a name="l00147"></a>00147 <span class="comment"> */</span>
173
+ <a name="l00148"></a>00148 EC_RO_CONNECTED,
174
+ <a name="l00149"></a>00149 <span class="comment"></span>
175
+ <a name="l00150"></a>00150 <span class="comment"> /**</span>
176
+ <a name="l00151"></a>00151 <span class="comment"> * This state is entered from EC_WRITES_PENDING when</span>
177
+ <a name="l00152"></a>00152 <span class="comment"> * closeWrite() has been called. The system will continue</span>
178
+ <a name="l00153"></a>00153 <span class="comment"> * to send out pending data but write() calls won&#39;t append more</span>
179
+ <a name="l00154"></a>00154 <span class="comment"> * data to the outbox. After pending data has been sent out,</span>
180
+ <a name="l00155"></a>00155 <span class="comment"> * the system will transition to EC_RO_CONNECTED.</span>
181
+ <a name="l00156"></a>00156 <span class="comment"> */</span>
182
+ <a name="l00157"></a>00157 EC_RO_CONNECTED_WITH_WRITES_PENDING,
183
+ <a name="l00158"></a>00158 <span class="comment"></span>
184
+ <a name="l00159"></a>00159 <span class="comment"> /**</span>
185
+ <a name="l00160"></a>00160 <span class="comment"> * This state is entered from the EC_WRITES_PENDING,</span>
186
+ <a name="l00161"></a>00161 <span class="comment"> * EC_TOO_MANY_WRITES_PENDING, EC_RO_CONNECTED_WITH_WIRTES_PENDING</span>
187
+ <a name="l00162"></a>00162 <span class="comment"> * or EC_RO_CONNECTED_WITH_TOO_MANY_WRITES_PENDING state when</span>
188
+ <a name="l00163"></a>00163 <span class="comment"> * disconnect() is called.</span>
189
+ <a name="l00164"></a>00164 <span class="comment"> * It means that we want to close the connection as soon as all</span>
190
+ <a name="l00165"></a>00165 <span class="comment"> * pending outgoing data has been sent. As soon as that happens</span>
191
+ <a name="l00166"></a>00166 <span class="comment"> * it&#39;ll transition to EC_DISCONNECTED. In this state no further</span>
192
+ <a name="l00167"></a>00167 <span class="comment"> * I/O should be allowed.</span>
193
+ <a name="l00168"></a>00168 <span class="comment"> */</span>
194
+ <a name="l00169"></a>00169 EC_DISCONNECTING_WITH_WRITES_PENDING,
195
+ <a name="l00170"></a>00170 <span class="comment"></span>
196
+ <a name="l00171"></a>00171 <span class="comment"> /**</span>
197
+ <a name="l00172"></a>00172 <span class="comment"> * Final state. Client connection has been closed. No</span>
198
+ <a name="l00173"></a>00173 <span class="comment"> * I/O with the client is possible.</span>
199
+ <a name="l00174"></a>00174 <span class="comment"> */</span>
200
+ <a name="l00175"></a>00175 EC_DISCONNECTED
201
+ <a name="l00176"></a>00176 } state;
202
+ <a name="l00177"></a>00177 <span class="comment"></span>
203
+ <a name="l00178"></a>00178 <span class="comment"> /** A libev watcher on for watching read events on &lt;tt&gt;fd&lt;/tt&gt;. */</span>
204
+ <a name="l00179"></a>00179 ev::io readWatcher;<span class="comment"></span>
205
+ <a name="l00180"></a>00180 <span class="comment"> /** A libev watcher on for watching write events on &lt;tt&gt;fd&lt;/tt&gt;. */</span>
206
+ <a name="l00181"></a>00181 ev::io writeWatcher;<span class="comment"></span>
207
+ <a name="l00182"></a>00182 <span class="comment"> /** Storage for data that could not be sent out immediately. */</span>
208
+ <a name="l00183"></a>00183 <span class="keywordtype">string</span> outbox;
209
+ <a name="l00184"></a>00184 <span class="keywordtype">int</span> refcount;
210
+ <a name="l00185"></a>00185 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> outboxLimit;
211
+ <a name="l00186"></a>00186 <span class="keywordtype">bool</span> m_notifyReads;
212
+ <a name="l00187"></a>00187
213
+ <a name="l00188"></a>00188 <span class="keywordtype">void</span> _onReadable(ev::io &amp;w, <span class="keywordtype">int</span> revents) {
214
+ <a name="l00189"></a>00189 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a155988f311fba920bef3031f3d9b6f6a" title="Called when the file descriptor becomes readable and read notifications are enabled...">onReadable</a>);
215
+ <a name="l00190"></a>00190 }
216
+ <a name="l00191"></a>00191
217
+ <a name="l00192"></a>00192 <span class="keywordtype">void</span> onWritable(ev::io &amp;w, <span class="keywordtype">int</span> revents) {
218
+ <a name="l00193"></a>00193 assert(state != EC_CONNECTED);
219
+ <a name="l00194"></a>00194 assert(state != EC_RO_CONNECTED);
220
+ <a name="l00195"></a>00195 assert(state != EC_DISCONNECTED);
221
+ <a name="l00196"></a>00196
222
+ <a name="l00197"></a>00197 this_thread::disable_interruption di;
223
+ <a name="l00198"></a>00198 this_thread::disable_syscall_interruption dsi;
224
+ <a name="l00199"></a>00199 <span class="keywordtype">size_t</span> sent = 0;
225
+ <a name="l00200"></a>00200 <span class="keywordtype">bool</span> done = outbox.empty();
226
226
  <a name="l00201"></a>00201
227
- <a name="l00202"></a>00202 updateWatcherStates();
228
- <a name="l00203"></a>00203 <span class="keywordflow">if</span> (outbox.empty()) {
229
- <a name="l00204"></a>00204 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9" title="Called after all pending outgoing data have been written out.">onPendingDataFlushed</a>);
230
- <a name="l00205"></a>00205 }
231
- <a name="l00206"></a>00206 }
232
- <a name="l00207"></a>00207
233
- <a name="l00208"></a>00208 <span class="keywordtype">bool</span> outboxTooLarge() {
234
- <a name="l00209"></a>00209 <span class="keywordflow">return</span> outbox.size() &gt; 0 &amp;&amp; outbox.size() &gt;= outboxLimit;
235
- <a name="l00210"></a>00210 }
236
- <a name="l00211"></a>00211
237
- <a name="l00212"></a>00212 <span class="keywordtype">void</span> updateWatcherStates() {
238
- <a name="l00213"></a>00213 <span class="keywordflow">if</span> (outbox.empty()) {
239
- <a name="l00214"></a>00214 <span class="keywordflow">switch</span> (state) {
240
- <a name="l00215"></a>00215 <span class="keywordflow">case</span> EC_CONNECTED:
241
- <a name="l00216"></a>00216 watchReadEvents(m_notifyReads);
242
- <a name="l00217"></a>00217 watchWriteEvents(<span class="keyword">false</span>);
243
- <a name="l00218"></a>00218 <span class="keywordflow">break</span>;
244
- <a name="l00219"></a>00219 <span class="keywordflow">case</span> EC_WRITES_PENDING:
245
- <a name="l00220"></a>00220 <span class="keywordflow">case</span> EC_TOO_MANY_WRITES_PENDING:
246
- <a name="l00221"></a>00221 state = EC_CONNECTED;
247
- <a name="l00222"></a>00222 watchReadEvents(m_notifyReads);
248
- <a name="l00223"></a>00223 watchWriteEvents(<span class="keyword">false</span>);
249
- <a name="l00224"></a>00224 <span class="keywordflow">break</span>;
250
- <a name="l00225"></a>00225 <span class="keywordflow">case</span> EC_DISCONNECTING_WITH_WRITES_PENDING:
251
- <a name="l00226"></a>00226 state = EC_DISCONNECTED;
252
- <a name="l00227"></a>00227 watchReadEvents(<span class="keyword">false</span>);
253
- <a name="l00228"></a>00228 watchWriteEvents(<span class="keyword">false</span>);
254
- <a name="l00229"></a>00229 <span class="keywordflow">try</span> {
255
- <a name="l00230"></a>00230 <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>.<a class="code" href="classPassenger_1_1FileDescriptor.html#ad7c1a99531181878cbab74a7400c5432" title="Close the underlying file descriptor.">close</a>();
256
- <a name="l00231"></a>00231 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;e) {
257
- <a name="l00232"></a>00232 emitSystemErrorEvent(e.<a class="code" href="classPassenger_1_1SystemException.html#a84fa2ab4f5b7b96704734fcdfdaa0269" title="Returns a brief version of the exception message.">brief</a>(), e.<a class="code" href="classPassenger_1_1SystemException.html#aee7a6672bf79b72a4c3ee70c57d6a47c" title="The value of errno at the time the error occured.">code</a>());
258
- <a name="l00233"></a>00233 }
259
- <a name="l00234"></a>00234 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d" title="Called when the client is disconnected.">onDisconnect</a>);
260
- <a name="l00235"></a>00235 <span class="keywordflow">break</span>;
261
- <a name="l00236"></a>00236 <span class="keywordflow">default</span>:
262
- <a name="l00237"></a>00237 <span class="comment">// Should never be reached.</span>
263
- <a name="l00238"></a>00238 abort();
264
- <a name="l00239"></a>00239 }
265
- <a name="l00240"></a>00240 } <span class="keywordflow">else</span> {
266
- <a name="l00241"></a>00241 <span class="keywordflow">switch</span> (state) {
267
- <a name="l00242"></a>00242 <span class="keywordflow">case</span> EC_CONNECTED:
268
- <a name="l00243"></a>00243 <span class="keywordflow">if</span> (outboxTooLarge()) {
269
- <a name="l00244"></a>00244 <span class="comment">// If we have way too much stuff in the outbox then</span>
270
- <a name="l00245"></a>00245 <span class="comment">// suspend reading until we&#39;ve sent out the entire outbox.</span>
271
- <a name="l00246"></a>00246 state = EC_TOO_MANY_WRITES_PENDING;
272
- <a name="l00247"></a>00247 watchReadEvents(<span class="keyword">false</span>);
273
- <a name="l00248"></a>00248 watchWriteEvents(<span class="keyword">true</span>);
274
- <a name="l00249"></a>00249 } <span class="keywordflow">else</span> {
275
- <a name="l00250"></a>00250 state = EC_WRITES_PENDING;
276
- <a name="l00251"></a>00251 watchReadEvents(m_notifyReads);
277
- <a name="l00252"></a>00252 watchWriteEvents(<span class="keyword">true</span>);
278
- <a name="l00253"></a>00253 }
279
- <a name="l00254"></a>00254 <span class="keywordflow">break</span>;
280
- <a name="l00255"></a>00255 <span class="keywordflow">case</span> EC_WRITES_PENDING:
281
- <a name="l00256"></a>00256 watchReadEvents(m_notifyReads);
282
- <a name="l00257"></a>00257 watchWriteEvents(<span class="keyword">true</span>);
283
- <a name="l00258"></a>00258 <span class="keywordflow">break</span>;
284
- <a name="l00259"></a>00259 <span class="keywordflow">case</span> EC_TOO_MANY_WRITES_PENDING:
285
- <a name="l00260"></a>00260 <span class="keywordflow">case</span> EC_DISCONNECTING_WITH_WRITES_PENDING:
286
- <a name="l00261"></a>00261 watchReadEvents(<span class="keyword">false</span>);
287
- <a name="l00262"></a>00262 watchWriteEvents(<span class="keyword">true</span>);
288
- <a name="l00263"></a>00263 <span class="keywordflow">break</span>;
289
- <a name="l00264"></a>00264 <span class="keywordflow">default</span>:
290
- <a name="l00265"></a>00265 <span class="comment">// Should never be reached.</span>
291
- <a name="l00266"></a>00266 abort();
292
- <a name="l00267"></a>00267 }
293
- <a name="l00268"></a>00268 }
294
- <a name="l00269"></a>00269 }
295
- <a name="l00270"></a>00270
296
- <a name="l00271"></a>00271 <span class="keywordtype">void</span> watchReadEvents(<span class="keywordtype">bool</span> enable = <span class="keyword">true</span>) {
297
- <a name="l00272"></a>00272 <span class="keywordflow">if</span> (readWatcher.is_active() &amp;&amp; !enable) {
298
- <a name="l00273"></a>00273 readWatcher.stop();
299
- <a name="l00274"></a>00274 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!readWatcher.is_active() &amp;&amp; enable) {
300
- <a name="l00275"></a>00275 readWatcher.start();
301
- <a name="l00276"></a>00276 }
302
- <a name="l00277"></a>00277 }
303
- <a name="l00278"></a>00278
304
- <a name="l00279"></a>00279 <span class="keywordtype">void</span> watchWriteEvents(<span class="keywordtype">bool</span> enable = <span class="keyword">true</span>) {
305
- <a name="l00280"></a>00280 <span class="keywordflow">if</span> (writeWatcher.is_active() &amp;&amp; !enable) {
306
- <a name="l00281"></a>00281 writeWatcher.stop();
307
- <a name="l00282"></a>00282 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!writeWatcher.is_active() &amp;&amp; enable) {
308
- <a name="l00283"></a>00283 writeWatcher.start();
309
- <a name="l00284"></a>00284 }
310
- <a name="l00285"></a>00285 }
311
- <a name="l00286"></a>00286
312
- <a name="l00287"></a>00287 <span class="keywordtype">void</span> emitEvent(Callback callback) {
313
- <a name="l00288"></a>00288 <span class="keywordflow">if</span> (callback != NULL) {
314
- <a name="l00289"></a>00289 callback(<span class="keyword">this</span>);
315
- <a name="l00290"></a>00290 }
316
- <a name="l00291"></a>00291 }
317
- <a name="l00292"></a>00292
318
- <a name="l00293"></a>00293 <span class="keywordtype">void</span> emitSystemErrorEvent(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;message, <span class="keywordtype">int</span> code) {
319
- <a name="l00294"></a>00294 <span class="keywordflow">if</span> (<a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f" title="System call errors are reported with this callback.">onSystemError</a> != NULL) {
320
- <a name="l00295"></a>00295 <a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f" title="System call errors are reported with this callback.">onSystemError</a>(<span class="keyword">this</span>, message, code);
321
- <a name="l00296"></a>00296 }
322
- <a name="l00297"></a>00297 }
323
- <a name="l00298"></a>00298
324
- <a name="l00299"></a>00299 <span class="keyword">public</span>:<span class="comment"></span>
325
- <a name="l00300"></a>00300 <span class="comment"> /** The client&#39;s file descriptor. Could be -1: see &lt;tt&gt;ioAllowed()&lt;/tt&gt;. */</span>
326
- <a name="l00301"></a><a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491">00301</a> <a class="code" href="classPassenger_1_1FileDescriptor.html" title="Wrapper class around a file descriptor integer, for RAII behavior.">FileDescriptor</a> <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>;
327
- <a name="l00302"></a>00302 <span class="comment"></span>
328
- <a name="l00303"></a>00303 <span class="comment"> /**</span>
329
- <a name="l00304"></a>00304 <span class="comment"> * Called when the file descriptor becomes readable and read notifications</span>
330
- <a name="l00305"></a>00305 <span class="comment"> * are enabled (see &lt;tt&gt;notifyRead()&lt;/tt&gt;). When there&#39;s too much pending</span>
331
- <a name="l00306"></a>00306 <span class="comment"> * outgoing data, readability notifications are temporarily disabled; see</span>
332
- <a name="l00307"></a>00307 <span class="comment"> * &lt;tt&gt;write()&lt;/tt&gt; for details.</span>
333
- <a name="l00308"></a>00308 <span class="comment"> */</span>
334
- <a name="l00309"></a><a class="code" href="classPassenger_1_1EventedClient.html#a155988f311fba920bef3031f3d9b6f6a">00309</a> Callback <a class="code" href="classPassenger_1_1EventedClient.html#a155988f311fba920bef3031f3d9b6f6a" title="Called when the file descriptor becomes readable and read notifications are enabled...">onReadable</a>;
335
- <a name="l00310"></a>00310 <span class="comment"></span>
336
- <a name="l00311"></a>00311 <span class="comment"> /**</span>
337
- <a name="l00312"></a>00312 <span class="comment"> * Called when the client is disconnected. This happens either immediately</span>
338
- <a name="l00313"></a>00313 <span class="comment"> * when &lt;tt&gt;disconnect()&lt;/tt&gt; is called, or a short amount of time later.</span>
339
- <a name="l00314"></a>00314 <span class="comment"> * See the documentation for that function for details.</span>
340
- <a name="l00315"></a>00315 <span class="comment"> *</span>
341
- <a name="l00316"></a>00316 <span class="comment"> * Please note that destroying an EventedClient object does *not* cause</span>
342
- <a name="l00317"></a>00317 <span class="comment"> * this callback to be called.</span>
343
- <a name="l00318"></a>00318 <span class="comment"> */</span>
344
- <a name="l00319"></a><a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d">00319</a> Callback <a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d" title="Called when the client is disconnected.">onDisconnect</a>;
345
- <a name="l00320"></a>00320 <span class="comment"></span>
346
- <a name="l00321"></a>00321 <span class="comment"> /**</span>
347
- <a name="l00322"></a>00322 <span class="comment"> * Called when &lt;tt&gt;detach()&lt;/tt&gt; is called for the first time.</span>
348
- <a name="l00323"></a>00323 <span class="comment"> */</span>
349
- <a name="l00324"></a><a class="code" href="classPassenger_1_1EventedClient.html#a742805d40508b0af89eb2ed2c1e50060">00324</a> Callback <a class="code" href="classPassenger_1_1EventedClient.html#a742805d40508b0af89eb2ed2c1e50060" title="Called when detach() is called for the first time.">onDetach</a>;
350
- <a name="l00325"></a>00325 <span class="comment"></span>
351
- <a name="l00326"></a>00326 <span class="comment"> /**</span>
352
- <a name="l00327"></a>00327 <span class="comment"> * Called after all pending outgoing data have been written out.</span>
353
- <a name="l00328"></a>00328 <span class="comment"> * If &lt;tt&gt;write()&lt;/tt&gt; can be completed immediately without scheduling</span>
354
- <a name="l00329"></a>00329 <span class="comment"> * data for later, then &lt;tt&gt;write()&lt;/tt&gt; will call this callback</span>
355
- <a name="l00330"></a>00330 <span class="comment"> * immediately after writing.</span>
356
- <a name="l00331"></a>00331 <span class="comment"> */</span>
357
- <a name="l00332"></a><a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9">00332</a> Callback <a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9" title="Called after all pending outgoing data have been written out.">onPendingDataFlushed</a>;
358
- <a name="l00333"></a>00333 <span class="comment"></span>
359
- <a name="l00334"></a>00334 <span class="comment"> /**</span>
360
- <a name="l00335"></a>00335 <span class="comment"> * System call errors are reported with this callback.</span>
361
- <a name="l00336"></a>00336 <span class="comment"> */</span>
362
- <a name="l00337"></a><a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f">00337</a> SystemErrorCallback <a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f" title="System call errors are reported with this callback.">onSystemError</a>;
227
+ <a name="l00202"></a>00202 <span class="keywordflow">while</span> (!done) {
228
+ <a name="l00203"></a>00203 ssize_t ret = syscalls::write(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>,
229
+ <a name="l00204"></a>00204 outbox.data() + sent,
230
+ <a name="l00205"></a>00205 outbox.size() - sent);
231
+ <a name="l00206"></a>00206 <span class="keywordflow">if</span> (ret == -1) {
232
+ <a name="l00207"></a>00207 <span class="keywordflow">if</span> (errno != EAGAIN) {
233
+ <a name="l00208"></a>00208 <span class="keywordtype">int</span> e = errno;
234
+ <a name="l00209"></a>00209 <span class="keywordflow">if</span> (<a class="code" href="classPassenger_1_1EventedClient.html#afc0934988a978a25538b7d8f2566c90a" title="Controls what to do when a write error is encountered.">writeErrorAction</a> == <a class="code" href="classPassenger_1_1EventedClient.html#a931edf284fed32f74ebf9dc35d993f17a627c2190c3a4dc848dc1a332ef9f5105" title="Forcefully disconnect the client.">DISCONNECT_FULL</a>) {
235
+ <a name="l00210"></a>00210 <a class="code" href="classPassenger_1_1EventedClient.html#a5b1a3011165ea9a47f6fe668a5010a20" title="Disconnects the client.">disconnect</a>(<span class="keyword">true</span>);
236
+ <a name="l00211"></a>00211 } <span class="keywordflow">else</span> {
237
+ <a name="l00212"></a>00212 <a class="code" href="classPassenger_1_1EventedClient.html#a9161e34ddc473c00fe4df8fdb1d1baef" title="Close only the writer side of the client connection.">closeWrite</a>();
238
+ <a name="l00213"></a>00213 }
239
+ <a name="l00214"></a>00214 emitSystemErrorEvent(<span class="stringliteral">&quot;Cannot write data to client&quot;</span>, e);
240
+ <a name="l00215"></a>00215 <span class="keywordflow">return</span>;
241
+ <a name="l00216"></a>00216 }
242
+ <a name="l00217"></a>00217 done = <span class="keyword">true</span>;
243
+ <a name="l00218"></a>00218 } <span class="keywordflow">else</span> {
244
+ <a name="l00219"></a>00219 sent += ret;
245
+ <a name="l00220"></a>00220 done = sent == outbox.size();
246
+ <a name="l00221"></a>00221 }
247
+ <a name="l00222"></a>00222 }
248
+ <a name="l00223"></a>00223 <span class="keywordflow">if</span> (sent &gt; 0) {
249
+ <a name="l00224"></a>00224 outbox.erase(0, sent);
250
+ <a name="l00225"></a>00225 }
251
+ <a name="l00226"></a>00226
252
+ <a name="l00227"></a>00227 updateWatcherStates();
253
+ <a name="l00228"></a>00228 <span class="keywordflow">if</span> (outbox.empty()) {
254
+ <a name="l00229"></a>00229 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9" title="Called after all pending outgoing data have been written out.">onPendingDataFlushed</a>);
255
+ <a name="l00230"></a>00230 }
256
+ <a name="l00231"></a>00231 }
257
+ <a name="l00232"></a>00232
258
+ <a name="l00233"></a>00233 <span class="keywordtype">bool</span> outboxTooLarge() {
259
+ <a name="l00234"></a>00234 <span class="keywordflow">return</span> outbox.size() &gt; 0 &amp;&amp; outbox.size() &gt;= outboxLimit;
260
+ <a name="l00235"></a>00235 }
261
+ <a name="l00236"></a>00236
262
+ <a name="l00237"></a>00237 <span class="keywordtype">void</span> updateWatcherStates() {
263
+ <a name="l00238"></a>00238 <span class="keywordflow">if</span> (outbox.empty()) {
264
+ <a name="l00239"></a>00239 <span class="keywordflow">switch</span> (state) {
265
+ <a name="l00240"></a>00240 <span class="keywordflow">case</span> EC_CONNECTED:
266
+ <a name="l00241"></a>00241 <span class="keywordflow">case</span> EC_RO_CONNECTED:
267
+ <a name="l00242"></a>00242 watchReadEvents(m_notifyReads);
268
+ <a name="l00243"></a>00243 watchWriteEvents(<span class="keyword">false</span>);
269
+ <a name="l00244"></a>00244 <span class="keywordflow">break</span>;
270
+ <a name="l00245"></a>00245 <span class="keywordflow">case</span> EC_WRITES_PENDING:
271
+ <a name="l00246"></a>00246 <span class="keywordflow">case</span> EC_TOO_MANY_WRITES_PENDING:
272
+ <a name="l00247"></a>00247 state = EC_CONNECTED;
273
+ <a name="l00248"></a>00248 watchReadEvents(m_notifyReads);
274
+ <a name="l00249"></a>00249 watchWriteEvents(<span class="keyword">false</span>);
275
+ <a name="l00250"></a>00250 <span class="keywordflow">break</span>;
276
+ <a name="l00251"></a>00251 <span class="keywordflow">case</span> EC_RO_CONNECTED_WITH_WRITES_PENDING:
277
+ <a name="l00252"></a>00252 state = EC_RO_CONNECTED;
278
+ <a name="l00253"></a>00253 watchReadEvents(m_notifyReads);
279
+ <a name="l00254"></a>00254 watchWriteEvents(<span class="keyword">false</span>);
280
+ <a name="l00255"></a>00255 <span class="keywordflow">break</span>;
281
+ <a name="l00256"></a>00256 <span class="keywordflow">case</span> EC_DISCONNECTING_WITH_WRITES_PENDING:
282
+ <a name="l00257"></a>00257 state = EC_DISCONNECTED;
283
+ <a name="l00258"></a>00258 watchReadEvents(<span class="keyword">false</span>);
284
+ <a name="l00259"></a>00259 watchWriteEvents(<span class="keyword">false</span>);
285
+ <a name="l00260"></a>00260 <span class="keywordflow">try</span> {
286
+ <a name="l00261"></a>00261 <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>.<a class="code" href="classPassenger_1_1FileDescriptor.html#a02062f3cfb689b32781e11114c0abe5b" title="Close the underlying file descriptor.">close</a>();
287
+ <a name="l00262"></a>00262 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;e) {
288
+ <a name="l00263"></a>00263 emitSystemErrorEvent(e.<a class="code" href="classPassenger_1_1SystemException.html#a84fa2ab4f5b7b96704734fcdfdaa0269" title="Returns a brief version of the exception message.">brief</a>(), e.<a class="code" href="classPassenger_1_1SystemException.html#aee7a6672bf79b72a4c3ee70c57d6a47c" title="The value of errno at the time the error occured.">code</a>());
289
+ <a name="l00264"></a>00264 }
290
+ <a name="l00265"></a>00265 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d" title="Called when the client is disconnected.">onDisconnect</a>);
291
+ <a name="l00266"></a>00266 <span class="keywordflow">break</span>;
292
+ <a name="l00267"></a>00267 <span class="keywordflow">default</span>:
293
+ <a name="l00268"></a>00268 <span class="comment">// Should never be reached.</span>
294
+ <a name="l00269"></a>00269 abort();
295
+ <a name="l00270"></a>00270 }
296
+ <a name="l00271"></a>00271 } <span class="keywordflow">else</span> {
297
+ <a name="l00272"></a>00272 <span class="keywordflow">switch</span> (state) {
298
+ <a name="l00273"></a>00273 <span class="keywordflow">case</span> EC_CONNECTED:
299
+ <a name="l00274"></a>00274 <span class="keywordflow">if</span> (outboxTooLarge()) {
300
+ <a name="l00275"></a>00275 <span class="comment">// If we have way too much stuff in the outbox then</span>
301
+ <a name="l00276"></a>00276 <span class="comment">// suspend reading until we&#39;ve sent out the entire outbox.</span>
302
+ <a name="l00277"></a>00277 state = EC_TOO_MANY_WRITES_PENDING;
303
+ <a name="l00278"></a>00278 watchReadEvents(<span class="keyword">false</span>);
304
+ <a name="l00279"></a>00279 watchWriteEvents(<span class="keyword">true</span>);
305
+ <a name="l00280"></a>00280 } <span class="keywordflow">else</span> {
306
+ <a name="l00281"></a>00281 state = EC_WRITES_PENDING;
307
+ <a name="l00282"></a>00282 watchReadEvents(m_notifyReads);
308
+ <a name="l00283"></a>00283 watchWriteEvents(<span class="keyword">true</span>);
309
+ <a name="l00284"></a>00284 }
310
+ <a name="l00285"></a>00285 <span class="keywordflow">break</span>;
311
+ <a name="l00286"></a>00286 <span class="keywordflow">case</span> EC_RO_CONNECTED:
312
+ <a name="l00287"></a>00287 fprintf(stderr, <span class="stringliteral">&quot;BUG: when outbox is non-empty the state should never be EC_RO_CONNECTED!\n&quot;</span>);
313
+ <a name="l00288"></a>00288 abort();
314
+ <a name="l00289"></a>00289 <span class="keywordflow">break</span>;
315
+ <a name="l00290"></a>00290 <span class="keywordflow">case</span> EC_WRITES_PENDING:
316
+ <a name="l00291"></a>00291 <span class="keywordflow">case</span> EC_RO_CONNECTED_WITH_WRITES_PENDING:
317
+ <a name="l00292"></a>00292 watchReadEvents(m_notifyReads);
318
+ <a name="l00293"></a>00293 watchWriteEvents(<span class="keyword">true</span>);
319
+ <a name="l00294"></a>00294 <span class="keywordflow">break</span>;
320
+ <a name="l00295"></a>00295 <span class="keywordflow">case</span> EC_TOO_MANY_WRITES_PENDING:
321
+ <a name="l00296"></a>00296 <span class="keywordflow">case</span> EC_DISCONNECTING_WITH_WRITES_PENDING:
322
+ <a name="l00297"></a>00297 watchReadEvents(<span class="keyword">false</span>);
323
+ <a name="l00298"></a>00298 watchWriteEvents(<span class="keyword">true</span>);
324
+ <a name="l00299"></a>00299 <span class="keywordflow">break</span>;
325
+ <a name="l00300"></a>00300 <span class="keywordflow">default</span>:
326
+ <a name="l00301"></a>00301 <span class="comment">// Should never be reached.</span>
327
+ <a name="l00302"></a>00302 abort();
328
+ <a name="l00303"></a>00303 }
329
+ <a name="l00304"></a>00304 }
330
+ <a name="l00305"></a>00305 }
331
+ <a name="l00306"></a>00306
332
+ <a name="l00307"></a>00307 <span class="keywordtype">void</span> watchReadEvents(<span class="keywordtype">bool</span> enable = <span class="keyword">true</span>) {
333
+ <a name="l00308"></a>00308 <span class="keywordflow">if</span> (readWatcher.is_active() &amp;&amp; !enable) {
334
+ <a name="l00309"></a>00309 readWatcher.stop();
335
+ <a name="l00310"></a>00310 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!readWatcher.is_active() &amp;&amp; enable) {
336
+ <a name="l00311"></a>00311 readWatcher.start();
337
+ <a name="l00312"></a>00312 }
338
+ <a name="l00313"></a>00313 }
339
+ <a name="l00314"></a>00314
340
+ <a name="l00315"></a>00315 <span class="keywordtype">void</span> watchWriteEvents(<span class="keywordtype">bool</span> enable = <span class="keyword">true</span>) {
341
+ <a name="l00316"></a>00316 <span class="keywordflow">if</span> (writeWatcher.is_active() &amp;&amp; !enable) {
342
+ <a name="l00317"></a>00317 writeWatcher.stop();
343
+ <a name="l00318"></a>00318 } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (!writeWatcher.is_active() &amp;&amp; enable) {
344
+ <a name="l00319"></a>00319 writeWatcher.start();
345
+ <a name="l00320"></a>00320 }
346
+ <a name="l00321"></a>00321 }
347
+ <a name="l00322"></a>00322
348
+ <a name="l00323"></a>00323 <span class="keywordtype">void</span> emitEvent(Callback callback) {
349
+ <a name="l00324"></a>00324 <span class="keywordflow">if</span> (callback != NULL) {
350
+ <a name="l00325"></a>00325 callback(<span class="keyword">this</span>);
351
+ <a name="l00326"></a>00326 }
352
+ <a name="l00327"></a>00327 }
353
+ <a name="l00328"></a>00328
354
+ <a name="l00329"></a>00329 <span class="keywordtype">void</span> emitSystemErrorEvent(<span class="keyword">const</span> <span class="keywordtype">string</span> &amp;message, <span class="keywordtype">int</span> code) {
355
+ <a name="l00330"></a>00330 <span class="keywordflow">if</span> (<a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f" title="System call errors are reported with this callback.">onSystemError</a> != NULL) {
356
+ <a name="l00331"></a>00331 <a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f" title="System call errors are reported with this callback.">onSystemError</a>(<span class="keyword">this</span>, message, code);
357
+ <a name="l00332"></a>00332 }
358
+ <a name="l00333"></a>00333 }
359
+ <a name="l00334"></a>00334
360
+ <a name="l00335"></a>00335 <span class="keyword">public</span>:<span class="comment"></span>
361
+ <a name="l00336"></a>00336 <span class="comment"> /** The client&#39;s file descriptor. Could be -1: see &lt;tt&gt;ioAllowed()&lt;/tt&gt;. */</span>
362
+ <a name="l00337"></a><a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491">00337</a> <a class="code" href="classPassenger_1_1FileDescriptor.html" title="Wrapper class around a file descriptor integer, for RAII behavior.">FileDescriptor</a> <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>;
363
363
  <a name="l00338"></a>00338 <span class="comment"></span>
364
- <a name="l00339"></a>00339 <span class="comment"> /**</span>
365
- <a name="l00340"></a>00340 <span class="comment"> * EventedClient doesn&#39;t do anything with this. Set it to whatever you want.</span>
366
- <a name="l00341"></a>00341 <span class="comment"> */</span>
367
- <a name="l00342"></a><a class="code" href="classPassenger_1_1EventedClient.html#a793c843b7ba01cc1bb2c568c6539b9e0">00342</a> <span class="keywordtype">void</span> *<a class="code" href="classPassenger_1_1EventedClient.html#a793c843b7ba01cc1bb2c568c6539b9e0" title="EventedClient doesn&amp;#39;t do anything with this.">userData</a>;
368
- <a name="l00343"></a>00343 <span class="comment"></span>
369
- <a name="l00344"></a>00344 <span class="comment"> /**</span>
370
- <a name="l00345"></a>00345 <span class="comment"> * Creates a new EventedClient with the given libev loop and file descriptor.</span>
371
- <a name="l00346"></a>00346 <span class="comment"> * The initial reference count is 1.</span>
372
- <a name="l00347"></a>00347 <span class="comment"> */</span>
373
- <a name="l00348"></a><a class="code" href="classPassenger_1_1EventedClient.html#ac3c45bfa7ac30b6d59ef08dc296f3c4e">00348</a> <a class="code" href="classPassenger_1_1EventedClient.html#ac3c45bfa7ac30b6d59ef08dc296f3c4e" title="Creates a new EventedClient with the given libev loop and file descriptor.">EventedClient</a>(<span class="keyword">struct</span> ev_loop *loop, <span class="keyword">const</span> <a class="code" href="classPassenger_1_1FileDescriptor.html" title="Wrapper class around a file descriptor integer, for RAII behavior.">FileDescriptor</a> &amp;_fd)
374
- <a name="l00349"></a>00349 : readWatcher(loop),
375
- <a name="l00350"></a>00350 writeWatcher(loop),
376
- <a name="l00351"></a>00351 <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>(_fd)
377
- <a name="l00352"></a>00352 {
378
- <a name="l00353"></a>00353 state = EC_CONNECTED;
379
- <a name="l00354"></a>00354 refcount = 1;
380
- <a name="l00355"></a>00355 m_notifyReads = <span class="keyword">false</span>;
381
- <a name="l00356"></a>00356 outboxLimit = 1024 * 32;
382
- <a name="l00357"></a>00357 <a class="code" href="classPassenger_1_1EventedClient.html#a155988f311fba920bef3031f3d9b6f6a" title="Called when the file descriptor becomes readable and read notifications are enabled...">onReadable</a> = NULL;
383
- <a name="l00358"></a>00358 <a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d" title="Called when the client is disconnected.">onDisconnect</a> = NULL;
384
- <a name="l00359"></a>00359 <a class="code" href="classPassenger_1_1EventedClient.html#a742805d40508b0af89eb2ed2c1e50060" title="Called when detach() is called for the first time.">onDetach</a> = NULL;
385
- <a name="l00360"></a>00360 <a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9" title="Called after all pending outgoing data have been written out.">onPendingDataFlushed</a> = NULL;
386
- <a name="l00361"></a>00361 <a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f" title="System call errors are reported with this callback.">onSystemError</a> = NULL;
387
- <a name="l00362"></a>00362 <a class="code" href="classPassenger_1_1EventedClient.html#a793c843b7ba01cc1bb2c568c6539b9e0" title="EventedClient doesn&amp;#39;t do anything with this.">userData</a> = NULL;
388
- <a name="l00363"></a>00363 readWatcher.set(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, ev::READ);
389
- <a name="l00364"></a>00364 readWatcher.set&lt;<a class="code" href="classPassenger_1_1EventedClient.html" title="A utility class for making I/O handling in non-blocking libev evented servers much...">EventedClient</a>, &amp;EventedClient::_onReadable&gt;(<span class="keyword">this</span>);
390
- <a name="l00365"></a>00365 writeWatcher.set&lt;<a class="code" href="classPassenger_1_1EventedClient.html" title="A utility class for making I/O handling in non-blocking libev evented servers much...">EventedClient</a>, &amp;EventedClient::onWritable&gt;(<span class="keyword">this</span>);
391
- <a name="l00366"></a>00366 writeWatcher.set(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, ev::WRITE);
392
- <a name="l00367"></a>00367 }
393
- <a name="l00368"></a>00368
394
- <a name="l00369"></a>00369 <span class="keyword">virtual</span> ~<a class="code" href="classPassenger_1_1EventedClient.html" title="A utility class for making I/O handling in non-blocking libev evented servers much...">EventedClient</a>() {
395
- <a name="l00370"></a>00370 <span class="comment">// Unregister file descriptor from the event loop poller before</span>
396
- <a name="l00371"></a>00371 <span class="comment">// closing the file descriptor.</span>
397
- <a name="l00372"></a>00372 watchReadEvents(<span class="keyword">false</span>);
398
- <a name="l00373"></a>00373 watchWriteEvents(<span class="keyword">false</span>);
399
- <a name="l00374"></a>00374 }
400
- <a name="l00375"></a>00375 <span class="comment"></span>
401
- <a name="l00376"></a>00376 <span class="comment"> /**</span>
402
- <a name="l00377"></a>00377 <span class="comment"> * Increase reference count.</span>
403
- <a name="l00378"></a>00378 <span class="comment"> */</span>
404
- <a name="l00379"></a><a class="code" href="classPassenger_1_1EventedClient.html#aec0aee41bd623d7a3f3cd8ae201ba717">00379</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#aec0aee41bd623d7a3f3cd8ae201ba717" title="Increase reference count.">ref</a>() {
405
- <a name="l00380"></a>00380 refcount++;
406
- <a name="l00381"></a>00381 }
364
+ <a name="l00339"></a>00339 <span class="comment"> /** Controls what to do when a write error is encountered. */</span>
365
+ <a name="l00340"></a>00340 <span class="keyword">enum</span> {<span class="comment"></span>
366
+ <a name="l00341"></a>00341 <span class="comment"> /** Forcefully disconnect the client. */</span>
367
+ <a name="l00342"></a><a class="code" href="classPassenger_1_1EventedClient.html#a931edf284fed32f74ebf9dc35d993f17a627c2190c3a4dc848dc1a332ef9f5105">00342</a> <a class="code" href="classPassenger_1_1EventedClient.html#a931edf284fed32f74ebf9dc35d993f17a627c2190c3a4dc848dc1a332ef9f5105" title="Forcefully disconnect the client.">DISCONNECT_FULL</a>,<span class="comment"></span>
368
+ <a name="l00343"></a>00343 <span class="comment"> /** Close the writer side of the connection, but continue allowing reading. */</span>
369
+ <a name="l00344"></a><a class="code" href="classPassenger_1_1EventedClient.html#a931edf284fed32f74ebf9dc35d993f17a232760bee5b535fd40e609ff8c088693">00344</a> <a class="code" href="classPassenger_1_1EventedClient.html#a931edf284fed32f74ebf9dc35d993f17a232760bee5b535fd40e609ff8c088693" title="Close the writer side of the connection, but continue allowing reading.">DISCONNECT_WRITE</a>
370
+ <a name="l00345"></a>00345 } <a class="code" href="classPassenger_1_1EventedClient.html#afc0934988a978a25538b7d8f2566c90a" title="Controls what to do when a write error is encountered.">writeErrorAction</a>;
371
+ <a name="l00346"></a>00346 <span class="comment"></span>
372
+ <a name="l00347"></a>00347 <span class="comment"> /**</span>
373
+ <a name="l00348"></a>00348 <span class="comment"> * Called when the file descriptor becomes readable and read notifications</span>
374
+ <a name="l00349"></a>00349 <span class="comment"> * are enabled (see &lt;tt&gt;notifyRead()&lt;/tt&gt;). When there&#39;s too much pending</span>
375
+ <a name="l00350"></a>00350 <span class="comment"> * outgoing data, readability notifications are temporarily disabled; see</span>
376
+ <a name="l00351"></a>00351 <span class="comment"> * &lt;tt&gt;write()&lt;/tt&gt; for details.</span>
377
+ <a name="l00352"></a>00352 <span class="comment"> */</span>
378
+ <a name="l00353"></a><a class="code" href="classPassenger_1_1EventedClient.html#a155988f311fba920bef3031f3d9b6f6a">00353</a> Callback <a class="code" href="classPassenger_1_1EventedClient.html#a155988f311fba920bef3031f3d9b6f6a" title="Called when the file descriptor becomes readable and read notifications are enabled...">onReadable</a>;
379
+ <a name="l00354"></a>00354 <span class="comment"></span>
380
+ <a name="l00355"></a>00355 <span class="comment"> /**</span>
381
+ <a name="l00356"></a>00356 <span class="comment"> * Called when the client is disconnected. This happens either immediately</span>
382
+ <a name="l00357"></a>00357 <span class="comment"> * when &lt;tt&gt;disconnect()&lt;/tt&gt; is called, or a short amount of time later.</span>
383
+ <a name="l00358"></a>00358 <span class="comment"> * See the documentation for that function for details.</span>
384
+ <a name="l00359"></a>00359 <span class="comment"> *</span>
385
+ <a name="l00360"></a>00360 <span class="comment"> * Please note that destroying an EventedClient object does *not* cause</span>
386
+ <a name="l00361"></a>00361 <span class="comment"> * this callback to be called.</span>
387
+ <a name="l00362"></a>00362 <span class="comment"> */</span>
388
+ <a name="l00363"></a><a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d">00363</a> Callback <a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d" title="Called when the client is disconnected.">onDisconnect</a>;
389
+ <a name="l00364"></a>00364 <span class="comment"></span>
390
+ <a name="l00365"></a>00365 <span class="comment"> /**</span>
391
+ <a name="l00366"></a>00366 <span class="comment"> * Called when &lt;tt&gt;detach()&lt;/tt&gt; is called for the first time.</span>
392
+ <a name="l00367"></a>00367 <span class="comment"> */</span>
393
+ <a name="l00368"></a><a class="code" href="classPassenger_1_1EventedClient.html#a742805d40508b0af89eb2ed2c1e50060">00368</a> Callback <a class="code" href="classPassenger_1_1EventedClient.html#a742805d40508b0af89eb2ed2c1e50060" title="Called when detach() is called for the first time.">onDetach</a>;
394
+ <a name="l00369"></a>00369 <span class="comment"></span>
395
+ <a name="l00370"></a>00370 <span class="comment"> /**</span>
396
+ <a name="l00371"></a>00371 <span class="comment"> * Called after all pending outgoing data have been written out.</span>
397
+ <a name="l00372"></a>00372 <span class="comment"> * If &lt;tt&gt;write()&lt;/tt&gt; can be completed immediately without scheduling</span>
398
+ <a name="l00373"></a>00373 <span class="comment"> * data for later, then &lt;tt&gt;write()&lt;/tt&gt; will call this callback</span>
399
+ <a name="l00374"></a>00374 <span class="comment"> * immediately after writing.</span>
400
+ <a name="l00375"></a>00375 <span class="comment"> */</span>
401
+ <a name="l00376"></a><a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9">00376</a> Callback <a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9" title="Called after all pending outgoing data have been written out.">onPendingDataFlushed</a>;
402
+ <a name="l00377"></a>00377 <span class="comment"></span>
403
+ <a name="l00378"></a>00378 <span class="comment"> /**</span>
404
+ <a name="l00379"></a>00379 <span class="comment"> * System call errors are reported with this callback.</span>
405
+ <a name="l00380"></a>00380 <span class="comment"> */</span>
406
+ <a name="l00381"></a><a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f">00381</a> SystemErrorCallback <a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f" title="System call errors are reported with this callback.">onSystemError</a>;
407
407
  <a name="l00382"></a>00382 <span class="comment"></span>
408
408
  <a name="l00383"></a>00383 <span class="comment"> /**</span>
409
- <a name="l00384"></a>00384 <span class="comment"> * Decrease reference count. Upon reaching 0, this EventedClient object</span>
410
- <a name="l00385"></a>00385 <span class="comment"> * will be destroyed.</span>
411
- <a name="l00386"></a>00386 <span class="comment"> */</span>
412
- <a name="l00387"></a><a class="code" href="classPassenger_1_1EventedClient.html#a1e480f15dfd339ff781f8daedc5b8190">00387</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#a1e480f15dfd339ff781f8daedc5b8190" title="Decrease reference count.">unref</a>() {
413
- <a name="l00388"></a>00388 refcount--;
414
- <a name="l00389"></a>00389 assert(refcount &gt;= 0);
415
- <a name="l00390"></a>00390 <span class="keywordflow">if</span> (refcount == 0) {
416
- <a name="l00391"></a>00391 <span class="keyword">delete</span> <span class="keyword">this</span>;
417
- <a name="l00392"></a>00392 }
418
- <a name="l00393"></a>00393 }
419
- <a name="l00394"></a>00394 <span class="comment"></span>
420
- <a name="l00395"></a>00395 <span class="comment"> /**</span>
421
- <a name="l00396"></a>00396 <span class="comment"> * Returns whether it is allowed to perform any I/O with this client.</span>
422
- <a name="l00397"></a>00397 <span class="comment"> * Usually true, and false when the client is either being disconnected</span>
423
- <a name="l00398"></a>00398 <span class="comment"> * or has been disconnected. A return value of false indicates that</span>
424
- <a name="l00399"></a>00399 <span class="comment"> * &lt;tt&gt;fd&lt;/tt&gt; might be -1, but even when it isn&#39;t -1 you shouldn&#39;t</span>
425
- <a name="l00400"></a>00400 <span class="comment"> * access &lt;tt&gt;fd&lt;/tt&gt; anymore.</span>
426
- <a name="l00401"></a>00401 <span class="comment"> */</span>
427
- <a name="l00402"></a><a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c">00402</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform any I/O with this client.">ioAllowed</a>()<span class="keyword"> const </span>{
428
- <a name="l00403"></a>00403 <span class="keywordflow">return</span> state != EC_DISCONNECTING_WITH_WRITES_PENDING
429
- <a name="l00404"></a>00404 &amp;&amp; state != EC_DISCONNECTED;
430
- <a name="l00405"></a>00405 }
431
- <a name="l00406"></a>00406 <span class="comment"></span>
432
- <a name="l00407"></a>00407 <span class="comment"> /** Used by unit tests. */</span>
433
- <a name="l00408"></a><a class="code" href="classPassenger_1_1EventedClient.html#a129f6d6a6123c9af1999eca4ae04a75a">00408</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1EventedClient.html#a129f6d6a6123c9af1999eca4ae04a75a" title="Used by unit tests.">readWatcherActive</a>()<span class="keyword"> const </span>{
434
- <a name="l00409"></a>00409 <span class="keywordflow">return</span> readWatcher.is_active();
435
- <a name="l00410"></a>00410 }
436
- <a name="l00411"></a>00411 <span class="comment"></span>
437
- <a name="l00412"></a>00412 <span class="comment"> /**</span>
438
- <a name="l00413"></a>00413 <span class="comment"> * Returns the number of bytes that are scheduled to be sent to the</span>
439
- <a name="l00414"></a>00414 <span class="comment"> * client at a later time.</span>
440
- <a name="l00415"></a>00415 <span class="comment"> * </span>
441
- <a name="l00416"></a>00416 <span class="comment"> * @see write()</span>
442
- <a name="l00417"></a>00417 <span class="comment"> */</span>
443
- <a name="l00418"></a><a class="code" href="classPassenger_1_1EventedClient.html#a0a032e54979b074641ffda807648a6e2">00418</a> <span class="keywordtype">size_t</span> <a class="code" href="classPassenger_1_1EventedClient.html#a0a032e54979b074641ffda807648a6e2" title="Returns the number of bytes that are scheduled to be sent to the client at a later...">pendingWrites</a>()<span class="keyword"> const </span>{
444
- <a name="l00419"></a>00419 <span class="keywordflow">return</span> outbox.size();
445
- <a name="l00420"></a>00420 }
446
- <a name="l00421"></a>00421 <span class="comment"></span>
447
- <a name="l00422"></a>00422 <span class="comment"> /**</span>
448
- <a name="l00423"></a>00423 <span class="comment"> * Sets whether you&#39;re interested in read events. This will start or</span>
449
- <a name="l00424"></a>00424 <span class="comment"> * stop the input readiness watcher appropriately according to the</span>
450
- <a name="l00425"></a>00425 <span class="comment"> * current state.</span>
451
- <a name="l00426"></a>00426 <span class="comment"> *</span>
452
- <a name="l00427"></a>00427 <span class="comment"> * If the client connection is already being closed or has already</span>
453
- <a name="l00428"></a>00428 <span class="comment"> * been closed then this method does nothing.</span>
454
- <a name="l00429"></a>00429 <span class="comment"> */</span>
455
- <a name="l00430"></a><a class="code" href="classPassenger_1_1EventedClient.html#a56ac52f1a4e77c49f72202d16e588f2f">00430</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#a56ac52f1a4e77c49f72202d16e588f2f" title="Sets whether you&amp;#39;re interested in read events.">notifyReads</a>(<span class="keywordtype">bool</span> enable) {
456
- <a name="l00431"></a>00431 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform any I/O with this client.">ioAllowed</a>()) {
457
- <a name="l00432"></a>00432 <span class="keywordflow">return</span>;
458
- <a name="l00433"></a>00433 }
459
- <a name="l00434"></a>00434
460
- <a name="l00435"></a>00435 this_thread::disable_interruption di;
461
- <a name="l00436"></a>00436 this_thread::disable_syscall_interruption dsi;
462
- <a name="l00437"></a>00437 m_notifyReads = enable;
463
- <a name="l00438"></a>00438 updateWatcherStates();
464
- <a name="l00439"></a>00439 }
465
- <a name="l00440"></a>00440 <span class="comment"></span>
466
- <a name="l00441"></a>00441 <span class="comment"> /**</span>
467
- <a name="l00442"></a>00442 <span class="comment"> * Sets a limit on the client outbox. The outbox is where data is stored</span>
468
- <a name="l00443"></a>00443 <span class="comment"> * that could not be immediately sent to the client, e.g. because of</span>
469
- <a name="l00444"></a>00444 <span class="comment"> * network congestion. Whenver the outbox&#39;s size grows past this limit,</span>
470
- <a name="l00445"></a>00445 <span class="comment"> * EventedClient will enter a state in which it will stop listening for</span>
471
- <a name="l00446"></a>00446 <span class="comment"> * read events and instead concentrate on sending out all pending data.</span>
472
- <a name="l00447"></a>00447 <span class="comment"> *</span>
473
- <a name="l00448"></a>00448 <span class="comment"> * Setting this to 0 means that the outbox has an unlimited size. Please</span>
474
- <a name="l00449"></a>00449 <span class="comment"> * note however that this also means that the outbox&#39;s memory could grow</span>
475
- <a name="l00450"></a>00450 <span class="comment"> * unbounded if the client is too slow at receiving data.</span>
476
- <a name="l00451"></a>00451 <span class="comment"> *</span>
477
- <a name="l00452"></a>00452 <span class="comment"> * The default value is some non-zero value.</span>
478
- <a name="l00453"></a>00453 <span class="comment"> *</span>
479
- <a name="l00454"></a>00454 <span class="comment"> * If the client connection is already being closed or has already</span>
480
- <a name="l00455"></a>00455 <span class="comment"> * been closed then this method does nothing.</span>
481
- <a name="l00456"></a>00456 <span class="comment"> */</span>
482
- <a name="l00457"></a><a class="code" href="classPassenger_1_1EventedClient.html#ac1eb48c0d5382a97facbf9af40924849">00457</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#ac1eb48c0d5382a97facbf9af40924849" title="Sets a limit on the client outbox.">setOutboxLimit</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size) {
483
- <a name="l00458"></a>00458 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform any I/O with this client.">ioAllowed</a>()) {
484
- <a name="l00459"></a>00459 <span class="keywordflow">return</span>;
485
- <a name="l00460"></a>00460 }
486
- <a name="l00461"></a>00461
487
- <a name="l00462"></a>00462 this_thread::disable_interruption di;
488
- <a name="l00463"></a>00463 this_thread::disable_syscall_interruption dsi;
489
- <a name="l00464"></a>00464 outboxLimit = size;
490
- <a name="l00465"></a>00465 updateWatcherStates();
491
- <a name="l00466"></a>00466 }
492
- <a name="l00467"></a>00467
493
- <a name="l00468"></a>00468 <span class="keywordtype">void</span> write(<span class="keyword">const</span> <a class="code" href="classPassenger_1_1StaticString.html" title="An immutable, static byte buffer.">StaticString</a> &amp;data) {
494
- <a name="l00469"></a>00469 write(&amp;data, 1);
495
- <a name="l00470"></a>00470 }
496
- <a name="l00471"></a>00471 <span class="comment"></span>
497
- <a name="l00472"></a>00472 <span class="comment"> /**</span>
498
- <a name="l00473"></a>00473 <span class="comment"> * Sends data to this client. This method will try to send the data</span>
499
- <a name="l00474"></a>00474 <span class="comment"> * immediately (in which no intermediate copies of the data will be made),</span>
500
- <a name="l00475"></a>00475 <span class="comment"> * but if the client is not yet ready to receive data (e.g. because of</span>
501
- <a name="l00476"></a>00476 <span class="comment"> * network congestion) then the data will be buffered and scheduled for</span>
502
- <a name="l00477"></a>00477 <span class="comment"> * sending later.</span>
503
- <a name="l00478"></a>00478 <span class="comment"> *</span>
504
- <a name="l00479"></a>00479 <span class="comment"> * If an I/O error was encountered then the client connection will be</span>
505
- <a name="l00480"></a>00480 <span class="comment"> * closed by calling &lt;tt&gt;disconnect(true)&lt;/tt&gt;. This means this method</span>
506
- <a name="l00481"></a>00481 <span class="comment"> * could potentially call the &lt;tt&gt;onDisconnect&lt;/tt&gt; callback.</span>
507
- <a name="l00482"></a>00482 <span class="comment"> *</span>
508
- <a name="l00483"></a>00483 <span class="comment"> * If the client connection is already being closed or has already</span>
509
- <a name="l00484"></a>00484 <span class="comment"> * been closed then this method does nothing.</span>
510
- <a name="l00485"></a>00485 <span class="comment"> *</span>
511
- <a name="l00486"></a>00486 <span class="comment"> * The &lt;tt&gt;onPendingDataFlushed&lt;/tt&gt; callback will be called after</span>
512
- <a name="l00487"></a>00487 <span class="comment"> * this data and whatever existing pending data have been written</span>
513
- <a name="l00488"></a>00488 <span class="comment"> * out. That may either be immediately or after a short period of</span>
514
- <a name="l00489"></a>00489 <span class="comment"> * of time.</span>
515
- <a name="l00490"></a>00490 <span class="comment"> */</span>
516
- <a name="l00491"></a><a class="code" href="classPassenger_1_1EventedClient.html#aa07723456786b9f18b973bd88ff51e27">00491</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#aa07723456786b9f18b973bd88ff51e27" title="Sends data to this client.">write</a>(<span class="keyword">const</span> <a class="code" href="classPassenger_1_1StaticString.html" title="An immutable, static byte buffer.">StaticString</a> data[], <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> count) {
517
- <a name="l00492"></a>00492 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform any I/O with this client.">ioAllowed</a>()) {
518
- <a name="l00493"></a>00493 <span class="keywordflow">return</span>;
519
- <a name="l00494"></a>00494 }
520
- <a name="l00495"></a>00495
521
- <a name="l00496"></a>00496 ssize_t ret;
522
- <a name="l00497"></a>00497 this_thread::disable_interruption di;
523
- <a name="l00498"></a>00498 this_thread::disable_syscall_interruption dsi;
524
- <a name="l00499"></a>00499
525
- <a name="l00500"></a>00500 ret = gatheredWrite(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, data, count, outbox);
526
- <a name="l00501"></a>00501 <span class="keywordflow">if</span> (ret == -1) {
527
- <a name="l00502"></a>00502 <span class="keywordtype">int</span> e = errno;
528
- <a name="l00503"></a>00503 <a class="code" href="classPassenger_1_1EventedClient.html#a5b1a3011165ea9a47f6fe668a5010a20" title="Disconnects the client.">disconnect</a>(<span class="keyword">true</span>);
529
- <a name="l00504"></a>00504 emitSystemErrorEvent(<span class="stringliteral">&quot;Cannot write data to client&quot;</span>, e);
530
- <a name="l00505"></a>00505 } <span class="keywordflow">else</span> {
531
- <a name="l00506"></a>00506 updateWatcherStates();
532
- <a name="l00507"></a>00507 <span class="keywordflow">if</span> (outbox.empty()) {
533
- <a name="l00508"></a>00508 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9" title="Called after all pending outgoing data have been written out.">onPendingDataFlushed</a>);
534
- <a name="l00509"></a>00509 }
535
- <a name="l00510"></a>00510 }
536
- <a name="l00511"></a>00511 }
537
- <a name="l00512"></a>00512 <span class="comment"></span>
538
- <a name="l00513"></a>00513 <span class="comment"> /**</span>
539
- <a name="l00514"></a>00514 <span class="comment"> * Disconnects the client. This actually closes the underlying file</span>
540
- <a name="l00515"></a>00515 <span class="comment"> * descriptor, even if the FileDescriptor object still has references.</span>
409
+ <a name="l00384"></a>00384 <span class="comment"> * EventedClient doesn&#39;t do anything with this. Set it to whatever you want.</span>
410
+ <a name="l00385"></a>00385 <span class="comment"> */</span>
411
+ <a name="l00386"></a><a class="code" href="classPassenger_1_1EventedClient.html#a793c843b7ba01cc1bb2c568c6539b9e0">00386</a> <span class="keywordtype">void</span> *<a class="code" href="classPassenger_1_1EventedClient.html#a793c843b7ba01cc1bb2c568c6539b9e0" title="EventedClient doesn&amp;#39;t do anything with this.">userData</a>;
412
+ <a name="l00387"></a>00387 <span class="comment"></span>
413
+ <a name="l00388"></a>00388 <span class="comment"> /**</span>
414
+ <a name="l00389"></a>00389 <span class="comment"> * Creates a new EventedClient with the given libev loop and file descriptor.</span>
415
+ <a name="l00390"></a>00390 <span class="comment"> * The initial reference count is 1.</span>
416
+ <a name="l00391"></a>00391 <span class="comment"> */</span>
417
+ <a name="l00392"></a><a class="code" href="classPassenger_1_1EventedClient.html#ac3c45bfa7ac30b6d59ef08dc296f3c4e">00392</a> <a class="code" href="classPassenger_1_1EventedClient.html#ac3c45bfa7ac30b6d59ef08dc296f3c4e" title="Creates a new EventedClient with the given libev loop and file descriptor.">EventedClient</a>(<span class="keyword">struct</span> ev_loop *loop, <span class="keyword">const</span> <a class="code" href="classPassenger_1_1FileDescriptor.html" title="Wrapper class around a file descriptor integer, for RAII behavior.">FileDescriptor</a> &amp;_fd)
418
+ <a name="l00393"></a>00393 : readWatcher(loop),
419
+ <a name="l00394"></a>00394 writeWatcher(loop),
420
+ <a name="l00395"></a>00395 <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>(_fd)
421
+ <a name="l00396"></a>00396 {
422
+ <a name="l00397"></a>00397 state = EC_CONNECTED;
423
+ <a name="l00398"></a>00398 refcount = 1;
424
+ <a name="l00399"></a>00399 m_notifyReads = <span class="keyword">false</span>;
425
+ <a name="l00400"></a>00400 outboxLimit = 1024 * 32;
426
+ <a name="l00401"></a>00401 <a class="code" href="classPassenger_1_1EventedClient.html#afc0934988a978a25538b7d8f2566c90a" title="Controls what to do when a write error is encountered.">writeErrorAction</a> = <a class="code" href="classPassenger_1_1EventedClient.html#a931edf284fed32f74ebf9dc35d993f17a627c2190c3a4dc848dc1a332ef9f5105" title="Forcefully disconnect the client.">DISCONNECT_FULL</a>;
427
+ <a name="l00402"></a>00402 <a class="code" href="classPassenger_1_1EventedClient.html#a155988f311fba920bef3031f3d9b6f6a" title="Called when the file descriptor becomes readable and read notifications are enabled...">onReadable</a> = NULL;
428
+ <a name="l00403"></a>00403 <a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d" title="Called when the client is disconnected.">onDisconnect</a> = NULL;
429
+ <a name="l00404"></a>00404 <a class="code" href="classPassenger_1_1EventedClient.html#a742805d40508b0af89eb2ed2c1e50060" title="Called when detach() is called for the first time.">onDetach</a> = NULL;
430
+ <a name="l00405"></a>00405 <a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9" title="Called after all pending outgoing data have been written out.">onPendingDataFlushed</a> = NULL;
431
+ <a name="l00406"></a>00406 <a class="code" href="classPassenger_1_1EventedClient.html#a9522b2c5a42d75a93ed865e74510818f" title="System call errors are reported with this callback.">onSystemError</a> = NULL;
432
+ <a name="l00407"></a>00407 <a class="code" href="classPassenger_1_1EventedClient.html#a793c843b7ba01cc1bb2c568c6539b9e0" title="EventedClient doesn&amp;#39;t do anything with this.">userData</a> = NULL;
433
+ <a name="l00408"></a>00408 readWatcher.set(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, ev::READ);
434
+ <a name="l00409"></a>00409 readWatcher.set&lt;<a class="code" href="classPassenger_1_1EventedClient.html" title="A utility class for making I/O handling in non-blocking libev evented servers much...">EventedClient</a>, &amp;EventedClient::_onReadable&gt;(<span class="keyword">this</span>);
435
+ <a name="l00410"></a>00410 writeWatcher.set&lt;<a class="code" href="classPassenger_1_1EventedClient.html" title="A utility class for making I/O handling in non-blocking libev evented servers much...">EventedClient</a>, &amp;EventedClient::onWritable&gt;(<span class="keyword">this</span>);
436
+ <a name="l00411"></a>00411 writeWatcher.set(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, ev::WRITE);
437
+ <a name="l00412"></a>00412 }
438
+ <a name="l00413"></a>00413
439
+ <a name="l00414"></a>00414 <span class="keyword">virtual</span> ~<a class="code" href="classPassenger_1_1EventedClient.html" title="A utility class for making I/O handling in non-blocking libev evented servers much...">EventedClient</a>() {
440
+ <a name="l00415"></a>00415 <span class="comment">// Unregister file descriptor from the event loop poller before</span>
441
+ <a name="l00416"></a>00416 <span class="comment">// closing the file descriptor.</span>
442
+ <a name="l00417"></a>00417 watchReadEvents(<span class="keyword">false</span>);
443
+ <a name="l00418"></a>00418 watchWriteEvents(<span class="keyword">false</span>);
444
+ <a name="l00419"></a>00419 }
445
+ <a name="l00420"></a>00420 <span class="comment"></span>
446
+ <a name="l00421"></a>00421 <span class="comment"> /**</span>
447
+ <a name="l00422"></a>00422 <span class="comment"> * Increase reference count.</span>
448
+ <a name="l00423"></a>00423 <span class="comment"> */</span>
449
+ <a name="l00424"></a><a class="code" href="classPassenger_1_1EventedClient.html#aec0aee41bd623d7a3f3cd8ae201ba717">00424</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#aec0aee41bd623d7a3f3cd8ae201ba717" title="Increase reference count.">ref</a>() {
450
+ <a name="l00425"></a>00425 refcount++;
451
+ <a name="l00426"></a>00426 }
452
+ <a name="l00427"></a>00427 <span class="comment"></span>
453
+ <a name="l00428"></a>00428 <span class="comment"> /**</span>
454
+ <a name="l00429"></a>00429 <span class="comment"> * Decrease reference count. Upon reaching 0, this EventedClient object</span>
455
+ <a name="l00430"></a>00430 <span class="comment"> * will be destroyed.</span>
456
+ <a name="l00431"></a>00431 <span class="comment"> */</span>
457
+ <a name="l00432"></a><a class="code" href="classPassenger_1_1EventedClient.html#a1e480f15dfd339ff781f8daedc5b8190">00432</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#a1e480f15dfd339ff781f8daedc5b8190" title="Decrease reference count.">unref</a>() {
458
+ <a name="l00433"></a>00433 refcount--;
459
+ <a name="l00434"></a>00434 assert(refcount &gt;= 0);
460
+ <a name="l00435"></a>00435 <span class="keywordflow">if</span> (refcount == 0) {
461
+ <a name="l00436"></a>00436 <span class="keyword">delete</span> <span class="keyword">this</span>;
462
+ <a name="l00437"></a>00437 }
463
+ <a name="l00438"></a>00438 }
464
+ <a name="l00439"></a>00439 <span class="comment"></span>
465
+ <a name="l00440"></a>00440 <span class="comment"> /**</span>
466
+ <a name="l00441"></a>00441 <span class="comment"> * Returns whether it is allowed to perform some kind of I/O with</span>
467
+ <a name="l00442"></a>00442 <span class="comment"> * this client, either reading or writing.</span>
468
+ <a name="l00443"></a>00443 <span class="comment"> * Usually true, and false when the client is either being disconnected</span>
469
+ <a name="l00444"></a>00444 <span class="comment"> * or has been disconnected. A return value of false indicates that</span>
470
+ <a name="l00445"></a>00445 <span class="comment"> * &lt;tt&gt;fd&lt;/tt&gt; might be -1, but even when it isn&#39;t -1 you shouldn&#39;t</span>
471
+ <a name="l00446"></a>00446 <span class="comment"> * access &lt;tt&gt;fd&lt;/tt&gt; anymore.</span>
472
+ <a name="l00447"></a>00447 <span class="comment"> * When the connection is half-closed (e.g. after closeWrite() has</span>
473
+ <a name="l00448"></a>00448 <span class="comment"> * been called) the return value is still be true. Only when I/O of any</span>
474
+ <a name="l00449"></a>00449 <span class="comment"> * kind is disallowed will this function return false.</span>
475
+ <a name="l00450"></a>00450 <span class="comment"> */</span>
476
+ <a name="l00451"></a><a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c">00451</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform some kind of I/O with this client, either...">ioAllowed</a>()<span class="keyword"> const </span>{
477
+ <a name="l00452"></a>00452 <span class="keywordflow">return</span> state != EC_DISCONNECTING_WITH_WRITES_PENDING
478
+ <a name="l00453"></a>00453 &amp;&amp; state != EC_DISCONNECTED;
479
+ <a name="l00454"></a>00454 }
480
+ <a name="l00455"></a>00455 <span class="comment"></span>
481
+ <a name="l00456"></a>00456 <span class="comment"> /**</span>
482
+ <a name="l00457"></a>00457 <span class="comment"> * Returns whether it is allowed to write data to the client.</span>
483
+ <a name="l00458"></a>00458 <span class="comment"> * Usually true, and false when the client is either being disconnected</span>
484
+ <a name="l00459"></a>00459 <span class="comment"> * or has been disconnected or when the writer side of the client</span>
485
+ <a name="l00460"></a>00460 <span class="comment"> * connection has been closed. write() will do nothing if this function</span>
486
+ <a name="l00461"></a>00461 <span class="comment"> * returns false.</span>
487
+ <a name="l00462"></a>00462 <span class="comment"> */</span>
488
+ <a name="l00463"></a><a class="code" href="classPassenger_1_1EventedClient.html#aca719fb03ade09839827a16caa0e6e30">00463</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1EventedClient.html#aca719fb03ade09839827a16caa0e6e30" title="Returns whether it is allowed to write data to the client.">writeAllowed</a>()<span class="keyword"> const </span>{
489
+ <a name="l00464"></a>00464 <span class="keywordflow">return</span> state == EC_CONNECTED
490
+ <a name="l00465"></a>00465 || state == EC_WRITES_PENDING
491
+ <a name="l00466"></a>00466 || state == EC_TOO_MANY_WRITES_PENDING
492
+ <a name="l00467"></a>00467 || state == EC_RO_CONNECTED_WITH_WRITES_PENDING;
493
+ <a name="l00468"></a>00468 }
494
+ <a name="l00469"></a>00469 <span class="comment"></span>
495
+ <a name="l00470"></a>00470 <span class="comment"> /** Used by unit tests. */</span>
496
+ <a name="l00471"></a><a class="code" href="classPassenger_1_1EventedClient.html#a129f6d6a6123c9af1999eca4ae04a75a">00471</a> <span class="keywordtype">bool</span> <a class="code" href="classPassenger_1_1EventedClient.html#a129f6d6a6123c9af1999eca4ae04a75a" title="Used by unit tests.">readWatcherActive</a>()<span class="keyword"> const </span>{
497
+ <a name="l00472"></a>00472 <span class="keywordflow">return</span> readWatcher.is_active();
498
+ <a name="l00473"></a>00473 }
499
+ <a name="l00474"></a>00474 <span class="comment"></span>
500
+ <a name="l00475"></a>00475 <span class="comment"> /**</span>
501
+ <a name="l00476"></a>00476 <span class="comment"> * Returns the number of bytes that are scheduled to be sent to the</span>
502
+ <a name="l00477"></a>00477 <span class="comment"> * client at a later time.</span>
503
+ <a name="l00478"></a>00478 <span class="comment"> * </span>
504
+ <a name="l00479"></a>00479 <span class="comment"> * @see write()</span>
505
+ <a name="l00480"></a>00480 <span class="comment"> */</span>
506
+ <a name="l00481"></a><a class="code" href="classPassenger_1_1EventedClient.html#a0a032e54979b074641ffda807648a6e2">00481</a> <span class="keywordtype">size_t</span> <a class="code" href="classPassenger_1_1EventedClient.html#a0a032e54979b074641ffda807648a6e2" title="Returns the number of bytes that are scheduled to be sent to the client at a later...">pendingWrites</a>()<span class="keyword"> const </span>{
507
+ <a name="l00482"></a>00482 <span class="keywordflow">return</span> outbox.size();
508
+ <a name="l00483"></a>00483 }
509
+ <a name="l00484"></a>00484 <span class="comment"></span>
510
+ <a name="l00485"></a>00485 <span class="comment"> /**</span>
511
+ <a name="l00486"></a>00486 <span class="comment"> * Sets whether you&#39;re interested in read events. This will start or</span>
512
+ <a name="l00487"></a>00487 <span class="comment"> * stop the input readiness watcher appropriately according to the</span>
513
+ <a name="l00488"></a>00488 <span class="comment"> * current state.</span>
514
+ <a name="l00489"></a>00489 <span class="comment"> *</span>
515
+ <a name="l00490"></a>00490 <span class="comment"> * If the client connection is already being closed or has already</span>
516
+ <a name="l00491"></a>00491 <span class="comment"> * been closed then this method does nothing.</span>
517
+ <a name="l00492"></a>00492 <span class="comment"> */</span>
518
+ <a name="l00493"></a><a class="code" href="classPassenger_1_1EventedClient.html#a56ac52f1a4e77c49f72202d16e588f2f">00493</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#a56ac52f1a4e77c49f72202d16e588f2f" title="Sets whether you&amp;#39;re interested in read events.">notifyReads</a>(<span class="keywordtype">bool</span> enable) {
519
+ <a name="l00494"></a>00494 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform some kind of I/O with this client, either...">ioAllowed</a>()) {
520
+ <a name="l00495"></a>00495 <span class="keywordflow">return</span>;
521
+ <a name="l00496"></a>00496 }
522
+ <a name="l00497"></a>00497
523
+ <a name="l00498"></a>00498 this_thread::disable_interruption di;
524
+ <a name="l00499"></a>00499 this_thread::disable_syscall_interruption dsi;
525
+ <a name="l00500"></a>00500 m_notifyReads = enable;
526
+ <a name="l00501"></a>00501 updateWatcherStates();
527
+ <a name="l00502"></a>00502 }
528
+ <a name="l00503"></a>00503 <span class="comment"></span>
529
+ <a name="l00504"></a>00504 <span class="comment"> /**</span>
530
+ <a name="l00505"></a>00505 <span class="comment"> * Sets a limit on the client outbox. The outbox is where data is stored</span>
531
+ <a name="l00506"></a>00506 <span class="comment"> * that could not be immediately sent to the client, e.g. because of</span>
532
+ <a name="l00507"></a>00507 <span class="comment"> * network congestion. Whenver the outbox&#39;s size grows past this limit,</span>
533
+ <a name="l00508"></a>00508 <span class="comment"> * EventedClient will enter a state in which it will stop listening for</span>
534
+ <a name="l00509"></a>00509 <span class="comment"> * read events and instead concentrate on sending out all pending data.</span>
535
+ <a name="l00510"></a>00510 <span class="comment"> *</span>
536
+ <a name="l00511"></a>00511 <span class="comment"> * Setting this to 0 means that the outbox has an unlimited size. Please</span>
537
+ <a name="l00512"></a>00512 <span class="comment"> * note however that this also means that the outbox&#39;s memory could grow</span>
538
+ <a name="l00513"></a>00513 <span class="comment"> * unbounded if the client is too slow at receiving data.</span>
539
+ <a name="l00514"></a>00514 <span class="comment"> *</span>
540
+ <a name="l00515"></a>00515 <span class="comment"> * The default value is some non-zero value.</span>
541
541
  <a name="l00516"></a>00516 <span class="comment"> *</span>
542
- <a name="l00517"></a>00517 <span class="comment"> * If &lt;em&gt;force&lt;/em&gt; is true then the client will be disconnected</span>
543
- <a name="l00518"></a>00518 <span class="comment"> * immediately, and any pending outgoing data will be discarded.</span>
544
- <a name="l00519"></a>00519 <span class="comment"> * Otherwise the client will be disconnected after all pending</span>
545
- <a name="l00520"></a>00520 <span class="comment"> * outgoing data have been sent; in the mean time no new data can be</span>
546
- <a name="l00521"></a>00521 <span class="comment"> * received from or sent to the client.</span>
547
- <a name="l00522"></a>00522 <span class="comment"> *</span>
548
- <a name="l00523"></a>00523 <span class="comment"> * After the client has actually been disconnected (which may be either</span>
549
- <a name="l00524"></a>00524 <span class="comment"> * immediately or after a short period of time), a disconnect event will</span>
550
- <a name="l00525"></a>00525 <span class="comment"> * be emitted.</span>
551
- <a name="l00526"></a>00526 <span class="comment"> *</span>
552
- <a name="l00527"></a>00527 <span class="comment"> * If the client connection has already been closed then this method</span>
553
- <a name="l00528"></a>00528 <span class="comment"> * does nothing. If the client connection is being closed (because</span>
554
- <a name="l00529"></a>00529 <span class="comment"> * there&#39;s pending outgoing data) then the behavior depends on the</span>
555
- <a name="l00530"></a>00530 <span class="comment"> * &lt;tt&gt;force&lt;/tt&gt; argument: if true then the connection is closed</span>
556
- <a name="l00531"></a>00531 <span class="comment"> * immediately and the pending data is discarded, otherwise this</span>
557
- <a name="l00532"></a>00532 <span class="comment"> * method does nothing.</span>
558
- <a name="l00533"></a>00533 <span class="comment"> *</span>
559
- <a name="l00534"></a>00534 <span class="comment"> * The &lt;tt&gt;onDisconnect&lt;/tt&gt; callback will be called after the file</span>
560
- <a name="l00535"></a>00535 <span class="comment"> * descriptor is closed, which is either immediately or after all</span>
561
- <a name="l00536"></a>00536 <span class="comment"> * pending data has been sent out.</span>
562
- <a name="l00537"></a>00537 <span class="comment"> */</span>
563
- <a name="l00538"></a><a class="code" href="classPassenger_1_1EventedClient.html#a5b1a3011165ea9a47f6fe668a5010a20">00538</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#a5b1a3011165ea9a47f6fe668a5010a20" title="Disconnects the client.">disconnect</a>(<span class="keywordtype">bool</span> force = <span class="keyword">false</span>) {
564
- <a name="l00539"></a>00539 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform any I/O with this client.">ioAllowed</a>() &amp;&amp; !(state == EC_DISCONNECTING_WITH_WRITES_PENDING &amp;&amp; force)) {
565
- <a name="l00540"></a>00540 <span class="keywordflow">return</span>;
566
- <a name="l00541"></a>00541 }
567
- <a name="l00542"></a>00542
568
- <a name="l00543"></a>00543 this_thread::disable_interruption di;
569
- <a name="l00544"></a>00544 this_thread::disable_syscall_interruption dsi;
570
- <a name="l00545"></a>00545
571
- <a name="l00546"></a>00546 <span class="keywordflow">if</span> (state == EC_CONNECTED || force) {
572
- <a name="l00547"></a>00547 state = EC_DISCONNECTED;
573
- <a name="l00548"></a>00548 watchReadEvents(<span class="keyword">false</span>);
574
- <a name="l00549"></a>00549 watchWriteEvents(<span class="keyword">false</span>);
575
- <a name="l00550"></a>00550 <span class="keywordflow">try</span> {
576
- <a name="l00551"></a>00551 <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>.<a class="code" href="classPassenger_1_1FileDescriptor.html#ad7c1a99531181878cbab74a7400c5432" title="Close the underlying file descriptor.">close</a>();
577
- <a name="l00552"></a>00552 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;e) {
578
- <a name="l00553"></a>00553 emitSystemErrorEvent(e.<a class="code" href="classPassenger_1_1SystemException.html#a84fa2ab4f5b7b96704734fcdfdaa0269" title="Returns a brief version of the exception message.">brief</a>(), e.<a class="code" href="classPassenger_1_1SystemException.html#aee7a6672bf79b72a4c3ee70c57d6a47c" title="The value of errno at the time the error occured.">code</a>());
579
- <a name="l00554"></a>00554 }
580
- <a name="l00555"></a>00555 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d" title="Called when the client is disconnected.">onDisconnect</a>);
581
- <a name="l00556"></a>00556 } <span class="keywordflow">else</span> {
582
- <a name="l00557"></a>00557 state = EC_DISCONNECTING_WITH_WRITES_PENDING;
583
- <a name="l00558"></a>00558 watchReadEvents(<span class="keyword">false</span>);
584
- <a name="l00559"></a>00559 watchWriteEvents(<span class="keyword">true</span>);
585
- <a name="l00560"></a>00560 <span class="keywordflow">if</span> (syscalls::shutdown(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, SHUT_RD) == -1) {
586
- <a name="l00561"></a>00561 <span class="keywordtype">int</span> e = errno;
587
- <a name="l00562"></a>00562 emitSystemErrorEvent(
588
- <a name="l00563"></a>00563 <span class="stringliteral">&quot;Cannot shutdown reader half of the client socket&quot;</span>,
589
- <a name="l00564"></a>00564 e);
590
- <a name="l00565"></a>00565 }
591
- <a name="l00566"></a>00566 }
592
- <a name="l00567"></a>00567 }
593
- <a name="l00568"></a>00568 <span class="comment"></span>
594
- <a name="l00569"></a>00569 <span class="comment"> /**</span>
595
- <a name="l00570"></a>00570 <span class="comment"> * Detaches the client file descriptor so that this EventedClient no longer</span>
596
- <a name="l00571"></a>00571 <span class="comment"> * has any control over it. Any EventedClient I/O watchers on the client file</span>
597
- <a name="l00572"></a>00572 <span class="comment"> * descriptor will be stopped and further I/O on the file descriptor via</span>
598
- <a name="l00573"></a>00573 <span class="comment"> * EventedClient will become impossible. The original client file descriptor</span>
599
- <a name="l00574"></a>00574 <span class="comment"> * is returned and &lt;tt&gt;onDetach&lt;/tt&gt; is called. Subsequent calls to this</span>
600
- <a name="l00575"></a>00575 <span class="comment"> * function will return -1 and will no longer call &lt;tt&gt;onDetach&lt;/tt&gt;.</span>
601
- <a name="l00576"></a>00576 <span class="comment"> *</span>
602
- <a name="l00577"></a>00577 <span class="comment"> * @post !ioAllowed()</span>
603
- <a name="l00578"></a>00578 <span class="comment"> * @post fd == -1</span>
604
- <a name="l00579"></a>00579 <span class="comment"> */</span>
605
- <a name="l00580"></a><a class="code" href="classPassenger_1_1EventedClient.html#a408b593d118c3483bcef8118a7edba0f">00580</a> <a class="code" href="classPassenger_1_1FileDescriptor.html" title="Wrapper class around a file descriptor integer, for RAII behavior.">FileDescriptor</a> <a class="code" href="classPassenger_1_1EventedClient.html#a408b593d118c3483bcef8118a7edba0f" title="Detaches the client file descriptor so that this EventedClient no longer has any...">detach</a>() {
606
- <a name="l00581"></a>00581 <span class="keywordflow">if</span> (state == EC_DISCONNECTED) {
607
- <a name="l00582"></a>00582 <span class="keywordflow">return</span> <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>;
608
- <a name="l00583"></a>00583 } <span class="keywordflow">else</span> {
609
- <a name="l00584"></a>00584 <a class="code" href="classPassenger_1_1FileDescriptor.html" title="Wrapper class around a file descriptor integer, for RAII behavior.">FileDescriptor</a> oldFd = <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>;
610
- <a name="l00585"></a>00585 state = EC_DISCONNECTED;
611
- <a name="l00586"></a>00586 watchReadEvents(<span class="keyword">false</span>);
612
- <a name="l00587"></a>00587 watchWriteEvents(<span class="keyword">false</span>);
613
- <a name="l00588"></a>00588 <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a> = -1;
614
- <a name="l00589"></a>00589 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a742805d40508b0af89eb2ed2c1e50060" title="Called when detach() is called for the first time.">onDetach</a>);
615
- <a name="l00590"></a>00590 <span class="keywordflow">return</span> oldFd;
616
- <a name="l00591"></a>00591 }
617
- <a name="l00592"></a>00592 }
618
- <a name="l00593"></a>00593 };
619
- <a name="l00594"></a>00594
620
- <a name="l00595"></a>00595
621
- <a name="l00596"></a>00596 } <span class="comment">// namespace Passenger</span>
622
- <a name="l00597"></a>00597
623
- <a name="l00598"></a>00598 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_EVENTED_CLIENT_H_ */</span>
542
+ <a name="l00517"></a>00517 <span class="comment"> * If the client connection is already being closed or has already</span>
543
+ <a name="l00518"></a>00518 <span class="comment"> * been closed then this method does nothing.</span>
544
+ <a name="l00519"></a>00519 <span class="comment"> */</span>
545
+ <a name="l00520"></a><a class="code" href="classPassenger_1_1EventedClient.html#ac1eb48c0d5382a97facbf9af40924849">00520</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#ac1eb48c0d5382a97facbf9af40924849" title="Sets a limit on the client outbox.">setOutboxLimit</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> size) {
546
+ <a name="l00521"></a>00521 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform some kind of I/O with this client, either...">ioAllowed</a>()) {
547
+ <a name="l00522"></a>00522 <span class="keywordflow">return</span>;
548
+ <a name="l00523"></a>00523 }
549
+ <a name="l00524"></a>00524
550
+ <a name="l00525"></a>00525 this_thread::disable_interruption di;
551
+ <a name="l00526"></a>00526 this_thread::disable_syscall_interruption dsi;
552
+ <a name="l00527"></a>00527 outboxLimit = size;
553
+ <a name="l00528"></a>00528 updateWatcherStates();
554
+ <a name="l00529"></a>00529 }
555
+ <a name="l00530"></a>00530
556
+ <a name="l00531"></a>00531 <span class="keywordtype">void</span> write(<span class="keyword">const</span> <a class="code" href="classPassenger_1_1StaticString.html" title="An immutable, static byte buffer.">StaticString</a> &amp;data) {
557
+ <a name="l00532"></a>00532 write(&amp;data, 1);
558
+ <a name="l00533"></a>00533 }
559
+ <a name="l00534"></a>00534 <span class="comment"></span>
560
+ <a name="l00535"></a>00535 <span class="comment"> /**</span>
561
+ <a name="l00536"></a>00536 <span class="comment"> * Sends data to this client. This method will try to send the data</span>
562
+ <a name="l00537"></a>00537 <span class="comment"> * immediately (in which no intermediate copies of the data will be made),</span>
563
+ <a name="l00538"></a>00538 <span class="comment"> * but if the client is not yet ready to receive data (e.g. because of</span>
564
+ <a name="l00539"></a>00539 <span class="comment"> * network congestion) then the data will be buffered and scheduled for</span>
565
+ <a name="l00540"></a>00540 <span class="comment"> * sending later.</span>
566
+ <a name="l00541"></a>00541 <span class="comment"> *</span>
567
+ <a name="l00542"></a>00542 <span class="comment"> * If an I/O error was encountered then the action taken depends on the</span>
568
+ <a name="l00543"></a>00543 <span class="comment"> * value of &lt;em&gt;writeActionError&lt;/em&gt;. By default it is DISCONNECT_FULL,</span>
569
+ <a name="l00544"></a>00544 <span class="comment"> * meaning the client connection will be closed by calling</span>
570
+ <a name="l00545"></a>00545 <span class="comment"> * &lt;tt&gt;disconnect(true)&lt;/tt&gt;. This means this method could potentially</span>
571
+ <a name="l00546"></a>00546 <span class="comment"> * call the &lt;tt&gt;onDisconnect&lt;/tt&gt; callback.</span>
572
+ <a name="l00547"></a>00547 <span class="comment"> *</span>
573
+ <a name="l00548"></a>00548 <span class="comment"> * If the client connection is already being closed, has already</span>
574
+ <a name="l00549"></a>00549 <span class="comment"> * been closed or if the writer side is closed, then this method does</span>
575
+ <a name="l00550"></a>00550 <span class="comment"> * nothing.</span>
576
+ <a name="l00551"></a>00551 <span class="comment"> *</span>
577
+ <a name="l00552"></a>00552 <span class="comment"> * The &lt;tt&gt;onPendingDataFlushed&lt;/tt&gt; callback will be called after</span>
578
+ <a name="l00553"></a>00553 <span class="comment"> * this data and whatever existing pending data have been written</span>
579
+ <a name="l00554"></a>00554 <span class="comment"> * out. That may either be immediately or after a short period of</span>
580
+ <a name="l00555"></a>00555 <span class="comment"> * of time.</span>
581
+ <a name="l00556"></a>00556 <span class="comment"> */</span>
582
+ <a name="l00557"></a><a class="code" href="classPassenger_1_1EventedClient.html#aa07723456786b9f18b973bd88ff51e27">00557</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#aa07723456786b9f18b973bd88ff51e27" title="Sends data to this client.">write</a>(<span class="keyword">const</span> <a class="code" href="classPassenger_1_1StaticString.html" title="An immutable, static byte buffer.">StaticString</a> data[], <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> count) {
583
+ <a name="l00558"></a>00558 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1EventedClient.html#aca719fb03ade09839827a16caa0e6e30" title="Returns whether it is allowed to write data to the client.">writeAllowed</a>()) {
584
+ <a name="l00559"></a>00559 <span class="keywordflow">return</span>;
585
+ <a name="l00560"></a>00560 }
586
+ <a name="l00561"></a>00561
587
+ <a name="l00562"></a>00562 ssize_t ret;
588
+ <a name="l00563"></a>00563 this_thread::disable_interruption di;
589
+ <a name="l00564"></a>00564 this_thread::disable_syscall_interruption dsi;
590
+ <a name="l00565"></a>00565
591
+ <a name="l00566"></a>00566 ret = gatheredWrite(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, data, count, outbox);
592
+ <a name="l00567"></a>00567 <span class="keywordflow">if</span> (ret == -1) {
593
+ <a name="l00568"></a>00568 <span class="keywordtype">int</span> e = errno;
594
+ <a name="l00569"></a>00569 <span class="keywordflow">if</span> (<a class="code" href="classPassenger_1_1EventedClient.html#afc0934988a978a25538b7d8f2566c90a" title="Controls what to do when a write error is encountered.">writeErrorAction</a> == <a class="code" href="classPassenger_1_1EventedClient.html#a931edf284fed32f74ebf9dc35d993f17a627c2190c3a4dc848dc1a332ef9f5105" title="Forcefully disconnect the client.">DISCONNECT_FULL</a>) {
595
+ <a name="l00570"></a>00570 <a class="code" href="classPassenger_1_1EventedClient.html#a5b1a3011165ea9a47f6fe668a5010a20" title="Disconnects the client.">disconnect</a>(<span class="keyword">true</span>);
596
+ <a name="l00571"></a>00571 } <span class="keywordflow">else</span> {
597
+ <a name="l00572"></a>00572 <a class="code" href="classPassenger_1_1EventedClient.html#a9161e34ddc473c00fe4df8fdb1d1baef" title="Close only the writer side of the client connection.">closeWrite</a>();
598
+ <a name="l00573"></a>00573 }
599
+ <a name="l00574"></a>00574 emitSystemErrorEvent(<span class="stringliteral">&quot;Cannot write data to client&quot;</span>, e);
600
+ <a name="l00575"></a>00575 } <span class="keywordflow">else</span> {
601
+ <a name="l00576"></a>00576 updateWatcherStates();
602
+ <a name="l00577"></a>00577 <span class="keywordflow">if</span> (outbox.empty()) {
603
+ <a name="l00578"></a>00578 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a22e93ce2be05a4f47dbeba95d79a79b9" title="Called after all pending outgoing data have been written out.">onPendingDataFlushed</a>);
604
+ <a name="l00579"></a>00579 }
605
+ <a name="l00580"></a>00580 }
606
+ <a name="l00581"></a>00581 }
607
+ <a name="l00582"></a>00582 <span class="comment"></span>
608
+ <a name="l00583"></a>00583 <span class="comment"> /**</span>
609
+ <a name="l00584"></a>00584 <span class="comment"> * Close only the writer side of the client connection.</span>
610
+ <a name="l00585"></a>00585 <span class="comment"> * After calling this method, subsequent write() calls won&#39;t do anything</span>
611
+ <a name="l00586"></a>00586 <span class="comment"> * anymore. Any pending outgoing data will be sent out whenever the</span>
612
+ <a name="l00587"></a>00587 <span class="comment"> * opportunity arises.</span>
613
+ <a name="l00588"></a>00588 <span class="comment"> *</span>
614
+ <a name="l00589"></a>00589 <span class="comment"> * This function does nothing if the client is being disconnected,</span>
615
+ <a name="l00590"></a>00590 <span class="comment"> * already disconnected or if only the writer side is closed.</span>
616
+ <a name="l00591"></a>00591 <span class="comment"> */</span>
617
+ <a name="l00592"></a><a class="code" href="classPassenger_1_1EventedClient.html#a9161e34ddc473c00fe4df8fdb1d1baef">00592</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#a9161e34ddc473c00fe4df8fdb1d1baef" title="Close only the writer side of the client connection.">closeWrite</a>() {
618
+ <a name="l00593"></a>00593 this_thread::disable_syscall_interruption dsi;
619
+ <a name="l00594"></a>00594
620
+ <a name="l00595"></a>00595 <span class="keywordflow">switch</span> (state) {
621
+ <a name="l00596"></a>00596 <span class="keywordflow">case</span> EC_CONNECTED:
622
+ <a name="l00597"></a>00597 assert(outbox.empty());
623
+ <a name="l00598"></a>00598 state = EC_RO_CONNECTED;
624
+ <a name="l00599"></a>00599 <span class="keywordflow">if</span> (syscalls::shutdown(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, SHUT_WR) == -1) {
625
+ <a name="l00600"></a>00600 <span class="keywordtype">int</span> e = errno;
626
+ <a name="l00601"></a>00601 emitSystemErrorEvent(
627
+ <a name="l00602"></a>00602 <span class="stringliteral">&quot;Cannot shutdown writer half of the client socket&quot;</span>,
628
+ <a name="l00603"></a>00603 e);
629
+ <a name="l00604"></a>00604 }
630
+ <a name="l00605"></a>00605 <span class="keywordflow">break</span>;
631
+ <a name="l00606"></a>00606 <span class="keywordflow">case</span> EC_WRITES_PENDING:
632
+ <a name="l00607"></a>00607 <span class="keywordflow">case</span> EC_TOO_MANY_WRITES_PENDING:
633
+ <a name="l00608"></a>00608 state = EC_RO_CONNECTED_WITH_WRITES_PENDING;
634
+ <a name="l00609"></a>00609 <span class="keywordflow">break</span>;
635
+ <a name="l00610"></a>00610 <span class="keywordflow">default</span>:
636
+ <a name="l00611"></a>00611 <span class="keywordflow">break</span>;
637
+ <a name="l00612"></a>00612 }
638
+ <a name="l00613"></a>00613 updateWatcherStates();
639
+ <a name="l00614"></a>00614 }
640
+ <a name="l00615"></a>00615 <span class="comment"></span>
641
+ <a name="l00616"></a>00616 <span class="comment"> /**</span>
642
+ <a name="l00617"></a>00617 <span class="comment"> * Disconnects the client. This actually closes the underlying file</span>
643
+ <a name="l00618"></a>00618 <span class="comment"> * descriptor, even if the FileDescriptor object still has references.</span>
644
+ <a name="l00619"></a>00619 <span class="comment"> *</span>
645
+ <a name="l00620"></a>00620 <span class="comment"> * If &lt;em&gt;force&lt;/em&gt; is true then the client will be disconnected</span>
646
+ <a name="l00621"></a>00621 <span class="comment"> * immediately, and any pending outgoing data will be discarded.</span>
647
+ <a name="l00622"></a>00622 <span class="comment"> * Otherwise the client will be disconnected after all pending</span>
648
+ <a name="l00623"></a>00623 <span class="comment"> * outgoing data have been sent; in the mean time no new data can be</span>
649
+ <a name="l00624"></a>00624 <span class="comment"> * received from or sent to the client.</span>
650
+ <a name="l00625"></a>00625 <span class="comment"> *</span>
651
+ <a name="l00626"></a>00626 <span class="comment"> * After the client has actually been disconnected (which may be either</span>
652
+ <a name="l00627"></a>00627 <span class="comment"> * immediately or after a short period of time), a disconnect event will</span>
653
+ <a name="l00628"></a>00628 <span class="comment"> * be emitted.</span>
654
+ <a name="l00629"></a>00629 <span class="comment"> *</span>
655
+ <a name="l00630"></a>00630 <span class="comment"> * If the client connection has already been closed then this method</span>
656
+ <a name="l00631"></a>00631 <span class="comment"> * does nothing. If the client connection is being closed (because</span>
657
+ <a name="l00632"></a>00632 <span class="comment"> * there&#39;s pending outgoing data) then the behavior depends on the</span>
658
+ <a name="l00633"></a>00633 <span class="comment"> * &lt;tt&gt;force&lt;/tt&gt; argument: if true then the connection is closed</span>
659
+ <a name="l00634"></a>00634 <span class="comment"> * immediately and the pending data is discarded, otherwise this</span>
660
+ <a name="l00635"></a>00635 <span class="comment"> * method does nothing.</span>
661
+ <a name="l00636"></a>00636 <span class="comment"> *</span>
662
+ <a name="l00637"></a>00637 <span class="comment"> * The &lt;tt&gt;onDisconnect&lt;/tt&gt; callback will be called after the file</span>
663
+ <a name="l00638"></a>00638 <span class="comment"> * descriptor is closed, which is either immediately or after all</span>
664
+ <a name="l00639"></a>00639 <span class="comment"> * pending data has been sent out.</span>
665
+ <a name="l00640"></a>00640 <span class="comment"> */</span>
666
+ <a name="l00641"></a><a class="code" href="classPassenger_1_1EventedClient.html#a5b1a3011165ea9a47f6fe668a5010a20">00641</a> <span class="keywordtype">void</span> <a class="code" href="classPassenger_1_1EventedClient.html#a5b1a3011165ea9a47f6fe668a5010a20" title="Disconnects the client.">disconnect</a>(<span class="keywordtype">bool</span> force = <span class="keyword">false</span>) {
667
+ <a name="l00642"></a>00642 <span class="keywordflow">if</span> (!<a class="code" href="classPassenger_1_1EventedClient.html#a50436eb8ec0cc38b5a7278962e98a22c" title="Returns whether it is allowed to perform some kind of I/O with this client, either...">ioAllowed</a>() &amp;&amp; !(state == EC_DISCONNECTING_WITH_WRITES_PENDING &amp;&amp; force)) {
668
+ <a name="l00643"></a>00643 <span class="keywordflow">return</span>;
669
+ <a name="l00644"></a>00644 }
670
+ <a name="l00645"></a>00645
671
+ <a name="l00646"></a>00646 this_thread::disable_interruption di;
672
+ <a name="l00647"></a>00647 this_thread::disable_syscall_interruption dsi;
673
+ <a name="l00648"></a>00648
674
+ <a name="l00649"></a>00649 <span class="keywordflow">if</span> (state == EC_CONNECTED || state == EC_RO_CONNECTED || force) {
675
+ <a name="l00650"></a>00650 state = EC_DISCONNECTED;
676
+ <a name="l00651"></a>00651 watchReadEvents(<span class="keyword">false</span>);
677
+ <a name="l00652"></a>00652 watchWriteEvents(<span class="keyword">false</span>);
678
+ <a name="l00653"></a>00653 <span class="keywordflow">try</span> {
679
+ <a name="l00654"></a>00654 <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>.<a class="code" href="classPassenger_1_1FileDescriptor.html#a02062f3cfb689b32781e11114c0abe5b" title="Close the underlying file descriptor.">close</a>();
680
+ <a name="l00655"></a>00655 } <span class="keywordflow">catch</span> (<span class="keyword">const</span> <a class="code" href="classPassenger_1_1SystemException.html" title="Represents an error returned by a system call or a standard library call.">SystemException</a> &amp;e) {
681
+ <a name="l00656"></a>00656 emitSystemErrorEvent(e.<a class="code" href="classPassenger_1_1SystemException.html#a84fa2ab4f5b7b96704734fcdfdaa0269" title="Returns a brief version of the exception message.">brief</a>(), e.<a class="code" href="classPassenger_1_1SystemException.html#aee7a6672bf79b72a4c3ee70c57d6a47c" title="The value of errno at the time the error occured.">code</a>());
682
+ <a name="l00657"></a>00657 }
683
+ <a name="l00658"></a>00658 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a211210ecd85eb2da47d200215132bb2d" title="Called when the client is disconnected.">onDisconnect</a>);
684
+ <a name="l00659"></a>00659 } <span class="keywordflow">else</span> {
685
+ <a name="l00660"></a>00660 state = EC_DISCONNECTING_WITH_WRITES_PENDING;
686
+ <a name="l00661"></a>00661 watchReadEvents(<span class="keyword">false</span>);
687
+ <a name="l00662"></a>00662 watchWriteEvents(<span class="keyword">true</span>);
688
+ <a name="l00663"></a>00663 <span class="keywordflow">if</span> (syscalls::shutdown(<a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>, SHUT_RD) == -1) {
689
+ <a name="l00664"></a>00664 <span class="keywordtype">int</span> e = errno;
690
+ <a name="l00665"></a>00665 emitSystemErrorEvent(
691
+ <a name="l00666"></a>00666 <span class="stringliteral">&quot;Cannot shutdown reader half of the client socket&quot;</span>,
692
+ <a name="l00667"></a>00667 e);
693
+ <a name="l00668"></a>00668 }
694
+ <a name="l00669"></a>00669 }
695
+ <a name="l00670"></a>00670 }
696
+ <a name="l00671"></a>00671 <span class="comment"></span>
697
+ <a name="l00672"></a>00672 <span class="comment"> /**</span>
698
+ <a name="l00673"></a>00673 <span class="comment"> * Detaches the client file descriptor so that this EventedClient no longer</span>
699
+ <a name="l00674"></a>00674 <span class="comment"> * has any control over it. Any EventedClient I/O watchers on the client file</span>
700
+ <a name="l00675"></a>00675 <span class="comment"> * descriptor will be stopped and further I/O on the file descriptor via</span>
701
+ <a name="l00676"></a>00676 <span class="comment"> * EventedClient will become impossible. Any pending outgoing data will be</span>
702
+ <a name="l00677"></a>00677 <span class="comment"> * discarded. The original client file descriptor is returned and</span>
703
+ <a name="l00678"></a>00678 <span class="comment"> * &lt;tt&gt;onDetach&lt;/tt&gt; is called. Subsequent calls to this function will</span>
704
+ <a name="l00679"></a>00679 <span class="comment"> * return -1 and will no longer call &lt;tt&gt;onDetach&lt;/tt&gt;.</span>
705
+ <a name="l00680"></a>00680 <span class="comment"> *</span>
706
+ <a name="l00681"></a>00681 <span class="comment"> * @post !ioAllowed()</span>
707
+ <a name="l00682"></a>00682 <span class="comment"> * @post fd == -1</span>
708
+ <a name="l00683"></a>00683 <span class="comment"> */</span>
709
+ <a name="l00684"></a><a class="code" href="classPassenger_1_1EventedClient.html#a408b593d118c3483bcef8118a7edba0f">00684</a> <a class="code" href="classPassenger_1_1FileDescriptor.html" title="Wrapper class around a file descriptor integer, for RAII behavior.">FileDescriptor</a> <a class="code" href="classPassenger_1_1EventedClient.html#a408b593d118c3483bcef8118a7edba0f" title="Detaches the client file descriptor so that this EventedClient no longer has any...">detach</a>() {
710
+ <a name="l00685"></a>00685 <span class="keywordflow">if</span> (state == EC_DISCONNECTED) {
711
+ <a name="l00686"></a>00686 <span class="keywordflow">return</span> <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>;
712
+ <a name="l00687"></a>00687 } <span class="keywordflow">else</span> {
713
+ <a name="l00688"></a>00688 <a class="code" href="classPassenger_1_1FileDescriptor.html" title="Wrapper class around a file descriptor integer, for RAII behavior.">FileDescriptor</a> oldFd = <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a>;
714
+ <a name="l00689"></a>00689 state = EC_DISCONNECTED;
715
+ <a name="l00690"></a>00690 watchReadEvents(<span class="keyword">false</span>);
716
+ <a name="l00691"></a>00691 watchWriteEvents(<span class="keyword">false</span>);
717
+ <a name="l00692"></a>00692 <a class="code" href="classPassenger_1_1EventedClient.html#a4473719c16cae760e1811b7ccb1dc491" title="The client&amp;#39;s file descriptor.">fd</a> = -1;
718
+ <a name="l00693"></a>00693 emitEvent(<a class="code" href="classPassenger_1_1EventedClient.html#a742805d40508b0af89eb2ed2c1e50060" title="Called when detach() is called for the first time.">onDetach</a>);
719
+ <a name="l00694"></a>00694 <span class="keywordflow">return</span> oldFd;
720
+ <a name="l00695"></a>00695 }
721
+ <a name="l00696"></a>00696 }
722
+ <a name="l00697"></a>00697 };
723
+ <a name="l00698"></a>00698
724
+ <a name="l00699"></a>00699
725
+ <a name="l00700"></a>00700 } <span class="comment">// namespace Passenger</span>
726
+ <a name="l00701"></a>00701
727
+ <a name="l00702"></a>00702 <span class="preprocessor">#endif </span><span class="comment">/* _PASSENGER_EVENTED_CLIENT_H_ */</span>
624
728
  </pre></div></div>
625
729
  <hr size="1"/><address style="text-align: right;"><small>Generated by&nbsp;
626
730
  <a href="http://www.doxygen.org/index.html">