amps-python-client 5.3.4.1__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- amps-python-client-5.3.4.1/HISTORY +7 -0
- amps-python-client-5.3.4.1/LICENSE +157 -0
- amps-python-client-5.3.4.1/PKG-INFO +112 -0
- amps-python-client-5.3.4.1/README.md +96 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/ack-messages.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/content-messages.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/intro.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/logon.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/protocol-reference.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/publishing.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/query-delimiters.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/query-subscribe.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/removing.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/utilities.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/environment.pickle +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/doctrees/index.doctree +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/.buildinfo +4 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_images/caution.svg +25 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/ack-messages.rst.txt +32 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/content-messages.rst.txt +27 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/intro.rst.txt +43 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/logon.rst.txt +231 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/protocol-reference.rst.txt +1474 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/publishing.rst.txt +25 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/query-delimiters.rst.txt +12 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/query-subscribe.rst.txt +23 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/removing.rst.txt +6 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/utilities.rst.txt +13 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_sources/index.rst.txt +56 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/ajax-loader.gif +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/alabaster.css +699 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/basic.css +632 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/comment-bright.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/comment-close.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/comment.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/custom.css +192 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/custom.css.backup +161 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/doctools.js +287 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/down-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/down.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/file.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/flag_logo.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/flag_logo.svg +153 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/jquery-3.1.0.js +10074 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/jquery.js +4 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/minus.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/plus.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/pygments.css +74 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/searchtools.js +758 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/underscore-1.3.1.js +999 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/underscore.js +31 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/up-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/up.png +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/_static/websupport.js +808 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/ack-messages.html +417 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/content-messages.html +417 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/intro.html +126 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/logon.html +295 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/protocol-reference.html +1190 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/publishing.html +436 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/query-delimiters.html +173 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/query-subscribe.html +2123 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/removing.html +299 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/chapters/utilities.html +287 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/genindex.html +97 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/index.html +138 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/objects.inv +0 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/search.html +107 -0
- amps-python-client-5.3.4.1/docs/command-reference/html/searchindex.js +1 -0
- amps-python-client-5.3.4.1/docs/html/.buildinfo +4 -0
- amps-python-client-5.3.4.1/docs/html/_sources/code.rst.txt +6 -0
- amps-python-client-5.3.4.1/docs/html/_sources/index.rst.txt +29 -0
- amps-python-client-5.3.4.1/docs/html/_static/ajax-loader.gif +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/basic.css +632 -0
- amps-python-client-5.3.4.1/docs/html/_static/classic.css +261 -0
- amps-python-client-5.3.4.1/docs/html/_static/comment-bright.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/comment-close.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/comment.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/default.css +1 -0
- amps-python-client-5.3.4.1/docs/html/_static/doctools.js +287 -0
- amps-python-client-5.3.4.1/docs/html/_static/down-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/down.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/file.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/jquery-3.1.0.js +10074 -0
- amps-python-client-5.3.4.1/docs/html/_static/jquery.js +4 -0
- amps-python-client-5.3.4.1/docs/html/_static/minus.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/plus.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/pygments.css +74 -0
- amps-python-client-5.3.4.1/docs/html/_static/searchtools.js +758 -0
- amps-python-client-5.3.4.1/docs/html/_static/sidebar.js +159 -0
- amps-python-client-5.3.4.1/docs/html/_static/underscore-1.3.1.js +999 -0
- amps-python-client-5.3.4.1/docs/html/_static/underscore.js +31 -0
- amps-python-client-5.3.4.1/docs/html/_static/up-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/up.png +0 -0
- amps-python-client-5.3.4.1/docs/html/_static/websupport.js +808 -0
- amps-python-client-5.3.4.1/docs/html/code.html +6503 -0
- amps-python-client-5.3.4.1/docs/html/genindex.html +1361 -0
- amps-python-client-5.3.4.1/docs/html/index.html +131 -0
- amps-python-client-5.3.4.1/docs/html/objects.inv +0 -0
- amps-python-client-5.3.4.1/docs/html/py-modindex.html +111 -0
- amps-python-client-5.3.4.1/docs/html/search.html +107 -0
- amps-python-client-5.3.4.1/docs/html/searchindex.js +1 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/advanced-topics.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/cpp-compiler-list.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/cpp-feature-table.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/creating-commands.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/deltas.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/error-handling.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/exceptions.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/first-program.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/high-availability.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/installing.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/introduction.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/moving-from-python-lite.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/performance-tips.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/queues.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/sow.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/subscriptions.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/chapters/utilities.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/environment.pickle +0 -0
- amps-python-client-5.3.4.1/docs/python/doctrees/index.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python/html/.buildinfo +4 -0
- amps-python-client-5.3.4.1/docs/python/html/_images/caution.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_images/caution.svg +25 -0
- amps-python-client-5.3.4.1/docs/python/html/_images/connection_string.svg +461 -0
- amps-python-client-5.3.4.1/docs/python/html/_images/important.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_images/important.svg +25 -0
- amps-python-client-5.3.4.1/docs/python/html/_images/tip.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_images/tip.svg +31 -0
- amps-python-client-5.3.4.1/docs/python/html/_images/warning.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/advanced-topics.rst.txt +398 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/cpp-compiler-list.rst.txt +6 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/cpp-feature-table.rst.txt +26 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/creating-commands.rst.txt +159 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/deltas.rst.txt +79 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/error-handling.rst.txt +482 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/exceptions.rst.txt +128 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/first-program.rst.txt +142 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/high-availability.rst.txt +876 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/installing.rst.txt +184 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/introduction.rst.txt +50 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/moving-from-python-lite.rst.txt +32 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/performance-tips.rst.txt +434 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/queues.rst.txt +282 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/sow.rst.txt +292 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/subscriptions.rst.txt +374 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/utilities.rst.txt +214 -0
- amps-python-client-5.3.4.1/docs/python/html/_sources/index.rst.txt +44 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/ajax-loader.gif +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/alabaster.css +699 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/basic.css +632 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/comment-bright.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/comment-close.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/comment.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/custom.css +192 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/custom.css.backup +161 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/doctools.js +287 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/down-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/down.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/file.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/flag_logo.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/flag_logo.svg +153 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/jquery-3.1.0.js +10074 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/jquery.js +4 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/minus.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/plus.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/pygments.css +74 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/searchtools.js +758 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/underscore-1.3.1.js +999 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/underscore.js +31 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/up-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/up.png +0 -0
- amps-python-client-5.3.4.1/docs/python/html/_static/websupport.js +808 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/advanced-topics.html +447 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/cpp-compiler-list.html +92 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/cpp-feature-table.html +156 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/creating-commands.html +2837 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/deltas.html +169 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/error-handling.html +746 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/exceptions.html +272 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/first-program.html +499 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/high-availability.html +1014 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/installing.html +264 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/introduction.html +245 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/moving-from-python-lite.html +118 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/performance-tips.html +499 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/queues.html +352 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/sow.html +381 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/subscriptions.html +535 -0
- amps-python-client-5.3.4.1/docs/python/html/chapters/utilities.html +302 -0
- amps-python-client-5.3.4.1/docs/python/html/genindex.html +351 -0
- amps-python-client-5.3.4.1/docs/python/html/index.html +380 -0
- amps-python-client-5.3.4.1/docs/python/html/objects.inv +0 -0
- amps-python-client-5.3.4.1/docs/python/html/search.html +107 -0
- amps-python-client-5.3.4.1/docs/python/html/searchindex.js +1 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/doctrees/chapters/crankitup.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/doctrees/chapters/equipment.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/doctrees/environment.pickle +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/doctrees/index.doctree +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/.buildinfo +4 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_sources/chapters/crankitup.rst.txt +155 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_sources/chapters/equipment.rst.txt +19 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_sources/index.rst.txt +20 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/ajax-loader.gif +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/alabaster.css +699 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/basic.css +632 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/comment-bright.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/comment-close.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/comment.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/custom.css +192 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/custom.css.backup +161 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/doctools.js +287 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/down-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/down.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/file.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/flag_logo.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/flag_logo.svg +153 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/jquery-3.1.0.js +10074 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/jquery.js +4 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/minus.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/plus.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/pygments.css +74 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/searchtools.js +758 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/underscore-1.3.1.js +999 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/underscore.js +31 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/up-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/up.png +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/websupport.js +808 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/chapters/crankitup.html +271 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/chapters/equipment.html +105 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/genindex.html +97 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/index.html +382 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/objects.inv +0 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/search.html +107 -0
- amps-python-client-5.3.4.1/docs/python-quickstart/html/searchindex.js +1 -0
- amps-python-client-5.3.4.1/docs/resources/custom.css +9 -0
- amps-python-client-5.3.4.1/docs/resources/flag_logo.svg +153 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/acks.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/actions.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/amps-statistics.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/amps_expressions.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/amps_functions.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/auxiliary_modules.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/config-file-shortcuts.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/conflated_topics.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/constructing-fields.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/daemon.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/delta.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/distribution.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/enrichment.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/events.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/file_format_versions.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/glossary.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/ha.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/installing_and_starting.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/intro.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/logging.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/messageTypes.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/monitoring.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/oof.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/operation.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/pub_sub.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/queues.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/replication.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/securing.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/sow.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/sow_queries.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/spark.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/transports.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/troubleshooting.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/txlog.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/usecases.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/utilities.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/views.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/environment.pickle +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/doctrees/index.doctree +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/.buildinfo +4 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/AMPS-Queues-Intro.svg +1330 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/GeoRepl.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/HA_async_ack.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/HA_sync_ack.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/Hot-Hot-Replication.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/MessageOrdering.svg +235 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/OOF5.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/OOF6.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/OOF7.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/OOF8.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/PubSub1.svg +1 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/PubSub2.svg +1 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/SOWAndSubscribeAndReplace.svg +684 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/SOWQuery1.svg +402 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/SOWQuery2.svg +505 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/UseCaseFig1.svg +1 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/UseCaseFig2.svg +1 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/UseCaseFig3.svg +1 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/UseCaseFig4.svg +1 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/caution.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/caution.svg +25 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/chicago_group.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/delta_original_messages.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/delta_update_message.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/important.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/important.svg +25 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/inline_view_conflation.svg +1 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/paginated_subs_pub.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/paginated_subs_sub.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/queue_usage_overview.svg +627 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/replication_hub.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/replication_scenario_with_ha.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/sow_overview_1.svg +248 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/sow_overview_2.svg +183 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/sow_update_sequence.svg +1 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/tip.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/tip.svg +31 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/warning.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_images/warning.svg +23 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/acks.rst.txt +232 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/actions.rst.txt +111 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/amps-statistics.rst.txt +358 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/amps_expressions.rst.txt +83 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/amps_functions.rst.txt +11 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/auxiliary_modules.rst.txt +86 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/config-file-shortcuts.rst.txt +9 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/conflated_topics.rst.txt +111 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/constructing-fields.rst.txt +269 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/daemon.rst.txt +232 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/delta.rst.txt +556 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/distribution.rst.txt +186 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/enrichment.rst.txt +191 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/events.rst.txt +39 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/file_format_versions.rst.txt +203 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/glossary.rst.txt +101 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/ha.rst.txt +465 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/installing_and_starting.rst.txt +23 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/intro.rst.txt +116 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/logging.rst.txt +34 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/messageTypes.rst.txt +1398 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/monitoring.rst.txt +326 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/oof.rst.txt +312 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/operation.rst.txt +27 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/pub_sub.rst.txt +49 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/queues.rst.txt +1351 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/replication.rst.txt +1228 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/securing.rst.txt +657 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/sow.rst.txt +57 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/sow_queries.rst.txt +25 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/spark.rst.txt +824 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/transports.rst.txt +291 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/troubleshooting.rst.txt +517 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/txlog.rst.txt +62 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/usecases.rst.txt +21 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/utilities.rst.txt +62 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/views.rst.txt +175 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_sources/index.rst.txt +110 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/ajax-loader.gif +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/alabaster.css +695 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/basic.css +632 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/comment-bright.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/comment-close.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/comment.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/custom.css +192 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/custom.css.backup +161 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/doctools.js +287 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/down-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/down.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/file.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/flag_logo.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/flag_logo.svg +153 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/jquery-3.1.0.js +10074 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/jquery.js +4 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/minus.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/plus.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/pygments.css +74 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/searchtools.js +758 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/underscore-1.3.1.js +999 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/underscore.js +31 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/up-pressed.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/up.png +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/_static/websupport.js +808 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/acks.html +289 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/actions.html +3782 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/amps-statistics.html +439 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/amps_expressions.html +1552 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/amps_functions.html +1626 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/auxiliary_modules.html +2548 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/config-file-shortcuts.html +508 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/conflated_topics.html +328 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/constructing-fields.html +447 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/daemon.html +295 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/delta.html +609 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/distribution.html +246 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/enrichment.html +264 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/events.html +449 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/file_format_versions.html +229 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/glossary.html +215 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/ha.html +978 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/installing_and_starting.html +357 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/intro.html +572 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/logging.html +972 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/messageTypes.html +1280 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/monitoring.html +718 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/oof.html +341 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/operation.html +1515 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/pub_sub.html +934 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/queues.html +1767 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/replication.html +1777 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/securing.html +697 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/sow.html +1038 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/sow_queries.html +621 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/spark.html +819 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/transports.html +352 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/troubleshooting.html +530 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/txlog.html +1013 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/usecases.html +288 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/utilities.html +133 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/chapters/views.html +1120 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/genindex.html +1261 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/index.html +163 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/objects.inv +0 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/search.html +106 -0
- amps-python-client-5.3.4.1/docs/user-guide/html/searchindex.js +1 -0
- amps-python-client-5.3.4.1/include/ampspy_bookmarkstore.hpp +63 -0
- amps-python-client-5.3.4.1/include/ampspy_compat.h +63 -0
- amps-python-client-5.3.4.1/include/ampspy_defs.hpp +181 -0
- amps-python-client-5.3.4.1/include/ampspy_recoverypointadapter.hpp +52 -0
- amps-python-client-5.3.4.1/include/ampspy_shims.hpp +113 -0
- amps-python-client-5.3.4.1/include/ampspy_type_object.hpp +242 -0
- amps-python-client-5.3.4.1/include/ampspy_types.hpp +1139 -0
- amps-python-client-5.3.4.1/include/ampspyver.h +30 -0
- amps-python-client-5.3.4.1/index.html +66 -0
- amps-python-client-5.3.4.1/samples/AMPSConsolePublisher.py +59 -0
- amps-python-client-5.3.4.1/samples/AMPSConsoleSubscriber.py +63 -0
- amps-python-client-5.3.4.1/samples/AMPSFIXBuilderPublisher.py +71 -0
- amps-python-client-5.3.4.1/samples/AMPSFIXShredderSubscriber.py +69 -0
- amps-python-client-5.3.4.1/samples/AMPSNVFIXBuilderPublisher.py +71 -0
- amps-python-client-5.3.4.1/samples/AMPSNVFIXShredderSubscriber.py +67 -0
- amps-python-client-5.3.4.1/samples/AMPSPublishForReplay.py +81 -0
- amps-python-client-5.3.4.1/samples/AMPSQueueConsumer.py +69 -0
- amps-python-client-5.3.4.1/samples/AMPSQueuePublisher.py +59 -0
- amps-python-client-5.3.4.1/samples/AMPSSOWConsolePublisher.py +67 -0
- amps-python-client-5.3.4.1/samples/AMPSSOWConsoleSubscriber.py +77 -0
- amps-python-client-5.3.4.1/samples/AMPSSOWandSubscribeConsoleSubscriber.py +79 -0
- amps-python-client-5.3.4.1/samples/AMPSSOWandSubscribeWithOOF.py +108 -0
- amps-python-client-5.3.4.1/samples/AMPSSubscribeForReplay.py +128 -0
- amps-python-client-5.3.4.1/samples/AMPSUpdateForOOF.py +123 -0
- amps-python-client-5.3.4.1/samples/CompositeMessagePublisher.py +84 -0
- amps-python-client-5.3.4.1/samples/CompositeMessageSubscriber.py +87 -0
- amps-python-client-5.3.4.1/samples/RandomServerChooser.py +41 -0
- amps-python-client-5.3.4.1/samples/sample.xml +335 -0
- amps-python-client-5.3.4.1/setup.py +209 -0
- amps-python-client-5.3.4.1/setup_amps.py +94 -0
- amps-python-client-5.3.4.1/src/ampspy_shims.cpp +203 -0
- amps-python-client-5.3.4.1/src/ampspy_type_object.cpp +484 -0
- amps-python-client-5.3.4.1/src/authenticator.cpp +128 -0
- amps-python-client-5.3.4.1/src/bookmarkstore.cpp +238 -0
- amps-python-client-5.3.4.1/src/client.cpp +2430 -0
- amps-python-client-5.3.4.1/src/client_docs.h +956 -0
- amps-python-client-5.3.4.1/src/cmessagehandler.cpp +151 -0
- amps-python-client-5.3.4.1/src/command.cpp +164 -0
- amps-python-client-5.3.4.1/src/command_docs.h +194 -0
- amps-python-client-5.3.4.1/src/compositemessagebuilder.cpp +111 -0
- amps-python-client-5.3.4.1/src/compositemessageparser.cpp +146 -0
- amps-python-client-5.3.4.1/src/conflatingrecoverypointadapter.cpp +194 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/BlockPublishStore.hpp +2053 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/BlockStore.hpp +677 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/BookmarkStore.hpp +542 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/Buffer.hpp +214 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/CompositeMessageBuilder.hpp +174 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/CompositeMessageParser.hpp +151 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/DefaultServerChooser.hpp +162 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/Field.hpp +719 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/HAClient.hpp +370 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/HAClientImpl.hpp +460 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/HybridPublishStore.hpp +481 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/LoggedBookmarkStore.hpp +1255 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/MMapBookmarkStore.hpp +1283 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/MMapStoreBuffer.hpp +290 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/MemoryBookmarkStore.hpp +1622 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/MemoryPublishStore.hpp +66 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/MemoryStoreBuffer.hpp +244 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/MemorySubscriptionManager.hpp +850 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/Message.hpp +1819 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/MessageRouter.hpp +618 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/PublishStore.hpp +158 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ReconnectDelayStrategy.hpp +106 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ReconnectDelayStrategyImpl.hpp +317 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/RecoveryPoint.hpp +323 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/RecoveryPointAdapter.hpp +501 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/RingBookmarkStore.hpp +669 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/SOWRecoveryPointAdapter.hpp +490 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ServerChooser.hpp +145 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ServerChooserImpl.hpp +95 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/amps.h +775 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/amps_generated.h +46 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/amps_impl.h +204 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/amps_ssl.h +78 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ampscrc.hpp +210 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ampsplusplus.hpp +8817 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ampsuri.h +84 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ampsver.h +41 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/ampsver.h.in +41 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/constants.hpp +194 -0
- amps-python-client-5.3.4.1/src/cpp/include/amps/util.hpp +1692 -0
- amps-python-client-5.3.4.1/src/cpp/src/amps_protocol.c +688 -0
- amps-python-client-5.3.4.1/src/cpp/src/amps_protocol_generated.h +80 -0
- amps-python-client-5.3.4.1/src/cpp/src/amps_ssl.c +489 -0
- amps-python-client-5.3.4.1/src/cpp/src/atfork.c +446 -0
- amps-python-client-5.3.4.1/src/cpp/src/client.c +483 -0
- amps-python-client-5.3.4.1/src/cpp/src/makefile +92 -0
- amps-python-client-5.3.4.1/src/cpp/src/message.c +837 -0
- amps-python-client-5.3.4.1/src/cpp/src/message_generated.h +611 -0
- amps-python-client-5.3.4.1/src/cpp/src/tcp.c +1489 -0
- amps-python-client-5.3.4.1/src/cpp/src/tcps.c +1894 -0
- amps-python-client-5.3.4.1/src/cpp/src/transports.c +123 -0
- amps-python-client-5.3.4.1/src/cpp/src/unix.c +984 -0
- amps-python-client-5.3.4.1/src/cpp/src/uri.c +301 -0
- amps-python-client-5.3.4.1/src/exponentialdelaystrategy.cpp +137 -0
- amps-python-client-5.3.4.1/src/failedwritehandler.cpp +116 -0
- amps-python-client-5.3.4.1/src/fixbuilder.cpp +146 -0
- amps-python-client-5.3.4.1/src/fixeddelaystrategy.cpp +114 -0
- amps-python-client-5.3.4.1/src/fixshredder.cpp +105 -0
- amps-python-client-5.3.4.1/src/fixshredder_docs.h +38 -0
- amps-python-client-5.3.4.1/src/haclient.cpp +691 -0
- amps-python-client-5.3.4.1/src/haclient_docs.h +132 -0
- amps-python-client-5.3.4.1/src/hybridpublishstore.cpp +137 -0
- amps-python-client-5.3.4.1/src/hybridpublishstore_docs.h +31 -0
- amps-python-client-5.3.4.1/src/memorybookmarkstore.cpp +373 -0
- amps-python-client-5.3.4.1/src/memorybookmarkstore_docs.h +39 -0
- amps-python-client-5.3.4.1/src/memorypublishstore.cpp +160 -0
- amps-python-client-5.3.4.1/src/memorypublishstore_docs.h +32 -0
- amps-python-client-5.3.4.1/src/message.cpp +765 -0
- amps-python-client-5.3.4.1/src/message_docs.h +306 -0
- amps-python-client-5.3.4.1/src/messagestream.cpp +623 -0
- amps-python-client-5.3.4.1/src/messagestream_docs.h +45 -0
- amps-python-client-5.3.4.1/src/mmapbookmarkstore.cpp +422 -0
- amps-python-client-5.3.4.1/src/nvfixbuilder.cpp +160 -0
- amps-python-client-5.3.4.1/src/nvfixbuilder_docs.h +33 -0
- amps-python-client-5.3.4.1/src/nvfixshredder.cpp +99 -0
- amps-python-client-5.3.4.1/src/nvfixshredder_docs.h +39 -0
- amps-python-client-5.3.4.1/src/publishstore.cpp +183 -0
- amps-python-client-5.3.4.1/src/raw_wrapper.cpp +756 -0
- amps-python-client-5.3.4.1/src/reason.cpp +71 -0
- amps-python-client-5.3.4.1/src/recoverypoint.cpp +135 -0
- amps-python-client-5.3.4.1/src/recoverypointadapter.cpp +171 -0
- amps-python-client-5.3.4.1/src/ringbookmarkstore.cpp +360 -0
- amps-python-client-5.3.4.1/src/serverchooser.cpp +245 -0
- amps-python-client-5.3.4.1/src/serverchooser_docs.h +39 -0
- amps-python-client-5.3.4.1/src/sowrecoverypointadapter.cpp +248 -0
- amps-python-client-5.3.4.1/src/store.cpp +62 -0
- amps-python-client-5.3.4.1/src/versioninfo.cpp +175 -0
|
@@ -0,0 +1,1894 @@
|
|
|
1
|
+
/*//////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// Copyright (c) 2010-2023 60East Technologies Inc., All Rights Reserved.
|
|
4
|
+
//
|
|
5
|
+
// This computer software is owned by 60East Technologies Inc. and is
|
|
6
|
+
// protected by U.S. copyright laws and other laws and by international
|
|
7
|
+
// treaties. This computer software is furnished by 60East Technologies
|
|
8
|
+
// Inc. pursuant to a written license agreement and may be used, copied,
|
|
9
|
+
// transmitted, and stored only in accordance with the terms of such
|
|
10
|
+
// license agreement and with the inclusion of the above copyright notice.
|
|
11
|
+
// This computer software or any other copies thereof may not be provided
|
|
12
|
+
// or otherwise made available to any other person.
|
|
13
|
+
//
|
|
14
|
+
// U.S. Government Restricted Rights. This computer software: (a) was
|
|
15
|
+
// developed at private expense and is in all respects the proprietary
|
|
16
|
+
// information of 60East Technologies Inc.; (b) was not developed with
|
|
17
|
+
// government funds; (c) is a trade secret of 60East Technologies Inc.
|
|
18
|
+
// for all purposes of the Freedom of Information Act; and (d) is a
|
|
19
|
+
// commercial item and thus, pursuant to Section 12.212 of the Federal
|
|
20
|
+
// Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
|
|
21
|
+
// Government's use, duplication or disclosure of the computer software
|
|
22
|
+
// is subject to the restrictions set forth by 60East Technologies Inc..
|
|
23
|
+
//
|
|
24
|
+
///////////////////////////////////////////////////////////////////////// */
|
|
25
|
+
#if _MSC_VER < 1400
|
|
26
|
+
/*support for visual c++ 2003 */
|
|
27
|
+
#define _WIN32_WINNT 0x0400
|
|
28
|
+
#endif
|
|
29
|
+
#include <amps/amps_impl.h>
|
|
30
|
+
#include <amps/amps_ssl.h>
|
|
31
|
+
#include <amps/ampsuri.h>
|
|
32
|
+
#if __STDC_VERSION__ >= 201100
|
|
33
|
+
#include <stdatomic.h>
|
|
34
|
+
#include <stdbool.h>
|
|
35
|
+
#define AMPS_IEX(ptr, value) atomic_exchange_explicit((ptr), (value), memory_order_acq_rel)
|
|
36
|
+
#define AMPS_IEX_GET(ptr, value) atomic_exchange_explicit((ptr), (value), memory_order_acq_rel)
|
|
37
|
+
#define AMPS_IEX_LONG(ptr, value) atomic_exchange_explicit((ptr), (value), memory_order_acq_rel)
|
|
38
|
+
#define AMPS_FETCH_ADD(ptr, value) atomic_fetch_add_explicit((ptr), (value), memory_order_acq_rel)
|
|
39
|
+
#define AMPS_FETCH_SUB(ptr, value) atomic_fetch_sub_explicit((ptr), (value), memory_order_acq_rel)
|
|
40
|
+
#elif defined(_WIN32)
|
|
41
|
+
#ifdef _WIN64
|
|
42
|
+
#define AMPS_IEX(ptr,value) _InterlockedExchange64((LONG64*)(ptr), (LONG64)(value))
|
|
43
|
+
#define AMPS_IEX_GET(ptr,value) _InterlockedExchange64((LONG64*)(ptr), (LONG64)(value))
|
|
44
|
+
#define AMPS_IEX_LONG(ptr,value) _InterlockedExchange((ptr), (value))
|
|
45
|
+
#define AMPS_FETCH_ADD(ptr, value) InterlockedExchangeAdd64((LONGLONG volatile*)(ptr), (LONGLONG)(value))
|
|
46
|
+
#define AMPS_FETCH_SUB(ptr, value) InterlockedExchangeAdd64((LONGLONG volatile*)(ptr), (LONGLONG)(-1 * (value)))
|
|
47
|
+
#else
|
|
48
|
+
#define AMPS_IEX(ptr,value) _InterlockedExchange((long*)(ptr), (LONG)(value))
|
|
49
|
+
#define AMPS_IEX_GET(ptr,value) _InterlockedExchange((long*)(ptr), (LONG)(value))
|
|
50
|
+
#define AMPS_IEX_LONG(ptr,value) _InterlockedExchange((ptr), (LONG)(value))
|
|
51
|
+
#define AMPS_FETCH_ADD(ptr, value) InterlockedExchangeAdd((LONG volatile*)(ptr), (LONG)(value))
|
|
52
|
+
#define AMPS_FETCH_SUB(ptr, value) InterlockedExchangeAdd((LONG volatile*)(ptr), (LONG)(-1 * (value)))
|
|
53
|
+
#endif
|
|
54
|
+
#else
|
|
55
|
+
#define AMPS_IEX(ptr, value) (void)__sync_lock_test_and_set((ptr), (value))
|
|
56
|
+
#define AMPS_IEX_GET(ptr, value) __sync_lock_test_and_set((ptr), (value))
|
|
57
|
+
#define AMPS_IEX_LONG(ptr, value) (void)__sync_lock_test_and_set((ptr), (value))
|
|
58
|
+
#define AMPS_FETCH_ADD(ptr, value) __sync_fetch_and_add((ptr), (value))
|
|
59
|
+
#define AMPS_FETCH_SUB(ptr, value) __sync_fetch_and_sub((ptr), (value))
|
|
60
|
+
#endif
|
|
61
|
+
|
|
62
|
+
#ifdef _WIN32
|
|
63
|
+
|
|
64
|
+
/* Causes linked programs to add ws2_32.lib which is required by
|
|
65
|
+
* this module. If you'd like to turn this off, define the macro
|
|
66
|
+
* AMPS_WINDOWS_NO_DEFAULT_LIBS.
|
|
67
|
+
*/
|
|
68
|
+
#ifndef AMPS_WINDOWS_NO_DEFAULT_LIBS
|
|
69
|
+
#pragma comment(lib,"ws2_32.lib")
|
|
70
|
+
#endif
|
|
71
|
+
|
|
72
|
+
#include <Ws2tcpip.h>
|
|
73
|
+
#define GET_ERRNO (WSAGetLastError())
|
|
74
|
+
#define SOCK_ERRORCODE(x) WSA##x
|
|
75
|
+
#define AMPS_INITLOCK(x) InitializeCriticalSection(x)
|
|
76
|
+
#define AMPS_LOCK(x) EnterCriticalSection(x)
|
|
77
|
+
/* defined in tcp.c */
|
|
78
|
+
int amps_win_spin_lock(LPCRITICAL_SECTION x);
|
|
79
|
+
#define AMPS_SPIN_LOCK(x) amps_win_spin_lock(x)
|
|
80
|
+
#define AMPS_SPIN_LOCK_UNLIMITED(x) EnterCriticalSection(x)
|
|
81
|
+
#define AMPS_UNLOCK(x) LeaveCriticalSection(x)
|
|
82
|
+
#define AMPS_KILLLOCK(x) DeleteCriticalSection(x)
|
|
83
|
+
int tcpsThreadTimeoutMillis = 10000;
|
|
84
|
+
#define AMPS_JOIN_DECLARE() \
|
|
85
|
+
DWORD tid = (DWORD)0; \
|
|
86
|
+
HANDLE tidH = (HANDLE)0
|
|
87
|
+
|
|
88
|
+
#define AMPS_JOIN(x) \
|
|
89
|
+
tid = (DWORD)AMPS_IEX(&x, 0); \
|
|
90
|
+
tidH = (HANDLE)AMPS_IEX(&x##H, 0); \
|
|
91
|
+
if (tid != 0 && tid != GetCurrentThreadId()) \
|
|
92
|
+
{ \
|
|
93
|
+
if(WAIT_TIMEOUT == WaitForSingleObject(tidH, tcpsThreadTimeoutMillis)) \
|
|
94
|
+
{ \
|
|
95
|
+
TerminateThread(tidH, -1); \
|
|
96
|
+
} \
|
|
97
|
+
}
|
|
98
|
+
#define AMPS_SLEEP(x) \
|
|
99
|
+
Sleep(x)
|
|
100
|
+
#define SHUT_RDWR SD_BOTH
|
|
101
|
+
#else
|
|
102
|
+
#define GET_ERRNO (errno)
|
|
103
|
+
#define SOCK_ERRORCODE(x) x
|
|
104
|
+
#include <pthread.h>
|
|
105
|
+
|
|
106
|
+
static pthread_mutexattr_t _mutexattr_recursive;
|
|
107
|
+
#define AMPS_INITLOCK(x) { \
|
|
108
|
+
pthread_mutexattr_init(&_mutexattr_recursive); \
|
|
109
|
+
pthread_mutexattr_settype(&_mutexattr_recursive, PTHREAD_MUTEX_RECURSIVE);\
|
|
110
|
+
pthread_mutex_init(x, &_mutexattr_recursive); }
|
|
111
|
+
#define AMPS_LOCK(x) pthread_mutex_lock(x)
|
|
112
|
+
#define AMPS_SPIN_LOCK(x) amps_spin_lock_counted(x)
|
|
113
|
+
#define AMPS_SPIN_LOCK_UNLIMITED(x) amps_spin_lock_unlimited(x)
|
|
114
|
+
|
|
115
|
+
#define AMPS_UNLOCK(x) pthread_mutex_unlock(x)
|
|
116
|
+
#define AMPS_KILLLOCK(x) pthread_mutex_destroy(x)
|
|
117
|
+
#define AMPS_JOIN_DECLARE() \
|
|
118
|
+
pthread_t tid = (pthread_t)0;
|
|
119
|
+
|
|
120
|
+
#if __STDC_VERSION__ >= 201100
|
|
121
|
+
#define AMPS_JOIN(x) \
|
|
122
|
+
tid = atomic_exchange((&x), (pthread_t)0); \
|
|
123
|
+
if(tid!=(pthread_t)0 && tid!=pthread_self()) \
|
|
124
|
+
{ \
|
|
125
|
+
pthread_join(tid, NULL); \
|
|
126
|
+
}
|
|
127
|
+
#else
|
|
128
|
+
#define AMPS_JOIN(x) \
|
|
129
|
+
tid = AMPS_FETCH_ADD(&x, (pthread_t)0); \
|
|
130
|
+
if(tid!=(pthread_t)0 && tid!=pthread_self()) \
|
|
131
|
+
{ \
|
|
132
|
+
if(__sync_bool_compare_and_swap(&x, tid, (pthread_t)0)) \
|
|
133
|
+
{ \
|
|
134
|
+
pthread_join(tid, NULL); \
|
|
135
|
+
} \
|
|
136
|
+
}
|
|
137
|
+
#endif
|
|
138
|
+
|
|
139
|
+
#define AMPS_SLEEP(x) { \
|
|
140
|
+
static struct timespec ts = { x/1000, (x%1000) * 1000000 }; \
|
|
141
|
+
nanosleep(&ts, NULL); }
|
|
142
|
+
#endif
|
|
143
|
+
|
|
144
|
+
typedef struct
|
|
145
|
+
{
|
|
146
|
+
amps_thread_created_callback threadCreatedCallback;
|
|
147
|
+
void* threadCreatedCallbackUserData;
|
|
148
|
+
char* buf;
|
|
149
|
+
amps_int64_t serializer;
|
|
150
|
+
amps_handler messageHandler;
|
|
151
|
+
void* messageHandlerUserData;
|
|
152
|
+
amps_transport_filter_function filterFunction;
|
|
153
|
+
void* filterUserData;
|
|
154
|
+
|
|
155
|
+
amps_predisconnect_handler predisconnectHandler;
|
|
156
|
+
void* predisconnectHandlerUserData;
|
|
157
|
+
amps_handler disconnectHandler;
|
|
158
|
+
void* disconnectHandlerUserData;
|
|
159
|
+
amps_uint64_t readTimeoutMillis;
|
|
160
|
+
amps_uint64_t idleTimeMillis;
|
|
161
|
+
#if __STDC_VERSION__ >= 201100
|
|
162
|
+
atomic_int_fast64_t threadCreatedCallbackResult;
|
|
163
|
+
_Atomic unsigned connectionVersion;
|
|
164
|
+
#else
|
|
165
|
+
#if defined(_WIN32) && !defined(_WIN64)
|
|
166
|
+
volatile long threadCreatedCallbackResult;
|
|
167
|
+
#else
|
|
168
|
+
volatile amps_int64_t threadCreatedCallbackResult;
|
|
169
|
+
#endif
|
|
170
|
+
volatile unsigned connectionVersion;
|
|
171
|
+
#endif
|
|
172
|
+
|
|
173
|
+
size_t capacity;
|
|
174
|
+
#if __STDC_VERSION__ >= 201100
|
|
175
|
+
_Atomic AMPS_SOCKET fd;
|
|
176
|
+
_Atomic(_amps_SSL*) ssl;
|
|
177
|
+
atomic_bool disconnecting;
|
|
178
|
+
atomic_bool destroying;
|
|
179
|
+
#else
|
|
180
|
+
volatile AMPS_SOCKET fd;
|
|
181
|
+
_amps_SSL* ssl;
|
|
182
|
+
volatile long disconnecting;
|
|
183
|
+
volatile long destroying;
|
|
184
|
+
#endif
|
|
185
|
+
#ifdef _WIN32
|
|
186
|
+
CRITICAL_SECTION lock;
|
|
187
|
+
CRITICAL_SECTION sendLock;
|
|
188
|
+
#if __STDC_VERSION__ >= 201100
|
|
189
|
+
_Atomic DWORD thread;
|
|
190
|
+
_Atomic HANDLE threadH;
|
|
191
|
+
#else
|
|
192
|
+
volatile DWORD thread;
|
|
193
|
+
volatile HANDLE threadH;
|
|
194
|
+
#endif
|
|
195
|
+
#else
|
|
196
|
+
pthread_mutex_t lock;
|
|
197
|
+
pthread_mutex_t sendLock;
|
|
198
|
+
#if __STDC_VERSION__ >= 201100
|
|
199
|
+
_Atomic pthread_t thread;
|
|
200
|
+
#else
|
|
201
|
+
volatile pthread_t thread;
|
|
202
|
+
#endif
|
|
203
|
+
#endif
|
|
204
|
+
char lastErrorBuf[1024];
|
|
205
|
+
}
|
|
206
|
+
amps_tcps_t;
|
|
207
|
+
|
|
208
|
+
const amps_char* amps_tcps_get_last_error(
|
|
209
|
+
amps_handle transport)
|
|
210
|
+
{
|
|
211
|
+
return ((amps_tcps_t*)transport)->lastErrorBuf;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
void amps_tcps_set_error(
|
|
215
|
+
amps_tcps_t* transport,
|
|
216
|
+
const amps_char* buffer)
|
|
217
|
+
{
|
|
218
|
+
_AMPS_SNPRINTF(transport->lastErrorBuf, sizeof(transport->lastErrorBuf), "%s", buffer);
|
|
219
|
+
transport->lastErrorBuf[sizeof(transport->lastErrorBuf) - 1] = '\0';
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
void amps_tcps_set_socket_error(
|
|
223
|
+
amps_tcps_t* transport,
|
|
224
|
+
int errorCode)
|
|
225
|
+
{
|
|
226
|
+
#ifdef _WIN32
|
|
227
|
+
char localBuf[256];
|
|
228
|
+
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, 0, localBuf, sizeof(localBuf), NULL);
|
|
229
|
+
amps_tcps_set_error(transport, localBuf);
|
|
230
|
+
#else
|
|
231
|
+
amps_tcps_set_error(transport, strerror(errorCode));
|
|
232
|
+
#endif
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
void amps_tcps_set_hostname_error(
|
|
236
|
+
amps_tcps_t* transport,
|
|
237
|
+
int rc,
|
|
238
|
+
int errorCode)
|
|
239
|
+
{
|
|
240
|
+
#ifdef _WIN32
|
|
241
|
+
amps_tcps_set_socket_error(transport, errorCode);
|
|
242
|
+
#else
|
|
243
|
+
strncpy(transport->lastErrorBuf, gai_strerror(rc), sizeof(transport->lastErrorBuf));
|
|
244
|
+
transport->lastErrorBuf[sizeof(transport->lastErrorBuf) - 1] = '\0';
|
|
245
|
+
#endif
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
void amps_tcps_set_error_stack_error(amps_tcps_t* transport)
|
|
249
|
+
{
|
|
250
|
+
char buffer[256];
|
|
251
|
+
_amps_ERR_error_string_n(_amps_ERR_get_error(), buffer, 256);
|
|
252
|
+
amps_tcps_set_error(transport, buffer);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
void amps_tcps_set_ssl_error(amps_tcps_t* transport,
|
|
256
|
+
int rc,
|
|
257
|
+
int sysError)
|
|
258
|
+
{
|
|
259
|
+
char buffer[256];
|
|
260
|
+
if (!transport->ssl)
|
|
261
|
+
{
|
|
262
|
+
_AMPS_SNPRINTF(buffer, 256, "SSL error, SSL is closing");
|
|
263
|
+
amps_tcps_set_error(transport, buffer);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
int sslError = _amps_SSL_get_error(transport->ssl, rc);
|
|
267
|
+
unsigned long errorQueue = 0;
|
|
268
|
+
switch (sslError)
|
|
269
|
+
{
|
|
270
|
+
case AMPS_SSL_ERROR_SSL:
|
|
271
|
+
amps_tcps_set_error_stack_error(transport);
|
|
272
|
+
break;
|
|
273
|
+
case AMPS_SSL_ERROR_SYSCALL:
|
|
274
|
+
errorQueue = _amps_ERR_get_error();
|
|
275
|
+
if (errorQueue)
|
|
276
|
+
{
|
|
277
|
+
_amps_ERR_error_string_n(errorQueue, buffer, 256);
|
|
278
|
+
amps_tcps_set_error(transport, buffer);
|
|
279
|
+
}
|
|
280
|
+
else if (rc == 0 || sysError == 0)
|
|
281
|
+
{
|
|
282
|
+
amps_tcps_set_error(transport, "An unexpected disconnect occurred.");
|
|
283
|
+
}
|
|
284
|
+
else
|
|
285
|
+
{
|
|
286
|
+
amps_tcps_set_socket_error(transport, sysError);
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
default:
|
|
290
|
+
_AMPS_SNPRINTF(buffer, 256, "Unexpected SSL error %d", sslError);
|
|
291
|
+
amps_tcps_set_error(transport, buffer);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
void
|
|
297
|
+
amps_tcps_noop_filter_function(const unsigned char* data, size_t length, short direction, void* userdata)
|
|
298
|
+
{;}
|
|
299
|
+
|
|
300
|
+
void amps_tcps_atfork_handler(amps_tcps_t* transport_, int code_)
|
|
301
|
+
{
|
|
302
|
+
switch (code_)
|
|
303
|
+
{
|
|
304
|
+
case 0:
|
|
305
|
+
break;
|
|
306
|
+
case 1:
|
|
307
|
+
break;
|
|
308
|
+
case 2:
|
|
309
|
+
/* Reinitialize the transport lock in the forked child */
|
|
310
|
+
AMPS_INITLOCK(&transport_->lock);
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
amps_handle amps_tcps_create(void)
|
|
316
|
+
{
|
|
317
|
+
amps_tcps_t* transport = (amps_tcps_t*)malloc(sizeof(amps_tcps_t));
|
|
318
|
+
|
|
319
|
+
if (transport != NULL)
|
|
320
|
+
{
|
|
321
|
+
memset(transport, 0, sizeof(amps_tcps_t));
|
|
322
|
+
transport->fd = AMPS_INVALID_SOCKET;
|
|
323
|
+
transport->ssl = NULL;
|
|
324
|
+
AMPS_INITLOCK(&transport->lock);
|
|
325
|
+
AMPS_INITLOCK(&transport->sendLock);
|
|
326
|
+
#if __STDC_VERSION__ >= 201100
|
|
327
|
+
transport->disconnecting = false;
|
|
328
|
+
transport->destroying = false;
|
|
329
|
+
#endif
|
|
330
|
+
transport->filterFunction = &s_tcps_noop_filter_function;
|
|
331
|
+
amps_atfork_add(transport, (_amps_atfork_callback_function)amps_tcps_atfork_handler);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return transport;
|
|
335
|
+
}
|
|
336
|
+
#ifdef _WIN32
|
|
337
|
+
DWORD amps_tcps_threaded_reader(void* userData);
|
|
338
|
+
#else
|
|
339
|
+
void* amps_tcps_threaded_reader(void* userData);
|
|
340
|
+
#endif
|
|
341
|
+
|
|
342
|
+
int
|
|
343
|
+
amps_tcps_opt_parse(const char* val, size_t valLen, int* parsed)
|
|
344
|
+
{
|
|
345
|
+
size_t i;
|
|
346
|
+
if (valLen == 4 && memcmp(val, "true", 4) == 0)
|
|
347
|
+
{
|
|
348
|
+
*parsed = 1;
|
|
349
|
+
return 1;
|
|
350
|
+
}
|
|
351
|
+
else if (valLen == 5 && memcmp(val, "false", 5) == 0)
|
|
352
|
+
{
|
|
353
|
+
*parsed = 0;
|
|
354
|
+
return 1;
|
|
355
|
+
}
|
|
356
|
+
else
|
|
357
|
+
{
|
|
358
|
+
*parsed = 0;
|
|
359
|
+
for (i = 0; i < valLen ; i++)
|
|
360
|
+
{
|
|
361
|
+
*parsed *= 10;
|
|
362
|
+
if (val[i] >= '0' && val[i] <= '9')
|
|
363
|
+
{
|
|
364
|
+
*parsed += val[i] - '0';
|
|
365
|
+
}
|
|
366
|
+
else
|
|
367
|
+
{
|
|
368
|
+
return 0;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return 1;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
amps_result
|
|
376
|
+
amps_tcps_apply_socket_property(AMPS_SOCKET fd, const char* key, size_t keyLen, const
|
|
377
|
+
char* val, size_t valLen)
|
|
378
|
+
{
|
|
379
|
+
int value = 0, level = SOL_SOCKET, optname;
|
|
380
|
+
unsigned int optValueSize = sizeof(int);
|
|
381
|
+
char* optValuePtr = (char*)&value;
|
|
382
|
+
struct linger lingerStruct;
|
|
383
|
+
if (keyLen == 4 && memcmp(key, "bind", keyLen) == 0)
|
|
384
|
+
{
|
|
385
|
+
struct addrinfo* pAddrInfo = NULL, addrhints;
|
|
386
|
+
char addr[256] = { 0 };
|
|
387
|
+
char port[256] = { 0 };
|
|
388
|
+
size_t addrLen = valLen, portLen = 0;
|
|
389
|
+
char* portStr = (char*)(memchr((void*)val, ':', valLen));
|
|
390
|
+
char* ipv6Str = (char*)(memchr((void*)val, '[', valLen));
|
|
391
|
+
|
|
392
|
+
#ifdef _WIN32
|
|
393
|
+
int addrFamily = 0;
|
|
394
|
+
WSAPROTOCOL_INFOW localProto;
|
|
395
|
+
int localProtoLen = sizeof(WSAPROTOCOL_INFO);
|
|
396
|
+
if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL_INFO, (char*)&localProto, &localProtoLen) == SOCKET_ERROR)
|
|
397
|
+
{
|
|
398
|
+
return AMPS_E_URI;
|
|
399
|
+
}
|
|
400
|
+
addrFamily = localProto.iAddressFamily;
|
|
401
|
+
#elif !defined(__APPLE__)
|
|
402
|
+
int addrFamily = 0;
|
|
403
|
+
socklen_t addrFamilyLen = sizeof(addrFamily);
|
|
404
|
+
if (getsockopt(fd, SOL_SOCKET, AMPS_SO_DOMAIN, (void*)&addrFamily, &addrFamilyLen) < 0)
|
|
405
|
+
{
|
|
406
|
+
return AMPS_E_URI;
|
|
407
|
+
}
|
|
408
|
+
#endif
|
|
409
|
+
|
|
410
|
+
if (ipv6Str)
|
|
411
|
+
{
|
|
412
|
+
++ipv6Str;
|
|
413
|
+
char* ipv6StrEnd = (char*)(memchr((void*)ipv6Str, ']', (size_t)(val + valLen - ipv6Str)));
|
|
414
|
+
if (!ipv6StrEnd)
|
|
415
|
+
{
|
|
416
|
+
return AMPS_E_URI;
|
|
417
|
+
}
|
|
418
|
+
addrLen = (size_t)(ipv6StrEnd - ipv6Str);
|
|
419
|
+
memcpy(addr, ipv6Str, addrLen);
|
|
420
|
+
addr[addrLen] = '\0';
|
|
421
|
+
|
|
422
|
+
if ((size_t)(val + valLen - ++ipv6StrEnd) < valLen && *ipv6StrEnd == ':')
|
|
423
|
+
{
|
|
424
|
+
portLen = (size_t)(val + valLen - ++ipv6StrEnd);
|
|
425
|
+
memcpy(port, ipv6StrEnd, portLen);
|
|
426
|
+
port[portLen] = '\0';
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
else if (portStr)
|
|
430
|
+
{
|
|
431
|
+
addrLen = (size_t)(portStr - val);
|
|
432
|
+
portLen = (size_t)(val + valLen - ++portStr);
|
|
433
|
+
memcpy(addr, val, addrLen);
|
|
434
|
+
addr[addrLen] = '\0';
|
|
435
|
+
memcpy(port, portStr, portLen);
|
|
436
|
+
port[portLen] = '\0';
|
|
437
|
+
}
|
|
438
|
+
else
|
|
439
|
+
{
|
|
440
|
+
memcpy(addr, val, addrLen);
|
|
441
|
+
addr[addrLen] = '\0';
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/* use getaddrinfo() to find an appropriate address */
|
|
445
|
+
memset(&addrhints, 0, sizeof(struct addrinfo));
|
|
446
|
+
addrhints.ai_socktype = SOCK_STREAM;
|
|
447
|
+
addrhints.ai_protocol = 0;
|
|
448
|
+
#ifndef __APPLE__
|
|
449
|
+
addrhints.ai_family = addrFamily; // match the family of the socket
|
|
450
|
+
#else
|
|
451
|
+
if (ipv6Str)
|
|
452
|
+
{
|
|
453
|
+
addrhints.ai_family = AF_INET6;
|
|
454
|
+
}
|
|
455
|
+
else
|
|
456
|
+
{
|
|
457
|
+
addrhints.ai_family = AF_INET;
|
|
458
|
+
}
|
|
459
|
+
#endif
|
|
460
|
+
addrhints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG | AI_PASSIVE);
|
|
461
|
+
|
|
462
|
+
int rc = getaddrinfo(addr, port, &addrhints, &pAddrInfo);
|
|
463
|
+
if (rc != 0 || pAddrInfo == NULL)
|
|
464
|
+
{
|
|
465
|
+
if (pAddrInfo)
|
|
466
|
+
{
|
|
467
|
+
freeaddrinfo(pAddrInfo);
|
|
468
|
+
}
|
|
469
|
+
return AMPS_E_URI;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (bind(fd, pAddrInfo->ai_addr, (socklen_t)pAddrInfo->ai_addrlen) != 0)
|
|
473
|
+
{
|
|
474
|
+
freeaddrinfo(pAddrInfo);
|
|
475
|
+
return AMPS_E_URI;
|
|
476
|
+
}
|
|
477
|
+
freeaddrinfo(pAddrInfo);
|
|
478
|
+
return AMPS_E_OK;
|
|
479
|
+
}
|
|
480
|
+
else if (keyLen == 18 && memcmp(key, "ip_protocol_prefer", keyLen) == 0)
|
|
481
|
+
{
|
|
482
|
+
// no-op; handled in the connect function
|
|
483
|
+
return AMPS_E_OK;
|
|
484
|
+
}
|
|
485
|
+
else if (keyLen == 3 && memcmp(key, "sni", keyLen) == 0)
|
|
486
|
+
{
|
|
487
|
+
// no-op; handled in amps_tcps_apply_ssl_properties
|
|
488
|
+
return AMPS_E_OK;
|
|
489
|
+
}
|
|
490
|
+
// properties after this point must only be boolean or numeric
|
|
491
|
+
if (!amps_tcps_opt_parse(val, valLen, &value))
|
|
492
|
+
{
|
|
493
|
+
return AMPS_E_URI;
|
|
494
|
+
}
|
|
495
|
+
if (keyLen == 10 && memcmp(key, "tcp_rcvbuf", keyLen) == 0)
|
|
496
|
+
{
|
|
497
|
+
optname = SO_RCVBUF;
|
|
498
|
+
}
|
|
499
|
+
else if (keyLen == 13 && memcmp(key, "tcp_keepalive", keyLen) == 0 )
|
|
500
|
+
{
|
|
501
|
+
optname = SO_KEEPALIVE;
|
|
502
|
+
}
|
|
503
|
+
else if (keyLen == 10 && memcmp(key, "tcp_sndbuf", keyLen) == 0)
|
|
504
|
+
{
|
|
505
|
+
optname = SO_SNDBUF;
|
|
506
|
+
}
|
|
507
|
+
else if (keyLen == 11 && memcmp(key, "tcp_nodelay", keyLen) == 0)
|
|
508
|
+
{
|
|
509
|
+
optname = TCP_NODELAY;
|
|
510
|
+
level = IPPROTO_TCP;
|
|
511
|
+
}
|
|
512
|
+
else if (keyLen == 10 && memcmp(key, "tcp_linger", keyLen) == 0)
|
|
513
|
+
{
|
|
514
|
+
optname = SO_LINGER;
|
|
515
|
+
lingerStruct.l_onoff = value != 0;
|
|
516
|
+
lingerStruct.l_linger = (u_short)value;
|
|
517
|
+
optValuePtr = (char*)&lingerStruct;
|
|
518
|
+
optValueSize = sizeof(struct linger);
|
|
519
|
+
}
|
|
520
|
+
else if (keyLen == 6 && memcmp(key, "pretty", keyLen) == 0)
|
|
521
|
+
{
|
|
522
|
+
// no-op; handled in C++ layer
|
|
523
|
+
return AMPS_E_OK;
|
|
524
|
+
}
|
|
525
|
+
else
|
|
526
|
+
{
|
|
527
|
+
return AMPS_E_URI;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/* set it */
|
|
531
|
+
if (setsockopt(fd, level, optname, optValuePtr, optValueSize))
|
|
532
|
+
{
|
|
533
|
+
return AMPS_E_URI;
|
|
534
|
+
}
|
|
535
|
+
return AMPS_E_OK;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
amps_result
|
|
539
|
+
amps_tcps_apply_socket_properties(AMPS_SOCKET fd, const char* uri,
|
|
540
|
+
size_t uriLength, amps_uri_state* uriState)
|
|
541
|
+
{
|
|
542
|
+
const char* key = NULL;
|
|
543
|
+
size_t keyLength = 0;
|
|
544
|
+
/* First, enable tcp_keepalive by default */
|
|
545
|
+
int value = 1;
|
|
546
|
+
unsigned int optValueSize = sizeof(int);
|
|
547
|
+
char* optValuePtr = (char*)&value;
|
|
548
|
+
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, optValuePtr, optValueSize))
|
|
549
|
+
{
|
|
550
|
+
return AMPS_E_URI;
|
|
551
|
+
}
|
|
552
|
+
/* Now, parse the rest of the URI */
|
|
553
|
+
while (uriState->part_id < AMPS_URI_ERROR)
|
|
554
|
+
{
|
|
555
|
+
amps_uri_parse(uri, uriLength, uriState);
|
|
556
|
+
if (uriState->part_id == AMPS_URI_OPTION_KEY)
|
|
557
|
+
{
|
|
558
|
+
key = uriState->part;
|
|
559
|
+
keyLength = uriState->part_length;
|
|
560
|
+
}
|
|
561
|
+
else if (uriState->part_id == AMPS_URI_OPTION_VALUE)
|
|
562
|
+
{
|
|
563
|
+
if (amps_tcps_apply_socket_property(fd, key, keyLength,
|
|
564
|
+
uriState->part, uriState->part_length) != AMPS_E_OK)
|
|
565
|
+
{
|
|
566
|
+
return AMPS_E_URI;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
if (uriState->part_id == AMPS_URI_ERROR)
|
|
571
|
+
{
|
|
572
|
+
return AMPS_E_URI;
|
|
573
|
+
}
|
|
574
|
+
return AMPS_E_OK;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
int
|
|
578
|
+
amps_tcps_apply_ssl_properties(_amps_SSL *ssl, const char* uri,
|
|
579
|
+
size_t uriLength, amps_uri_state* uriState)
|
|
580
|
+
{
|
|
581
|
+
int rc = 1;
|
|
582
|
+
const char *key = NULL;
|
|
583
|
+
size_t keyLength = 0;
|
|
584
|
+
while (uriState->part_id < AMPS_URI_ERROR)
|
|
585
|
+
{
|
|
586
|
+
amps_uri_parse(uri, uriLength, uriState);
|
|
587
|
+
if (uriState->part_id == AMPS_URI_OPTION_KEY)
|
|
588
|
+
{
|
|
589
|
+
key = uriState->part;
|
|
590
|
+
keyLength = uriState->part_length;
|
|
591
|
+
}
|
|
592
|
+
else if (uriState->part_id == AMPS_URI_OPTION_VALUE)
|
|
593
|
+
{
|
|
594
|
+
if (keyLength == 3 && memcmp(key, "sni", keyLength) == 0)
|
|
595
|
+
{
|
|
596
|
+
char* hostname = (char*)malloc(uriState->part_length + 1);
|
|
597
|
+
memcpy(hostname, uriState->part, uriState->part_length);
|
|
598
|
+
hostname[uriState->part_length] = '\0';
|
|
599
|
+
rc = _amps_SSL_ctrl(ssl, AMPS_SSL_CTRL_SET_TLSEXT_HOSTNAME, AMPS_TLSEXT_NAMETYPE_host_name, hostname);
|
|
600
|
+
free(hostname);
|
|
601
|
+
if (rc != 1)
|
|
602
|
+
{
|
|
603
|
+
return rc;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return rc;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
amps_result amps_tcps_set_idle_time(amps_handle transport, int idleTimeMillis);
|
|
612
|
+
amps_result amps_tcps_connect(amps_handle transport, const amps_char* address)
|
|
613
|
+
{
|
|
614
|
+
AMPS_JOIN_DECLARE();
|
|
615
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
616
|
+
char* host = NULL, *port = NULL, *protocol = NULL;
|
|
617
|
+
amps_uri_state uri_state_socket_props, uri_state_addr_props, uri_state_ssl_props;
|
|
618
|
+
amps_ip_protocol_preference ip_proto_prefer = AMPS_DEFAULT_IP_PROTOCOL_PREFERENCE;
|
|
619
|
+
int ip_proto_pref_override = 0;
|
|
620
|
+
int rc, sysError, i;
|
|
621
|
+
amps_result result = AMPS_E_OK;
|
|
622
|
+
struct addrinfo* pAddrInfo = NULL, addrhints;
|
|
623
|
+
size_t address_length = 0;
|
|
624
|
+
AMPS_SOCKET fd = AMPS_INVALID_SOCKET;
|
|
625
|
+
_amps_SSL* ssl = 0;
|
|
626
|
+
|
|
627
|
+
#ifdef _WIN32
|
|
628
|
+
WSADATA wsaData;
|
|
629
|
+
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
630
|
+
if (rc != 0)
|
|
631
|
+
{
|
|
632
|
+
amps_tcps_set_error(me, "Windows Sockets could not be started.");
|
|
633
|
+
return AMPS_E_MEMORY;
|
|
634
|
+
}
|
|
635
|
+
#endif
|
|
636
|
+
|
|
637
|
+
AMPS_LOCK(&me->lock);
|
|
638
|
+
#ifndef _WIN32
|
|
639
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->lock);
|
|
640
|
+
#endif
|
|
641
|
+
/* if we were previously marked as disconnecting, forget that. */
|
|
642
|
+
AMPS_IEX_LONG(&me->disconnecting, 0);
|
|
643
|
+
AMPS_LOCK(&me->sendLock);
|
|
644
|
+
#ifndef _WIN32
|
|
645
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->sendLock);
|
|
646
|
+
#endif
|
|
647
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
648
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
649
|
+
|
|
650
|
+
/* were we previously connected? go ahead and close that. */
|
|
651
|
+
if (ssl)
|
|
652
|
+
{
|
|
653
|
+
rc = _amps_SSL_shutdown(ssl);
|
|
654
|
+
#ifdef _WIN32
|
|
655
|
+
sysError = GetLastError();
|
|
656
|
+
#else
|
|
657
|
+
sysError = errno;
|
|
658
|
+
#endif
|
|
659
|
+
if (rc < 0)
|
|
660
|
+
{
|
|
661
|
+
amps_tcps_set_ssl_error(me, rc, sysError);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
if (fd != AMPS_INVALID_SOCKET)
|
|
665
|
+
{
|
|
666
|
+
/* this is a reconnect */
|
|
667
|
+
shutdown(fd, SHUT_RDWR);
|
|
668
|
+
closesocket(fd);
|
|
669
|
+
fd = AMPS_INVALID_SOCKET;
|
|
670
|
+
}
|
|
671
|
+
AMPS_JOIN(me->thread);
|
|
672
|
+
if (ssl)
|
|
673
|
+
{
|
|
674
|
+
_amps_SSL_free(ssl);
|
|
675
|
+
ssl = 0;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/* parse out the address */
|
|
679
|
+
memset(&uri_state_socket_props, 0, sizeof(amps_uri_state));
|
|
680
|
+
memset(&uri_state_addr_props, 0, sizeof(amps_uri_state));
|
|
681
|
+
memset(&uri_state_ssl_props, 0, sizeof(amps_uri_state));
|
|
682
|
+
address_length = strlen(address);
|
|
683
|
+
while (uri_state_addr_props.part_id < AMPS_URI_ERROR)
|
|
684
|
+
{
|
|
685
|
+
amps_uri_parse(address, address_length, &uri_state_addr_props);
|
|
686
|
+
switch (uri_state_addr_props.part_id)
|
|
687
|
+
{
|
|
688
|
+
case AMPS_URI_PROTOCOL:
|
|
689
|
+
protocol = _AMPS_STRNDUP(uri_state_addr_props.part, uri_state_addr_props.part_length);
|
|
690
|
+
me->serializer = amps_message_get_protocol(protocol);
|
|
691
|
+
if (me->serializer == -1)
|
|
692
|
+
{
|
|
693
|
+
amps_tcps_set_error(me,
|
|
694
|
+
"The URI specified an unavailable protocol.");
|
|
695
|
+
result = AMPS_E_URI;
|
|
696
|
+
goto error;
|
|
697
|
+
}
|
|
698
|
+
memcpy(&uri_state_socket_props, &uri_state_addr_props, sizeof(amps_uri_state));
|
|
699
|
+
memcpy(&uri_state_ssl_props, &uri_state_addr_props, sizeof(amps_uri_state));
|
|
700
|
+
break;
|
|
701
|
+
case AMPS_URI_HOST:
|
|
702
|
+
host = _AMPS_STRNDUP(uri_state_addr_props.part, uri_state_addr_props.part_length);
|
|
703
|
+
break;
|
|
704
|
+
case AMPS_URI_PORT:
|
|
705
|
+
port = _AMPS_STRNDUP(uri_state_addr_props.part, uri_state_addr_props.part_length);
|
|
706
|
+
break;
|
|
707
|
+
case AMPS_URI_OPTION_KEY:
|
|
708
|
+
if (uri_state_addr_props.part_length == 18 && memcmp(uri_state_addr_props.part, "ip_protocol_prefer", uri_state_addr_props.part_length) == 0)
|
|
709
|
+
{
|
|
710
|
+
ip_proto_pref_override = 1;
|
|
711
|
+
}
|
|
712
|
+
break;
|
|
713
|
+
case AMPS_URI_OPTION_VALUE:
|
|
714
|
+
if (ip_proto_pref_override)
|
|
715
|
+
{
|
|
716
|
+
if (uri_state_addr_props.part_length == 4 && memcmp(uri_state_addr_props.part, "ipv4", uri_state_addr_props.part_length) == 0)
|
|
717
|
+
{
|
|
718
|
+
ip_proto_prefer = AMPS_PREFER_IPV4;
|
|
719
|
+
}
|
|
720
|
+
else if (uri_state_addr_props.part_length == 4 && memcmp(uri_state_addr_props.part, "ipv6", uri_state_addr_props.part_length) == 0)
|
|
721
|
+
{
|
|
722
|
+
ip_proto_prefer = AMPS_PREFER_IPV6;
|
|
723
|
+
}
|
|
724
|
+
else
|
|
725
|
+
{
|
|
726
|
+
amps_tcps_set_error(me,
|
|
727
|
+
"The URI specified an invalid ip protocol preference.");
|
|
728
|
+
result = AMPS_E_URI;
|
|
729
|
+
goto error;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
break;
|
|
733
|
+
default:
|
|
734
|
+
break;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
if (uri_state_addr_props.part_id == AMPS_URI_ERROR)
|
|
738
|
+
{
|
|
739
|
+
amps_tcps_set_error(me, "URI format invalid.");
|
|
740
|
+
result = AMPS_E_URI;
|
|
741
|
+
goto error;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/* use getaddrinfo() to find an appropriate address */
|
|
745
|
+
memset(&addrhints, 0, sizeof(struct addrinfo));
|
|
746
|
+
addrhints.ai_socktype = SOCK_STREAM;
|
|
747
|
+
addrhints.ai_protocol = 0;
|
|
748
|
+
addrhints.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG);
|
|
749
|
+
addrhints.ai_family = ip_proto_prefer == AMPS_PREFER_IPV6 ? AF_INET6 : AF_INET; /* Try the preferred protocol first */
|
|
750
|
+
|
|
751
|
+
rc = getaddrinfo(host, port, &addrhints, &pAddrInfo);
|
|
752
|
+
#ifdef _WIN32
|
|
753
|
+
sysError = GetLastError();
|
|
754
|
+
if (rc == EAI_FAMILY || rc == EAI_NONAME || rc == EAI_AGAIN || rc == EAI_SERVICE)
|
|
755
|
+
#else
|
|
756
|
+
sysError = errno;
|
|
757
|
+
if (rc == EAI_ADDRFAMILY || rc == EAI_NONAME || rc == EAI_AGAIN || rc == EAI_SERVICE)
|
|
758
|
+
#endif
|
|
759
|
+
{
|
|
760
|
+
// didn't find any addresses of the preferred protocol, try the other one.
|
|
761
|
+
addrhints.ai_family = ip_proto_prefer == AMPS_PREFER_IPV6 ? AF_INET : AF_INET6;
|
|
762
|
+
rc = getaddrinfo(host, port, &addrhints, &pAddrInfo);
|
|
763
|
+
#ifdef _WIN32
|
|
764
|
+
sysError = GetLastError();
|
|
765
|
+
#else
|
|
766
|
+
sysError = errno;
|
|
767
|
+
#endif
|
|
768
|
+
if (rc != 0)
|
|
769
|
+
{
|
|
770
|
+
/* Try preferred protocol again without AI_ADDRCONFIG */
|
|
771
|
+
addrhints.ai_flags = AI_V4MAPPED;
|
|
772
|
+
addrhints.ai_family = ip_proto_prefer == AMPS_PREFER_IPV6 ? AF_INET6 : AF_INET;
|
|
773
|
+
rc = getaddrinfo(host, port, &addrhints, &pAddrInfo);
|
|
774
|
+
#ifdef _WIN32
|
|
775
|
+
sysError = GetLastError();
|
|
776
|
+
#else
|
|
777
|
+
sysError = errno;
|
|
778
|
+
#endif
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
if (rc != 0)
|
|
782
|
+
{
|
|
783
|
+
result = AMPS_E_CONNECTION_REFUSED;
|
|
784
|
+
amps_tcps_set_hostname_error(me, rc, sysError);
|
|
785
|
+
freeaddrinfo(pAddrInfo);
|
|
786
|
+
goto error;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
me->fd = socket(pAddrInfo->ai_family, pAddrInfo->ai_socktype, pAddrInfo->ai_protocol);
|
|
790
|
+
#ifdef _WIN32
|
|
791
|
+
sysError = GetLastError();
|
|
792
|
+
#else
|
|
793
|
+
sysError = errno;
|
|
794
|
+
#endif
|
|
795
|
+
if (me->fd == AMPS_INVALID_SOCKET)
|
|
796
|
+
{
|
|
797
|
+
freeaddrinfo(pAddrInfo);
|
|
798
|
+
amps_tcps_set_socket_error(me, sysError);
|
|
799
|
+
result = AMPS_E_CONNECTION_REFUSED;
|
|
800
|
+
goto error;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/* apply socket properties */
|
|
804
|
+
if (amps_tcps_apply_socket_properties(me->fd, address, address_length, &uri_state_socket_props) != AMPS_E_OK)
|
|
805
|
+
{
|
|
806
|
+
freeaddrinfo(pAddrInfo);
|
|
807
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
808
|
+
amps_tcps_set_error(me, "The URI specified invalid properties.");
|
|
809
|
+
result = AMPS_E_URI;
|
|
810
|
+
goto error;
|
|
811
|
+
}
|
|
812
|
+
#ifdef __APPLE__
|
|
813
|
+
rc = 1; /* Set NOSIGPIPE to ON */
|
|
814
|
+
if (setsockopt(me->fd, SOL_SOCKET, SO_NOSIGPIPE, &rc, sizeof(rc)) < 0)
|
|
815
|
+
{
|
|
816
|
+
freeaddrinfo(pAddrInfo);
|
|
817
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
818
|
+
amps_tcps_set_error(me, "Failed to set no SIGPIPE.");
|
|
819
|
+
result = AMPS_E_CONNECTION;
|
|
820
|
+
goto error;
|
|
821
|
+
}
|
|
822
|
+
#endif
|
|
823
|
+
|
|
824
|
+
rc = connect(me->fd, pAddrInfo->ai_addr,
|
|
825
|
+
(socklen_t)pAddrInfo->ai_addrlen);
|
|
826
|
+
#ifdef _WIN32
|
|
827
|
+
sysError = GetLastError();
|
|
828
|
+
#else
|
|
829
|
+
sysError = errno;
|
|
830
|
+
#endif
|
|
831
|
+
freeaddrinfo(pAddrInfo);
|
|
832
|
+
if (rc == -1)
|
|
833
|
+
{
|
|
834
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
835
|
+
amps_tcps_set_socket_error(me, sysError);
|
|
836
|
+
result = AMPS_E_CONNECTION_REFUSED;
|
|
837
|
+
goto error;
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/* On first use, initialize an SSL context if one hasn't been created. */
|
|
841
|
+
if (!_amps_ssl_ctx)
|
|
842
|
+
{
|
|
843
|
+
rc = amps_ssl_init(NULL);
|
|
844
|
+
if (rc)
|
|
845
|
+
{
|
|
846
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
847
|
+
amps_tcps_set_error(me, "Could not initialize an SSL context.");
|
|
848
|
+
result = AMPS_E_SSL;
|
|
849
|
+
goto error;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
/* Handshake via SSL */
|
|
853
|
+
_amps_ERR_clear_error();
|
|
854
|
+
if (!me->ssl)
|
|
855
|
+
{
|
|
856
|
+
me->ssl = _amps_SSL_new(_amps_ssl_ctx);
|
|
857
|
+
}
|
|
858
|
+
if (me->ssl == 0)
|
|
859
|
+
{
|
|
860
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
861
|
+
amps_tcps_set_error_stack_error(me);
|
|
862
|
+
result = AMPS_E_SSL;
|
|
863
|
+
goto error;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
rc = _amps_SSL_set_fd(me->ssl, (int)me->fd);
|
|
867
|
+
#ifdef _WIN32
|
|
868
|
+
sysError = GetLastError();
|
|
869
|
+
#else
|
|
870
|
+
sysError = errno;
|
|
871
|
+
#endif
|
|
872
|
+
if (rc != 1)
|
|
873
|
+
{
|
|
874
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
875
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
876
|
+
amps_tcps_set_ssl_error(me, rc, sysError);
|
|
877
|
+
result = AMPS_E_SSL;
|
|
878
|
+
goto error;
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
rc = amps_tcps_apply_ssl_properties(me->ssl, address, address_length, &uri_state_ssl_props);
|
|
882
|
+
#ifdef _WIN32
|
|
883
|
+
sysError = GetLastError();
|
|
884
|
+
#else
|
|
885
|
+
sysError = errno;
|
|
886
|
+
#endif
|
|
887
|
+
if (rc != 1)
|
|
888
|
+
{
|
|
889
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
890
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
891
|
+
amps_tcps_set_ssl_error(me, rc, sysError);
|
|
892
|
+
result = AMPS_E_SSL;
|
|
893
|
+
goto error;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
_amps_SSL_ctrl(me->ssl, AMPS_SSL_CTRL_MODE, AMPS_SSL_AUTO_RETRY, NULL);
|
|
897
|
+
|
|
898
|
+
rc = _amps_SSL_connect(me->ssl);
|
|
899
|
+
#ifdef _WIN32
|
|
900
|
+
sysError = GetLastError();
|
|
901
|
+
#else
|
|
902
|
+
sysError = errno;
|
|
903
|
+
#endif
|
|
904
|
+
if (rc != 1)
|
|
905
|
+
{
|
|
906
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
907
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
908
|
+
amps_tcps_set_ssl_error(me, rc, sysError);
|
|
909
|
+
result = AMPS_E_SSL;
|
|
910
|
+
goto error;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// tcps transport must use read with a timeout.
|
|
914
|
+
amps_tcps_set_idle_time(transport, 100);
|
|
915
|
+
|
|
916
|
+
/* Increase the connection version now, so that anyone else attempting a reconnect knows
|
|
917
|
+
* that they may not need to. */
|
|
918
|
+
me->connectionVersion++;
|
|
919
|
+
result = AMPS_E_OK;
|
|
920
|
+
|
|
921
|
+
/* and, start up a new reader thread */
|
|
922
|
+
if (me->threadCreatedCallback)
|
|
923
|
+
{
|
|
924
|
+
AMPS_IEX(&me->threadCreatedCallbackResult, -1);
|
|
925
|
+
}
|
|
926
|
+
#ifdef _WIN32
|
|
927
|
+
me->threadH = CreateThread(NULL, 0,
|
|
928
|
+
(LPTHREAD_START_ROUTINE)amps_tcps_threaded_reader,
|
|
929
|
+
me, CREATE_SUSPENDED, (LPDWORD)&me->thread);
|
|
930
|
+
/* Now that me->thread is populated, we can start the thread.
|
|
931
|
+
* important to do it in two steps, since we use me->thread as a poor-man's cancellation mechanism */
|
|
932
|
+
if (me->threadH)
|
|
933
|
+
{
|
|
934
|
+
ResumeThread(me->threadH);
|
|
935
|
+
}
|
|
936
|
+
else
|
|
937
|
+
{
|
|
938
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
939
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
940
|
+
amps_tcps_set_error(me, "Failed to create thread for receive");
|
|
941
|
+
result = AMPS_E_MEMORY;
|
|
942
|
+
goto error;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
#else
|
|
946
|
+
rc = pthread_create((pthread_t*)(&me->thread), NULL,
|
|
947
|
+
&s_tcps_threaded_reader, me);
|
|
948
|
+
if (rc != 0)
|
|
949
|
+
{
|
|
950
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
951
|
+
ssl = AMPS_IEX_GET(&me->ssl, 0);
|
|
952
|
+
amps_tcps_set_error(me, "Failed to create thread for receive");
|
|
953
|
+
result = AMPS_E_MEMORY;
|
|
954
|
+
goto error;
|
|
955
|
+
}
|
|
956
|
+
#endif
|
|
957
|
+
for (i = 0; i < AMPS_THREAD_START_TIMEOUT && me->threadCreatedCallbackResult == -1; ++i)
|
|
958
|
+
{
|
|
959
|
+
AMPS_SLEEP(4);
|
|
960
|
+
}
|
|
961
|
+
result = (amps_result)me->threadCreatedCallbackResult;
|
|
962
|
+
if (me->threadCreatedCallbackResult == -1)
|
|
963
|
+
{
|
|
964
|
+
amps_tcps_set_error(me, "Thread created callback failed to return in a timely manner or returned -1.");
|
|
965
|
+
result = AMPS_E_MEMORY;
|
|
966
|
+
}
|
|
967
|
+
if (result != AMPS_E_OK)
|
|
968
|
+
{
|
|
969
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
970
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
971
|
+
amps_tcps_set_error(me, "Thread creation callback failed");
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
error:
|
|
975
|
+
if (result != AMPS_E_OK)
|
|
976
|
+
{
|
|
977
|
+
if (ssl)
|
|
978
|
+
{
|
|
979
|
+
rc = _amps_SSL_shutdown(ssl);
|
|
980
|
+
#ifdef _WIN32
|
|
981
|
+
sysError = GetLastError();
|
|
982
|
+
#else
|
|
983
|
+
sysError = errno;
|
|
984
|
+
#endif
|
|
985
|
+
if (rc < 0)
|
|
986
|
+
{
|
|
987
|
+
amps_tcps_set_ssl_error(me, rc, sysError);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
if (fd != AMPS_INVALID_SOCKET)
|
|
991
|
+
{
|
|
992
|
+
shutdown(fd, SHUT_RDWR);
|
|
993
|
+
closesocket(fd);
|
|
994
|
+
}
|
|
995
|
+
if (ssl)
|
|
996
|
+
{
|
|
997
|
+
_amps_SSL_free(ssl);
|
|
998
|
+
ssl = 0;
|
|
999
|
+
}
|
|
1000
|
+
#ifdef _WIN32
|
|
1001
|
+
me->thread = 0;
|
|
1002
|
+
#else
|
|
1003
|
+
me->thread = (pthread_t)0;
|
|
1004
|
+
#endif
|
|
1005
|
+
}
|
|
1006
|
+
free(protocol);
|
|
1007
|
+
free(host);
|
|
1008
|
+
free(port);
|
|
1009
|
+
AMPS_UNLOCK(&me->sendLock);
|
|
1010
|
+
AMPS_UNLOCK(&me->lock);
|
|
1011
|
+
#ifndef _WIN32
|
|
1012
|
+
pthread_cleanup_pop(0);
|
|
1013
|
+
pthread_cleanup_pop(0);
|
|
1014
|
+
#endif
|
|
1015
|
+
return result;
|
|
1016
|
+
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
amps_result amps_tcps_set_receiver(amps_handle transport, amps_handler receiver, void* userData)
|
|
1020
|
+
{
|
|
1021
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1022
|
+
me->messageHandlerUserData = userData;
|
|
1023
|
+
me->messageHandler = receiver;
|
|
1024
|
+
return AMPS_E_OK;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
amps_result amps_tcps_set_predisconnect(amps_handle transport,
|
|
1028
|
+
amps_predisconnect_handler receiver,
|
|
1029
|
+
void* userData)
|
|
1030
|
+
{
|
|
1031
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1032
|
+
me->predisconnectHandlerUserData = userData;
|
|
1033
|
+
me->predisconnectHandler = receiver;
|
|
1034
|
+
return AMPS_E_OK;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
amps_result amps_tcps_set_disconnect(amps_handle transport, amps_handler receiver, void* userData)
|
|
1038
|
+
{
|
|
1039
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1040
|
+
me->disconnectHandlerUserData = userData;
|
|
1041
|
+
me->disconnectHandler = receiver;
|
|
1042
|
+
return AMPS_E_OK;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
void amps_tcps_close(amps_handle transport)
|
|
1046
|
+
{
|
|
1047
|
+
AMPS_JOIN_DECLARE();
|
|
1048
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1049
|
+
AMPS_SOCKET fd = AMPS_INVALID_SOCKET;
|
|
1050
|
+
_amps_SSL* ssl = 0;
|
|
1051
|
+
AMPS_IEX_LONG(&me->disconnecting, 1);
|
|
1052
|
+
AMPS_LOCK(&me->sendLock);
|
|
1053
|
+
#ifndef _WIN32
|
|
1054
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->sendLock);
|
|
1055
|
+
#endif
|
|
1056
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
1057
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
1058
|
+
AMPS_UNLOCK(&me->sendLock);
|
|
1059
|
+
#ifndef _WIN32
|
|
1060
|
+
pthread_cleanup_pop(0);
|
|
1061
|
+
#endif
|
|
1062
|
+
AMPS_SPIN_LOCK_UNLIMITED(&me->lock);
|
|
1063
|
+
#ifndef _WIN32
|
|
1064
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->lock);
|
|
1065
|
+
#endif
|
|
1066
|
+
if (ssl)
|
|
1067
|
+
{
|
|
1068
|
+
int rc = _amps_SSL_shutdown(ssl);
|
|
1069
|
+
#ifdef _WIN32
|
|
1070
|
+
int sysError = GetLastError();
|
|
1071
|
+
#else
|
|
1072
|
+
int sysError = errno;
|
|
1073
|
+
#endif
|
|
1074
|
+
if (rc == 0 && fd != AMPS_INVALID_SOCKET)
|
|
1075
|
+
{
|
|
1076
|
+
// attempt to wait for the server to send back the matching close notify.
|
|
1077
|
+
struct timeval tv;
|
|
1078
|
+
fd_set readfds, exceptfds;
|
|
1079
|
+
tv.tv_sec = 0;
|
|
1080
|
+
tv.tv_usec = 10000;
|
|
1081
|
+
FD_ZERO(&readfds);
|
|
1082
|
+
FD_SET(fd, &readfds);
|
|
1083
|
+
FD_ZERO(&exceptfds);
|
|
1084
|
+
FD_SET(fd, &exceptfds);
|
|
1085
|
+
#ifdef _WIN32
|
|
1086
|
+
select(1, &readfds, 0, &exceptfds, &tv);
|
|
1087
|
+
#else
|
|
1088
|
+
select(fd + 1, &readfds, 0, &exceptfds, &tv);
|
|
1089
|
+
#endif
|
|
1090
|
+
rc = _amps_SSL_shutdown(ssl);
|
|
1091
|
+
}
|
|
1092
|
+
if (rc < 0)
|
|
1093
|
+
{
|
|
1094
|
+
amps_tcps_set_ssl_error(me, rc, sysError);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
if (fd != AMPS_INVALID_SOCKET)
|
|
1098
|
+
{
|
|
1099
|
+
shutdown(fd, SHUT_RDWR);
|
|
1100
|
+
closesocket(fd);
|
|
1101
|
+
}
|
|
1102
|
+
if (ssl)
|
|
1103
|
+
{
|
|
1104
|
+
_amps_SSL_free(ssl);
|
|
1105
|
+
}
|
|
1106
|
+
AMPS_UNLOCK(&me->lock);
|
|
1107
|
+
#ifndef _WIN32
|
|
1108
|
+
pthread_cleanup_pop(0);
|
|
1109
|
+
#endif
|
|
1110
|
+
AMPS_JOIN(me->thread);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
void amps_tcps_destroy(amps_handle transport)
|
|
1114
|
+
{
|
|
1115
|
+
AMPS_JOIN_DECLARE();
|
|
1116
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1117
|
+
AMPS_SOCKET fd = AMPS_INVALID_SOCKET;
|
|
1118
|
+
_amps_SSL* ssl = 0;
|
|
1119
|
+
amps_atfork_remove(me, (_amps_atfork_callback_function)amps_tcps_atfork_handler);
|
|
1120
|
+
AMPS_LOCK(&me->sendLock);
|
|
1121
|
+
#ifndef _WIN32
|
|
1122
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->sendLock);
|
|
1123
|
+
#endif
|
|
1124
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
1125
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
1126
|
+
AMPS_UNLOCK(&me->sendLock);
|
|
1127
|
+
#ifndef _WIN32
|
|
1128
|
+
pthread_cleanup_pop(0);
|
|
1129
|
+
#endif
|
|
1130
|
+
AMPS_LOCK(&me->lock);
|
|
1131
|
+
#ifndef _WIN32
|
|
1132
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->lock);
|
|
1133
|
+
#endif
|
|
1134
|
+
#if __STDC_VERSION__ >= 201100
|
|
1135
|
+
me->destroying = true;
|
|
1136
|
+
me->disconnecting = true;
|
|
1137
|
+
#else
|
|
1138
|
+
AMPS_IEX_LONG(&me->destroying, 1);
|
|
1139
|
+
AMPS_IEX_LONG(&me->disconnecting, 1);
|
|
1140
|
+
#endif
|
|
1141
|
+
if (ssl)
|
|
1142
|
+
{
|
|
1143
|
+
int rc = _amps_SSL_shutdown(ssl);
|
|
1144
|
+
#ifdef _WIN32
|
|
1145
|
+
int sysError = GetLastError();
|
|
1146
|
+
#else
|
|
1147
|
+
int sysError = errno;
|
|
1148
|
+
#endif
|
|
1149
|
+
if (rc == 0 && fd != AMPS_INVALID_SOCKET)
|
|
1150
|
+
{
|
|
1151
|
+
// attempt to wait for the server to send back the matching close notify.
|
|
1152
|
+
struct timeval tv;
|
|
1153
|
+
fd_set readfds, exceptfds;
|
|
1154
|
+
tv.tv_sec = 0;
|
|
1155
|
+
tv.tv_usec = 10000;
|
|
1156
|
+
FD_ZERO(&readfds);
|
|
1157
|
+
FD_SET(fd, &readfds);
|
|
1158
|
+
FD_ZERO(&exceptfds);
|
|
1159
|
+
FD_SET(fd, &exceptfds);
|
|
1160
|
+
#ifdef _WIN32
|
|
1161
|
+
select(1, &readfds, 0, &exceptfds, &tv);
|
|
1162
|
+
#else
|
|
1163
|
+
select(fd + 1, &readfds, 0, &exceptfds, &tv);
|
|
1164
|
+
#endif
|
|
1165
|
+
rc = _amps_SSL_shutdown(ssl);
|
|
1166
|
+
}
|
|
1167
|
+
if (rc < 0)
|
|
1168
|
+
{
|
|
1169
|
+
amps_tcps_set_ssl_error(me, rc, sysError);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
if (fd != AMPS_INVALID_SOCKET)
|
|
1173
|
+
{
|
|
1174
|
+
shutdown(fd, SHUT_RDWR);
|
|
1175
|
+
closesocket(fd);
|
|
1176
|
+
}
|
|
1177
|
+
if (ssl)
|
|
1178
|
+
{
|
|
1179
|
+
_amps_SSL_free(ssl);
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
AMPS_UNLOCK(&me->lock);
|
|
1183
|
+
#ifndef _WIN32
|
|
1184
|
+
pthread_cleanup_pop(0);
|
|
1185
|
+
#endif
|
|
1186
|
+
AMPS_JOIN(me->thread);
|
|
1187
|
+
AMPS_SLEEP(1);
|
|
1188
|
+
free(me->buf);
|
|
1189
|
+
/* Hopefully, nobody else is using me right now. */
|
|
1190
|
+
|
|
1191
|
+
AMPS_KILLLOCK(&me->lock);
|
|
1192
|
+
AMPS_KILLLOCK(&me->sendLock);
|
|
1193
|
+
|
|
1194
|
+
free(me);
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/* called with me->lock not already taken */
|
|
1198
|
+
amps_result amps_tcps_handle_disconnect(
|
|
1199
|
+
amps_tcps_t* me, unsigned failedConnectionVersion)
|
|
1200
|
+
{
|
|
1201
|
+
AMPS_SOCKET fd = AMPS_INVALID_SOCKET;
|
|
1202
|
+
_amps_SSL* ssl = 0;
|
|
1203
|
+
#ifndef _WIN32
|
|
1204
|
+
int cancelState = 0;
|
|
1205
|
+
int unusedCancelState = 0;
|
|
1206
|
+
#endif
|
|
1207
|
+
amps_result result = AMPS_E_OK;
|
|
1208
|
+
AMPS_LOCK(&me->sendLock);
|
|
1209
|
+
#ifndef _WIN32
|
|
1210
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->sendLock);
|
|
1211
|
+
#endif
|
|
1212
|
+
fd = AMPS_IEX_GET(&me->fd, AMPS_INVALID_SOCKET);
|
|
1213
|
+
ssl = (_amps_SSL*)AMPS_IEX_GET(&me->ssl, 0);
|
|
1214
|
+
AMPS_UNLOCK(&me->sendLock);
|
|
1215
|
+
#ifndef _WIN32
|
|
1216
|
+
pthread_cleanup_pop(0);
|
|
1217
|
+
#endif
|
|
1218
|
+
/* close what we have right now. */
|
|
1219
|
+
if (ssl)
|
|
1220
|
+
{
|
|
1221
|
+
int rc = _amps_SSL_shutdown(ssl);
|
|
1222
|
+
#ifdef _WIN32
|
|
1223
|
+
int sysError = GetLastError();
|
|
1224
|
+
#else
|
|
1225
|
+
int sysError = errno;
|
|
1226
|
+
#endif
|
|
1227
|
+
if (rc == 0 && fd != AMPS_INVALID_SOCKET)
|
|
1228
|
+
{
|
|
1229
|
+
// attempt to wait for the server to send back the matching close notify.
|
|
1230
|
+
struct timeval tv;
|
|
1231
|
+
fd_set readfds, exceptfds;
|
|
1232
|
+
tv.tv_sec = 0;
|
|
1233
|
+
tv.tv_usec = 10000;
|
|
1234
|
+
FD_ZERO(&readfds);
|
|
1235
|
+
FD_SET(fd, &readfds);
|
|
1236
|
+
FD_ZERO(&exceptfds);
|
|
1237
|
+
FD_SET(fd, &exceptfds);
|
|
1238
|
+
#ifdef _WIN32
|
|
1239
|
+
select(1, &readfds, 0, &exceptfds, &tv);
|
|
1240
|
+
#else
|
|
1241
|
+
select(fd + 1, &readfds, 0, &exceptfds, &tv);
|
|
1242
|
+
#endif
|
|
1243
|
+
rc = _amps_SSL_shutdown(ssl);
|
|
1244
|
+
}
|
|
1245
|
+
if (rc < 0)
|
|
1246
|
+
{
|
|
1247
|
+
amps_tcps_set_ssl_error(me, rc, sysError);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
if (fd != AMPS_INVALID_SOCKET)
|
|
1251
|
+
{
|
|
1252
|
+
shutdown(fd, SHUT_RDWR);
|
|
1253
|
+
closesocket(fd);
|
|
1254
|
+
}
|
|
1255
|
+
if (ssl)
|
|
1256
|
+
{
|
|
1257
|
+
_amps_SSL_free(ssl);
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/* first let waiters know that we've failed. */
|
|
1261
|
+
me->predisconnectHandler(me, failedConnectionVersion, me->predisconnectHandlerUserData);
|
|
1262
|
+
|
|
1263
|
+
/* Now take the lock on self.
|
|
1264
|
+
* Use a spin, the only case where it might fail should be if a recv
|
|
1265
|
+
* thread ends up here while a send thread is already handling disconnect
|
|
1266
|
+
* and it is trying to join this thread in disconnect. */
|
|
1267
|
+
if (AMPS_SPIN_LOCK(&me->lock) == 0)
|
|
1268
|
+
{
|
|
1269
|
+
return AMPS_E_RETRY;
|
|
1270
|
+
}
|
|
1271
|
+
#ifndef _WIN32
|
|
1272
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->lock);
|
|
1273
|
+
#endif
|
|
1274
|
+
|
|
1275
|
+
/* if we're being destroyed, get out of here; don't worry about unlocking */
|
|
1276
|
+
if (me->destroying)
|
|
1277
|
+
{
|
|
1278
|
+
result = AMPS_E_DISCONNECTED; return result;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/* a new connection is available. let someone else try. */
|
|
1282
|
+
if (failedConnectionVersion != me->connectionVersion)
|
|
1283
|
+
{
|
|
1284
|
+
result = AMPS_E_RETRY;
|
|
1285
|
+
goto error;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/* if we're disconnecting, get out of here; don't reconnect */
|
|
1289
|
+
if (me->disconnecting)
|
|
1290
|
+
{
|
|
1291
|
+
result = AMPS_E_DISCONNECTED;
|
|
1292
|
+
goto error;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
#ifndef _WIN32
|
|
1296
|
+
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState);
|
|
1297
|
+
#endif
|
|
1298
|
+
/* Call the disconect handler. */
|
|
1299
|
+
result = me->disconnectHandler(me, me->disconnectHandlerUserData);
|
|
1300
|
+
#ifndef _WIN32
|
|
1301
|
+
pthread_setcancelstate(cancelState, &unusedCancelState);
|
|
1302
|
+
#endif
|
|
1303
|
+
if (result == AMPS_E_OK)
|
|
1304
|
+
{
|
|
1305
|
+
result = AMPS_E_RETRY;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
error:
|
|
1309
|
+
#ifndef _WIN32
|
|
1310
|
+
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState);
|
|
1311
|
+
#endif
|
|
1312
|
+
AMPS_UNLOCK(&me->lock);
|
|
1313
|
+
#ifndef _WIN32
|
|
1314
|
+
pthread_cleanup_pop(0);
|
|
1315
|
+
pthread_setcancelstate(cancelState, &unusedCancelState);
|
|
1316
|
+
#endif
|
|
1317
|
+
|
|
1318
|
+
return result;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
void amps_tcps_handle_stream_corruption(
|
|
1322
|
+
amps_tcps_t* me, unsigned failedConnectionVersion)
|
|
1323
|
+
{
|
|
1324
|
+
amps_tcps_set_error(me, "The connection appears corrupt. Disconnecting.");
|
|
1325
|
+
amps_tcps_handle_disconnect(me, failedConnectionVersion);
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
amps_result
|
|
1330
|
+
amps_tcps_send_with_version(amps_handle transport,
|
|
1331
|
+
amps_handle message,
|
|
1332
|
+
unsigned* version_out)
|
|
1333
|
+
{
|
|
1334
|
+
amps_result result = AMPS_E_OK;
|
|
1335
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1336
|
+
size_t len = 16 * 1024;
|
|
1337
|
+
int bytesWritten = -1;
|
|
1338
|
+
unsigned int bytesWrittenN = 0;
|
|
1339
|
+
int bytesSent = 0;
|
|
1340
|
+
|
|
1341
|
+
*version_out = me->connectionVersion;
|
|
1342
|
+
|
|
1343
|
+
if (me->disconnecting)
|
|
1344
|
+
{
|
|
1345
|
+
amps_tcps_set_error(me, "Disconnecting.");
|
|
1346
|
+
return AMPS_E_DISCONNECTED;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
if (me->fd == AMPS_INVALID_SOCKET)
|
|
1350
|
+
{
|
|
1351
|
+
amps_tcps_set_error(me, "Not connected.");
|
|
1352
|
+
return AMPS_E_DISCONNECTED;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/* serialize */
|
|
1356
|
+
AMPS_LOCK(&me->sendLock);
|
|
1357
|
+
#ifndef _WIN32
|
|
1358
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me->sendLock);
|
|
1359
|
+
#endif
|
|
1360
|
+
if (me->ssl == 0)
|
|
1361
|
+
{
|
|
1362
|
+
amps_tcps_set_error(me, "Not connected.");
|
|
1363
|
+
result = AMPS_E_CONNECTION;
|
|
1364
|
+
goto error;
|
|
1365
|
+
}
|
|
1366
|
+
while (bytesWritten < 0)
|
|
1367
|
+
{
|
|
1368
|
+
if (me->buf == NULL)
|
|
1369
|
+
{
|
|
1370
|
+
me->buf = (char*)malloc(len);
|
|
1371
|
+
if (me->buf == NULL)
|
|
1372
|
+
{
|
|
1373
|
+
amps_tcps_set_error(me, "Unable to allocate memory to send message.");
|
|
1374
|
+
result = AMPS_E_MEMORY;
|
|
1375
|
+
goto error;
|
|
1376
|
+
}
|
|
1377
|
+
me->capacity = len;
|
|
1378
|
+
}
|
|
1379
|
+
else
|
|
1380
|
+
{
|
|
1381
|
+
len = me->capacity;
|
|
1382
|
+
}
|
|
1383
|
+
/* reserve 4 bytes for the length of the message */
|
|
1384
|
+
bytesWritten = amps_message_serialize(message, me->serializer, (me->buf) + 4, len - 4);
|
|
1385
|
+
/* amps_message_serialize could have written 0 bytes.
|
|
1386
|
+
* who are we to judge? If it returns less than 0,
|
|
1387
|
+
* there wasn't enough room. */
|
|
1388
|
+
if (bytesWritten >= 0)
|
|
1389
|
+
{
|
|
1390
|
+
break;
|
|
1391
|
+
}
|
|
1392
|
+
/* free this buffer, allocate a larger buffer next time */
|
|
1393
|
+
free(me->buf);
|
|
1394
|
+
me->capacity = 0;
|
|
1395
|
+
me->buf = NULL;
|
|
1396
|
+
len = (size_t)((double)len * 1.5);
|
|
1397
|
+
}
|
|
1398
|
+
/* once we're done, we don't free buf -- it hangs around until we need it next time.
|
|
1399
|
+
* record the message length all up in the first 4 bytes. */
|
|
1400
|
+
bytesWrittenN = htonl((unsigned int)bytesWritten);
|
|
1401
|
+
me->filterFunction((const unsigned char*)(me->buf + 4), (size_t)bytesWritten, 0, me->filterUserData);
|
|
1402
|
+
*((unsigned int*)(me->buf)) = bytesWrittenN;
|
|
1403
|
+
bytesWritten += 4;
|
|
1404
|
+
/*now, send */
|
|
1405
|
+
while (bytesSent < bytesWritten)
|
|
1406
|
+
{
|
|
1407
|
+
int bytesWrittenThisTime;
|
|
1408
|
+
bytesWrittenThisTime = _amps_SSL_write(me->ssl, (me->buf) + bytesSent, bytesWritten - bytesSent);
|
|
1409
|
+
if (bytesWrittenThisTime <= 0)
|
|
1410
|
+
{
|
|
1411
|
+
/* record the error */
|
|
1412
|
+
amps_tcps_set_error(me, "The connection is closed.");
|
|
1413
|
+
result = AMPS_E_DISCONNECTED;
|
|
1414
|
+
goto error;
|
|
1415
|
+
}
|
|
1416
|
+
bytesSent += bytesWrittenThisTime;
|
|
1417
|
+
}
|
|
1418
|
+
error:
|
|
1419
|
+
AMPS_UNLOCK(&me->sendLock);
|
|
1420
|
+
#ifndef _WIN32
|
|
1421
|
+
pthread_cleanup_pop(0);
|
|
1422
|
+
#endif
|
|
1423
|
+
|
|
1424
|
+
return result;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
amps_result
|
|
1428
|
+
amps_tcps_send(amps_handle transport,
|
|
1429
|
+
amps_handle message)
|
|
1430
|
+
{
|
|
1431
|
+
unsigned version_out;
|
|
1432
|
+
return amps_tcps_send_with_version(transport, message, &version_out);
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
/* Returns # bytes read, 0 if a timeout occurred without a read,
|
|
1436
|
+
* and <0 if an error occurred.
|
|
1437
|
+
*/
|
|
1438
|
+
int amps_tcps_locked_read(amps_tcps_t* me_,
|
|
1439
|
+
char* readPoint_,
|
|
1440
|
+
int bytes_)
|
|
1441
|
+
{
|
|
1442
|
+
int rc = 0;
|
|
1443
|
+
int errorcode = 0;
|
|
1444
|
+
int fd = (int)me_->fd;
|
|
1445
|
+
int locked = 0;
|
|
1446
|
+
|
|
1447
|
+
while (locked == 0)
|
|
1448
|
+
{
|
|
1449
|
+
if (me_->disconnecting || fd != me_->fd || !me_->ssl
|
|
1450
|
+
#ifdef _WIN32
|
|
1451
|
+
|| me_->thread != GetCurrentThreadId() /* our cancellation mechanism on win32 */
|
|
1452
|
+
#else
|
|
1453
|
+
|| me_->thread != pthread_self()
|
|
1454
|
+
#endif
|
|
1455
|
+
|| me_->destroying || fd == AMPS_INVALID_SOCKET)
|
|
1456
|
+
{
|
|
1457
|
+
return 0;
|
|
1458
|
+
}
|
|
1459
|
+
locked = (int)AMPS_SPIN_LOCK(&me_->sendLock);
|
|
1460
|
+
}
|
|
1461
|
+
if (me_->disconnecting || fd != me_->fd || !me_->ssl
|
|
1462
|
+
#ifdef _WIN32
|
|
1463
|
+
|| me_->thread != GetCurrentThreadId() /* our cancellation mechanism on win32 */
|
|
1464
|
+
#else
|
|
1465
|
+
|| me_->thread != pthread_self()
|
|
1466
|
+
#endif
|
|
1467
|
+
|| me_->destroying || fd == AMPS_INVALID_SOCKET)
|
|
1468
|
+
{
|
|
1469
|
+
AMPS_UNLOCK(&me_->sendLock);
|
|
1470
|
+
return 0;
|
|
1471
|
+
}
|
|
1472
|
+
// Use select to wait for data if none already exists on the ssl.
|
|
1473
|
+
if (!_amps_SSL_pending(me_->ssl))
|
|
1474
|
+
{
|
|
1475
|
+
struct timeval tv;
|
|
1476
|
+
fd_set readfds, exceptfds;
|
|
1477
|
+
tv.tv_sec = 0;
|
|
1478
|
+
tv.tv_usec = 1000;
|
|
1479
|
+
FD_ZERO(&readfds);
|
|
1480
|
+
FD_SET(fd, &readfds);
|
|
1481
|
+
FD_ZERO(&exceptfds);
|
|
1482
|
+
FD_SET(fd, &exceptfds);
|
|
1483
|
+
AMPS_UNLOCK(&me_->sendLock);
|
|
1484
|
+
#ifdef _WIN32
|
|
1485
|
+
if (select(1, &readfds, 0, &exceptfds, &tv) == 0)
|
|
1486
|
+
#else
|
|
1487
|
+
if (select(fd + 1, &readfds, 0, &exceptfds, &tv) == 0)
|
|
1488
|
+
#endif
|
|
1489
|
+
{
|
|
1490
|
+
return 0;
|
|
1491
|
+
}
|
|
1492
|
+
AMPS_LOCK(&me_->sendLock);
|
|
1493
|
+
if (me_->disconnecting || fd != me_->fd || !me_->ssl
|
|
1494
|
+
#ifdef _WIN32
|
|
1495
|
+
|| me_->thread != GetCurrentThreadId() /* our cancellation mechanism on win32 */
|
|
1496
|
+
#else
|
|
1497
|
+
|| me_->thread != pthread_self()
|
|
1498
|
+
#endif
|
|
1499
|
+
|| me_->destroying || fd == AMPS_INVALID_SOCKET)
|
|
1500
|
+
{
|
|
1501
|
+
AMPS_UNLOCK(&me_->sendLock);
|
|
1502
|
+
return 0;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
#ifndef _WIN32
|
|
1507
|
+
pthread_cleanup_push(amps_cleanup_unlock_mutex, (void*)&me_->sendLock);
|
|
1508
|
+
#endif
|
|
1509
|
+
rc = _amps_SSL_read(me_->ssl, readPoint_, bytes_);
|
|
1510
|
+
errorcode = rc <= 0 ? _amps_SSL_get_error(me_->ssl, rc) : 0;
|
|
1511
|
+
|
|
1512
|
+
AMPS_UNLOCK(&me_->sendLock);
|
|
1513
|
+
#ifndef _WIN32
|
|
1514
|
+
pthread_cleanup_pop(0);
|
|
1515
|
+
#endif
|
|
1516
|
+
|
|
1517
|
+
if (rc <= 0)
|
|
1518
|
+
{
|
|
1519
|
+
if (errorcode == AMPS_SSL_ERROR_WANT_READ)
|
|
1520
|
+
{
|
|
1521
|
+
return 0;
|
|
1522
|
+
}
|
|
1523
|
+
// End of stream
|
|
1524
|
+
return -1;
|
|
1525
|
+
}
|
|
1526
|
+
return rc;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
#ifdef _WIN32
|
|
1530
|
+
DWORD amps_tcps_threaded_reader(void* userData)
|
|
1531
|
+
{
|
|
1532
|
+
DWORD self = GetCurrentThreadId();
|
|
1533
|
+
HANDLE selfH = GetCurrentThread();
|
|
1534
|
+
amps_tcps_t* me = (amps_tcps_t*)userData;
|
|
1535
|
+
if (me->threadCreatedCallback)
|
|
1536
|
+
{
|
|
1537
|
+
amps_result result = me->threadCreatedCallback(selfH,
|
|
1538
|
+
me->threadCreatedCallbackUserData);
|
|
1539
|
+
AMPS_IEX(&me->threadCreatedCallbackResult, (long)result);
|
|
1540
|
+
if (result != AMPS_E_OK)
|
|
1541
|
+
{
|
|
1542
|
+
return (DWORD)0;
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
else
|
|
1546
|
+
{
|
|
1547
|
+
AMPS_IEX(&me->threadCreatedCallbackResult, (long)AMPS_E_OK);
|
|
1548
|
+
}
|
|
1549
|
+
#else
|
|
1550
|
+
void* amps_tcps_threaded_reader(void* userData)
|
|
1551
|
+
{
|
|
1552
|
+
int unusedCancelState = 0;
|
|
1553
|
+
amps_tcps_t* me = (amps_tcps_t*)userData;
|
|
1554
|
+
/* Wait for pthread_create to set me->thread */
|
|
1555
|
+
while (me->thread != pthread_self()
|
|
1556
|
+
&& !me->disconnecting
|
|
1557
|
+
&& !me->destroying)
|
|
1558
|
+
{
|
|
1559
|
+
AMPS_SLEEP(5);
|
|
1560
|
+
}
|
|
1561
|
+
if (me->threadCreatedCallback)
|
|
1562
|
+
{
|
|
1563
|
+
amps_result result = me->threadCreatedCallback(me->thread,
|
|
1564
|
+
me->threadCreatedCallbackUserData);
|
|
1565
|
+
AMPS_IEX(&me->threadCreatedCallbackResult, (long)result);
|
|
1566
|
+
if (result != AMPS_E_OK)
|
|
1567
|
+
{
|
|
1568
|
+
return NULL;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
else
|
|
1572
|
+
{
|
|
1573
|
+
AMPS_IEX(&me->threadCreatedCallbackResult, (long)AMPS_E_OK);
|
|
1574
|
+
}
|
|
1575
|
+
#endif
|
|
1576
|
+
unsigned char* buffer, *newBuffer, *end, *readPoint, *parsePoint;
|
|
1577
|
+
|
|
1578
|
+
unsigned int msglenN;
|
|
1579
|
+
unsigned long msglen, currentPosition, bytesRead = 0;
|
|
1580
|
+
int received;
|
|
1581
|
+
int cancelState = 0;
|
|
1582
|
+
const size_t BUFFER_SIZE = 16 * 1024;
|
|
1583
|
+
const unsigned MAX_MESSAGE_SIZE = 1024 * 1024 * 1024;
|
|
1584
|
+
amps_uint64_t lastReadTime = 0;
|
|
1585
|
+
amps_uint64_t lastIdleTime = 0;
|
|
1586
|
+
amps_handle message;
|
|
1587
|
+
|
|
1588
|
+
/* capture the connection version we are using now. */
|
|
1589
|
+
unsigned connectionVersion = me->connectionVersion;
|
|
1590
|
+
AMPS_SOCKET fd = me->fd;
|
|
1591
|
+
|
|
1592
|
+
lastReadTime = amps_now();
|
|
1593
|
+
lastIdleTime = lastReadTime;
|
|
1594
|
+
|
|
1595
|
+
#ifndef _WIN32
|
|
1596
|
+
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState);
|
|
1597
|
+
#endif
|
|
1598
|
+
message = amps_message_create(NULL);
|
|
1599
|
+
buffer = (unsigned char*)malloc(BUFFER_SIZE);
|
|
1600
|
+
#ifndef _WIN32
|
|
1601
|
+
pthread_cleanup_push(amps_message_destroy, (void*)message);
|
|
1602
|
+
pthread_cleanup_push(amps_cleanup_free_buffer, (void*)(&buffer));
|
|
1603
|
+
pthread_setcancelstate(cancelState, &unusedCancelState);
|
|
1604
|
+
#endif
|
|
1605
|
+
if (!buffer)
|
|
1606
|
+
{
|
|
1607
|
+
amps_tcps_handle_disconnect(me, connectionVersion);
|
|
1608
|
+
goto cleanup;
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
end = buffer + BUFFER_SIZE;
|
|
1612
|
+
readPoint = buffer;
|
|
1613
|
+
parsePoint = buffer;
|
|
1614
|
+
|
|
1615
|
+
/* while we're open and not disconnecting */
|
|
1616
|
+
while (connectionVersion == me->connectionVersion
|
|
1617
|
+
&& !me->disconnecting
|
|
1618
|
+
&& fd == me->fd
|
|
1619
|
+
#ifdef _WIN32
|
|
1620
|
+
&& me->thread == GetCurrentThreadId() /* our cancellation mechanism on win32 */
|
|
1621
|
+
#else
|
|
1622
|
+
&& me->thread == pthread_self()
|
|
1623
|
+
#endif
|
|
1624
|
+
)
|
|
1625
|
+
{
|
|
1626
|
+
if (me->destroying)
|
|
1627
|
+
{
|
|
1628
|
+
goto cleanup;
|
|
1629
|
+
}
|
|
1630
|
+
if (me->idleTimeMillis > 0 &&
|
|
1631
|
+
(amps_now() - lastIdleTime) > me->idleTimeMillis)
|
|
1632
|
+
{
|
|
1633
|
+
lastIdleTime = amps_now();
|
|
1634
|
+
#ifndef _WIN32
|
|
1635
|
+
cancelState = 0;
|
|
1636
|
+
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState);
|
|
1637
|
+
#endif
|
|
1638
|
+
me->messageHandler(0L,
|
|
1639
|
+
me->messageHandlerUserData);
|
|
1640
|
+
#ifndef _WIN32
|
|
1641
|
+
pthread_setcancelstate(cancelState, &unusedCancelState);
|
|
1642
|
+
#endif
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
received = amps_tcps_locked_read(me, (char*) readPoint, (int)(end - readPoint));
|
|
1646
|
+
|
|
1647
|
+
if (received > 0)
|
|
1648
|
+
{
|
|
1649
|
+
/* Call filter function without the 4 byte size */
|
|
1650
|
+
me->filterFunction(readPoint, (size_t)received, 1, me->filterUserData);
|
|
1651
|
+
readPoint += received;
|
|
1652
|
+
lastReadTime = amps_now();
|
|
1653
|
+
}
|
|
1654
|
+
else if (received < 0)
|
|
1655
|
+
{
|
|
1656
|
+
int errorcode = GET_ERRNO;
|
|
1657
|
+
if (errorcode == SOCK_ERRORCODE(EINTR))
|
|
1658
|
+
{
|
|
1659
|
+
continue;
|
|
1660
|
+
}
|
|
1661
|
+
/* disconnect if not a timeout error, or the user only set a read timeout, or the
|
|
1662
|
+
* read timeout has been exceeded. */
|
|
1663
|
+
if ( (errorcode != SOCK_ERRORCODE(ETIMEDOUT) && errorcode != SOCK_ERRORCODE(EWOULDBLOCK))
|
|
1664
|
+
|| me->idleTimeMillis == 0
|
|
1665
|
+
|| (me->readTimeoutMillis && amps_now() - lastReadTime > me->readTimeoutMillis))
|
|
1666
|
+
{
|
|
1667
|
+
if (!me->disconnecting)
|
|
1668
|
+
{
|
|
1669
|
+
amps_tcps_handle_disconnect(me, connectionVersion);
|
|
1670
|
+
}
|
|
1671
|
+
goto cleanup;
|
|
1672
|
+
}
|
|
1673
|
+
continue;
|
|
1674
|
+
}
|
|
1675
|
+
else
|
|
1676
|
+
{
|
|
1677
|
+
continue;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
while (readPoint >= parsePoint + 4 &&
|
|
1681
|
+
fd == me->fd &&
|
|
1682
|
+
me->connectionVersion == connectionVersion)
|
|
1683
|
+
{
|
|
1684
|
+
msglenN = *(unsigned int*)parsePoint;
|
|
1685
|
+
msglen = ntohl(msglenN);
|
|
1686
|
+
if (msglen > MAX_MESSAGE_SIZE)
|
|
1687
|
+
{
|
|
1688
|
+
amps_tcps_handle_stream_corruption(me, connectionVersion);
|
|
1689
|
+
goto cleanup;
|
|
1690
|
+
}
|
|
1691
|
+
if (readPoint >= (parsePoint + msglen + 4))
|
|
1692
|
+
{
|
|
1693
|
+
/* there are enough bytes to parse this guy. */
|
|
1694
|
+
parsePoint += 4;
|
|
1695
|
+
if (amps_message_pre_deserialize(message, me->serializer,
|
|
1696
|
+
(amps_char*)parsePoint, msglen) == AMPS_E_OK)
|
|
1697
|
+
{
|
|
1698
|
+
currentPosition = 0;
|
|
1699
|
+
while (currentPosition < msglen &&
|
|
1700
|
+
fd == me->fd &&
|
|
1701
|
+
me->connectionVersion == connectionVersion)
|
|
1702
|
+
{
|
|
1703
|
+
if (amps_message_deserialize(message, me->serializer,
|
|
1704
|
+
currentPosition,
|
|
1705
|
+
&bytesRead) != AMPS_E_OK)
|
|
1706
|
+
{
|
|
1707
|
+
amps_tcps_handle_stream_corruption(me, connectionVersion);
|
|
1708
|
+
goto cleanup;
|
|
1709
|
+
}
|
|
1710
|
+
if (me->messageHandler)
|
|
1711
|
+
{
|
|
1712
|
+
#ifndef _WIN32
|
|
1713
|
+
cancelState = 0;
|
|
1714
|
+
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState);
|
|
1715
|
+
#endif
|
|
1716
|
+
me->messageHandler(message,
|
|
1717
|
+
me->messageHandlerUserData);
|
|
1718
|
+
#ifndef _WIN32
|
|
1719
|
+
pthread_setcancelstate(cancelState, &unusedCancelState);
|
|
1720
|
+
#endif
|
|
1721
|
+
}
|
|
1722
|
+
currentPosition += bytesRead;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
else
|
|
1726
|
+
{
|
|
1727
|
+
amps_tcps_handle_stream_corruption(me, connectionVersion);
|
|
1728
|
+
goto cleanup;
|
|
1729
|
+
}
|
|
1730
|
+
parsePoint += msglen;
|
|
1731
|
+
}
|
|
1732
|
+
else if (end < buffer + msglen + 4)
|
|
1733
|
+
{
|
|
1734
|
+
/* this message is larger than the buffer
|
|
1735
|
+
* resize to 2* larger of this message or current buffer size */
|
|
1736
|
+
size_t newLength = end < buffer + (msglen * 2) ?
|
|
1737
|
+
msglen * 2 : (size_t)(end - buffer);
|
|
1738
|
+
newBuffer = (unsigned char*)malloc( newLength );
|
|
1739
|
+
if (newBuffer == NULL)
|
|
1740
|
+
{
|
|
1741
|
+
assert(readPoint >= parsePoint);
|
|
1742
|
+
/* stream broken */
|
|
1743
|
+
amps_tcps_handle_disconnect(me, connectionVersion);
|
|
1744
|
+
goto cleanup;
|
|
1745
|
+
}
|
|
1746
|
+
memcpy(newBuffer, parsePoint, (size_t)(readPoint - parsePoint));
|
|
1747
|
+
readPoint = newBuffer + (readPoint - parsePoint);
|
|
1748
|
+
parsePoint = newBuffer;
|
|
1749
|
+
#ifndef _WIN32
|
|
1750
|
+
cancelState = 0;
|
|
1751
|
+
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState);
|
|
1752
|
+
#endif
|
|
1753
|
+
free(buffer);
|
|
1754
|
+
buffer = newBuffer;
|
|
1755
|
+
#ifndef _WIN32
|
|
1756
|
+
pthread_setcancelstate(cancelState, &unusedCancelState);
|
|
1757
|
+
#endif
|
|
1758
|
+
end = newBuffer + newLength;
|
|
1759
|
+
assert(readPoint >= parsePoint);
|
|
1760
|
+
break;
|
|
1761
|
+
}
|
|
1762
|
+
else
|
|
1763
|
+
{
|
|
1764
|
+
/* Need to read more data to finish this message
|
|
1765
|
+
* Move what we have to the front of the buffer. */
|
|
1766
|
+
break;
|
|
1767
|
+
}
|
|
1768
|
+
} /*while(readPoint >= parsePoint + 4) */
|
|
1769
|
+
if (readPoint > parsePoint)
|
|
1770
|
+
{
|
|
1771
|
+
memmove(buffer, parsePoint, (size_t)(readPoint - parsePoint));
|
|
1772
|
+
}
|
|
1773
|
+
readPoint = buffer + (readPoint - parsePoint);
|
|
1774
|
+
parsePoint = buffer;
|
|
1775
|
+
} /* while(fd == me->fd) */
|
|
1776
|
+
cleanup:
|
|
1777
|
+
#ifndef _WIN32
|
|
1778
|
+
cancelState = 0;
|
|
1779
|
+
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancelState);
|
|
1780
|
+
pthread_cleanup_pop(0);
|
|
1781
|
+
pthread_cleanup_pop(0);
|
|
1782
|
+
#endif
|
|
1783
|
+
amps_message_destroy(message);
|
|
1784
|
+
free(buffer);
|
|
1785
|
+
if (me->destroying)
|
|
1786
|
+
{
|
|
1787
|
+
return 0;
|
|
1788
|
+
}
|
|
1789
|
+
#ifndef _WIN32
|
|
1790
|
+
pthread_t tid = pthread_self();
|
|
1791
|
+
#if __STDC_VERSION__ >= 201100
|
|
1792
|
+
if (atomic_compare_exchange_strong(&(me->thread), &tid, (pthread_t)0))
|
|
1793
|
+
{
|
|
1794
|
+
pthread_detach(tid);
|
|
1795
|
+
}
|
|
1796
|
+
#else
|
|
1797
|
+
if (__sync_bool_compare_and_swap(&(me->thread), tid, 0))
|
|
1798
|
+
{
|
|
1799
|
+
pthread_detach(tid);
|
|
1800
|
+
}
|
|
1801
|
+
#endif
|
|
1802
|
+
#endif
|
|
1803
|
+
|
|
1804
|
+
return 0;
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
amps_result
|
|
1808
|
+
amps_tcps_attempt_reconnect(amps_handle transport, unsigned version)
|
|
1809
|
+
{
|
|
1810
|
+
amps_result res;
|
|
1811
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1812
|
+
if (version == 0)
|
|
1813
|
+
{
|
|
1814
|
+
version = me->connectionVersion;
|
|
1815
|
+
}
|
|
1816
|
+
res = amps_tcps_handle_disconnect(me, version);
|
|
1817
|
+
return res;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
/* public-api -- get a socket */
|
|
1821
|
+
AMPS_SOCKET
|
|
1822
|
+
amps_tcps_get_socket(amps_handle transport)
|
|
1823
|
+
{
|
|
1824
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1825
|
+
return me->fd;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
void* amps_tcps_get_SSL(amps_handle transport)
|
|
1829
|
+
{
|
|
1830
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1831
|
+
return me->ssl;
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
amps_result
|
|
1835
|
+
amps_tcps_update_read_timeout(amps_tcps_t* me)
|
|
1836
|
+
{
|
|
1837
|
+
int timeout = (int)((me->readTimeoutMillis && me->idleTimeMillis) ?
|
|
1838
|
+
AMPS_MIN(me->readTimeoutMillis, me->idleTimeMillis) :
|
|
1839
|
+
AMPS_MAX(me->readTimeoutMillis, me->idleTimeMillis));
|
|
1840
|
+
int rc = 0;
|
|
1841
|
+
#ifdef _WIN32
|
|
1842
|
+
DWORD timeoutMillis = timeout;
|
|
1843
|
+
rc = setsockopt(me->fd, SOL_SOCKET, SO_RCVTIMEO,
|
|
1844
|
+
(const char*)&timeoutMillis, sizeof(DWORD));
|
|
1845
|
+
int sysError = GetLastError();
|
|
1846
|
+
#else
|
|
1847
|
+
struct timeval tv;
|
|
1848
|
+
tv.tv_sec = timeout / 1000;
|
|
1849
|
+
tv.tv_usec = (timeout % 1000) * 1000;
|
|
1850
|
+
rc = setsockopt(me->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
|
|
1851
|
+
int sysError = errno;
|
|
1852
|
+
#endif
|
|
1853
|
+
if (rc == -1)
|
|
1854
|
+
{
|
|
1855
|
+
amps_tcps_set_socket_error(me, sysError);
|
|
1856
|
+
return AMPS_E_USAGE;
|
|
1857
|
+
}
|
|
1858
|
+
return AMPS_E_OK;
|
|
1859
|
+
}
|
|
1860
|
+
amps_result
|
|
1861
|
+
amps_tcps_set_read_timeout(amps_handle transport, int readTimeout)
|
|
1862
|
+
{
|
|
1863
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1864
|
+
me->readTimeoutMillis = (amps_uint64_t)readTimeout * 1000;
|
|
1865
|
+
return amps_tcps_update_read_timeout(me);
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
|
|
1869
|
+
void
|
|
1870
|
+
amps_tcps_set_filter_function(amps_handle transport, amps_transport_filter_function filterFunction_, void* userdata_)
|
|
1871
|
+
{
|
|
1872
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1873
|
+
me->filterUserData = userdata_;
|
|
1874
|
+
me->filterFunction = filterFunction_ ? filterFunction_ : amps_tcps_noop_filter_function;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
void
|
|
1878
|
+
amps_tcps_set_thread_created_callback(amps_handle transport_, amps_thread_created_callback threadCreatedCallback_, void* userdata_)
|
|
1879
|
+
{
|
|
1880
|
+
amps_tcps_t* me = (amps_tcps_t*)transport_;
|
|
1881
|
+
me->threadCreatedCallbackUserData = userdata_;
|
|
1882
|
+
me->threadCreatedCallback = threadCreatedCallback_;
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
amps_result
|
|
1886
|
+
amps_tcps_set_idle_time(amps_handle transport, int millis)
|
|
1887
|
+
{
|
|
1888
|
+
amps_tcps_t* me = (amps_tcps_t*)transport;
|
|
1889
|
+
if (!me->idleTimeMillis || (amps_uint64_t)millis < me->idleTimeMillis)
|
|
1890
|
+
{
|
|
1891
|
+
me->idleTimeMillis = (amps_uint64_t)millis;
|
|
1892
|
+
}
|
|
1893
|
+
return amps_tcps_update_read_timeout(me);
|
|
1894
|
+
}
|