
github.com/Azure/go-ntlmssp/LICENSE:

	The MIT License (MIT)
	
	Copyright (c) 2016 Microsoft
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.

github.com/ChrisTrenkamp/goxpath/LICENSE:

	The MIT License (MIT)
	
	Copyright (c) 2015 ChrisTrenkamp
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.
	

github.com/bodgit/ntlmssp/LICENSE:

	BSD 3-Clause License
	
	Copyright (c) 2019, Matt Dainty
	All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:
	
	* Redistributions of source code must retain the above copyright notice, this
	list of conditions and the following disclaimer.
	
	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.
	
	* Neither the name of the copyright holder nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
	FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
	OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	

github.com/bodgit/windows/LICENSE:

	BSD 3-Clause License
	
	Copyright (c) 2020, Matt Dainty
	All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are met:
	
	* Redistributions of source code must retain the above copyright notice, this
	list of conditions and the following disclaimer.
	
	* Redistributions in binary form must reproduce the above copyright notice,
	this list of conditions and the following disclaimer in the documentation
	and/or other materials provided with the distribution.
	
	* Neither the name of the copyright holder nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
	FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
	OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	

github.com/buger/goterm/LICENSE:

	MIT License
	
	Copyright (c) 2016 Leonid Bugaev
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.

github.com/davecgh/go-spew/spew/LICENSE:

	ISC License
	
	Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
	
	Permission to use, copy, modify, and/or distribute this software for any
	purpose with or without fee is hereby granted, provided that the above
	copyright notice and this permission notice appear in all copies.
	
	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
	WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
	MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
	ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
	ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

github.com/diskfs/go-diskfs/LICENSE:

	MIT License
	
	Copyright (c) 2017 Avi Deitcher
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.

github.com/fatih/color/LICENSE.md:

	The MIT License (MIT)
	
	Copyright (c) 2013 Fatih Arslan
	
	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
	the Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

github.com/go-logr/logr/LICENSE:

	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "{}"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright {yyyy} {name of copyright owner}
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/gofrs/uuid/LICENSE:

	Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
	
	Permission is hereby granted, free of charge, to any person obtaining
	a copy of this software and associated documentation files (the
	"Software"), to deal in the Software without restriction, including
	without limitation the rights to use, copy, modify, merge, publish,
	distribute, sublicense, and/or sell copies of the Software, and to
	permit persons to whom the Software is furnished to do so, subject to
	the following conditions:
	
	The above copyright notice and this permission notice shall be
	included in all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
	NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
	LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
	OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

github.com/golang/protobuf/ptypes/empty/LICENSE:

	Copyright 2010 The Go Authors.  All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google Inc. nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	

github.com/gorilla/websocket/LICENSE:

	Copyright (c) 2023 The Gorilla Authors. All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google Inc. nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

github.com/hashicorp/go-cleanhttp/LICENSE:

	Mozilla Public License, version 2.0
	
	1. Definitions
	
	1.1. "Contributor"
	
	means each individual or legal entity that creates, contributes to the
	creation of, or owns Covered Software.
	
	1.2. "Contributor Version"
	
	means the combination of the Contributions of others (if any) used by a
	Contributor and that particular Contributor's Contribution.
	
	1.3. "Contribution"
	
	means Covered Software of a particular Contributor.
	
	1.4. "Covered Software"
	
	means Source Code Form to which the initial Contributor has attached the
	notice in Exhibit A, the Executable Form of such Source Code Form, and
	Modifications of such Source Code Form, in each case including portions
	thereof.
	
	1.5. "Incompatible With Secondary Licenses"
	means
	
	a. that the initial Contributor has attached the notice described in
	Exhibit B to the Covered Software; or
	
	b. that the Covered Software was made available under the terms of
	version 1.1 or earlier of the License, but not also under the terms of
	a Secondary License.
	
	1.6. "Executable Form"
	
	means any form of the work other than Source Code Form.
	
	1.7. "Larger Work"
	
	means a work that combines Covered Software with other material, in a
	separate file or files, that is not Covered Software.
	
	1.8. "License"
	
	means this document.
	
	1.9. "Licensable"
	
	means having the right to grant, to the maximum extent possible, whether
	at the time of the initial grant or subsequently, any and all of the
	rights conveyed by this License.
	
	1.10. "Modifications"
	
	means any of the following:
	
	a. any file in Source Code Form that results from an addition to,
	deletion from, or modification of the contents of Covered Software; or
	
	b. any new file in Source Code Form that contains any Covered Software.
	
	1.11. "Patent Claims" of a Contributor
	
	means any patent claim(s), including without limitation, method,
	process, and apparatus claims, in any patent Licensable by such
	Contributor that would be infringed, but for the grant of the License,
	by the making, using, selling, offering for sale, having made, import,
	or transfer of either its Contributions or its Contributor Version.
	
	1.12. "Secondary License"
	
	means either the GNU General Public License, Version 2.0, the GNU Lesser
	General Public License, Version 2.1, the GNU Affero General Public
	License, Version 3.0, or any later versions of those licenses.
	
	1.13. "Source Code Form"
	
	means the form of the work preferred for making modifications.
	
	1.14. "You" (or "Your")
	
	means an individual or a legal entity exercising rights under this
	License. For legal entities, "You" includes any entity that controls, is
	controlled by, or is under common control with You. For purposes of this
	definition, "control" means (a) the power, direct or indirect, to cause
	the direction or management of such entity, whether by contract or
	otherwise, or (b) ownership of more than fifty percent (50%) of the
	outstanding shares or beneficial ownership of such entity.
	
	
	2. License Grants and Conditions
	
	2.1. Grants
	
	Each Contributor hereby grants You a world-wide, royalty-free,
	non-exclusive license:
	
	a. under intellectual property rights (other than patent or trademark)
	Licensable by such Contributor to use, reproduce, make available,
	modify, display, perform, distribute, and otherwise exploit its
	Contributions, either on an unmodified basis, with Modifications, or
	as part of a Larger Work; and
	
	b. under Patent Claims of such Contributor to make, use, sell, offer for
	sale, have made, import, and otherwise transfer either its
	Contributions or its Contributor Version.
	
	2.2. Effective Date
	
	The licenses granted in Section 2.1 with respect to any Contribution
	become effective for each Contribution on the date the Contributor first
	distributes such Contribution.
	
	2.3. Limitations on Grant Scope
	
	The licenses granted in this Section 2 are the only rights granted under
	this License. No additional rights or licenses will be implied from the
	distribution or licensing of Covered Software under this License.
	Notwithstanding Section 2.1(b) above, no patent license is granted by a
	Contributor:
	
	a. for any code that a Contributor has removed from Covered Software; or
	
	b. for infringements caused by: (i) Your and any other third party's
	modifications of Covered Software, or (ii) the combination of its
	Contributions with other software (except as part of its Contributor
	Version); or
	
	c. under Patent Claims infringed by Covered Software in the absence of
	its Contributions.
	
	This License does not grant any rights in the trademarks, service marks,
	or logos of any Contributor (except as may be necessary to comply with
	the notice requirements in Section 3.4).
	
	2.4. Subsequent Licenses
	
	No Contributor makes additional grants as a result of Your choice to
	distribute the Covered Software under a subsequent version of this
	License (see Section 10.2) or under the terms of a Secondary License (if
	permitted under the terms of Section 3.3).
	
	2.5. Representation
	
	Each Contributor represents that the Contributor believes its
	Contributions are its original creation(s) or it has sufficient rights to
	grant the rights to its Contributions conveyed by this License.
	
	2.6. Fair Use
	
	This License is not intended to limit any rights You have under
	applicable copyright doctrines of fair use, fair dealing, or other
	equivalents.
	
	2.7. Conditions
	
	Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
	Section 2.1.
	
	
	3. Responsibilities
	
	3.1. Distribution of Source Form
	
	All distribution of Covered Software in Source Code Form, including any
	Modifications that You create or to which You contribute, must be under
	the terms of this License. You must inform recipients that the Source
	Code Form of the Covered Software is governed by the terms of this
	License, and how they can obtain a copy of this License. You may not
	attempt to alter or restrict the recipients' rights in the Source Code
	Form.
	
	3.2. Distribution of Executable Form
	
	If You distribute Covered Software in Executable Form then:
	
	a. such Covered Software must also be made available in Source Code Form,
	as described in Section 3.1, and You must inform recipients of the
	Executable Form how they can obtain a copy of such Source Code Form by
	reasonable means in a timely manner, at a charge no more than the cost
	of distribution to the recipient; and
	
	b. You may distribute such Executable Form under the terms of this
	License, or sublicense it under different terms, provided that the
	license for the Executable Form does not attempt to limit or alter the
	recipients' rights in the Source Code Form under this License.
	
	3.3. Distribution of a Larger Work
	
	You may create and distribute a Larger Work under terms of Your choice,
	provided that You also comply with the requirements of this License for
	the Covered Software. If the Larger Work is a combination of Covered
	Software with a work governed by one or more Secondary Licenses, and the
	Covered Software is not Incompatible With Secondary Licenses, this
	License permits You to additionally distribute such Covered Software
	under the terms of such Secondary License(s), so that the recipient of
	the Larger Work may, at their option, further distribute the Covered
	Software under the terms of either this License or such Secondary
	License(s).
	
	3.4. Notices
	
	You may not remove or alter the substance of any license notices
	(including copyright notices, patent notices, disclaimers of warranty, or
	limitations of liability) contained within the Source Code Form of the
	Covered Software, except that You may alter any license notices to the
	extent required to remedy known factual inaccuracies.
	
	3.5. Application of Additional Terms
	
	You may choose to offer, and to charge a fee for, warranty, support,
	indemnity or liability obligations to one or more recipients of Covered
	Software. However, You may do so only on Your own behalf, and not on
	behalf of any Contributor. You must make it absolutely clear that any
	such warranty, support, indemnity, or liability obligation is offered by
	You alone, and You hereby agree to indemnify every Contributor for any
	liability incurred by such Contributor as a result of warranty, support,
	indemnity or liability terms You offer. You may include additional
	disclaimers of warranty and limitations of liability specific to any
	jurisdiction.
	
	4. Inability to Comply Due to Statute or Regulation
	
	If it is impossible for You to comply with any of the terms of this License
	with respect to some or all of the Covered Software due to statute,
	judicial order, or regulation then You must: (a) comply with the terms of
	this License to the maximum extent possible; and (b) describe the
	limitations and the code they affect. Such description must be placed in a
	text file included with all distributions of the Covered Software under
	this License. Except to the extent prohibited by statute or regulation,
	such description must be sufficiently detailed for a recipient of ordinary
	skill to be able to understand it.
	
	5. Termination
	
	5.1. The rights granted under this License will terminate automatically if You
	fail to comply with any of its terms. However, if You become compliant,
	then the rights granted under this License from a particular Contributor
	are reinstated (a) provisionally, unless and until such Contributor
	explicitly and finally terminates Your grants, and (b) on an ongoing
	basis, if such Contributor fails to notify You of the non-compliance by
	some reasonable means prior to 60 days after You have come back into
	compliance. Moreover, Your grants from a particular Contributor are
	reinstated on an ongoing basis if such Contributor notifies You of the
	non-compliance by some reasonable means, this is the first time You have
	received notice of non-compliance with this License from such
	Contributor, and You become compliant prior to 30 days after Your receipt
	of the notice.
	
	5.2. If You initiate litigation against any entity by asserting a patent
	infringement claim (excluding declaratory judgment actions,
	counter-claims, and cross-claims) alleging that a Contributor Version
	directly or indirectly infringes any patent, then the rights granted to
	You by any and all Contributors for the Covered Software under Section
	2.1 of this License shall terminate.
	
	5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
	license agreements (excluding distributors and resellers) which have been
	validly granted by You or Your distributors under this License prior to
	termination shall survive termination.
	
	6. Disclaimer of Warranty
	
	Covered Software is provided under this License on an "as is" basis,
	without warranty of any kind, either expressed, implied, or statutory,
	including, without limitation, warranties that the Covered Software is free
	of defects, merchantable, fit for a particular purpose or non-infringing.
	The entire risk as to the quality and performance of the Covered Software
	is with You. Should any Covered Software prove defective in any respect,
	You (not any Contributor) assume the cost of any necessary servicing,
	repair, or correction. This disclaimer of warranty constitutes an essential
	part of this License. No use of  any Covered Software is authorized under
	this License except under this disclaimer.
	
	7. Limitation of Liability
	
	Under no circumstances and under no legal theory, whether tort (including
	negligence), contract, or otherwise, shall any Contributor, or anyone who
	distributes Covered Software as permitted above, be liable to You for any
	direct, indirect, special, incidental, or consequential damages of any
	character including, without limitation, damages for lost profits, loss of
	goodwill, work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses, even if such party shall have been
	informed of the possibility of such damages. This limitation of liability
	shall not apply to liability for death or personal injury resulting from
	such party's negligence to the extent applicable law prohibits such
	limitation. Some jurisdictions do not allow the exclusion or limitation of
	incidental or consequential damages, so this exclusion and limitation may
	not apply to You.
	
	8. Litigation
	
	Any litigation relating to this License may be brought only in the courts
	of a jurisdiction where the defendant maintains its principal place of
	business and such litigation shall be governed by laws of that
	jurisdiction, without reference to its conflict-of-law provisions. Nothing
	in this Section shall prevent a party's ability to bring cross-claims or
	counter-claims.
	
	9. Miscellaneous
	
	This License represents the complete agreement concerning the subject
	matter hereof. If any provision of this License is held to be
	unenforceable, such provision shall be reformed only to the extent
	necessary to make it enforceable. Any law or regulation which provides that
	the language of a contract shall be construed against the drafter shall not
	be used to construe this License against a Contributor.
	
	
	10. Versions of the License
	
	10.1. New Versions
	
	Mozilla Foundation is the license steward. Except as provided in Section
	10.3, no one other than the license steward has the right to modify or
	publish new versions of this License. Each version will be given a
	distinguishing version number.
	
	10.2. Effect of New Versions
	
	You may distribute the Covered Software under the terms of the version
	of the License under which You originally received the Covered Software,
	or under the terms of any subsequent version published by the license
	steward.
	
	10.3. Modified Versions
	
	If you create software not governed by this License, and you want to
	create a new license for such software, you may create and use a
	modified version of this License if you rename the license and remove
	any references to the name of the license steward (except to note that
	such modified license differs from this License).
	
	10.4. Distributing Source Code Form that is Incompatible With Secondary
	Licenses If You choose to distribute Source Code Form that is
	Incompatible With Secondary Licenses under the terms of this version of
	the License, the notice described in Exhibit B of this License must be
	attached.
	
	Exhibit A - Source Code Form License Notice
	
	This Source Code Form is subject to the
	terms of the Mozilla Public License, v.
	2.0. If a copy of the MPL was not
	distributed with this file, You can
	obtain one at
	http://mozilla.org/MPL/2.0/.
	
	If it is not possible or desirable to put the notice in a particular file,
	then You may include the notice in a location (such as a LICENSE file in a
	relevant directory) where a recipient would be likely to look for such a
	notice.
	
	You may add additional accurate notices of copyright ownership.
	
	Exhibit B - "Incompatible With Secondary Licenses" Notice
	
	This Source Code Form is "Incompatible
	With Secondary Licenses", as defined by
	the Mozilla Public License, v. 2.0.
	

github.com/hashicorp/go-cleanhttp/README.md:

	# cleanhttp
	
	Functions for accessing "clean" Go http.Client values
	
	-------------
	
	The Go standard library contains a default `http.Client` called
	`http.DefaultClient`. It is a common idiom in Go code to start with
	`http.DefaultClient` and tweak it as necessary, and in fact, this is
	encouraged; from the `http` package documentation:
	
	> The Client's Transport typically has internal state (cached TCP connections),
	so Clients should be reused instead of created as needed. Clients are safe for
	concurrent use by multiple goroutines.
	
	Unfortunately, this is a shared value, and it is not uncommon for libraries to
	assume that they are free to modify it at will. With enough dependencies, it
	can be very easy to encounter strange problems and race conditions due to
	manipulation of this shared value across libraries and goroutines (clients are
	safe for concurrent use, but writing values to the client struct itself is not
	protected).
	
	Making things worse is the fact that a bare `http.Client` will use a default
	`http.Transport` called `http.DefaultTransport`, which is another global value
	that behaves the same way. So it is not simply enough to replace
	`http.DefaultClient` with `&http.Client{}`.
	
	This repository provides some simple functions to get a "clean" `http.Client`
	-- one that uses the same default values as the Go standard library, but
	returns a client that does not share any state with other clients.

github.com/hashicorp/go-cleanhttp/cleanhttp.go:

	package cleanhttp
	
	import (
	"net"
	"net/http"
	"runtime"
	"time"
	)
	
	// DefaultTransport returns a new http.Transport with similar default values to
	// http.DefaultTransport, but with idle connections and keepalives disabled.
	func DefaultTransport() *http.Transport {
	transport := DefaultPooledTransport()
	transport.DisableKeepAlives = true
	transport.MaxIdleConnsPerHost = -1
	return transport
	}
	
	// DefaultPooledTransport returns a new http.Transport with similar default
	// values to http.DefaultTransport. Do not use this for transient transports as
	// it can leak file descriptors over time. Only use this for transports that
	// will be re-used for the same host(s).
	func DefaultPooledTransport() *http.Transport {
	transport := &http.Transport{
	Proxy: http.ProxyFromEnvironment,
	DialContext: (&net.Dialer{
	Timeout:   30 * time.Second,
	KeepAlive: 30 * time.Second,
	DualStack: true,
	}).DialContext,
	MaxIdleConns:          100,
	IdleConnTimeout:       90 * time.Second,
	TLSHandshakeTimeout:   10 * time.Second,
	ExpectContinueTimeout: 1 * time.Second,
	ForceAttemptHTTP2:     true,
	MaxIdleConnsPerHost:   runtime.GOMAXPROCS(0) + 1,
	}
	return transport
	}
	
	// DefaultClient returns a new http.Client with similar default values to
	// http.Client, but with a non-shared Transport, idle connections disabled, and
	// keepalives disabled.
	func DefaultClient() *http.Client {
	return &http.Client{
	Transport: DefaultTransport(),
	}
	}
	
	// DefaultPooledClient returns a new http.Client with similar default values to
	// http.Client, but with a shared Transport. Do not use this function for
	// transient clients as it can leak file descriptors over time. Only use this
	// for clients that will be re-used for the same host(s).
	func DefaultPooledClient() *http.Client {
	return &http.Client{
	Transport: DefaultPooledTransport(),
	}
	}

github.com/hashicorp/go-cleanhttp/doc.go:

	// Package cleanhttp offers convenience utilities for acquiring "clean"
	// http.Transport and http.Client structs.
	//
	// Values set on http.DefaultClient and http.DefaultTransport affect all
	// callers. This can have detrimental effects, esepcially in TLS contexts,
	// where client or root certificates set to talk to multiple endpoints can end
	// up displacing each other, leading to hard-to-debug issues. This package
	// provides non-shared http.Client and http.Transport structs to ensure that
	// the configuration will not be overwritten by other parts of the application
	// or dependencies.
	//
	// The DefaultClient and DefaultTransport functions disable idle connections
	// and keepalives. Without ensuring that idle connections are closed before
	// garbage collection, short-term clients/transports can leak file descriptors,
	// eventually leading to "too many open files" errors. If you will be
	// connecting to the same hosts repeatedly from the same client, you can use
	// DefaultPooledClient to receive a client that has connection pooling
	// semantics similar to http.DefaultClient.
	//
	package cleanhttp

github.com/hashicorp/go-cleanhttp/handlers.go:

	package cleanhttp
	
	import (
	"net/http"
	"strings"
	"unicode"
	)
	
	// HandlerInput provides input options to cleanhttp's handlers
	type HandlerInput struct {
	ErrStatus int
	}
	
	// PrintablePathCheckHandler is a middleware that ensures the request path
	// contains only printable runes.
	func PrintablePathCheckHandler(next http.Handler, input *HandlerInput) http.Handler {
	// Nil-check on input to make it optional
	if input == nil {
	input = &HandlerInput{
	ErrStatus: http.StatusBadRequest,
	}
	}
	
	// Default to http.StatusBadRequest on error
	if input.ErrStatus == 0 {
	input.ErrStatus = http.StatusBadRequest
	}
	
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	if r != nil {
	// Check URL path for non-printable characters
	idx := strings.IndexFunc(r.URL.Path, func(c rune) bool {
	return !unicode.IsPrint(c)
	})
	
	if idx != -1 {
	w.WriteHeader(input.ErrStatus)
	return
	}
	
	if next != nil {
	next.ServeHTTP(w, r)
	}
	}
	
	return
	})
	}

github.com/hashicorp/go-hclog/LICENSE:

	Copyright (c) 2017 HashiCorp, Inc.
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.

github.com/hashicorp/go-plugin/.gitignore:

	.DS_Store
	.idea

github.com/hashicorp/go-plugin/CHANGELOG.md:

	## v1.6.1
	
	BUGS:
	
	* Suppress spurious `os.ErrClosed` on plugin shutdown [[GH-299](https://github.com/hashicorp/go-plugin/pull/299)]
	
	ENHANCEMENTS:
	
	* deps: bump google.golang.org/grpc to v1.58.3 [[GH-296](https://github.com/hashicorp/go-plugin/pull/296)]
	
	## v1.6.0
	
	CHANGES:
	
	* plugin: Plugins written in other languages can optionally start to advertise whether they support gRPC broker multiplexing.
	If the environment variable `PLUGIN_MULTIPLEX_GRPC` is set, it is safe to include a seventh field containing a boolean
	value in the `|`-separated protocol negotiation line.
	
	ENHANCEMENTS:
	
	* Support muxing gRPC broker connections over a single listener [[GH-288](https://github.com/hashicorp/go-plugin/pull/288)]
	* client: Configurable buffer size for reading plugin log lines [[GH-265](https://github.com/hashicorp/go-plugin/pull/265)]
	* Use `buf` for proto generation [[GH-286](https://github.com/hashicorp/go-plugin/pull/286)]
	* deps: bump golang.org/x/net to v0.17.0 [[GH-285](https://github.com/hashicorp/go-plugin/pull/285)]
	* deps: bump golang.org/x/sys to v0.13.0 [[GH-285](https://github.com/hashicorp/go-plugin/pull/285)]
	* deps: bump golang.org/x/text to v0.13.0 [[GH-285](https://github.com/hashicorp/go-plugin/pull/285)]
	
	## v1.5.2
	
	ENHANCEMENTS:
	
	client: New `UnixSocketConfig.TempDir` option allows setting the directory to use when creating plugin-specific Unix socket directories [[GH-282](https://github.com/hashicorp/go-plugin/pull/282)]
	
	## v1.5.1
	
	BUGS:
	
	* server: `PLUGIN_UNIX_SOCKET_DIR` is consistently used for gRPC broker sockets as well as the initial socket [[GH-277](https://github.com/hashicorp/go-plugin/pull/277)]
	
	ENHANCEMENTS:
	
	* client: New `UnixSocketConfig` option in `ClientConfig` to support making the client's Unix sockets group-writable [[GH-277](https://github.com/hashicorp/go-plugin/pull/277)]
	
	## v1.5.0
	
	ENHANCEMENTS:
	
	* client: New `runner.Runner` interface to support clients providing custom plugin command runner implementations [[GH-270](https://github.com/hashicorp/go-plugin/pull/270)]
	* Accessible via new `ClientConfig` field `RunnerFunc`, which is mutually exclusive with `Cmd` and `Reattach`
	* Reattaching support via `ReattachConfig` field `ReattachFunc`
	* client: New `ClientConfig` field `SkipHostEnv` allows omitting the client process' own environment variables from the plugin command's environment [[GH-270](https://github.com/hashicorp/go-plugin/pull/270)]
	* client: Add `ID()` method to `Client` for retrieving the pid or other unique ID of a running plugin [[GH-272](https://github.com/hashicorp/go-plugin/pull/272)]
	* server: Support setting the directory to create Unix sockets in with the env var `PLUGIN_UNIX_SOCKET_DIR` [[GH-270](https://github.com/hashicorp/go-plugin/pull/270)]
	* server: Support setting group write permission and a custom group name or gid owner with the env var `PLUGIN_UNIX_SOCKET_GROUP` [[GH-270](https://github.com/hashicorp/go-plugin/pull/270)]
	
	## v1.4.11-rc1
	
	ENHANCEMENTS:
	
	* deps: bump protoreflect to v1.15.1 [[GH-264](https://github.com/hashicorp/go-plugin/pull/264)]
	
	## v1.4.10
	
	BUG FIXES:
	
	* additional notes: ensure to close files [[GH-241](https://github.com/hashicorp/go-plugin/pull/241)]
	
	ENHANCEMENTS:
	
	* deps: Remove direct dependency on golang.org/x/net [[GH-240](https://github.com/hashicorp/go-plugin/pull/240)]
	
	## v1.4.9
	
	ENHANCEMENTS:
	
	* client: Remove log warning introduced in 1.4.5 when SecureConfig is nil. [[GH-238](https://github.com/hashicorp/go-plugin/pull/238)]
	
	## v1.4.8
	
	BUG FIXES:
	
	* Fix windows build: [[GH-227](https://github.com/hashicorp/go-plugin/pull/227)]
	
	## v1.4.7
	
	ENHANCEMENTS:
	
	* More detailed error message on plugin start failure: [[GH-223](https://github.com/hashicorp/go-plugin/pull/223)]
	
	## v1.4.6
	
	BUG FIXES:
	
	* server: Prevent gRPC broker goroutine leak when using `GRPCServer` type `GracefulStop()` or `Stop()` methods [[GH-220](https://github.com/hashicorp/go-plugin/pull/220)]
	
	## v1.4.5
	
	ENHANCEMENTS:
	
	* client: log warning when SecureConfig is nil [[GH-207](https://github.com/hashicorp/go-plugin/pull/207)]
	
	
	## v1.4.4
	
	ENHANCEMENTS:
	
	* client: increase level of plugin exit logs [[GH-195](https://github.com/hashicorp/go-plugin/pull/195)]
	
	BUG FIXES:
	
	* Bidirectional communication: fix bidirectional communication when AutoMTLS is enabled [[GH-193](https://github.com/hashicorp/go-plugin/pull/193)]
	* RPC: Trim a spurious log message for plugins using RPC [[GH-186](https://github.com/hashicorp/go-plugin/pull/186)]

github.com/hashicorp/go-plugin/LICENSE:

	Copyright (c) 2016 HashiCorp, Inc.
	
	Mozilla Public License, version 2.0
	
	1. Definitions
	
	1.1. “Contributor”
	
	means each individual or legal entity that creates, contributes to the
	creation of, or owns Covered Software.
	
	1.2. “Contributor Version”
	
	means the combination of the Contributions of others (if any) used by a
	Contributor and that particular Contributor’s Contribution.
	
	1.3. “Contribution”
	
	means Covered Software of a particular Contributor.
	
	1.4. “Covered Software”
	
	means Source Code Form to which the initial Contributor has attached the
	notice in Exhibit A, the Executable Form of such Source Code Form, and
	Modifications of such Source Code Form, in each case including portions
	thereof.
	
	1.5. “Incompatible With Secondary Licenses”
	means
	
	a. that the initial Contributor has attached the notice described in
	Exhibit B to the Covered Software; or
	
	b. that the Covered Software was made available under the terms of version
	1.1 or earlier of the License, but not also under the terms of a
	Secondary License.
	
	1.6. “Executable Form”
	
	means any form of the work other than Source Code Form.
	
	1.7. “Larger Work”
	
	means a work that combines Covered Software with other material, in a separate
	file or files, that is not Covered Software.
	
	1.8. “License”
	
	means this document.
	
	1.9. “Licensable”
	
	means having the right to grant, to the maximum extent possible, whether at the
	time of the initial grant or subsequently, any and all of the rights conveyed by
	this License.
	
	1.10. “Modifications”
	
	means any of the following:
	
	a. any file in Source Code Form that results from an addition to, deletion
	from, or modification of the contents of Covered Software; or
	
	b. any new file in Source Code Form that contains any Covered Software.
	
	1.11. “Patent Claims” of a Contributor
	
	means any patent claim(s), including without limitation, method, process,
	and apparatus claims, in any patent Licensable by such Contributor that
	would be infringed, but for the grant of the License, by the making,
	using, selling, offering for sale, having made, import, or transfer of
	either its Contributions or its Contributor Version.
	
	1.12. “Secondary License”
	
	means either the GNU General Public License, Version 2.0, the GNU Lesser
	General Public License, Version 2.1, the GNU Affero General Public
	License, Version 3.0, or any later versions of those licenses.
	
	1.13. “Source Code Form”
	
	means the form of the work preferred for making modifications.
	
	1.14. “You” (or “Your”)
	
	means an individual or a legal entity exercising rights under this
	License. For legal entities, “You” includes any entity that controls, is
	controlled by, or is under common control with You. For purposes of this
	definition, “control” means (a) the power, direct or indirect, to cause
	the direction or management of such entity, whether by contract or
	otherwise, or (b) ownership of more than fifty percent (50%) of the
	outstanding shares or beneficial ownership of such entity.
	
	
	2. License Grants and Conditions
	
	2.1. Grants
	
	Each Contributor hereby grants You a world-wide, royalty-free,
	non-exclusive license:
	
	a. under intellectual property rights (other than patent or trademark)
	Licensable by such Contributor to use, reproduce, make available,
	modify, display, perform, distribute, and otherwise exploit its
	Contributions, either on an unmodified basis, with Modifications, or as
	part of a Larger Work; and
	
	b. under Patent Claims of such Contributor to make, use, sell, offer for
	sale, have made, import, and otherwise transfer either its Contributions
	or its Contributor Version.
	
	2.2. Effective Date
	
	The licenses granted in Section 2.1 with respect to any Contribution become
	effective for each Contribution on the date the Contributor first distributes
	such Contribution.
	
	2.3. Limitations on Grant Scope
	
	The licenses granted in this Section 2 are the only rights granted under this
	License. No additional rights or licenses will be implied from the distribution
	or licensing of Covered Software under this License. Notwithstanding Section
	2.1(b) above, no patent license is granted by a Contributor:
	
	a. for any code that a Contributor has removed from Covered Software; or
	
	b. for infringements caused by: (i) Your and any other third party’s
	modifications of Covered Software, or (ii) the combination of its
	Contributions with other software (except as part of its Contributor
	Version); or
	
	c. under Patent Claims infringed by Covered Software in the absence of its
	Contributions.
	
	This License does not grant any rights in the trademarks, service marks, or
	logos of any Contributor (except as may be necessary to comply with the
	notice requirements in Section 3.4).
	
	2.4. Subsequent Licenses
	
	No Contributor makes additional grants as a result of Your choice to
	distribute the Covered Software under a subsequent version of this License
	(see Section 10.2) or under the terms of a Secondary License (if permitted
	under the terms of Section 3.3).
	
	2.5. Representation
	
	Each Contributor represents that the Contributor believes its Contributions
	are its original creation(s) or it has sufficient rights to grant the
	rights to its Contributions conveyed by this License.
	
	2.6. Fair Use
	
	This License is not intended to limit any rights You have under applicable
	copyright doctrines of fair use, fair dealing, or other equivalents.
	
	2.7. Conditions
	
	Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
	Section 2.1.
	
	
	3. Responsibilities
	
	3.1. Distribution of Source Form
	
	All distribution of Covered Software in Source Code Form, including any
	Modifications that You create or to which You contribute, must be under the
	terms of this License. You must inform recipients that the Source Code Form
	of the Covered Software is governed by the terms of this License, and how
	they can obtain a copy of this License. You may not attempt to alter or
	restrict the recipients’ rights in the Source Code Form.
	
	3.2. Distribution of Executable Form
	
	If You distribute Covered Software in Executable Form then:
	
	a. such Covered Software must also be made available in Source Code Form,
	as described in Section 3.1, and You must inform recipients of the
	Executable Form how they can obtain a copy of such Source Code Form by
	reasonable means in a timely manner, at a charge no more than the cost
	of distribution to the recipient; and
	
	b. You may distribute such Executable Form under the terms of this License,
	or sublicense it under different terms, provided that the license for
	the Executable Form does not attempt to limit or alter the recipients’
	rights in the Source Code Form under this License.
	
	3.3. Distribution of a Larger Work
	
	You may create and distribute a Larger Work under terms of Your choice,
	provided that You also comply with the requirements of this License for the
	Covered Software. If the Larger Work is a combination of Covered Software
	with a work governed by one or more Secondary Licenses, and the Covered
	Software is not Incompatible With Secondary Licenses, this License permits
	You to additionally distribute such Covered Software under the terms of
	such Secondary License(s), so that the recipient of the Larger Work may, at
	their option, further distribute the Covered Software under the terms of
	either this License or such Secondary License(s).
	
	3.4. Notices
	
	You may not remove or alter the substance of any license notices (including
	copyright notices, patent notices, disclaimers of warranty, or limitations
	of liability) contained within the Source Code Form of the Covered
	Software, except that You may alter any license notices to the extent
	required to remedy known factual inaccuracies.
	
	3.5. Application of Additional Terms
	
	You may choose to offer, and to charge a fee for, warranty, support,
	indemnity or liability obligations to one or more recipients of Covered
	Software. However, You may do so only on Your own behalf, and not on behalf
	of any Contributor. You must make it absolutely clear that any such
	warranty, support, indemnity, or liability obligation is offered by You
	alone, and You hereby agree to indemnify every Contributor for any
	liability incurred by such Contributor as a result of warranty, support,
	indemnity or liability terms You offer. You may include additional
	disclaimers of warranty and limitations of liability specific to any
	jurisdiction.
	
	4. Inability to Comply Due to Statute or Regulation
	
	If it is impossible for You to comply with any of the terms of this License
	with respect to some or all of the Covered Software due to statute, judicial
	order, or regulation then You must: (a) comply with the terms of this License
	to the maximum extent possible; and (b) describe the limitations and the code
	they affect. Such description must be placed in a text file included with all
	distributions of the Covered Software under this License. Except to the
	extent prohibited by statute or regulation, such description must be
	sufficiently detailed for a recipient of ordinary skill to be able to
	understand it.
	
	5. Termination
	
	5.1. The rights granted under this License will terminate automatically if You
	fail to comply with any of its terms. However, if You become compliant,
	then the rights granted under this License from a particular Contributor
	are reinstated (a) provisionally, unless and until such Contributor
	explicitly and finally terminates Your grants, and (b) on an ongoing basis,
	if such Contributor fails to notify You of the non-compliance by some
	reasonable means prior to 60 days after You have come back into compliance.
	Moreover, Your grants from a particular Contributor are reinstated on an
	ongoing basis if such Contributor notifies You of the non-compliance by
	some reasonable means, this is the first time You have received notice of
	non-compliance with this License from such Contributor, and You become
	compliant prior to 30 days after Your receipt of the notice.
	
	5.2. If You initiate litigation against any entity by asserting a patent
	infringement claim (excluding declaratory judgment actions, counter-claims,
	and cross-claims) alleging that a Contributor Version directly or
	indirectly infringes any patent, then the rights granted to You by any and
	all Contributors for the Covered Software under Section 2.1 of this License
	shall terminate.
	
	5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
	license agreements (excluding distributors and resellers) which have been
	validly granted by You or Your distributors under this License prior to
	termination shall survive termination.
	
	6. Disclaimer of Warranty
	
	Covered Software is provided under this License on an “as is” basis, without
	warranty of any kind, either expressed, implied, or statutory, including,
	without limitation, warranties that the Covered Software is free of defects,
	merchantable, fit for a particular purpose or non-infringing. The entire
	risk as to the quality and performance of the Covered Software is with You.
	Should any Covered Software prove defective in any respect, You (not any
	Contributor) assume the cost of any necessary servicing, repair, or
	correction. This disclaimer of warranty constitutes an essential part of this
	License. No use of  any Covered Software is authorized under this License
	except under this disclaimer.
	
	7. Limitation of Liability
	
	Under no circumstances and under no legal theory, whether tort (including
	negligence), contract, or otherwise, shall any Contributor, or anyone who
	distributes Covered Software as permitted above, be liable to You for any
	direct, indirect, special, incidental, or consequential damages of any
	character including, without limitation, damages for lost profits, loss of
	goodwill, work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses, even if such party shall have been
	informed of the possibility of such damages. This limitation of liability
	shall not apply to liability for death or personal injury resulting from such
	party’s negligence to the extent applicable law prohibits such limitation.
	Some jurisdictions do not allow the exclusion or limitation of incidental or
	consequential damages, so this exclusion and limitation may not apply to You.
	
	8. Litigation
	
	Any litigation relating to this License may be brought only in the courts of
	a jurisdiction where the defendant maintains its principal place of business
	and such litigation shall be governed by laws of that jurisdiction, without
	reference to its conflict-of-law provisions. Nothing in this Section shall
	prevent a party’s ability to bring cross-claims or counter-claims.
	
	9. Miscellaneous
	
	This License represents the complete agreement concerning the subject matter
	hereof. If any provision of this License is held to be unenforceable, such
	provision shall be reformed only to the extent necessary to make it
	enforceable. Any law or regulation which provides that the language of a
	contract shall be construed against the drafter shall not be used to construe
	this License against a Contributor.
	
	
	10. Versions of the License
	
	10.1. New Versions
	
	Mozilla Foundation is the license steward. Except as provided in Section
	10.3, no one other than the license steward has the right to modify or
	publish new versions of this License. Each version will be given a
	distinguishing version number.
	
	10.2. Effect of New Versions
	
	You may distribute the Covered Software under the terms of the version of
	the License under which You originally received the Covered Software, or
	under the terms of any subsequent version published by the license
	steward.
	
	10.3. Modified Versions
	
	If you create software not governed by this License, and you want to
	create a new license for such software, you may create and use a modified
	version of this License if you rename the license and remove any
	references to the name of the license steward (except to note that such
	modified license differs from this License).
	
	10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
	If You choose to distribute Source Code Form that is Incompatible With
	Secondary Licenses under the terms of this version of the License, the
	notice described in Exhibit B of this License must be attached.
	
	Exhibit A - Source Code Form License Notice
	
	This Source Code Form is subject to the
	terms of the Mozilla Public License, v.
	2.0. If a copy of the MPL was not
	distributed with this file, You can
	obtain one at
	http://mozilla.org/MPL/2.0/.
	
	If it is not possible or desirable to put the notice in a particular file, then
	You may include the notice in a location (such as a LICENSE file in a relevant
	directory) where a recipient would be likely to look for such a notice.
	
	You may add additional accurate notices of copyright ownership.
	
	Exhibit B - “Incompatible With Secondary Licenses” Notice
	
	This Source Code Form is “Incompatible
	With Secondary Licenses”, as defined by
	the Mozilla Public License, v. 2.0.

github.com/hashicorp/go-plugin/README.md:

	# Go Plugin System over RPC
	
	`go-plugin` is a Go (golang) plugin system over RPC. It is the plugin system
	that has been in use by HashiCorp tooling for over 4 years. While initially
	created for [Packer](https://www.packer.io), it is additionally in use by
	[Terraform](https://www.terraform.io), [Nomad](https://www.nomadproject.io),
	[Vault](https://www.vaultproject.io),
	[Boundary](https://www.boundaryproject.io),
	and [Waypoint](https://www.waypointproject.io).
	
	While the plugin system is over RPC, it is currently only designed to work
	over a local [reliable] network. Plugins over a real network are not supported
	and will lead to unexpected behavior.
	
	This plugin system has been used on millions of machines across many different
	projects and has proven to be battle hardened and ready for production use.
	
	## Features
	
	The HashiCorp plugin system supports a number of features:
	
	**Plugins are Go interface implementations.** This makes writing and consuming
	plugins feel very natural. To a plugin author: you just implement an
	interface as if it were going to run in the same process. For a plugin user:
	you just use and call functions on an interface as if it were in the same
	process. This plugin system handles the communication in between.
	
	**Cross-language support.** Plugins can be written (and consumed) by
	almost every major language. This library supports serving plugins via
	[gRPC](http://www.grpc.io). gRPC-based plugins enable plugins to be written
	in any language.
	
	**Complex arguments and return values are supported.** This library
	provides APIs for handling complex arguments and return values such
	as interfaces, `io.Reader/Writer`, etc. We do this by giving you a library
	(`MuxBroker`) for creating new connections between the client/server to
	serve additional interfaces or transfer raw data.
	
	**Bidirectional communication.** Because the plugin system supports
	complex arguments, the host process can send it interface implementations
	and the plugin can call back into the host process.
	
	**Built-in Logging.** Any plugins that use the `log` standard library
	will have log data automatically sent to the host process. The host
	process will mirror this output prefixed with the path to the plugin
	binary. This makes debugging with plugins simple. If the host system
	uses [hclog](https://github.com/hashicorp/go-hclog) then the log data
	will be structured. If the plugin also uses hclog, logs from the plugin
	will be sent to the host hclog and be structured.
	
	**Protocol Versioning.** A very basic "protocol version" is supported that
	can be incremented to invalidate any previous plugins. This is useful when
	interface signatures are changing, protocol level changes are necessary,
	etc. When a protocol version is incompatible, a human friendly error
	message is shown to the end user.
	
	**Stdout/Stderr Syncing.** While plugins are subprocesses, they can continue
	to use stdout/stderr as usual and the output will get mirrored back to
	the host process. The host process can control what `io.Writer` these
	streams go to to prevent this from happening.
	
	**TTY Preservation.** Plugin subprocesses are connected to the identical
	stdin file descriptor as the host process, allowing software that requires
	a TTY to work. For example, a plugin can execute `ssh` and even though there
	are multiple subprocesses and RPC happening, it will look and act perfectly
	to the end user.
	
	**Host upgrade while a plugin is running.** Plugins can be "reattached"
	so that the host process can be upgraded while the plugin is still running.
	This requires the host/plugin to know this is possible and daemonize
	properly. `NewClient` takes a `ReattachConfig` to determine if and how to
	reattach.
	
	**Cryptographically Secure Plugins.** Plugins can be verified with an expected
	checksum and RPC communications can be configured to use TLS. The host process
	must be properly secured to protect this configuration.
	
	## Architecture
	
	The HashiCorp plugin system works by launching subprocesses and communicating
	over RPC (using standard `net/rpc` or [gRPC](http://www.grpc.io)). A single
	connection is made between any plugin and the host process. For net/rpc-based
	plugins, we use a [connection multiplexing](https://github.com/hashicorp/yamux)
	library to multiplex any other connections on top. For gRPC-based plugins,
	the HTTP2 protocol handles multiplexing.
	
	This architecture has a number of benefits:
	
	* Plugins can't crash your host process: A panic in a plugin doesn't
	panic the plugin user.
	
	* Plugins are very easy to write: just write a Go application and `go build`.
	Or use any other language to write a gRPC server with a tiny amount of
	boilerplate to support go-plugin.
	
	* Plugins are very easy to install: just put the binary in a location where
	the host will find it (depends on the host but this library also provides
	helpers), and the plugin host handles the rest.
	
	* Plugins can be relatively secure: The plugin only has access to the
	interfaces and args given to it, not to the entire memory space of the
	process. Additionally, go-plugin can communicate with the plugin over
	TLS.
	
	## Usage
	
	To use the plugin system, you must take the following steps. These are
	high-level steps that must be done. Examples are available in the
	`examples/` directory.
	
	1. Choose the interface(s) you want to expose for plugins.
	
	2. For each interface, implement an implementation of that interface
	that communicates over a `net/rpc` connection or over a
	[gRPC](http://www.grpc.io) connection or both. You'll have to implement
	both a client and server implementation.
	
	3. Create a `Plugin` implementation that knows how to create the RPC
	client/server for a given plugin type.
	
	4. Plugin authors call `plugin.Serve` to serve a plugin from the
	`main` function.
	
	5. Plugin users use `plugin.Client` to launch a subprocess and request
	an interface implementation over RPC.
	
	That's it! In practice, step 2 is the most tedious and time consuming step.
	Even so, it isn't very difficult and you can see examples in the `examples/`
	directory as well as throughout our various open source projects.
	
	For complete API documentation, see [GoDoc](https://godoc.org/github.com/hashicorp/go-plugin).
	
	## Roadmap
	
	Our plugin system is constantly evolving. As we use the plugin system for
	new projects or for new features in existing projects, we constantly find
	improvements we can make.
	
	At this point in time, the roadmap for the plugin system is:
	
	**Semantic Versioning.** Plugins will be able to implement a semantic version.
	This plugin system will give host processes a system for constraining
	versions. This is in addition to the protocol versioning already present
	which is more for larger underlying changes.
	
	## What About Shared Libraries?
	
	When we started using plugins (late 2012, early 2013), plugins over RPC
	were the only option since Go didn't support dynamic library loading. Today,
	Go supports the [plugin](https://golang.org/pkg/plugin/) standard library with
	a number of  limitations. Since 2012, our plugin system has stabilized
	from tens of millions of users using it, and has many benefits we've come to
	value greatly.
	
	For example, we use this plugin system in
	[Vault](https://www.vaultproject.io) where dynamic library loading is
	not acceptable for security reasons. That is an extreme
	example, but we believe our library system has more upsides than downsides
	over dynamic library loading and since we've had it built and tested for years,
	we'll continue to use it.
	
	Shared libraries have one major advantage over our system which is much
	higher performance. In real world scenarios across our various tools,
	we've never required any more performance out of our plugin system and it
	has seen very high throughput, so this isn't a concern for us at the moment.

github.com/hashicorp/go-plugin/buf.gen.yaml:

	# Copyright (c) HashiCorp, Inc.
	# SPDX-License-Identifier: MPL-2.0
	
	version: v1
	plugins:
	- plugin: buf.build/protocolbuffers/go
	out: .
	opt:
	- paths=source_relative
	- plugin: buf.build/grpc/go:v1.3.0
	out: .
	opt:
	- paths=source_relative
	- require_unimplemented_servers=false

github.com/hashicorp/go-plugin/buf.yaml:

	# Copyright (c) HashiCorp, Inc.
	# SPDX-License-Identifier: MPL-2.0
	
	version: v1
	build:
	excludes:

github.com/hashicorp/go-plugin/client.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"bufio"
	"context"
	"crypto/subtle"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"errors"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	
	"github.com/hashicorp/go-hclog"
	"github.com/hashicorp/go-plugin/internal/cmdrunner"
	"github.com/hashicorp/go-plugin/internal/grpcmux"
	"github.com/hashicorp/go-plugin/runner"
	"google.golang.org/grpc"
	)
	
	// If this is 1, then we've called CleanupClients. This can be used
	// by plugin RPC implementations to change error behavior since you
	// can expected network connection errors at this point. This should be
	// read by using sync/atomic.
	var Killed uint32 = 0
	
	// This is a slice of the "managed" clients which are cleaned up when
	// calling Cleanup
	var managedClients = make([]*Client, 0, 5)
	var managedClientsLock sync.Mutex
	
	// Error types
	var (
	// ErrProcessNotFound is returned when a client is instantiated to
	// reattach to an existing process and it isn't found.
	ErrProcessNotFound = cmdrunner.ErrProcessNotFound
	
	// ErrChecksumsDoNotMatch is returned when binary's checksum doesn't match
	// the one provided in the SecureConfig.
	ErrChecksumsDoNotMatch = errors.New("checksums did not match")
	
	// ErrSecureNoChecksum is returned when an empty checksum is provided to the
	// SecureConfig.
	ErrSecureConfigNoChecksum = errors.New("no checksum provided")
	
	// ErrSecureNoHash is returned when a nil Hash object is provided to the
	// SecureConfig.
	ErrSecureConfigNoHash = errors.New("no hash implementation provided")
	
	// ErrSecureConfigAndReattach is returned when both Reattach and
	// SecureConfig are set.
	ErrSecureConfigAndReattach = errors.New("only one of Reattach or SecureConfig can be set")
	
	// ErrGRPCBrokerMuxNotSupported is returned when the client requests
	// multiplexing over the gRPC broker, but the plugin does not support the
	// feature. In most cases, this should be resolvable by updating and
	// rebuilding the plugin, or restarting the plugin with
	// ClientConfig.GRPCBrokerMultiplex set to false.
	ErrGRPCBrokerMuxNotSupported = errors.New("client requested gRPC broker multiplexing but plugin does not support the feature")
	)
	
	// defaultPluginLogBufferSize is the default size of the buffer used to read from stderr for plugin log lines.
	const defaultPluginLogBufferSize = 64 * 1024
	
	// Client handles the lifecycle of a plugin application. It launches
	// plugins, connects to them, dispenses interface implementations, and handles
	// killing the process.
	//
	// Plugin hosts should use one Client for each plugin executable. To
	// dispense a plugin type, use the `Client.Client` function, and then
	// cal `Dispense`. This awkward API is mostly historical but is used to split
	// the client that deals with subprocess management and the client that
	// does RPC management.
	//
	// See NewClient and ClientConfig for using a Client.
	type Client struct {
	config            *ClientConfig
	exited            bool
	l                 sync.Mutex
	address           net.Addr
	runner            runner.AttachedRunner
	client            ClientProtocol
	protocol          Protocol
	logger            hclog.Logger
	doneCtx           context.Context
	ctxCancel         context.CancelFunc
	negotiatedVersion int
	
	// clientWaitGroup is used to manage the lifecycle of the plugin management
	// goroutines.
	clientWaitGroup sync.WaitGroup
	
	// pipesWaitGroup is used to prevent the command's Wait() function from
	// being called before we've finished reading from the stdout and stderr pipe.
	pipesWaitGroup sync.WaitGroup
	
	// processKilled is used for testing only, to flag when the process was
	// forcefully killed.
	processKilled bool
	
	unixSocketCfg UnixSocketConfig
	
	grpcMuxerOnce sync.Once
	grpcMuxer     *grpcmux.GRPCClientMuxer
	}
	
	// NegotiatedVersion returns the protocol version negotiated with the server.
	// This is only valid after Start() is called.
	func (c *Client) NegotiatedVersion() int {
	return c.negotiatedVersion
	}
	
	// ID returns a unique ID for the running plugin. By default this is the process
	// ID (pid), but it could take other forms if RunnerFunc was provided.
	func (c *Client) ID() string {
	c.l.Lock()
	defer c.l.Unlock()
	
	if c.runner != nil {
	return c.runner.ID()
	}
	
	return ""
	}
	
	// ClientConfig is the configuration used to initialize a new
	// plugin client. After being used to initialize a plugin client,
	// that configuration must not be modified again.
	type ClientConfig struct {
	// HandshakeConfig is the configuration that must match servers.
	HandshakeConfig
	
	// Plugins are the plugins that can be consumed.
	// The implied version of this PluginSet is the Handshake.ProtocolVersion.
	Plugins PluginSet
	
	// VersionedPlugins is a map of PluginSets for specific protocol versions.
	// These can be used to negotiate a compatible version between client and
	// server. If this is set, Handshake.ProtocolVersion is not required.
	VersionedPlugins map[int]PluginSet
	
	// One of the following must be set, but not both.
	//
	// Cmd is the unstarted subprocess for starting the plugin. If this is
	// set, then the Client starts the plugin process on its own and connects
	// to it.
	//
	// Reattach is configuration for reattaching to an existing plugin process
	// that is already running. This isn't common.
	Cmd      *exec.Cmd
	Reattach *ReattachConfig
	
	// RunnerFunc allows consumers to provide their own implementation of
	// runner.Runner and control the context within which a plugin is executed.
	// The cmd argument will have been copied from the config and populated with
	// environment variables that a go-plugin server expects to read such as
	// AutoMTLS certs and the magic cookie key.
	RunnerFunc func(l hclog.Logger, cmd *exec.Cmd, tmpDir string) (runner.Runner, error)
	
	// SecureConfig is configuration for verifying the integrity of the
	// executable. It can not be used with Reattach.
	SecureConfig *SecureConfig
	
	// TLSConfig is used to enable TLS on the RPC client.
	TLSConfig *tls.Config
	
	// Managed represents if the client should be managed by the
	// plugin package or not. If true, then by calling CleanupClients,
	// it will automatically be cleaned up. Otherwise, the client
	// user is fully responsible for making sure to Kill all plugin
	// clients. By default the client is _not_ managed.
	Managed bool
	
	// The minimum and maximum port to use for communicating with
	// the subprocess. If not set, this defaults to 10,000 and 25,000
	// respectively.
	MinPort, MaxPort uint
	
	// StartTimeout is the timeout to wait for the plugin to say it
	// has started successfully.
	StartTimeout time.Duration
	
	// If non-nil, then the stderr of the client will be written to here
	// (as well as the log). This is the original os.Stderr of the subprocess.
	// This isn't the output of synced stderr.
	Stderr io.Writer
	
	// SyncStdout, SyncStderr can be set to override the
	// respective os.Std* values in the plugin. Care should be taken to
	// avoid races here. If these are nil, then this will be set to
	// ioutil.Discard.
	SyncStdout io.Writer
	SyncStderr io.Writer
	
	// AllowedProtocols is a list of allowed protocols. If this isn't set,
	// then only netrpc is allowed. This is so that older go-plugin systems
	// can show friendly errors if they see a plugin with an unknown
	// protocol.
	//
	// By setting this, you can cause an error immediately on plugin start
	// if an unsupported protocol is used with a good error message.
	//
	// If this isn't set at all (nil value), then only net/rpc is accepted.
	// This is done for legacy reasons. You must explicitly opt-in to
	// new protocols.
	AllowedProtocols []Protocol
	
	// Logger is the logger that the client will used. If none is provided,
	// it will default to hclog's default logger.
	Logger hclog.Logger
	
	// PluginLogBufferSize is the buffer size(bytes) to read from stderr for plugin log lines.
	// If this is 0, then the default of 64KB is used.
	PluginLogBufferSize int
	
	// AutoMTLS has the client and server automatically negotiate mTLS for
	// transport authentication. This ensures that only the original client will
	// be allowed to connect to the server, and all other connections will be
	// rejected. The client will also refuse to connect to any server that isn't
	// the original instance started by the client.
	//
	// In this mode of operation, the client generates a one-time use tls
	// certificate, sends the public x.509 certificate to the new server, and
	// the server generates a one-time use tls certificate, and sends the public
	// x.509 certificate back to the client. These are used to authenticate all
	// rpc connections between the client and server.
	//
	// Setting AutoMTLS to true implies that the server must support the
	// protocol, and correctly negotiate the tls certificates, or a connection
	// failure will result.
	//
	// The client should not set TLSConfig, nor should the server set a
	// TLSProvider, because AutoMTLS implies that a new certificate and tls
	// configuration will be generated at startup.
	//
	// You cannot Reattach to a server with this option enabled.
	AutoMTLS bool
	
	// GRPCDialOptions allows plugin users to pass custom grpc.DialOption
	// to create gRPC connections. This only affects plugins using the gRPC
	// protocol.
	GRPCDialOptions []grpc.DialOption
	
	// GRPCBrokerMultiplex turns on multiplexing for the gRPC broker. The gRPC
	// broker will multiplex all brokered gRPC servers over the plugin's original
	// listener socket instead of making a new listener for each server. The
	// go-plugin library currently only includes a Go implementation for the
	// server (i.e. plugin) side of gRPC broker multiplexing.
	//
	// Does not support reattaching.
	//
	// Multiplexed gRPC streams MUST be established sequentially, i.e. after
	// calling AcceptAndServe from one side, wait for the other side to Dial
	// before calling AcceptAndServe again.
	GRPCBrokerMultiplex bool
	
	// SkipHostEnv allows plugins to run without inheriting the parent process'
	// environment variables.
	SkipHostEnv bool
	
	// UnixSocketConfig configures additional options for any Unix sockets
	// that are created. Not normally required. Not supported on Windows.
	UnixSocketConfig *UnixSocketConfig
	}
	
	type UnixSocketConfig struct {
	// If set, go-plugin will change the owner of any Unix sockets created to
	// this group, and set them as group-writable. Can be a name or gid. The
	// client process must be a member of this group or chown will fail.
	Group string
	
	// TempDir specifies the base directory to use when creating a plugin-specific
	// temporary directory. It is expected to already exist and be writable. If
	// not set, defaults to the directory chosen by os.MkdirTemp.
	TempDir string
	
	// The directory to create Unix sockets in. Internally created and managed
	// by go-plugin and deleted when the plugin is killed. Will be created
	// inside TempDir if specified.
	socketDir string
	}
	
	// ReattachConfig is used to configure a client to reattach to an
	// already-running plugin process. You can retrieve this information by
	// calling ReattachConfig on Client.
	type ReattachConfig struct {
	Protocol        Protocol
	ProtocolVersion int
	Addr            net.Addr
	Pid             int
	
	// ReattachFunc allows consumers to provide their own implementation of
	// runner.AttachedRunner and attach to something other than a plain process.
	// At least one of Pid or ReattachFunc must be set.
	ReattachFunc runner.ReattachFunc
	
	// Test is set to true if this is reattaching to to a plugin in "test mode"
	// (see ServeConfig.Test). In this mode, client.Kill will NOT kill the
	// process and instead will rely on the plugin to terminate itself. This
	// should not be used in non-test environments.
	Test bool
	}
	
	// SecureConfig is used to configure a client to verify the integrity of an
	// executable before running. It does this by verifying the checksum is
	// expected. Hash is used to specify the hashing method to use when checksumming
	// the file.  The configuration is verified by the client by calling the
	// SecureConfig.Check() function.
	//
	// The host process should ensure the checksum was provided by a trusted and
	// authoritative source. The binary should be installed in such a way that it
	// can not be modified by an unauthorized user between the time of this check
	// and the time of execution.
	type SecureConfig struct {
	Checksum []byte
	Hash     hash.Hash
	}
	
	// Check takes the filepath to an executable and returns true if the checksum of
	// the file matches the checksum provided in the SecureConfig.
	func (s *SecureConfig) Check(filePath string) (bool, error) {
	if len(s.Checksum) == 0 {
	return false, ErrSecureConfigNoChecksum
	}
	
	if s.Hash == nil {
	return false, ErrSecureConfigNoHash
	}
	
	file, err := os.Open(filePath)
	if err != nil {
	return false, err
	}
	defer file.Close()
	
	_, err = io.Copy(s.Hash, file)
	if err != nil {
	return false, err
	}
	
	sum := s.Hash.Sum(nil)
	
	return subtle.ConstantTimeCompare(sum, s.Checksum) == 1, nil
	}
	
	// This makes sure all the managed subprocesses are killed and properly
	// logged. This should be called before the parent process running the
	// plugins exits.
	//
	// This must only be called _once_.
	func CleanupClients() {
	// Set the killed to true so that we don't get unexpected panics
	atomic.StoreUint32(&Killed, 1)
	
	// Kill all the managed clients in parallel and use a WaitGroup
	// to wait for them all to finish up.
	var wg sync.WaitGroup
	managedClientsLock.Lock()
	for _, client := range managedClients {
	wg.Add(1)
	
	go func(client *Client) {
	client.Kill()
	wg.Done()
	}(client)
	}
	managedClientsLock.Unlock()
	
	wg.Wait()
	}
	
	// NewClient creates a new plugin client which manages the lifecycle of an external
	// plugin and gets the address for the RPC connection.
	//
	// The client must be cleaned up at some point by calling Kill(). If
	// the client is a managed client (created with ClientConfig.Managed) you
	// can just call CleanupClients at the end of your program and they will
	// be properly cleaned.
	func NewClient(config *ClientConfig) (c *Client) {
	if config.MinPort == 0 && config.MaxPort == 0 {
	config.MinPort = 10000
	config.MaxPort = 25000
	}
	
	if config.StartTimeout == 0 {
	config.StartTimeout = 1 * time.Minute
	}
	
	if config.Stderr == nil {
	config.Stderr = ioutil.Discard
	}
	
	if config.SyncStdout == nil {
	config.SyncStdout = io.Discard
	}
	if config.SyncStderr == nil {
	config.SyncStderr = io.Discard
	}
	
	if config.AllowedProtocols == nil {
	config.AllowedProtocols = []Protocol{ProtocolNetRPC}
	}
	
	if config.Logger == nil {
	config.Logger = hclog.New(&hclog.LoggerOptions{
	Output: hclog.DefaultOutput,
	Level:  hclog.Trace,
	Name:   "plugin",
	})
	}
	
	if config.PluginLogBufferSize == 0 {
	config.PluginLogBufferSize = defaultPluginLogBufferSize
	}
	
	c = &Client{
	config: config,
	logger: config.Logger,
	}
	if config.Managed {
	managedClientsLock.Lock()
	managedClients = append(managedClients, c)
	managedClientsLock.Unlock()
	}
	
	return
	}
	
	// Client returns the protocol client for this connection.
	//
	// Subsequent calls to this will return the same client.
	func (c *Client) Client() (ClientProtocol, error) {
	_, err := c.Start()
	if err != nil {
	return nil, err
	}
	
	c.l.Lock()
	defer c.l.Unlock()
	
	if c.client != nil {
	return c.client, nil
	}
	
	switch c.protocol {
	case ProtocolNetRPC:
	c.client, err = newRPCClient(c)
	
	case ProtocolGRPC:
	c.client, err = newGRPCClient(c.doneCtx, c)
	
	default:
	return nil, fmt.Errorf("unknown server protocol: %s", c.protocol)
	}
	
	if err != nil {
	c.client = nil
	return nil, err
	}
	
	return c.client, nil
	}
	
	// Tells whether or not the underlying process has exited.
	func (c *Client) Exited() bool {
	c.l.Lock()
	defer c.l.Unlock()
	return c.exited
	}
	
	// killed is used in tests to check if a process failed to exit gracefully, and
	// needed to be killed.
	func (c *Client) killed() bool {
	c.l.Lock()
	defer c.l.Unlock()
	return c.processKilled
	}
	
	// End the executing subprocess (if it is running) and perform any cleanup
	// tasks necessary such as capturing any remaining logs and so on.
	//
	// This method blocks until the process successfully exits.
	//
	// This method can safely be called multiple times.
	func (c *Client) Kill() {
	// Grab a lock to read some private fields.
	c.l.Lock()
	runner := c.runner
	addr := c.address
	hostSocketDir := c.unixSocketCfg.socketDir
	c.l.Unlock()
	
	// If there is no runner or ID, there is nothing to kill.
	if runner == nil || runner.ID() == "" {
	return
	}
	
	defer func() {
	// Wait for the all client goroutines to finish.
	c.clientWaitGroup.Wait()
	
	if hostSocketDir != "" {
	os.RemoveAll(hostSocketDir)
	}
	
	// Make sure there is no reference to the old process after it has been
	// killed.
	c.l.Lock()
	c.runner = nil
	c.l.Unlock()
	}()
	
	// We need to check for address here. It is possible that the plugin
	// started (process != nil) but has no address (addr == nil) if the
	// plugin failed at startup. If we do have an address, we need to close
	// the plugin net connections.
	graceful := false
	if addr != nil {
	// Close the client to cleanly exit the process.
	client, err := c.Client()
	if err == nil {
	err = client.Close()
	
	// If there is no error, then we attempt to wait for a graceful
	// exit. If there was an error, we assume that graceful cleanup
	// won't happen and just force kill.
	graceful = err == nil
	if err != nil {
	// If there was an error just log it. We're going to force
	// kill in a moment anyways.
	c.logger.Warn("error closing client during Kill", "err", err)
	}
	} else {
	c.logger.Error("client", "error", err)
	}
	}
	
	// If we're attempting a graceful exit, then we wait for a short period
	// of time to allow that to happen. To wait for this we just wait on the
	// doneCh which would be closed if the process exits.
	if graceful {
	select {
	case <-c.doneCtx.Done():
	c.logger.Debug("plugin exited")
	return
	case <-time.After(2 * time.Second):
	}
	}
	
	// If graceful exiting failed, just kill it
	c.logger.Warn("plugin failed to exit gracefully")
	if err := runner.Kill(context.Background()); err != nil {
	c.logger.Debug("error killing plugin", "error", err)
	}
	
	c.l.Lock()
	c.processKilled = true
	c.l.Unlock()
	}
	
	// Start the underlying subprocess, communicating with it to negotiate
	// a port for RPC connections, and returning the address to connect via RPC.
	//
	// This method is safe to call multiple times. Subsequent calls have no effect.
	// Once a client has been started once, it cannot be started again, even if
	// it was killed.
	func (c *Client) Start() (addr net.Addr, err error) {
	c.l.Lock()
	defer c.l.Unlock()
	
	if c.address != nil {
	return c.address, nil
	}
	
	// If one of cmd or reattach isn't set, then it is an error. We wrap
	// this in a {} for scoping reasons, and hopeful that the escape
	// analysis will pop the stack here.
	{
	var mutuallyExclusiveOptions int
	if c.config.Cmd != nil {
	mutuallyExclusiveOptions += 1
	}
	if c.config.Reattach != nil {
	mutuallyExclusiveOptions += 1
	}
	if c.config.RunnerFunc != nil {
	mutuallyExclusiveOptions += 1
	}
	if mutuallyExclusiveOptions != 1 {
	return nil, fmt.Errorf("exactly one of Cmd, or Reattach, or RunnerFunc must be set")
	}
	
	if c.config.SecureConfig != nil && c.config.Reattach != nil {
	return nil, ErrSecureConfigAndReattach
	}
	
	if c.config.GRPCBrokerMultiplex && c.config.Reattach != nil {
	return nil, fmt.Errorf("gRPC broker multiplexing is not supported with Reattach config")
	}
	}
	
	if c.config.Reattach != nil {
	return c.reattach()
	}
	
	if c.config.VersionedPlugins == nil {
	c.config.VersionedPlugins = make(map[int]PluginSet)
	}
	
	// handle all plugins as versioned, using the handshake config as the default.
	version := int(c.config.ProtocolVersion)
	
	// Make sure we're not overwriting a real version 0. If ProtocolVersion was
	// non-zero, then we have to just assume the user made sure that
	// VersionedPlugins doesn't conflict.
	if _, ok := c.config.VersionedPlugins[version]; !ok && c.config.Plugins != nil {
	c.config.VersionedPlugins[version] = c.config.Plugins
	}
	
	var versionStrings []string
	for v := range c.config.VersionedPlugins {
	versionStrings = append(versionStrings, strconv.Itoa(v))
	}
	
	env := []string{
	fmt.Sprintf("%s=%s", c.config.MagicCookieKey, c.config.MagicCookieValue),
	fmt.Sprintf("PLUGIN_MIN_PORT=%d", c.config.MinPort),
	fmt.Sprintf("PLUGIN_MAX_PORT=%d", c.config.MaxPort),
	fmt.Sprintf("PLUGIN_PROTOCOL_VERSIONS=%s", strings.Join(versionStrings, ",")),
	}
	if c.config.GRPCBrokerMultiplex {
	env = append(env, fmt.Sprintf("%s=true", envMultiplexGRPC))
	}
	
	cmd := c.config.Cmd
	if cmd == nil {
	// It's only possible to get here if RunnerFunc is non-nil, but we'll
	// still use cmd as a spec to populate metadata for the external
	// implementation to consume.
	cmd = exec.Command("")
	}
	if !c.config.SkipHostEnv {
	cmd.Env = append(cmd.Env, os.Environ()...)
	}
	cmd.Env = append(cmd.Env, env...)
	cmd.Stdin = os.Stdin
	
	if c.config.SecureConfig != nil {
	if ok, err := c.config.SecureConfig.Check(cmd.Path); err != nil {
	return nil, fmt.Errorf("error verifying checksum: %s", err)
	} else if !ok {
	return nil, ErrChecksumsDoNotMatch
	}
	}
	
	// Setup a temporary certificate for client/server mtls, and send the public
	// certificate to the plugin.
	if c.config.AutoMTLS {
	c.logger.Info("configuring client automatic mTLS")
	certPEM, keyPEM, err := generateCert()
	if err != nil {
	c.logger.Error("failed to generate client certificate", "error", err)
	return nil, err
	}
	cert, err := tls.X509KeyPair(certPEM, keyPEM)
	if err != nil {
	c.logger.Error("failed to parse client certificate", "error", err)
	return nil, err
	}
	
	cmd.Env = append(cmd.Env, fmt.Sprintf("PLUGIN_CLIENT_CERT=%s", certPEM))
	
	c.config.TLSConfig = &tls.Config{
	Certificates: []tls.Certificate{cert},
	ClientAuth:   tls.RequireAndVerifyClientCert,
	MinVersion:   tls.VersionTLS12,
	ServerName:   "localhost",
	}
	}
	
	if c.config.UnixSocketConfig != nil {
	c.unixSocketCfg = *c.config.UnixSocketConfig
	}
	
	if c.unixSocketCfg.Group != "" {
	cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvUnixSocketGroup, c.unixSocketCfg.Group))
	}
	
	var runner runner.Runner
	switch {
	case c.config.RunnerFunc != nil:
	c.unixSocketCfg.socketDir, err = os.MkdirTemp(c.unixSocketCfg.TempDir, "plugin-dir")
	if err != nil {
	return nil, err
	}
	// os.MkdirTemp creates folders with 0o700, so if we have a group
	// configured we need to make it group-writable.
	if c.unixSocketCfg.Group != "" {
	err = setGroupWritable(c.unixSocketCfg.socketDir, c.unixSocketCfg.Group, 0o770)
	if err != nil {
	return nil, err
	}
	}
	cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", EnvUnixSocketDir, c.unixSocketCfg.socketDir))
	c.logger.Trace("created temporary directory for unix sockets", "dir", c.unixSocketCfg.socketDir)
	
	runner, err = c.config.RunnerFunc(c.logger, cmd, c.unixSocketCfg.socketDir)
	if err != nil {
	return nil, err
	}
	default:
	runner, err = cmdrunner.NewCmdRunner(c.logger, cmd)
	if err != nil {
	return nil, err
	}
	
	}
	
	c.runner = runner
	startCtx, startCtxCancel := context.WithTimeout(context.Background(), c.config.StartTimeout)
	defer startCtxCancel()
	err = runner.Start(startCtx)
	if err != nil {
	return nil, err
	}
	
	// Make sure the command is properly cleaned up if there is an error
	defer func() {
	rErr := recover()
	
	if err != nil || rErr != nil {
	runner.Kill(context.Background())
	}
	
	if rErr != nil {
	panic(rErr)
	}
	}()
	
	// Create a context for when we kill
	c.doneCtx, c.ctxCancel = context.WithCancel(context.Background())
	
	// Start goroutine that logs the stderr
	c.clientWaitGroup.Add(1)
	c.pipesWaitGroup.Add(1)
	// logStderr calls c.pipesWaitGroup.Done()
	go c.logStderr(runner.Name(), runner.Stderr())
	
	c.clientWaitGroup.Add(1)
	go func() {
	// ensure the context is cancelled when we're done
	defer c.ctxCancel()
	
	defer c.clientWaitGroup.Done()
	
	// wait to finish reading from stdout/stderr since the stdout/stderr pipe readers
	// will be closed by the subsequent call to cmd.Wait().
	c.pipesWaitGroup.Wait()
	
	// Wait for the command to end.
	err := runner.Wait(context.Background())
	if err != nil {
	c.logger.Error("plugin process exited", "plugin", runner.Name(), "id", runner.ID(), "error", err.Error())
	} else {
	// Log and make sure to flush the logs right away
	c.logger.Info("plugin process exited", "plugin", runner.Name(), "id", runner.ID())
	}
	
	os.Stderr.Sync()
	
	// Set that we exited, which takes a lock
	c.l.Lock()
	defer c.l.Unlock()
	c.exited = true
	}()
	
	// Start a goroutine that is going to be reading the lines
	// out of stdout
	linesCh := make(chan string)
	c.clientWaitGroup.Add(1)
	c.pipesWaitGroup.Add(1)
	go func() {
	defer c.clientWaitGroup.Done()
	defer c.pipesWaitGroup.Done()
	defer close(linesCh)
	
	scanner := bufio.NewScanner(runner.Stdout())
	for scanner.Scan() {
	linesCh <- scanner.Text()
	}
	if scanner.Err() != nil {
	c.logger.Error("error encountered while scanning stdout", "error", scanner.Err())
	}
	}()
	
	// Make sure after we exit we read the lines from stdout forever
	// so they don't block since it is a pipe.
	// The scanner goroutine above will close this, but track it with a wait
	// group for completeness.
	c.clientWaitGroup.Add(1)
	defer func() {
	go func() {
	defer c.clientWaitGroup.Done()
	for range linesCh {
	}
	}()
	}()
	
	// Some channels for the next step
	timeout := time.After(c.config.StartTimeout)
	
	// Start looking for the address
	c.logger.Debug("waiting for RPC address", "plugin", runner.Name())
	select {
	case <-timeout:
	err = errors.New("timeout while waiting for plugin to start")
	case <-c.doneCtx.Done():
	err = errors.New("plugin exited before we could connect")
	case line, ok := <-linesCh:
	// Trim the line and split by "|" in order to get the parts of
	// the output.
	line = strings.TrimSpace(line)
	parts := strings.Split(line, "|")
	if len(parts) < 4 {
	errText := fmt.Sprintf("Unrecognized remote plugin message: %s", line)
	if !ok {
	errText += "\n" + "Failed to read any lines from plugin's stdout"
	}
	additionalNotes := runner.Diagnose(context.Background())
	if additionalNotes != "" {
	errText += "\n" + additionalNotes
	}
	err = errors.New(errText)
	return
	}
	
	// Check the core protocol. Wrapped in a {} for scoping.
	{
	var coreProtocol int
	coreProtocol, err = strconv.Atoi(parts[0])
	if err != nil {
	err = fmt.Errorf("Error parsing core protocol version: %s", err)
	return
	}
	
	if coreProtocol != CoreProtocolVersion {
	err = fmt.Errorf("Incompatible core API version with plugin. "+
	"Plugin version: %s, Core version: %d\n\n"+
	"To fix this, the plugin usually only needs to be recompiled.\n"+
	"Please report this to the plugin author.", parts[0], CoreProtocolVersion)
	return
	}
	}
	
	// Test the API version
	version, pluginSet, err := c.checkProtoVersion(parts[1])
	if err != nil {
	return addr, err
	}
	
	// set the Plugins value to the compatible set, so the version
	// doesn't need to be passed through to the ClientProtocol
	// implementation.
	c.config.Plugins = pluginSet
	c.negotiatedVersion = version
	c.logger.Debug("using plugin", "version", version)
	
	network, address, err := runner.PluginToHost(parts[2], parts[3])
	if err != nil {
	return addr, err
	}
	
	switch network {
	case "tcp":
	addr, err = net.ResolveTCPAddr("tcp", address)
	case "unix":
	addr, err = net.ResolveUnixAddr("unix", address)
	default:
	err = fmt.Errorf("Unknown address type: %s", address)
	}
	
	// If we have a server type, then record that. We default to net/rpc
	// for backwards compatibility.
	c.protocol = ProtocolNetRPC
	if len(parts) >= 5 {
	c.protocol = Protocol(parts[4])
	}
	
	found := false
	for _, p := range c.config.AllowedProtocols {
	if p == c.protocol {
	found = true
	break
	}
	}
	if !found {
	err = fmt.Errorf("Unsupported plugin protocol %q. Supported: %v",
	c.protocol, c.config.AllowedProtocols)
	return addr, err
	}
	
	// See if we have a TLS certificate from the server.
	// Checking if the length is > 50 rules out catching the unused "extra"
	// data returned from some older implementations.
	if len(parts) >= 6 && len(parts[5]) > 50 {
	err := c.loadServerCert(parts[5])
	if err != nil {
	return nil, fmt.Errorf("error parsing server cert: %s", err)
	}
	}
	
	if c.config.GRPCBrokerMultiplex && c.protocol == ProtocolGRPC {
	if len(parts) <= 6 {
	return nil, fmt.Errorf("%w; for Go plugins, you will need to update the "+
	"github.com/hashicorp/go-plugin dependency and recompile", ErrGRPCBrokerMuxNotSupported)
	}
	if muxSupported, err := strconv.ParseBool(parts[6]); err != nil {
	return nil, fmt.Errorf("error parsing %q as a boolean for gRPC broker multiplexing support", parts[6])
	} else if !muxSupported {
	return nil, ErrGRPCBrokerMuxNotSupported
	}
	}
	}
	
	c.address = addr
	return
	}
	
	// loadServerCert is used by AutoMTLS to read an x.509 cert returned by the
	// server, and load it as the RootCA and ClientCA for the client TLSConfig.
	func (c *Client) loadServerCert(cert string) error {
	certPool := x509.NewCertPool()
	
	asn1, err := base64.RawStdEncoding.DecodeString(cert)
	if err != nil {
	return err
	}
	
	x509Cert, err := x509.ParseCertificate([]byte(asn1))
	if err != nil {
	return err
	}
	
	certPool.AddCert(x509Cert)
	
	c.config.TLSConfig.RootCAs = certPool
	c.config.TLSConfig.ClientCAs = certPool
	return nil
	}
	
	func (c *Client) reattach() (net.Addr, error) {
	reattachFunc := c.config.Reattach.ReattachFunc
	// For backwards compatibility default to cmdrunner.ReattachFunc
	if reattachFunc == nil {
	reattachFunc = cmdrunner.ReattachFunc(c.config.Reattach.Pid, c.config.Reattach.Addr)
	}
	
	r, err := reattachFunc()
	if err != nil {
	return nil, err
	}
	
	// Create a context for when we kill
	c.doneCtx, c.ctxCancel = context.WithCancel(context.Background())
	
	c.clientWaitGroup.Add(1)
	// Goroutine to mark exit status
	go func(r runner.AttachedRunner) {
	defer c.clientWaitGroup.Done()
	
	// ensure the context is cancelled when we're done
	defer c.ctxCancel()
	
	// Wait for the process to die
	r.Wait(context.Background())
	
	// Log so we can see it
	c.logger.Debug("reattached plugin process exited")
	
	// Mark it
	c.l.Lock()
	defer c.l.Unlock()
	c.exited = true
	}(r)
	
	// Set the address and protocol
	c.address = c.config.Reattach.Addr
	c.protocol = c.config.Reattach.Protocol
	if c.protocol == "" {
	// Default the protocol to net/rpc for backwards compatibility
	c.protocol = ProtocolNetRPC
	}
	
	if c.config.Reattach.Test {
	c.negotiatedVersion = c.config.Reattach.ProtocolVersion
	} else {
	// If we're in test mode, we do NOT set the runner. This avoids the
	// runner being killed (the only purpose we have for setting c.runner
	// when reattaching), since in test mode the process is responsible for
	// exiting on its own.
	c.runner = r
	}
	
	return c.address, nil
	}
	
	// checkProtoVersion returns the negotiated version and PluginSet.
	// This returns an error if the server returned an incompatible protocol
	// version, or an invalid handshake response.
	func (c *Client) checkProtoVersion(protoVersion string) (int, PluginSet, error) {
	serverVersion, err := strconv.Atoi(protoVersion)
	if err != nil {
	return 0, nil, fmt.Errorf("Error parsing protocol version %q: %s", protoVersion, err)
	}
	
	// record these for the error message
	var clientVersions []int
	
	// all versions, including the legacy ProtocolVersion have been added to
	// the versions set
	for version, plugins := range c.config.VersionedPlugins {
	clientVersions = append(clientVersions, version)
	
	if serverVersion != version {
	continue
	}
	return version, plugins, nil
	}
	
	return 0, nil, fmt.Errorf("Incompatible API version with plugin. "+
	"Plugin version: %d, Client versions: %d", serverVersion, clientVersions)
	}
	
	// ReattachConfig returns the information that must be provided to NewClient
	// to reattach to the plugin process that this client started. This is
	// useful for plugins that detach from their parent process.
	//
	// If this returns nil then the process hasn't been started yet. Please
	// call Start or Client before calling this.
	//
	// Clients who specified a RunnerFunc will need to populate their own
	// ReattachFunc in the returned ReattachConfig before it can be used.
	func (c *Client) ReattachConfig() *ReattachConfig {
	c.l.Lock()
	defer c.l.Unlock()
	
	if c.address == nil {
	return nil
	}
	
	if c.config.Cmd != nil && c.config.Cmd.Process == nil {
	return nil
	}
	
	// If we connected via reattach, just return the information as-is
	if c.config.Reattach != nil {
	return c.config.Reattach
	}
	
	reattach := &ReattachConfig{
	Protocol: c.protocol,
	Addr:     c.address,
	}
	
	if c.config.Cmd != nil && c.config.Cmd.Process != nil {
	reattach.Pid = c.config.Cmd.Process.Pid
	}
	
	return reattach
	}
	
	// Protocol returns the protocol of server on the remote end. This will
	// start the plugin process if it isn't already started. Errors from
	// starting the plugin are surpressed and ProtocolInvalid is returned. It
	// is recommended you call Start explicitly before calling Protocol to ensure
	// no errors occur.
	func (c *Client) Protocol() Protocol {
	_, err := c.Start()
	if err != nil {
	return ProtocolInvalid
	}
	
	return c.protocol
	}
	
	func netAddrDialer(addr net.Addr) func(string, time.Duration) (net.Conn, error) {
	return func(_ string, _ time.Duration) (net.Conn, error) {
	// Connect to the client
	conn, err := net.Dial(addr.Network(), addr.String())
	if err != nil {
	return nil, err
	}
	if tcpConn, ok := conn.(*net.TCPConn); ok {
	// Make sure to set keep alive so that the connection doesn't die
	tcpConn.SetKeepAlive(true)
	}
	
	return conn, nil
	}
	}
	
	// dialer is compatible with grpc.WithDialer and creates the connection
	// to the plugin.
	func (c *Client) dialer(_ string, timeout time.Duration) (net.Conn, error) {
	muxer, err := c.getGRPCMuxer(c.address)
	if err != nil {
	return nil, err
	}
	
	var conn net.Conn
	if muxer.Enabled() {
	conn, err = muxer.Dial()
	if err != nil {
	return nil, err
	}
	} else {
	conn, err = netAddrDialer(c.address)("", timeout)
	if err != nil {
	return nil, err
	}
	}
	
	// If we have a TLS config we wrap our connection. We only do this
	// for net/rpc since gRPC uses its own mechanism for TLS.
	if c.protocol == ProtocolNetRPC && c.config.TLSConfig != nil {
	conn = tls.Client(conn, c.config.TLSConfig)
	}
	
	return conn, nil
	}
	
	func (c *Client) getGRPCMuxer(addr net.Addr) (*grpcmux.GRPCClientMuxer, error) {
	if c.protocol != ProtocolGRPC || !c.config.GRPCBrokerMultiplex {
	return nil, nil
	}
	
	var err error
	c.grpcMuxerOnce.Do(func() {
	c.grpcMuxer, err = grpcmux.NewGRPCClientMuxer(c.logger, addr)
	})
	if err != nil {
	return nil, err
	}
	
	return c.grpcMuxer, nil
	}
	
	func (c *Client) logStderr(name string, r io.Reader) {
	defer c.clientWaitGroup.Done()
	defer c.pipesWaitGroup.Done()
	l := c.logger.Named(filepath.Base(name))
	
	reader := bufio.NewReaderSize(r, c.config.PluginLogBufferSize)
	// continuation indicates the previous line was a prefix
	continuation := false
	
	for {
	line, isPrefix, err := reader.ReadLine()
	switch {
	case err == io.EOF:
	return
	case err != nil:
	l.Error("reading plugin stderr", "error", err)
	return
	}
	
	c.config.Stderr.Write(line)
	
	// The line was longer than our max token size, so it's likely
	// incomplete and won't unmarshal.
	if isPrefix || continuation {
	l.Debug(string(line))
	
	// if we're finishing a continued line, add the newline back in
	if !isPrefix {
	c.config.Stderr.Write([]byte{'\n'})
	}
	
	continuation = isPrefix
	continue
	}
	
	c.config.Stderr.Write([]byte{'\n'})
	
	entry, err := parseJSON(line)
	// If output is not JSON format, print directly to Debug
	if err != nil {
	// Attempt to infer the desired log level from the commonly used
	// string prefixes
	switch line := string(line); {
	case strings.HasPrefix(line, "[TRACE]"):
	l.Trace(line)
	case strings.HasPrefix(line, "[DEBUG]"):
	l.Debug(line)
	case strings.HasPrefix(line, "[INFO]"):
	l.Info(line)
	case strings.HasPrefix(line, "[WARN]"):
	l.Warn(line)
	case strings.HasPrefix(line, "[ERROR]"):
	l.Error(line)
	default:
	l.Debug(line)
	}
	} else {
	out := flattenKVPairs(entry.KVPairs)
	
	out = append(out, "timestamp", entry.Timestamp.Format(hclog.TimeFormat))
	switch hclog.LevelFromString(entry.Level) {
	case hclog.Trace:
	l.Trace(entry.Message, out...)
	case hclog.Debug:
	l.Debug(entry.Message, out...)
	case hclog.Info:
	l.Info(entry.Message, out...)
	case hclog.Warn:
	l.Warn(entry.Message, out...)
	case hclog.Error:
	l.Error(entry.Message, out...)
	default:
	// if there was no log level, it's likely this is unexpected
	// json from something other than hclog, and we should output
	// it verbatim.
	l.Debug(string(line))
	}
	}
	}
	}

github.com/hashicorp/go-plugin/constants.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	const (
	// EnvUnixSocketDir specifies the directory that _plugins_ should create unix
	// sockets in. Does not affect client behavior.
	EnvUnixSocketDir = "PLUGIN_UNIX_SOCKET_DIR"
	
	// EnvUnixSocketGroup specifies the owning, writable group to set for Unix
	// sockets created by _plugins_. Does not affect client behavior.
	EnvUnixSocketGroup = "PLUGIN_UNIX_SOCKET_GROUP"
	
	envMultiplexGRPC = "PLUGIN_MULTIPLEX_GRPC"
	)

github.com/hashicorp/go-plugin/discover.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"path/filepath"
	)
	
	// Discover discovers plugins that are in a given directory.
	//
	// The directory doesn't need to be absolute. For example, "." will work fine.
	//
	// This currently assumes any file matching the glob is a plugin.
	// In the future this may be smarter about checking that a file is
	// executable and so on.
	//
	// TODO: test
	func Discover(glob, dir string) ([]string, error) {
	var err error
	
	// Make the directory absolute if it isn't already
	if !filepath.IsAbs(dir) {
	dir, err = filepath.Abs(dir)
	if err != nil {
	return nil, err
	}
	}
	
	return filepath.Glob(filepath.Join(dir, glob))
	}

github.com/hashicorp/go-plugin/error.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	// This is a type that wraps error types so that they can be messaged
	// across RPC channels. Since "error" is an interface, we can't always
	// gob-encode the underlying structure. This is a valid error interface
	// implementer that we will push across.
	type BasicError struct {
	Message string
	}
	
	// NewBasicError is used to create a BasicError.
	//
	// err is allowed to be nil.
	func NewBasicError(err error) *BasicError {
	if err == nil {
	return nil
	}
	
	return &BasicError{err.Error()}
	}
	
	func (e *BasicError) Error() string {
	return e.Message
	}

github.com/hashicorp/go-plugin/grpc_broker.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"log"
	"net"
	"sync"
	"sync/atomic"
	"time"
	
	"github.com/hashicorp/go-plugin/internal/grpcmux"
	"github.com/hashicorp/go-plugin/internal/plugin"
	"github.com/hashicorp/go-plugin/runner"
	
	"github.com/oklog/run"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	)
	
	// streamer interface is used in the broker to send/receive connection
	// information.
	type streamer interface {
	Send(*plugin.ConnInfo) error
	Recv() (*plugin.ConnInfo, error)
	Close()
	}
	
	// sendErr is used to pass errors back during a send.
	type sendErr struct {
	i  *plugin.ConnInfo
	ch chan error
	}
	
	// gRPCBrokerServer is used by the plugin to start a stream and to send
	// connection information to/from the plugin. Implements GRPCBrokerServer and
	// streamer interfaces.
	type gRPCBrokerServer struct {
	plugin.UnimplementedGRPCBrokerServer
	
	// send is used to send connection info to the gRPC stream.
	send chan *sendErr
	
	// recv is used to receive connection info from the gRPC stream.
	recv chan *plugin.ConnInfo
	
	// quit closes down the stream.
	quit chan struct{}
	
	// o is used to ensure we close the quit channel only once.
	o sync.Once
	}
	
	func newGRPCBrokerServer() *gRPCBrokerServer {
	return &gRPCBrokerServer{
	send: make(chan *sendErr),
	recv: make(chan *plugin.ConnInfo),
	quit: make(chan struct{}),
	}
	}
	
	// StartStream implements the GRPCBrokerServer interface and will block until
	// the quit channel is closed or the context reports Done. The stream will pass
	// connection information to/from the client.
	func (s *gRPCBrokerServer) StartStream(stream plugin.GRPCBroker_StartStreamServer) error {
	doneCh := stream.Context().Done()
	defer s.Close()
	
	// Proccess send stream
	go func() {
	for {
	select {
	case <-doneCh:
	return
	case <-s.quit:
	return
	case se := <-s.send:
	err := stream.Send(se.i)
	se.ch <- err
	}
	}
	}()
	
	// Process receive stream
	for {
	i, err := stream.Recv()
	if err != nil {
	return err
	}
	select {
	case <-doneCh:
	return nil
	case <-s.quit:
	return nil
	case s.recv <- i:
	}
	}
	
	return nil
	}
	
	// Send is used by the GRPCBroker to pass connection information into the stream
	// to the client.
	func (s *gRPCBrokerServer) Send(i *plugin.ConnInfo) error {
	ch := make(chan error)
	defer close(ch)
	
	select {
	case <-s.quit:
	return errors.New("broker closed")
	case s.send <- &sendErr{
	i:  i,
	ch: ch,
	}:
	}
	
	return <-ch
	}
	
	// Recv is used by the GRPCBroker to pass connection information that has been
	// sent from the client from the stream to the broker.
	func (s *gRPCBrokerServer) Recv() (*plugin.ConnInfo, error) {
	select {
	case <-s.quit:
	return nil, errors.New("broker closed")
	case i := <-s.recv:
	return i, nil
	}
	}
	
	// Close closes the quit channel, shutting down the stream.
	func (s *gRPCBrokerServer) Close() {
	s.o.Do(func() {
	close(s.quit)
	})
	}
	
	// gRPCBrokerClientImpl is used by the client to start a stream and to send
	// connection information to/from the client. Implements GRPCBrokerClient and
	// streamer interfaces.
	type gRPCBrokerClientImpl struct {
	// client is the underlying GRPC client used to make calls to the server.
	client plugin.GRPCBrokerClient
	
	// send is used to send connection info to the gRPC stream.
	send chan *sendErr
	
	// recv is used to receive connection info from the gRPC stream.
	recv chan *plugin.ConnInfo
	
	// quit closes down the stream.
	quit chan struct{}
	
	// o is used to ensure we close the quit channel only once.
	o sync.Once
	}
	
	func newGRPCBrokerClient(conn *grpc.ClientConn) *gRPCBrokerClientImpl {
	return &gRPCBrokerClientImpl{
	client: plugin.NewGRPCBrokerClient(conn),
	send:   make(chan *sendErr),
	recv:   make(chan *plugin.ConnInfo),
	quit:   make(chan struct{}),
	}
	}
	
	// StartStream implements the GRPCBrokerClient interface and will block until
	// the quit channel is closed or the context reports Done. The stream will pass
	// connection information to/from the plugin.
	func (s *gRPCBrokerClientImpl) StartStream() error {
	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	defer s.Close()
	
	stream, err := s.client.StartStream(ctx)
	if err != nil {
	return err
	}
	doneCh := stream.Context().Done()
	
	go func() {
	for {
	select {
	case <-doneCh:
	return
	case <-s.quit:
	return
	case se := <-s.send:
	err := stream.Send(se.i)
	se.ch <- err
	}
	}
	}()
	
	for {
	i, err := stream.Recv()
	if err != nil {
	return err
	}
	select {
	case <-doneCh:
	return nil
	case <-s.quit:
	return nil
	case s.recv <- i:
	}
	}
	
	return nil
	}
	
	// Send is used by the GRPCBroker to pass connection information into the stream
	// to the plugin.
	func (s *gRPCBrokerClientImpl) Send(i *plugin.ConnInfo) error {
	ch := make(chan error)
	defer close(ch)
	
	select {
	case <-s.quit:
	return errors.New("broker closed")
	case s.send <- &sendErr{
	i:  i,
	ch: ch,
	}:
	}
	
	return <-ch
	}
	
	// Recv is used by the GRPCBroker to pass connection information that has been
	// sent from the plugin to the broker.
	func (s *gRPCBrokerClientImpl) Recv() (*plugin.ConnInfo, error) {
	select {
	case <-s.quit:
	return nil, errors.New("broker closed")
	case i := <-s.recv:
	return i, nil
	}
	}
	
	// Close closes the quit channel, shutting down the stream.
	func (s *gRPCBrokerClientImpl) Close() {
	s.o.Do(func() {
	close(s.quit)
	})
	}
	
	// GRPCBroker is responsible for brokering connections by unique ID.
	//
	// It is used by plugins to create multiple gRPC connections and data
	// streams between the plugin process and the host process.
	//
	// This allows a plugin to request a channel with a specific ID to connect to
	// or accept a connection from, and the broker handles the details of
	// holding these channels open while they're being negotiated.
	//
	// The Plugin interface has access to these for both Server and Client.
	// The broker can be used by either (optionally) to reserve and connect to
	// new streams. This is useful for complex args and return values,
	// or anything else you might need a data stream for.
	type GRPCBroker struct {
	nextId   uint32
	streamer streamer
	tls      *tls.Config
	doneCh   chan struct{}
	o        sync.Once
	
	clientStreams map[uint32]*gRPCBrokerPending
	serverStreams map[uint32]*gRPCBrokerPending
	
	unixSocketCfg  UnixSocketConfig
	addrTranslator runner.AddrTranslator
	
	dialMutex sync.Mutex
	
	muxer grpcmux.GRPCMuxer
	
	sync.Mutex
	}
	
	type gRPCBrokerPending struct {
	ch     chan *plugin.ConnInfo
	doneCh chan struct{}
	once   sync.Once
	}
	
	func newGRPCBroker(s streamer, tls *tls.Config, unixSocketCfg UnixSocketConfig, addrTranslator runner.AddrTranslator, muxer grpcmux.GRPCMuxer) *GRPCBroker {
	return &GRPCBroker{
	streamer: s,
	tls:      tls,
	doneCh:   make(chan struct{}),
	
	clientStreams: make(map[uint32]*gRPCBrokerPending),
	serverStreams: make(map[uint32]*gRPCBrokerPending),
	muxer:         muxer,
	
	unixSocketCfg:  unixSocketCfg,
	addrTranslator: addrTranslator,
	}
	}
	
	// Accept accepts a connection by ID.
	//
	// This should not be called multiple times with the same ID at one time.
	func (b *GRPCBroker) Accept(id uint32) (net.Listener, error) {
	if b.muxer.Enabled() {
	p := b.getServerStream(id)
	go func() {
	err := b.listenForKnocks(id)
	if err != nil {
	log.Printf("[ERR]: error listening for knocks, id: %d, error: %s", id, err)
	}
	}()
	
	ln, err := b.muxer.Listener(id, p.doneCh)
	if err != nil {
	return nil, err
	}
	
	ln = &rmListener{
	Listener: ln,
	close: func() error {
	// We could have multiple listeners on the same ID, so use sync.Once
	// for closing doneCh to ensure we don't get a panic.
	p.once.Do(func() {
	close(p.doneCh)
	})
	
	b.Lock()
	defer b.Unlock()
	
	// No longer need to listen for knocks once the listener is closed.
	delete(b.serverStreams, id)
	
	return nil
	},
	}
	
	return ln, nil
	}
	
	listener, err := serverListener(b.unixSocketCfg)
	if err != nil {
	return nil, err
	}
	
	advertiseNet := listener.Addr().Network()
	advertiseAddr := listener.Addr().String()
	if b.addrTranslator != nil {
	advertiseNet, advertiseAddr, err = b.addrTranslator.HostToPlugin(advertiseNet, advertiseAddr)
	if err != nil {
	return nil, err
	}
	}
	err = b.streamer.Send(&plugin.ConnInfo{
	ServiceId: id,
	Network:   advertiseNet,
	Address:   advertiseAddr,
	})
	if err != nil {
	return nil, err
	}
	
	return listener, nil
	}
	
	// AcceptAndServe is used to accept a specific stream ID and immediately
	// serve a gRPC server on that stream ID. This is used to easily serve
	// complex arguments. Each AcceptAndServe call opens a new listener socket and
	// sends the connection info down the stream to the dialer. Since a new
	// connection is opened every call, these calls should be used sparingly.
	// Multiple gRPC server implementations can be registered to a single
	// AcceptAndServe call.
	func (b *GRPCBroker) AcceptAndServe(id uint32, newGRPCServer func([]grpc.ServerOption) *grpc.Server) {
	ln, err := b.Accept(id)
	if err != nil {
	log.Printf("[ERR] plugin: plugin acceptAndServe error: %s", err)
	return
	}
	defer ln.Close()
	
	var opts []grpc.ServerOption
	if b.tls != nil {
	opts = []grpc.ServerOption{grpc.Creds(credentials.NewTLS(b.tls))}
	}
	
	server := newGRPCServer(opts)
	
	// Here we use a run group to close this goroutine if the server is shutdown
	// or the broker is shutdown.
	var g run.Group
	{
	// Serve on the listener, if shutting down call GracefulStop.
	g.Add(func() error {
	return server.Serve(ln)
	}, func(err error) {
	server.GracefulStop()
	})
	}
	{
	// block on the closeCh or the doneCh. If we are shutting down close the
	// closeCh.
	closeCh := make(chan struct{})
	g.Add(func() error {
	select {
	case <-b.doneCh:
	case <-closeCh:
	}
	return nil
	}, func(err error) {
	close(closeCh)
	})
	}
	
	// Block until we are done
	g.Run()
	}
	
	// Close closes the stream and all servers.
	func (b *GRPCBroker) Close() error {
	b.streamer.Close()
	b.o.Do(func() {
	close(b.doneCh)
	})
	return nil
	}
	
	func (b *GRPCBroker) listenForKnocks(id uint32) error {
	p := b.getServerStream(id)
	for {
	select {
	case msg := <-p.ch:
	// Shouldn't be possible.
	if msg.ServiceId != id {
	return fmt.Errorf("knock received with wrong service ID; expected %d but got %d", id, msg.ServiceId)
	}
	
	// Also shouldn't be possible.
	if msg.Knock == nil || !msg.Knock.Knock || msg.Knock.Ack {
	return fmt.Errorf("knock received for service ID %d with incorrect values; knock=%+v", id, msg.Knock)
	}
	
	// Successful knock, open the door for the given ID.
	var ackError string
	err := b.muxer.AcceptKnock(id)
	if err != nil {
	ackError = err.Error()
	}
	
	// Send back an acknowledgement to allow the client to start dialling.
	err = b.streamer.Send(&plugin.ConnInfo{
	ServiceId: id,
	Knock: &plugin.ConnInfo_Knock{
	Knock: true,
	Ack:   true,
	Error: ackError,
	},
	})
	if err != nil {
	return fmt.Errorf("error sending back knock acknowledgement: %w", err)
	}
	case <-p.doneCh:
	return nil
	}
	}
	}
	
	func (b *GRPCBroker) knock(id uint32) error {
	// Send a knock.
	err := b.streamer.Send(&plugin.ConnInfo{
	ServiceId: id,
	Knock: &plugin.ConnInfo_Knock{
	Knock: true,
	},
	})
	if err != nil {
	return err
	}
	
	// Wait for the ack.
	p := b.getClientStream(id)
	select {
	case msg := <-p.ch:
	if msg.ServiceId != id {
	return fmt.Errorf("handshake failed for multiplexing on id %d; got response for %d", id, msg.ServiceId)
	}
	if msg.Knock == nil || !msg.Knock.Knock || !msg.Knock.Ack {
	return fmt.Errorf("handshake failed for multiplexing on id %d; expected knock and ack, but got %+v", id, msg.Knock)
	}
	if msg.Knock.Error != "" {
	return fmt.Errorf("failed to knock for id %d: %s", id, msg.Knock.Error)
	}
	case <-time.After(5 * time.Second):
	return fmt.Errorf("timeout waiting for multiplexing knock handshake on id %d", id)
	}
	
	return nil
	}
	
	func (b *GRPCBroker) muxDial(id uint32) func(string, time.Duration) (net.Conn, error) {
	return func(string, time.Duration) (net.Conn, error) {
	b.dialMutex.Lock()
	defer b.dialMutex.Unlock()
	
	// Tell the other side the listener ID it should give the next stream to.
	err := b.knock(id)
	if err != nil {
	return nil, fmt.Errorf("failed to knock before dialling client: %w", err)
	}
	
	conn, err := b.muxer.Dial()
	if err != nil {
	return nil, err
	}
	
	return conn, nil
	}
	}
	
	// Dial opens a connection by ID.
	func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) {
	if b.muxer.Enabled() {
	return dialGRPCConn(b.tls, b.muxDial(id))
	}
	
	var c *plugin.ConnInfo
	
	// Open the stream
	p := b.getClientStream(id)
	select {
	case c = <-p.ch:
	close(p.doneCh)
	case <-time.After(5 * time.Second):
	return nil, fmt.Errorf("timeout waiting for connection info")
	}
	
	network, address := c.Network, c.Address
	if b.addrTranslator != nil {
	network, address, err = b.addrTranslator.PluginToHost(network, address)
	if err != nil {
	return nil, err
	}
	}
	
	var addr net.Addr
	switch network {
	case "tcp":
	addr, err = net.ResolveTCPAddr("tcp", address)
	case "unix":
	addr, err = net.ResolveUnixAddr("unix", address)
	default:
	err = fmt.Errorf("Unknown address type: %s", c.Address)
	}
	if err != nil {
	return nil, err
	}
	
	return dialGRPCConn(b.tls, netAddrDialer(addr))
	}
	
	// NextId returns a unique ID to use next.
	//
	// It is possible for very long-running plugin hosts to wrap this value,
	// though it would require a very large amount of calls. In practice
	// we've never seen it happen.
	func (m *GRPCBroker) NextId() uint32 {
	return atomic.AddUint32(&m.nextId, 1)
	}
	
	// Run starts the brokering and should be executed in a goroutine, since it
	// blocks forever, or until the session closes.
	//
	// Uses of GRPCBroker never need to call this. It is called internally by
	// the plugin host/client.
	func (m *GRPCBroker) Run() {
	for {
	msg, err := m.streamer.Recv()
	if err != nil {
	// Once we receive an error, just exit
	break
	}
	
	// Initialize the waiter
	var p *gRPCBrokerPending
	if msg.Knock != nil && msg.Knock.Knock && !msg.Knock.Ack {
	p = m.getServerStream(msg.ServiceId)
	// The server side doesn't close the channel immediately as it needs
	// to continuously listen for knocks.
	} else {
	p = m.getClientStream(msg.ServiceId)
	go m.timeoutWait(msg.ServiceId, p)
	}
	select {
	case p.ch <- msg:
	default:
	}
	}
	}
	
	// getClientStream is a buffer to receive new connection info and knock acks
	// by stream ID.
	func (m *GRPCBroker) getClientStream(id uint32) *gRPCBrokerPending {
	m.Lock()
	defer m.Unlock()
	
	p, ok := m.clientStreams[id]
	if ok {
	return p
	}
	
	m.clientStreams[id] = &gRPCBrokerPending{
	ch:     make(chan *plugin.ConnInfo, 1),
	doneCh: make(chan struct{}),
	}
	return m.clientStreams[id]
	}
	
	// getServerStream is a buffer to receive knocks to a multiplexed stream ID
	// that its side is listening on. Not used unless multiplexing is enabled.
	func (m *GRPCBroker) getServerStream(id uint32) *gRPCBrokerPending {
	m.Lock()
	defer m.Unlock()
	
	p, ok := m.serverStreams[id]
	if ok {
	return p
	}
	
	m.serverStreams[id] = &gRPCBrokerPending{
	ch:     make(chan *plugin.ConnInfo, 1),
	doneCh: make(chan struct{}),
	}
	return m.serverStreams[id]
	}
	
	func (m *GRPCBroker) timeoutWait(id uint32, p *gRPCBrokerPending) {
	// Wait for the stream to either be picked up and connected, or
	// for a timeout.
	select {
	case <-p.doneCh:
	case <-time.After(5 * time.Second):
	}
	
	m.Lock()
	defer m.Unlock()
	
	// Delete the stream so no one else can grab it
	delete(m.clientStreams, id)
	}

github.com/hashicorp/go-plugin/grpc_client.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"context"
	"crypto/tls"
	"fmt"
	"math"
	"net"
	"time"
	
	"github.com/hashicorp/go-plugin/internal/plugin"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/health/grpc_health_v1"
	)
	
	func dialGRPCConn(tls *tls.Config, dialer func(string, time.Duration) (net.Conn, error), dialOpts ...grpc.DialOption) (*grpc.ClientConn, error) {
	// Build dialing options.
	opts := make([]grpc.DialOption, 0)
	
	// We use a custom dialer so that we can connect over unix domain sockets.
	opts = append(opts, grpc.WithDialer(dialer))
	
	// Fail right away
	opts = append(opts, grpc.FailOnNonTempDialError(true))
	
	// If we have no TLS configuration set, we need to explicitly tell grpc
	// that we're connecting with an insecure connection.
	if tls == nil {
	opts = append(opts, grpc.WithInsecure())
	} else {
	opts = append(opts, grpc.WithTransportCredentials(
	credentials.NewTLS(tls)))
	}
	
	opts = append(opts,
	grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32)),
	grpc.WithDefaultCallOptions(grpc.MaxCallSendMsgSize(math.MaxInt32)))
	
	// Add our custom options if we have any
	opts = append(opts, dialOpts...)
	
	// Connect. Note the first parameter is unused because we use a custom
	// dialer that has the state to see the address.
	conn, err := grpc.Dial("unused", opts...)
	if err != nil {
	return nil, err
	}
	
	return conn, nil
	}
	
	// newGRPCClient creates a new GRPCClient. The Client argument is expected
	// to be successfully started already with a lock held.
	func newGRPCClient(doneCtx context.Context, c *Client) (*GRPCClient, error) {
	conn, err := dialGRPCConn(c.config.TLSConfig, c.dialer, c.config.GRPCDialOptions...)
	if err != nil {
	return nil, err
	}
	
	muxer, err := c.getGRPCMuxer(c.address)
	if err != nil {
	return nil, err
	}
	
	// Start the broker.
	brokerGRPCClient := newGRPCBrokerClient(conn)
	broker := newGRPCBroker(brokerGRPCClient, c.config.TLSConfig, c.unixSocketCfg, c.runner, muxer)
	go broker.Run()
	go brokerGRPCClient.StartStream()
	
	// Start the stdio client
	stdioClient, err := newGRPCStdioClient(doneCtx, c.logger.Named("stdio"), conn)
	if err != nil {
	return nil, err
	}
	go stdioClient.Run(c.config.SyncStdout, c.config.SyncStderr)
	
	cl := &GRPCClient{
	Conn:       conn,
	Plugins:    c.config.Plugins,
	doneCtx:    doneCtx,
	broker:     broker,
	controller: plugin.NewGRPCControllerClient(conn),
	}
	
	return cl, nil
	}
	
	// GRPCClient connects to a GRPCServer over gRPC to dispense plugin types.
	type GRPCClient struct {
	Conn    *grpc.ClientConn
	Plugins map[string]Plugin
	
	doneCtx context.Context
	broker  *GRPCBroker
	
	controller plugin.GRPCControllerClient
	}
	
	// ClientProtocol impl.
	func (c *GRPCClient) Close() error {
	c.broker.Close()
	c.controller.Shutdown(c.doneCtx, &plugin.Empty{})
	return c.Conn.Close()
	}
	
	// ClientProtocol impl.
	func (c *GRPCClient) Dispense(name string) (interface{}, error) {
	raw, ok := c.Plugins[name]
	if !ok {
	return nil, fmt.Errorf("unknown plugin type: %s", name)
	}
	
	p, ok := raw.(GRPCPlugin)
	if !ok {
	return nil, fmt.Errorf("plugin %q doesn't support gRPC", name)
	}
	
	return p.GRPCClient(c.doneCtx, c.broker, c.Conn)
	}
	
	// ClientProtocol impl.
	func (c *GRPCClient) Ping() error {
	client := grpc_health_v1.NewHealthClient(c.Conn)
	_, err := client.Check(context.Background(), &grpc_health_v1.HealthCheckRequest{
	Service: GRPCServiceName,
	})
	
	return err
	}

github.com/hashicorp/go-plugin/grpc_controller.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"context"
	
	"github.com/hashicorp/go-plugin/internal/plugin"
	)
	
	// GRPCControllerServer handles shutdown calls to terminate the server when the
	// plugin client is closed.
	type grpcControllerServer struct {
	server *GRPCServer
	}
	
	// Shutdown stops the grpc server. It first will attempt a graceful stop, then a
	// full stop on the server.
	func (s *grpcControllerServer) Shutdown(ctx context.Context, _ *plugin.Empty) (*plugin.Empty, error) {
	resp := &plugin.Empty{}
	
	// TODO: figure out why GracefullStop doesn't work.
	s.server.Stop()
	return resp, nil
	}

github.com/hashicorp/go-plugin/grpc_server.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"net"
	
	hclog "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/go-plugin/internal/grpcmux"
	"github.com/hashicorp/go-plugin/internal/plugin"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/health"
	"google.golang.org/grpc/health/grpc_health_v1"
	"google.golang.org/grpc/reflection"
	)
	
	// GRPCServiceName is the name of the service that the health check should
	// return as passing.
	const GRPCServiceName = "plugin"
	
	// DefaultGRPCServer can be used with the "GRPCServer" field for Server
	// as a default factory method to create a gRPC server with no extra options.
	func DefaultGRPCServer(opts []grpc.ServerOption) *grpc.Server {
	return grpc.NewServer(opts...)
	}
	
	// GRPCServer is a ServerType implementation that serves plugins over
	// gRPC. This allows plugins to easily be written for other languages.
	//
	// The GRPCServer outputs a custom configuration as a base64-encoded
	// JSON structure represented by the GRPCServerConfig config structure.
	type GRPCServer struct {
	// Plugins are the list of plugins to serve.
	Plugins map[string]Plugin
	
	// Server is the actual server that will accept connections. This
	// will be used for plugin registration as well.
	Server func([]grpc.ServerOption) *grpc.Server
	
	// TLS should be the TLS configuration if available. If this is nil,
	// the connection will not have transport security.
	TLS *tls.Config
	
	// DoneCh is the channel that is closed when this server has exited.
	DoneCh chan struct{}
	
	// Stdout/StderrLis are the readers for stdout/stderr that will be copied
	// to the stdout/stderr connection that is output.
	Stdout io.Reader
	Stderr io.Reader
	
	config      GRPCServerConfig
	server      *grpc.Server
	broker      *GRPCBroker
	stdioServer *grpcStdioServer
	
	logger hclog.Logger
	
	muxer *grpcmux.GRPCServerMuxer
	}
	
	// ServerProtocol impl.
	func (s *GRPCServer) Init() error {
	// Create our server
	var opts []grpc.ServerOption
	if s.TLS != nil {
	opts = append(opts, grpc.Creds(credentials.NewTLS(s.TLS)))
	}
	s.server = s.Server(opts)
	
	// Register the health service
	healthCheck := health.NewServer()
	healthCheck.SetServingStatus(
	GRPCServiceName, grpc_health_v1.HealthCheckResponse_SERVING)
	grpc_health_v1.RegisterHealthServer(s.server, healthCheck)
	
	// Register the reflection service
	reflection.Register(s.server)
	
	// Register the broker service
	brokerServer := newGRPCBrokerServer()
	plugin.RegisterGRPCBrokerServer(s.server, brokerServer)
	s.broker = newGRPCBroker(brokerServer, s.TLS, unixSocketConfigFromEnv(), nil, s.muxer)
	go s.broker.Run()
	
	// Register the controller
	controllerServer := &grpcControllerServer{server: s}
	plugin.RegisterGRPCControllerServer(s.server, controllerServer)
	
	// Register the stdio service
	s.stdioServer = newGRPCStdioServer(s.logger, s.Stdout, s.Stderr)
	plugin.RegisterGRPCStdioServer(s.server, s.stdioServer)
	
	// Register all our plugins onto the gRPC server.
	for k, raw := range s.Plugins {
	p, ok := raw.(GRPCPlugin)
	if !ok {
	return fmt.Errorf("%q is not a GRPC-compatible plugin", k)
	}
	
	if err := p.GRPCServer(s.broker, s.server); err != nil {
	return fmt.Errorf("error registering %q: %s", k, err)
	}
	}
	
	return nil
	}
	
	// Stop calls Stop on the underlying grpc.Server and Close on the underlying
	// grpc.Broker if present.
	func (s *GRPCServer) Stop() {
	s.server.Stop()
	
	if s.broker != nil {
	s.broker.Close()
	s.broker = nil
	}
	}
	
	// GracefulStop calls GracefulStop on the underlying grpc.Server and Close on
	// the underlying grpc.Broker if present.
	func (s *GRPCServer) GracefulStop() {
	s.server.GracefulStop()
	
	if s.broker != nil {
	s.broker.Close()
	s.broker = nil
	}
	}
	
	// Config is the GRPCServerConfig encoded as JSON then base64.
	func (s *GRPCServer) Config() string {
	// Create a buffer that will contain our final contents
	var buf bytes.Buffer
	
	// Wrap the base64 encoding with JSON encoding.
	if err := json.NewEncoder(&buf).Encode(s.config); err != nil {
	// We panic since ths shouldn't happen under any scenario. We
	// carefully control the structure being encoded here and it should
	// always be successful.
	panic(err)
	}
	
	return buf.String()
	}
	
	func (s *GRPCServer) Serve(lis net.Listener) {
	defer close(s.DoneCh)
	err := s.server.Serve(lis)
	if err != nil {
	s.logger.Error("grpc server", "error", err)
	}
	}
	
	// GRPCServerConfig is the extra configuration passed along for consumers
	// to facilitate using GRPC plugins.
	type GRPCServerConfig struct {
	StdoutAddr string `json:"stdout_addr"`
	StderrAddr string `json:"stderr_addr"`
	}

github.com/hashicorp/go-plugin/grpc_stdio.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"bufio"
	"bytes"
	"context"
	"io"
	
	empty "github.com/golang/protobuf/ptypes/empty"
	hclog "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/go-plugin/internal/plugin"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	)
	
	// grpcStdioBuffer is the buffer size we try to fill when sending a chunk of
	// stdio data. This is currently 1 KB for no reason other than that seems like
	// enough (stdio data isn't that common) and is fairly low.
	const grpcStdioBuffer = 1 * 1024
	
	// grpcStdioServer implements the Stdio service and streams stdiout/stderr.
	type grpcStdioServer struct {
	stdoutCh <-chan []byte
	stderrCh <-chan []byte
	}
	
	// newGRPCStdioServer creates a new grpcStdioServer and starts the stream
	// copying for the given out and err readers.
	//
	// This must only be called ONCE per srcOut, srcErr.
	func newGRPCStdioServer(log hclog.Logger, srcOut, srcErr io.Reader) *grpcStdioServer {
	stdoutCh := make(chan []byte)
	stderrCh := make(chan []byte)
	
	// Begin copying the streams
	go copyChan(log, stdoutCh, srcOut)
	go copyChan(log, stderrCh, srcErr)
	
	// Construct our server
	return &grpcStdioServer{
	stdoutCh: stdoutCh,
	stderrCh: stderrCh,
	}
	}
	
	// StreamStdio streams our stdout/err as the response.
	func (s *grpcStdioServer) StreamStdio(
	_ *empty.Empty,
	srv plugin.GRPCStdio_StreamStdioServer,
	) error {
	// Share the same data value between runs. Sending this over the wire
	// marshals it so we can reuse this.
	var data plugin.StdioData
	
	for {
	// Read our data
	select {
	case data.Data = <-s.stdoutCh:
	data.Channel = plugin.StdioData_STDOUT
	
	case data.Data = <-s.stderrCh:
	data.Channel = plugin.StdioData_STDERR
	
	case <-srv.Context().Done():
	return nil
	}
	
	// Not sure if this is possible, but if we somehow got here and
	// we didn't populate any data at all, then just continue.
	if len(data.Data) == 0 {
	continue
	}
	
	// Send our data to the client.
	if err := srv.Send(&data); err != nil {
	return err
	}
	}
	}
	
	// grpcStdioClient wraps the stdio service as a client to copy
	// the stdio data to output writers.
	type grpcStdioClient struct {
	log         hclog.Logger
	stdioClient plugin.GRPCStdio_StreamStdioClient
	}
	
	// newGRPCStdioClient creates a grpcStdioClient. This will perform the
	// initial connection to the stdio service. If the stdio service is unavailable
	// then this will be a no-op. This allows this to work without error for
	// plugins that don't support this.
	func newGRPCStdioClient(
	ctx context.Context,
	log hclog.Logger,
	conn *grpc.ClientConn,
	) (*grpcStdioClient, error) {
	client := plugin.NewGRPCStdioClient(conn)
	
	// Connect immediately to the endpoint
	stdioClient, err := client.StreamStdio(ctx, &empty.Empty{})
	
	// If we get an Unavailable or Unimplemented error, this means that the plugin isn't
	// updated and linking to the latest version of go-plugin that supports
	// this. We fall back to the previous behavior of just not syncing anything.
	if status.Code(err) == codes.Unavailable || status.Code(err) == codes.Unimplemented {
	log.Warn("stdio service not available, stdout/stderr syncing unavailable")
	stdioClient = nil
	err = nil
	}
	if err != nil {
	return nil, err
	}
	
	return &grpcStdioClient{
	log:         log,
	stdioClient: stdioClient,
	}, nil
	}
	
	// Run starts the loop that receives stdio data and writes it to the given
	// writers. This blocks and should be run in a goroutine.
	func (c *grpcStdioClient) Run(stdout, stderr io.Writer) {
	// This will be nil if stdio is not supported by the plugin
	if c.stdioClient == nil {
	c.log.Warn("stdio service unavailable, run will do nothing")
	return
	}
	
	for {
	c.log.Trace("waiting for stdio data")
	data, err := c.stdioClient.Recv()
	if err != nil {
	if err == io.EOF ||
	status.Code(err) == codes.Unavailable ||
	status.Code(err) == codes.Canceled ||
	status.Code(err) == codes.Unimplemented ||
	err == context.Canceled {
	c.log.Debug("received EOF, stopping recv loop", "err", err)
	return
	}
	
	c.log.Error("error receiving data", "err", err)
	return
	}
	
	// Determine our output writer based on channel
	var w io.Writer
	switch data.Channel {
	case plugin.StdioData_STDOUT:
	w = stdout
	
	case plugin.StdioData_STDERR:
	w = stderr
	
	default:
	c.log.Warn("unknown channel, dropping", "channel", data.Channel)
	continue
	}
	
	// Write! In the event of an error we just continue.
	if c.log.IsTrace() {
	c.log.Trace("received data", "channel", data.Channel.String(), "len", len(data.Data))
	}
	if _, err := io.Copy(w, bytes.NewReader(data.Data)); err != nil {
	c.log.Error("failed to copy all bytes", "err", err)
	}
	}
	}
	
	// copyChan copies an io.Reader into a channel.
	func copyChan(log hclog.Logger, dst chan<- []byte, src io.Reader) {
	bufsrc := bufio.NewReader(src)
	
	for {
	// Make our data buffer. We allocate a new one per loop iteration
	// so that we can send it over the channel.
	var data [1024]byte
	
	// Read the data, this will block until data is available
	n, err := bufsrc.Read(data[:])
	
	// We have to check if we have data BEFORE err != nil. The bufio
	// docs guarantee n == 0 on EOF but its better to be safe here.
	if n > 0 {
	// We have data! Send it on the channel. This will block if there
	// is no reader on the other side. We expect that go-plugin will
	// connect immediately to the stdio server to drain this so we want
	// this block to happen for backpressure.
	dst <- data[:n]
	}
	
	// If we hit EOF we're done copying
	if err == io.EOF {
	log.Debug("stdio EOF, exiting copy loop")
	return
	}
	
	// Any other error we just exit the loop. We don't expect there to
	// be errors since our use case for this is reading/writing from
	// a in-process pipe (os.Pipe).
	if err != nil {
	log.Warn("error copying stdio data, stopping copy", "err", err)
	return
	}
	}
	}

github.com/hashicorp/go-plugin/internal/cmdrunner/addr_translator.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package cmdrunner
	
	// addrTranslator implements stateless identity functions, as the host and plugin
	// run in the same context wrt Unix and network addresses.
	type addrTranslator struct{}
	
	func (*addrTranslator) PluginToHost(pluginNet, pluginAddr string) (string, string, error) {
	return pluginNet, pluginAddr, nil
	}
	
	func (*addrTranslator) HostToPlugin(hostNet, hostAddr string) (string, string, error) {
	return hostNet, hostAddr, nil
	}

github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package cmdrunner
	
	import (
	"context"
	"fmt"
	"net"
	"os"
	
	"github.com/hashicorp/go-plugin/runner"
	)
	
	// ReattachFunc returns a function that allows reattaching to a plugin running
	// as a plain process. The process may or may not be a child process.
	func ReattachFunc(pid int, addr net.Addr) runner.ReattachFunc {
	return func() (runner.AttachedRunner, error) {
	p, err := os.FindProcess(pid)
	if err != nil {
	// On Unix systems, FindProcess never returns an error.
	// On Windows, for non-existent pids it returns:
	// os.SyscallError - 'OpenProcess: the paremter is incorrect'
	return nil, ErrProcessNotFound
	}
	
	// Attempt to connect to the addr since on Unix systems FindProcess
	// doesn't actually return an error if it can't find the process.
	conn, err := net.Dial(addr.Network(), addr.String())
	if err != nil {
	p.Kill()
	return nil, ErrProcessNotFound
	}
	conn.Close()
	
	return &CmdAttachedRunner{
	pid:     pid,
	process: p,
	}, nil
	}
	}
	
	// CmdAttachedRunner is mostly a subset of CmdRunner, except the Wait function
	// does not assume the process is a child of the host process, and so uses a
	// different implementation to wait on the process.
	type CmdAttachedRunner struct {
	pid     int
	process *os.Process
	
	addrTranslator
	}
	
	func (c *CmdAttachedRunner) Wait(_ context.Context) error {
	return pidWait(c.pid)
	}
	
	func (c *CmdAttachedRunner) Kill(_ context.Context) error {
	return c.process.Kill()
	}
	
	func (c *CmdAttachedRunner) ID() string {
	return fmt.Sprintf("%d", c.pid)
	}

github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_runner.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package cmdrunner
	
	import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"os/exec"
	
	"github.com/hashicorp/go-hclog"
	"github.com/hashicorp/go-plugin/runner"
	)
	
	var (
	_ runner.Runner = (*CmdRunner)(nil)
	
	// ErrProcessNotFound is returned when a client is instantiated to
	// reattach to an existing process and it isn't found.
	ErrProcessNotFound = errors.New("Reattachment process not found")
	)
	
	const unrecognizedRemotePluginMessage = `This usually means
	the plugin was not compiled for this architecture,
	the plugin is missing dynamic-link libraries necessary to run,
	the plugin is not executable by this process due to file permissions, or
	the plugin failed to negotiate the initial go-plugin protocol handshake
	%s`
	
	// CmdRunner implements the runner.Runner interface. It mostly just passes through
	// to exec.Cmd methods.
	type CmdRunner struct {
	logger hclog.Logger
	cmd    *exec.Cmd
	
	stdout io.ReadCloser
	stderr io.ReadCloser
	
	// Cmd info is persisted early, since the process information will be removed
	// after Kill is called.
	path string
	pid  int
	
	addrTranslator
	}
	
	// NewCmdRunner returns an implementation of runner.Runner for running a plugin
	// as a subprocess. It must be passed a cmd that hasn't yet been started.
	func NewCmdRunner(logger hclog.Logger, cmd *exec.Cmd) (*CmdRunner, error) {
	stdout, err := cmd.StdoutPipe()
	if err != nil {
	return nil, err
	}
	
	stderr, err := cmd.StderrPipe()
	if err != nil {
	return nil, err
	}
	
	return &CmdRunner{
	logger: logger,
	cmd:    cmd,
	stdout: stdout,
	stderr: stderr,
	path:   cmd.Path,
	}, nil
	}
	
	func (c *CmdRunner) Start(_ context.Context) error {
	c.logger.Debug("starting plugin", "path", c.cmd.Path, "args", c.cmd.Args)
	err := c.cmd.Start()
	if err != nil {
	return err
	}
	
	c.pid = c.cmd.Process.Pid
	c.logger.Debug("plugin started", "path", c.path, "pid", c.pid)
	return nil
	}
	
	func (c *CmdRunner) Wait(_ context.Context) error {
	return c.cmd.Wait()
	}
	
	func (c *CmdRunner) Kill(_ context.Context) error {
	if c.cmd.Process != nil {
	err := c.cmd.Process.Kill()
	// Swallow ErrProcessDone, we support calling Kill multiple times.
	if !errors.Is(err, os.ErrProcessDone) {
	return err
	}
	return nil
	}
	
	return nil
	}
	
	func (c *CmdRunner) Stdout() io.ReadCloser {
	return c.stdout
	}
	
	func (c *CmdRunner) Stderr() io.ReadCloser {
	return c.stderr
	}
	
	func (c *CmdRunner) Name() string {
	return c.path
	}
	
	func (c *CmdRunner) ID() string {
	return fmt.Sprintf("%d", c.pid)
	}
	
	// peTypes is a list of Portable Executable (PE) machine types from https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
	// mapped to GOARCH types. It is not comprehensive, and only includes machine types that Go supports.
	var peTypes = map[uint16]string{
	0x14c:  "386",
	0x1c0:  "arm",
	0x6264: "loong64",
	0x8664: "amd64",
	0xaa64: "arm64",
	}
	
	func (c *CmdRunner) Diagnose(_ context.Context) string {
	return fmt.Sprintf(unrecognizedRemotePluginMessage, additionalNotesAboutCommand(c.cmd.Path))
	}

github.com/hashicorp/go-plugin/internal/cmdrunner/notes_unix.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	//go:build !windows
	// +build !windows
	
	package cmdrunner
	
	import (
	"debug/elf"
	"debug/macho"
	"debug/pe"
	"fmt"
	"os"
	"os/user"
	"runtime"
	"strconv"
	"syscall"
	)
	
	// additionalNotesAboutCommand tries to get additional information about a command that might help diagnose
	// why it won't run correctly. It runs as a best effort only.
	func additionalNotesAboutCommand(path string) string {
	notes := ""
	stat, err := os.Stat(path)
	if err != nil {
	return notes
	}
	
	notes += "\nAdditional notes about plugin:\n"
	notes += fmt.Sprintf("  Path: %s\n", path)
	notes += fmt.Sprintf("  Mode: %s\n", stat.Mode())
	statT, ok := stat.Sys().(*syscall.Stat_t)
	if ok {
	currentUsername := "?"
	if u, err := user.LookupId(strconv.FormatUint(uint64(os.Getuid()), 10)); err == nil {
	currentUsername = u.Username
	}
	currentGroup := "?"
	if g, err := user.LookupGroupId(strconv.FormatUint(uint64(os.Getgid()), 10)); err == nil {
	currentGroup = g.Name
	}
	username := "?"
	if u, err := user.LookupId(strconv.FormatUint(uint64(statT.Uid), 10)); err == nil {
	username = u.Username
	}
	group := "?"
	if g, err := user.LookupGroupId(strconv.FormatUint(uint64(statT.Gid), 10)); err == nil {
	group = g.Name
	}
	notes += fmt.Sprintf("  Owner: %d [%s] (current: %d [%s])\n", statT.Uid, username, os.Getuid(), currentUsername)
	notes += fmt.Sprintf("  Group: %d [%s] (current: %d [%s])\n", statT.Gid, group, os.Getgid(), currentGroup)
	}
	
	if elfFile, err := elf.Open(path); err == nil {
	defer elfFile.Close()
	notes += fmt.Sprintf("  ELF architecture: %s (current architecture: %s)\n", elfFile.Machine, runtime.GOARCH)
	} else if machoFile, err := macho.Open(path); err == nil {
	defer machoFile.Close()
	notes += fmt.Sprintf("  MachO architecture: %s (current architecture: %s)\n", machoFile.Cpu, runtime.GOARCH)
	} else if peFile, err := pe.Open(path); err == nil {
	defer peFile.Close()
	machine, ok := peTypes[peFile.Machine]
	if !ok {
	machine = "unknown"
	}
	notes += fmt.Sprintf("  PE architecture: %s (current architecture: %s)\n", machine, runtime.GOARCH)
	}
	return notes
	}

github.com/hashicorp/go-plugin/internal/cmdrunner/notes_windows.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	//go:build windows
	// +build windows
	
	package cmdrunner
	
	import (
	"debug/elf"
	"debug/macho"
	"debug/pe"
	"fmt"
	"os"
	"runtime"
	)
	
	// additionalNotesAboutCommand tries to get additional information about a command that might help diagnose
	// why it won't run correctly. It runs as a best effort only.
	func additionalNotesAboutCommand(path string) string {
	notes := ""
	stat, err := os.Stat(path)
	if err != nil {
	return notes
	}
	
	notes += "\nAdditional notes about plugin:\n"
	notes += fmt.Sprintf("  Path: %s\n", path)
	notes += fmt.Sprintf("  Mode: %s\n", stat.Mode())
	
	if elfFile, err := elf.Open(path); err == nil {
	defer elfFile.Close()
	notes += fmt.Sprintf("  ELF architecture: %s (current architecture: %s)\n", elfFile.Machine, runtime.GOARCH)
	} else if machoFile, err := macho.Open(path); err == nil {
	defer machoFile.Close()
	notes += fmt.Sprintf("  MachO architecture: %s (current architecture: %s)\n", machoFile.Cpu, runtime.GOARCH)
	} else if peFile, err := pe.Open(path); err == nil {
	defer peFile.Close()
	machine, ok := peTypes[peFile.Machine]
	if !ok {
	machine = "unknown"
	}
	notes += fmt.Sprintf("  PE architecture: %s (current architecture: %s)\n", machine, runtime.GOARCH)
	}
	return notes
	}

github.com/hashicorp/go-plugin/internal/cmdrunner/process.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package cmdrunner
	
	import "time"
	
	// pidAlive checks whether a pid is alive.
	func pidAlive(pid int) bool {
	return _pidAlive(pid)
	}
	
	// pidWait blocks for a process to exit.
	func pidWait(pid int) error {
	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()
	
	for range ticker.C {
	if !pidAlive(pid) {
	break
	}
	}
	
	return nil
	}

github.com/hashicorp/go-plugin/internal/cmdrunner/process_posix.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	//go:build !windows
	// +build !windows
	
	package cmdrunner
	
	import (
	"os"
	"syscall"
	)
	
	// _pidAlive tests whether a process is alive or not by sending it Signal 0,
	// since Go otherwise has no way to test this.
	func _pidAlive(pid int) bool {
	proc, err := os.FindProcess(pid)
	if err == nil {
	err = proc.Signal(syscall.Signal(0))
	}
	
	return err == nil
	}

github.com/hashicorp/go-plugin/internal/cmdrunner/process_windows.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package cmdrunner
	
	import (
	"syscall"
	)
	
	const (
	// Weird name but matches the MSDN docs
	exit_STILL_ACTIVE = 259
	
	processDesiredAccess = syscall.STANDARD_RIGHTS_READ |
	syscall.PROCESS_QUERY_INFORMATION |
	syscall.SYNCHRONIZE
	)
	
	// _pidAlive tests whether a process is alive or not
	func _pidAlive(pid int) bool {
	h, err := syscall.OpenProcess(processDesiredAccess, false, uint32(pid))
	if err != nil {
	return false
	}
	defer syscall.CloseHandle(h)
	
	var ec uint32
	if e := syscall.GetExitCodeProcess(h, &ec); e != nil {
	return false
	}
	
	return ec == exit_STILL_ACTIVE
	}

github.com/hashicorp/go-plugin/internal/grpcmux/blocked_client_listener.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package grpcmux
	
	import (
	"io"
	"net"
	
	"github.com/hashicorp/yamux"
	)
	
	var _ net.Listener = (*blockedClientListener)(nil)
	
	// blockedClientListener accepts connections for a specific gRPC broker stream
	// ID on the client (host) side of the connection.
	type blockedClientListener struct {
	session *yamux.Session
	waitCh  chan struct{}
	doneCh  <-chan struct{}
	}
	
	func newBlockedClientListener(session *yamux.Session, doneCh <-chan struct{}) *blockedClientListener {
	return &blockedClientListener{
	waitCh:  make(chan struct{}, 1),
	doneCh:  doneCh,
	session: session,
	}
	}
	
	func (b *blockedClientListener) Accept() (net.Conn, error) {
	select {
	case <-b.waitCh:
	return b.session.Accept()
	case <-b.doneCh:
	return nil, io.EOF
	}
	}
	
	func (b *blockedClientListener) Addr() net.Addr {
	return b.session.Addr()
	}
	
	func (b *blockedClientListener) Close() error {
	// We don't close the session, the client muxer is responsible for that.
	return nil
	}
	
	func (b *blockedClientListener) unblock() {
	b.waitCh <- struct{}{}
	}

github.com/hashicorp/go-plugin/internal/grpcmux/blocked_server_listener.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package grpcmux
	
	import (
	"io"
	"net"
	)
	
	var _ net.Listener = (*blockedServerListener)(nil)
	
	// blockedServerListener accepts connections for a specific gRPC broker stream
	// ID on the server (plugin) side of the connection.
	type blockedServerListener struct {
	addr     net.Addr
	acceptCh chan acceptResult
	doneCh   <-chan struct{}
	}
	
	type acceptResult struct {
	conn net.Conn
	err  error
	}
	
	func newBlockedServerListener(addr net.Addr, doneCh <-chan struct{}) *blockedServerListener {
	return &blockedServerListener{
	addr:     addr,
	acceptCh: make(chan acceptResult),
	doneCh:   doneCh,
	}
	}
	
	func (b *blockedServerListener) Accept() (net.Conn, error) {
	select {
	case accept := <-b.acceptCh:
	return accept.conn, accept.err
	case <-b.doneCh:
	return nil, io.EOF
	}
	}
	
	func (b *blockedServerListener) Addr() net.Addr {
	return b.addr
	}
	
	func (b *blockedServerListener) Close() error {
	return nil
	}

github.com/hashicorp/go-plugin/internal/grpcmux/grpc_client_muxer.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package grpcmux
	
	import (
	"fmt"
	"net"
	"sync"
	
	"github.com/hashicorp/go-hclog"
	"github.com/hashicorp/yamux"
	)
	
	var _ GRPCMuxer = (*GRPCClientMuxer)(nil)
	
	// GRPCClientMuxer implements the client (host) side of the gRPC broker's
	// GRPCMuxer interface for multiplexing multiple gRPC broker connections over
	// a single net.Conn.
	//
	// The client dials the initial net.Conn eagerly, and creates a yamux.Session
	// as the implementation for multiplexing any additional connections.
	//
	// Each net.Listener returned from Listener will block until the client receives
	// a knock that matches its gRPC broker stream ID. There is no default listener
	// on the client, as it is a client for the gRPC broker's control services. (See
	// GRPCServerMuxer for more details).
	type GRPCClientMuxer struct {
	logger  hclog.Logger
	session *yamux.Session
	
	acceptMutex     sync.Mutex
	acceptListeners map[uint32]*blockedClientListener
	}
	
	func NewGRPCClientMuxer(logger hclog.Logger, addr net.Addr) (*GRPCClientMuxer, error) {
	// Eagerly establish the underlying connection as early as possible.
	logger.Debug("making new client mux initial connection", "addr", addr)
	conn, err := net.Dial(addr.Network(), addr.String())
	if err != nil {
	return nil, err
	}
	if tcpConn, ok := conn.(*net.TCPConn); ok {
	// Make sure to set keep alive so that the connection doesn't die
	_ = tcpConn.SetKeepAlive(true)
	}
	
	cfg := yamux.DefaultConfig()
	cfg.Logger = logger.Named("yamux").StandardLogger(&hclog.StandardLoggerOptions{
	InferLevels: true,
	})
	cfg.LogOutput = nil
	sess, err := yamux.Client(conn, cfg)
	if err != nil {
	return nil, err
	}
	
	logger.Debug("client muxer connected", "addr", addr)
	m := &GRPCClientMuxer{
	logger:          logger,
	session:         sess,
	acceptListeners: make(map[uint32]*blockedClientListener),
	}
	
	return m, nil
	}
	
	func (m *GRPCClientMuxer) Enabled() bool {
	return m != nil
	}
	
	func (m *GRPCClientMuxer) Listener(id uint32, doneCh <-chan struct{}) (net.Listener, error) {
	ln := newBlockedClientListener(m.session, doneCh)
	
	m.acceptMutex.Lock()
	m.acceptListeners[id] = ln
	m.acceptMutex.Unlock()
	
	return ln, nil
	}
	
	func (m *GRPCClientMuxer) AcceptKnock(id uint32) error {
	m.acceptMutex.Lock()
	defer m.acceptMutex.Unlock()
	
	ln, ok := m.acceptListeners[id]
	if !ok {
	return fmt.Errorf("no listener for id %d", id)
	}
	ln.unblock()
	return nil
	}
	
	func (m *GRPCClientMuxer) Dial() (net.Conn, error) {
	stream, err := m.session.Open()
	if err != nil {
	return nil, fmt.Errorf("error dialling new client stream: %w", err)
	}
	
	return stream, nil
	}
	
	func (m *GRPCClientMuxer) Close() error {
	return m.session.Close()
	}

github.com/hashicorp/go-plugin/internal/grpcmux/grpc_muxer.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package grpcmux
	
	import (
	"net"
	)
	
	// GRPCMuxer enables multiple implementations of net.Listener to accept
	// connections over a single "main" multiplexed net.Conn, and dial multiple
	// client connections over the same multiplexed net.Conn.
	//
	// The first multiplexed connection is used to serve the gRPC broker's own
	// control services: plugin.GRPCBroker, plugin.GRPCController, plugin.GRPCStdio.
	//
	// Clients must "knock" before dialling, to tell the server side that the
	// next net.Conn should be accepted onto a specific stream ID. The knock is a
	// bidirectional streaming message on the plugin.GRPCBroker service.
	type GRPCMuxer interface {
	// Enabled determines whether multiplexing should be used. It saves users
	// of the interface from having to compare an interface with nil, which
	// is a bit awkward to do correctly.
	Enabled() bool
	
	// Listener returns a multiplexed listener that will wait until AcceptKnock
	// is called with a matching ID before its Accept function returns.
	Listener(id uint32, doneCh <-chan struct{}) (net.Listener, error)
	
	// AcceptKnock unblocks the listener with the matching ID, and returns an
	// error if it hasn't been created yet.
	AcceptKnock(id uint32) error
	
	// Dial makes a new multiplexed client connection. To dial a specific ID,
	// a knock must be sent first.
	Dial() (net.Conn, error)
	
	// Close closes connections and releases any resources associated with the
	// muxer.
	Close() error
	}

github.com/hashicorp/go-plugin/internal/grpcmux/grpc_server_muxer.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package grpcmux
	
	import (
	"errors"
	"fmt"
	"net"
	"sync"
	"time"
	
	"github.com/hashicorp/go-hclog"
	"github.com/hashicorp/yamux"
	)
	
	var _ GRPCMuxer = (*GRPCServerMuxer)(nil)
	var _ net.Listener = (*GRPCServerMuxer)(nil)
	
	// GRPCServerMuxer implements the server (plugin) side of the gRPC broker's
	// GRPCMuxer interface for multiplexing multiple gRPC broker connections over
	// a single net.Conn.
	//
	// The server side needs a listener to serve the gRPC broker's control services,
	// which includes the service we will receive knocks on. That means we always
	// accept the first connection onto a "default" main listener, and if we accept
	// any further connections without receiving a knock first, they are also given
	// to the default listener.
	//
	// When creating additional multiplexed listeners for specific stream IDs, we
	// can't control the order in which gRPC servers will call Accept() on each
	// listener, but we do need to control which gRPC server accepts which connection.
	// As such, each multiplexed listener blocks waiting on a channel. It will be
	// unblocked when a knock is received for the matching stream ID.
	type GRPCServerMuxer struct {
	addr   net.Addr
	logger hclog.Logger
	
	sessionErrCh chan error
	sess         *yamux.Session
	
	knockCh chan uint32
	
	acceptMutex    sync.Mutex
	acceptChannels map[uint32]chan acceptResult
	}
	
	func NewGRPCServerMuxer(logger hclog.Logger, ln net.Listener) *GRPCServerMuxer {
	m := &GRPCServerMuxer{
	addr:   ln.Addr(),
	logger: logger,
	
	sessionErrCh: make(chan error),
	
	knockCh:        make(chan uint32, 1),
	acceptChannels: make(map[uint32]chan acceptResult),
	}
	
	go m.acceptSession(ln)
	
	return m
	}
	
	// acceptSessionAndMuxAccept is responsible for establishing the yamux session,
	// and then kicking off the acceptLoop function.
	func (m *GRPCServerMuxer) acceptSession(ln net.Listener) {
	defer close(m.sessionErrCh)
	
	m.logger.Debug("accepting initial connection", "addr", m.addr)
	conn, err := ln.Accept()
	if err != nil {
	m.sessionErrCh <- err
	return
	}
	
	m.logger.Debug("initial server connection accepted", "addr", m.addr)
	cfg := yamux.DefaultConfig()
	cfg.Logger = m.logger.Named("yamux").StandardLogger(&hclog.StandardLoggerOptions{
	InferLevels: true,
	})
	cfg.LogOutput = nil
	m.sess, err = yamux.Server(conn, cfg)
	if err != nil {
	m.sessionErrCh <- err
	return
	}
	}
	
	func (m *GRPCServerMuxer) session() (*yamux.Session, error) {
	select {
	case err := <-m.sessionErrCh:
	if err != nil {
	return nil, err
	}
	case <-time.After(5 * time.Second):
	return nil, errors.New("timed out waiting for connection to be established")
	}
	
	// Should never happen.
	if m.sess == nil {
	return nil, errors.New("no connection established and no error received")
	}
	
	return m.sess, nil
	}
	
	// Accept accepts all incoming connections and routes them to the correct
	// stream ID based on the most recent knock received.
	func (m *GRPCServerMuxer) Accept() (net.Conn, error) {
	session, err := m.session()
	if err != nil {
	return nil, fmt.Errorf("error establishing yamux session: %w", err)
	}
	
	for {
	conn, acceptErr := session.Accept()
	
	select {
	case id := <-m.knockCh:
	m.acceptMutex.Lock()
	acceptCh, ok := m.acceptChannels[id]
	m.acceptMutex.Unlock()
	
	if !ok {
	if conn != nil {
	_ = conn.Close()
	}
	return nil, fmt.Errorf("received knock on ID %d that doesn't have a listener", id)
	}
	m.logger.Debug("sending conn to brokered listener", "id", id)
	acceptCh <- acceptResult{
	conn: conn,
	err:  acceptErr,
	}
	default:
	m.logger.Debug("sending conn to default listener")
	return conn, acceptErr
	}
	}
	}
	
	func (m *GRPCServerMuxer) Addr() net.Addr {
	return m.addr
	}
	
	func (m *GRPCServerMuxer) Close() error {
	session, err := m.session()
	if err != nil {
	return err
	}
	
	return session.Close()
	}
	
	func (m *GRPCServerMuxer) Enabled() bool {
	return m != nil
	}
	
	func (m *GRPCServerMuxer) Listener(id uint32, doneCh <-chan struct{}) (net.Listener, error) {
	sess, err := m.session()
	if err != nil {
	return nil, err
	}
	
	ln := newBlockedServerListener(sess.Addr(), doneCh)
	m.acceptMutex.Lock()
	m.acceptChannels[id] = ln.acceptCh
	m.acceptMutex.Unlock()
	
	return ln, nil
	}
	
	func (m *GRPCServerMuxer) Dial() (net.Conn, error) {
	sess, err := m.session()
	if err != nil {
	return nil, err
	}
	
	stream, err := sess.OpenStream()
	if err != nil {
	return nil, fmt.Errorf("error dialling new server stream: %w", err)
	}
	
	return stream, nil
	}
	
	func (m *GRPCServerMuxer) AcceptKnock(id uint32) error {
	m.knockCh <- id
	return nil
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_broker.pb.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	// Code generated by protoc-gen-go. DO NOT EDIT.
	// versions:
	// 	protoc-gen-go v1.31.0
	// 	protoc        (unknown)
	// source: internal/plugin/grpc_broker.proto
	
	package plugin
	
	import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
	)
	
	const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
	)
	
	type ConnInfo struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
	
	ServiceId uint32          `protobuf:"varint,1,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"`
	Network   string          `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
	Address   string          `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
	Knock     *ConnInfo_Knock `protobuf:"bytes,4,opt,name=knock,proto3" json:"knock,omitempty"`
	}
	
	func (x *ConnInfo) Reset() {
	*x = ConnInfo{}
	if protoimpl.UnsafeEnabled {
	mi := &file_internal_plugin_grpc_broker_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
	}
	}
	
	func (x *ConnInfo) String() string {
	return protoimpl.X.MessageStringOf(x)
	}
	
	func (*ConnInfo) ProtoMessage() {}
	
	func (x *ConnInfo) ProtoReflect() protoreflect.Message {
	mi := &file_internal_plugin_grpc_broker_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	if ms.LoadMessageInfo() == nil {
	ms.StoreMessageInfo(mi)
	}
	return ms
	}
	return mi.MessageOf(x)
	}
	
	// Deprecated: Use ConnInfo.ProtoReflect.Descriptor instead.
	func (*ConnInfo) Descriptor() ([]byte, []int) {
	return file_internal_plugin_grpc_broker_proto_rawDescGZIP(), []int{0}
	}
	
	func (x *ConnInfo) GetServiceId() uint32 {
	if x != nil {
	return x.ServiceId
	}
	return 0
	}
	
	func (x *ConnInfo) GetNetwork() string {
	if x != nil {
	return x.Network
	}
	return ""
	}
	
	func (x *ConnInfo) GetAddress() string {
	if x != nil {
	return x.Address
	}
	return ""
	}
	
	func (x *ConnInfo) GetKnock() *ConnInfo_Knock {
	if x != nil {
	return x.Knock
	}
	return nil
	}
	
	type ConnInfo_Knock struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
	
	Knock bool   `protobuf:"varint,1,opt,name=knock,proto3" json:"knock,omitempty"`
	Ack   bool   `protobuf:"varint,2,opt,name=ack,proto3" json:"ack,omitempty"`
	Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"`
	}
	
	func (x *ConnInfo_Knock) Reset() {
	*x = ConnInfo_Knock{}
	if protoimpl.UnsafeEnabled {
	mi := &file_internal_plugin_grpc_broker_proto_msgTypes[1]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
	}
	}
	
	func (x *ConnInfo_Knock) String() string {
	return protoimpl.X.MessageStringOf(x)
	}
	
	func (*ConnInfo_Knock) ProtoMessage() {}
	
	func (x *ConnInfo_Knock) ProtoReflect() protoreflect.Message {
	mi := &file_internal_plugin_grpc_broker_proto_msgTypes[1]
	if protoimpl.UnsafeEnabled && x != nil {
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	if ms.LoadMessageInfo() == nil {
	ms.StoreMessageInfo(mi)
	}
	return ms
	}
	return mi.MessageOf(x)
	}
	
	// Deprecated: Use ConnInfo_Knock.ProtoReflect.Descriptor instead.
	func (*ConnInfo_Knock) Descriptor() ([]byte, []int) {
	return file_internal_plugin_grpc_broker_proto_rawDescGZIP(), []int{0, 0}
	}
	
	func (x *ConnInfo_Knock) GetKnock() bool {
	if x != nil {
	return x.Knock
	}
	return false
	}
	
	func (x *ConnInfo_Knock) GetAck() bool {
	if x != nil {
	return x.Ack
	}
	return false
	}
	
	func (x *ConnInfo_Knock) GetError() string {
	if x != nil {
	return x.Error
	}
	return ""
	}
	
	var File_internal_plugin_grpc_broker_proto protoreflect.FileDescriptor
	
	var file_internal_plugin_grpc_broker_proto_rawDesc = []byte{
	0x0a, 0x21, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
	0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x2e, 0x70, 0x72,
	0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x22, 0xd2, 0x01, 0x0a, 0x08,
	0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76,
	0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x65,
	0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f,
	0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
	0x6b, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01,
	0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2c, 0x0a, 0x05, 0x6b,
	0x6e, 0x6f, 0x63, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x6c, 0x75,
	0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4b, 0x6e, 0x6f,
	0x63, 0x6b, 0x52, 0x05, 0x6b, 0x6e, 0x6f, 0x63, 0x6b, 0x1a, 0x45, 0x0a, 0x05, 0x4b, 0x6e, 0x6f,
	0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x6b, 0x6e, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
	0x08, 0x52, 0x05, 0x6b, 0x6e, 0x6f, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x6b, 0x18,
	0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72,
	0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72,
	0x32, 0x43, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x12, 0x35,
	0x0a, 0x0b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x10, 0x2e,
	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x1a,
	0x10, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x49, 0x6e, 0x66,
	0x6f, 0x28, 0x01, 0x30, 0x01, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
	0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
	}
	
	var (
	file_internal_plugin_grpc_broker_proto_rawDescOnce sync.Once
	file_internal_plugin_grpc_broker_proto_rawDescData = file_internal_plugin_grpc_broker_proto_rawDesc
	)
	
	func file_internal_plugin_grpc_broker_proto_rawDescGZIP() []byte {
	file_internal_plugin_grpc_broker_proto_rawDescOnce.Do(func() {
	file_internal_plugin_grpc_broker_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_plugin_grpc_broker_proto_rawDescData)
	})
	return file_internal_plugin_grpc_broker_proto_rawDescData
	}
	
	var file_internal_plugin_grpc_broker_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
	var file_internal_plugin_grpc_broker_proto_goTypes = []interface{}{
	(*ConnInfo)(nil),       // 0: plugin.ConnInfo
	(*ConnInfo_Knock)(nil), // 1: plugin.ConnInfo.Knock
	}
	var file_internal_plugin_grpc_broker_proto_depIdxs = []int32{
	1, // 0: plugin.ConnInfo.knock:type_name -> plugin.ConnInfo.Knock
	0, // 1: plugin.GRPCBroker.StartStream:input_type -> plugin.ConnInfo
	0, // 2: plugin.GRPCBroker.StartStream:output_type -> plugin.ConnInfo
	2, // [2:3] is the sub-list for method output_type
	1, // [1:2] is the sub-list for method input_type
	1, // [1:1] is the sub-list for extension type_name
	1, // [1:1] is the sub-list for extension extendee
	0, // [0:1] is the sub-list for field type_name
	}
	
	func init() { file_internal_plugin_grpc_broker_proto_init() }
	func file_internal_plugin_grpc_broker_proto_init() {
	if File_internal_plugin_grpc_broker_proto != nil {
	return
	}
	if !protoimpl.UnsafeEnabled {
	file_internal_plugin_grpc_broker_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
	switch v := v.(*ConnInfo); i {
	case 0:
	return &v.state
	case 1:
	return &v.sizeCache
	case 2:
	return &v.unknownFields
	default:
	return nil
	}
	}
	file_internal_plugin_grpc_broker_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
	switch v := v.(*ConnInfo_Knock); i {
	case 0:
	return &v.state
	case 1:
	return &v.sizeCache
	case 2:
	return &v.unknownFields
	default:
	return nil
	}
	}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
	File: protoimpl.DescBuilder{
	GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
	RawDescriptor: file_internal_plugin_grpc_broker_proto_rawDesc,
	NumEnums:      0,
	NumMessages:   2,
	NumExtensions: 0,
	NumServices:   1,
	},
	GoTypes:           file_internal_plugin_grpc_broker_proto_goTypes,
	DependencyIndexes: file_internal_plugin_grpc_broker_proto_depIdxs,
	MessageInfos:      file_internal_plugin_grpc_broker_proto_msgTypes,
	}.Build()
	File_internal_plugin_grpc_broker_proto = out.File
	file_internal_plugin_grpc_broker_proto_rawDesc = nil
	file_internal_plugin_grpc_broker_proto_goTypes = nil
	file_internal_plugin_grpc_broker_proto_depIdxs = nil
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_broker.proto:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	syntax = "proto3";
	package plugin;
	option go_package = "./plugin";
	
	message ConnInfo {
	uint32 service_id = 1;
	string network = 2;
	string address = 3;
	message Knock {
	bool knock = 1;
	bool ack = 2;
	string error = 3;
	}
	Knock knock = 4;
	}
	
	service GRPCBroker {
	rpc StartStream(stream ConnInfo) returns (stream ConnInfo);
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_broker_grpc.pb.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
	// versions:
	// - protoc-gen-go-grpc v1.3.0
	// - protoc             (unknown)
	// source: internal/plugin/grpc_broker.proto
	
	package plugin
	
	import (
	context "context"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	)
	
	// This is a compile-time assertion to ensure that this generated file
	// is compatible with the grpc package it is being compiled against.
	// Requires gRPC-Go v1.32.0 or later.
	const _ = grpc.SupportPackageIsVersion7
	
	const (
	GRPCBroker_StartStream_FullMethodName = "/plugin.GRPCBroker/StartStream"
	)
	
	// GRPCBrokerClient is the client API for GRPCBroker service.
	//
	// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
	type GRPCBrokerClient interface {
	StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error)
	}
	
	type gRPCBrokerClient struct {
	cc grpc.ClientConnInterface
	}
	
	func NewGRPCBrokerClient(cc grpc.ClientConnInterface) GRPCBrokerClient {
	return &gRPCBrokerClient{cc}
	}
	
	func (c *gRPCBrokerClient) StartStream(ctx context.Context, opts ...grpc.CallOption) (GRPCBroker_StartStreamClient, error) {
	stream, err := c.cc.NewStream(ctx, &GRPCBroker_ServiceDesc.Streams[0], GRPCBroker_StartStream_FullMethodName, opts...)
	if err != nil {
	return nil, err
	}
	x := &gRPCBrokerStartStreamClient{stream}
	return x, nil
	}
	
	type GRPCBroker_StartStreamClient interface {
	Send(*ConnInfo) error
	Recv() (*ConnInfo, error)
	grpc.ClientStream
	}
	
	type gRPCBrokerStartStreamClient struct {
	grpc.ClientStream
	}
	
	func (x *gRPCBrokerStartStreamClient) Send(m *ConnInfo) error {
	return x.ClientStream.SendMsg(m)
	}
	
	func (x *gRPCBrokerStartStreamClient) Recv() (*ConnInfo, error) {
	m := new(ConnInfo)
	if err := x.ClientStream.RecvMsg(m); err != nil {
	return nil, err
	}
	return m, nil
	}
	
	// GRPCBrokerServer is the server API for GRPCBroker service.
	// All implementations should embed UnimplementedGRPCBrokerServer
	// for forward compatibility
	type GRPCBrokerServer interface {
	StartStream(GRPCBroker_StartStreamServer) error
	}
	
	// UnimplementedGRPCBrokerServer should be embedded to have forward compatible implementations.
	type UnimplementedGRPCBrokerServer struct {
	}
	
	func (UnimplementedGRPCBrokerServer) StartStream(GRPCBroker_StartStreamServer) error {
	return status.Errorf(codes.Unimplemented, "method StartStream not implemented")
	}
	
	// UnsafeGRPCBrokerServer may be embedded to opt out of forward compatibility for this service.
	// Use of this interface is not recommended, as added methods to GRPCBrokerServer will
	// result in compilation errors.
	type UnsafeGRPCBrokerServer interface {
	mustEmbedUnimplementedGRPCBrokerServer()
	}
	
	func RegisterGRPCBrokerServer(s grpc.ServiceRegistrar, srv GRPCBrokerServer) {
	s.RegisterService(&GRPCBroker_ServiceDesc, srv)
	}
	
	func _GRPCBroker_StartStream_Handler(srv interface{}, stream grpc.ServerStream) error {
	return srv.(GRPCBrokerServer).StartStream(&gRPCBrokerStartStreamServer{stream})
	}
	
	type GRPCBroker_StartStreamServer interface {
	Send(*ConnInfo) error
	Recv() (*ConnInfo, error)
	grpc.ServerStream
	}
	
	type gRPCBrokerStartStreamServer struct {
	grpc.ServerStream
	}
	
	func (x *gRPCBrokerStartStreamServer) Send(m *ConnInfo) error {
	return x.ServerStream.SendMsg(m)
	}
	
	func (x *gRPCBrokerStartStreamServer) Recv() (*ConnInfo, error) {
	m := new(ConnInfo)
	if err := x.ServerStream.RecvMsg(m); err != nil {
	return nil, err
	}
	return m, nil
	}
	
	// GRPCBroker_ServiceDesc is the grpc.ServiceDesc for GRPCBroker service.
	// It's only intended for direct use with grpc.RegisterService,
	// and not to be introspected or modified (even as a copy)
	var GRPCBroker_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "plugin.GRPCBroker",
	HandlerType: (*GRPCBrokerServer)(nil),
	Methods:     []grpc.MethodDesc{},
	Streams: []grpc.StreamDesc{
	{
	StreamName:    "StartStream",
	Handler:       _GRPCBroker_StartStream_Handler,
	ServerStreams: true,
	ClientStreams: true,
	},
	},
	Metadata: "internal/plugin/grpc_broker.proto",
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.pb.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	// Code generated by protoc-gen-go. DO NOT EDIT.
	// versions:
	// 	protoc-gen-go v1.31.0
	// 	protoc        (unknown)
	// source: internal/plugin/grpc_controller.proto
	
	package plugin
	
	import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
	)
	
	const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
	)
	
	type Empty struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
	}
	
	func (x *Empty) Reset() {
	*x = Empty{}
	if protoimpl.UnsafeEnabled {
	mi := &file_internal_plugin_grpc_controller_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
	}
	}
	
	func (x *Empty) String() string {
	return protoimpl.X.MessageStringOf(x)
	}
	
	func (*Empty) ProtoMessage() {}
	
	func (x *Empty) ProtoReflect() protoreflect.Message {
	mi := &file_internal_plugin_grpc_controller_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	if ms.LoadMessageInfo() == nil {
	ms.StoreMessageInfo(mi)
	}
	return ms
	}
	return mi.MessageOf(x)
	}
	
	// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
	func (*Empty) Descriptor() ([]byte, []int) {
	return file_internal_plugin_grpc_controller_proto_rawDescGZIP(), []int{0}
	}
	
	var File_internal_plugin_grpc_controller_proto protoreflect.FileDescriptor
	
	var file_internal_plugin_grpc_controller_proto_rawDesc = []byte{
	0x0a, 0x25, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
	0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
	0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x22,
	0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0x3a, 0x0a, 0x0e, 0x47, 0x52, 0x50, 0x43,
	0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x08, 0x53, 0x68,
	0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x0d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
	0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x45,
	0x6d, 0x70, 0x74, 0x79, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
	}
	
	var (
	file_internal_plugin_grpc_controller_proto_rawDescOnce sync.Once
	file_internal_plugin_grpc_controller_proto_rawDescData = file_internal_plugin_grpc_controller_proto_rawDesc
	)
	
	func file_internal_plugin_grpc_controller_proto_rawDescGZIP() []byte {
	file_internal_plugin_grpc_controller_proto_rawDescOnce.Do(func() {
	file_internal_plugin_grpc_controller_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_plugin_grpc_controller_proto_rawDescData)
	})
	return file_internal_plugin_grpc_controller_proto_rawDescData
	}
	
	var file_internal_plugin_grpc_controller_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
	var file_internal_plugin_grpc_controller_proto_goTypes = []interface{}{
	(*Empty)(nil), // 0: plugin.Empty
	}
	var file_internal_plugin_grpc_controller_proto_depIdxs = []int32{
	0, // 0: plugin.GRPCController.Shutdown:input_type -> plugin.Empty
	0, // 1: plugin.GRPCController.Shutdown:output_type -> plugin.Empty
	1, // [1:2] is the sub-list for method output_type
	0, // [0:1] is the sub-list for method input_type
	0, // [0:0] is the sub-list for extension type_name
	0, // [0:0] is the sub-list for extension extendee
	0, // [0:0] is the sub-list for field type_name
	}
	
	func init() { file_internal_plugin_grpc_controller_proto_init() }
	func file_internal_plugin_grpc_controller_proto_init() {
	if File_internal_plugin_grpc_controller_proto != nil {
	return
	}
	if !protoimpl.UnsafeEnabled {
	file_internal_plugin_grpc_controller_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
	switch v := v.(*Empty); i {
	case 0:
	return &v.state
	case 1:
	return &v.sizeCache
	case 2:
	return &v.unknownFields
	default:
	return nil
	}
	}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
	File: protoimpl.DescBuilder{
	GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
	RawDescriptor: file_internal_plugin_grpc_controller_proto_rawDesc,
	NumEnums:      0,
	NumMessages:   1,
	NumExtensions: 0,
	NumServices:   1,
	},
	GoTypes:           file_internal_plugin_grpc_controller_proto_goTypes,
	DependencyIndexes: file_internal_plugin_grpc_controller_proto_depIdxs,
	MessageInfos:      file_internal_plugin_grpc_controller_proto_msgTypes,
	}.Build()
	File_internal_plugin_grpc_controller_proto = out.File
	file_internal_plugin_grpc_controller_proto_rawDesc = nil
	file_internal_plugin_grpc_controller_proto_goTypes = nil
	file_internal_plugin_grpc_controller_proto_depIdxs = nil
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_controller.proto:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	syntax = "proto3";
	package plugin;
	option go_package = "./plugin";
	
	message Empty {
	}
	
	// The GRPCController is responsible for telling the plugin server to shutdown.
	service GRPCController {
	rpc Shutdown(Empty) returns (Empty);
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_controller_grpc.pb.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
	// versions:
	// - protoc-gen-go-grpc v1.3.0
	// - protoc             (unknown)
	// source: internal/plugin/grpc_controller.proto
	
	package plugin
	
	import (
	context "context"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	)
	
	// This is a compile-time assertion to ensure that this generated file
	// is compatible with the grpc package it is being compiled against.
	// Requires gRPC-Go v1.32.0 or later.
	const _ = grpc.SupportPackageIsVersion7
	
	const (
	GRPCController_Shutdown_FullMethodName = "/plugin.GRPCController/Shutdown"
	)
	
	// GRPCControllerClient is the client API for GRPCController service.
	//
	// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
	type GRPCControllerClient interface {
	Shutdown(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
	}
	
	type gRPCControllerClient struct {
	cc grpc.ClientConnInterface
	}
	
	func NewGRPCControllerClient(cc grpc.ClientConnInterface) GRPCControllerClient {
	return &gRPCControllerClient{cc}
	}
	
	func (c *gRPCControllerClient) Shutdown(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
	out := new(Empty)
	err := c.cc.Invoke(ctx, GRPCController_Shutdown_FullMethodName, in, out, opts...)
	if err != nil {
	return nil, err
	}
	return out, nil
	}
	
	// GRPCControllerServer is the server API for GRPCController service.
	// All implementations should embed UnimplementedGRPCControllerServer
	// for forward compatibility
	type GRPCControllerServer interface {
	Shutdown(context.Context, *Empty) (*Empty, error)
	}
	
	// UnimplementedGRPCControllerServer should be embedded to have forward compatible implementations.
	type UnimplementedGRPCControllerServer struct {
	}
	
	func (UnimplementedGRPCControllerServer) Shutdown(context.Context, *Empty) (*Empty, error) {
	return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented")
	}
	
	// UnsafeGRPCControllerServer may be embedded to opt out of forward compatibility for this service.
	// Use of this interface is not recommended, as added methods to GRPCControllerServer will
	// result in compilation errors.
	type UnsafeGRPCControllerServer interface {
	mustEmbedUnimplementedGRPCControllerServer()
	}
	
	func RegisterGRPCControllerServer(s grpc.ServiceRegistrar, srv GRPCControllerServer) {
	s.RegisterService(&GRPCController_ServiceDesc, srv)
	}
	
	func _GRPCController_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(Empty)
	if err := dec(in); err != nil {
	return nil, err
	}
	if interceptor == nil {
	return srv.(GRPCControllerServer).Shutdown(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
	Server:     srv,
	FullMethod: GRPCController_Shutdown_FullMethodName,
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
	return srv.(GRPCControllerServer).Shutdown(ctx, req.(*Empty))
	}
	return interceptor(ctx, in, info, handler)
	}
	
	// GRPCController_ServiceDesc is the grpc.ServiceDesc for GRPCController service.
	// It's only intended for direct use with grpc.RegisterService,
	// and not to be introspected or modified (even as a copy)
	var GRPCController_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "plugin.GRPCController",
	HandlerType: (*GRPCControllerServer)(nil),
	Methods: []grpc.MethodDesc{
	{
	MethodName: "Shutdown",
	Handler:    _GRPCController_Shutdown_Handler,
	},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "internal/plugin/grpc_controller.proto",
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_stdio.pb.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	// Code generated by protoc-gen-go. DO NOT EDIT.
	// versions:
	// 	protoc-gen-go v1.31.0
	// 	protoc        (unknown)
	// source: internal/plugin/grpc_stdio.proto
	
	package plugin
	
	import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
	reflect "reflect"
	sync "sync"
	)
	
	const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
	)
	
	type StdioData_Channel int32
	
	const (
	StdioData_INVALID StdioData_Channel = 0
	StdioData_STDOUT  StdioData_Channel = 1
	StdioData_STDERR  StdioData_Channel = 2
	)
	
	// Enum value maps for StdioData_Channel.
	var (
	StdioData_Channel_name = map[int32]string{
	0: "INVALID",
	1: "STDOUT",
	2: "STDERR",
	}
	StdioData_Channel_value = map[string]int32{
	"INVALID": 0,
	"STDOUT":  1,
	"STDERR":  2,
	}
	)
	
	func (x StdioData_Channel) Enum() *StdioData_Channel {
	p := new(StdioData_Channel)
	*p = x
	return p
	}
	
	func (x StdioData_Channel) String() string {
	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
	}
	
	func (StdioData_Channel) Descriptor() protoreflect.EnumDescriptor {
	return file_internal_plugin_grpc_stdio_proto_enumTypes[0].Descriptor()
	}
	
	func (StdioData_Channel) Type() protoreflect.EnumType {
	return &file_internal_plugin_grpc_stdio_proto_enumTypes[0]
	}
	
	func (x StdioData_Channel) Number() protoreflect.EnumNumber {
	return protoreflect.EnumNumber(x)
	}
	
	// Deprecated: Use StdioData_Channel.Descriptor instead.
	func (StdioData_Channel) EnumDescriptor() ([]byte, []int) {
	return file_internal_plugin_grpc_stdio_proto_rawDescGZIP(), []int{0, 0}
	}
	
	// StdioData is a single chunk of stdout or stderr data that is streamed
	// from GRPCStdio.
	type StdioData struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields
	
	Channel StdioData_Channel `protobuf:"varint,1,opt,name=channel,proto3,enum=plugin.StdioData_Channel" json:"channel,omitempty"`
	Data    []byte            `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
	}
	
	func (x *StdioData) Reset() {
	*x = StdioData{}
	if protoimpl.UnsafeEnabled {
	mi := &file_internal_plugin_grpc_stdio_proto_msgTypes[0]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)
	}
	}
	
	func (x *StdioData) String() string {
	return protoimpl.X.MessageStringOf(x)
	}
	
	func (*StdioData) ProtoMessage() {}
	
	func (x *StdioData) ProtoReflect() protoreflect.Message {
	mi := &file_internal_plugin_grpc_stdio_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	if ms.LoadMessageInfo() == nil {
	ms.StoreMessageInfo(mi)
	}
	return ms
	}
	return mi.MessageOf(x)
	}
	
	// Deprecated: Use StdioData.ProtoReflect.Descriptor instead.
	func (*StdioData) Descriptor() ([]byte, []int) {
	return file_internal_plugin_grpc_stdio_proto_rawDescGZIP(), []int{0}
	}
	
	func (x *StdioData) GetChannel() StdioData_Channel {
	if x != nil {
	return x.Channel
	}
	return StdioData_INVALID
	}
	
	func (x *StdioData) GetData() []byte {
	if x != nil {
	return x.Data
	}
	return nil
	}
	
	var File_internal_plugin_grpc_stdio_proto protoreflect.FileDescriptor
	
	var file_internal_plugin_grpc_stdio_proto_rawDesc = []byte{
	0x0a, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
	0x6e, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x74, 0x64, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f,
	0x74, 0x6f, 0x12, 0x06, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67,
	0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74,
	0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x84, 0x01, 0x0a, 0x09, 0x53, 0x74, 0x64, 0x69,
	0x6f, 0x44, 0x61, 0x74, 0x61, 0x12, 0x33, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c,
	0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
	0x53, 0x74, 0x64, 0x69, 0x6f, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65,
	0x6c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61,
	0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x2e,
	0x0a, 0x07, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x56,
	0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x44, 0x4f, 0x55, 0x54,
	0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x44, 0x45, 0x52, 0x52, 0x10, 0x02, 0x32, 0x47,
	0x0a, 0x09, 0x47, 0x52, 0x50, 0x43, 0x53, 0x74, 0x64, 0x69, 0x6f, 0x12, 0x3a, 0x0a, 0x0b, 0x53,
	0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x74, 0x64, 0x69, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f,
	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70,
	0x74, 0x79, 0x1a, 0x11, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x64, 0x69,
	0x6f, 0x44, 0x61, 0x74, 0x61, 0x30, 0x01, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x70, 0x6c, 0x75,
	0x67, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
	}
	
	var (
	file_internal_plugin_grpc_stdio_proto_rawDescOnce sync.Once
	file_internal_plugin_grpc_stdio_proto_rawDescData = file_internal_plugin_grpc_stdio_proto_rawDesc
	)
	
	func file_internal_plugin_grpc_stdio_proto_rawDescGZIP() []byte {
	file_internal_plugin_grpc_stdio_proto_rawDescOnce.Do(func() {
	file_internal_plugin_grpc_stdio_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_plugin_grpc_stdio_proto_rawDescData)
	})
	return file_internal_plugin_grpc_stdio_proto_rawDescData
	}
	
	var file_internal_plugin_grpc_stdio_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
	var file_internal_plugin_grpc_stdio_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
	var file_internal_plugin_grpc_stdio_proto_goTypes = []interface{}{
	(StdioData_Channel)(0), // 0: plugin.StdioData.Channel
	(*StdioData)(nil),      // 1: plugin.StdioData
	(*emptypb.Empty)(nil),  // 2: google.protobuf.Empty
	}
	var file_internal_plugin_grpc_stdio_proto_depIdxs = []int32{
	0, // 0: plugin.StdioData.channel:type_name -> plugin.StdioData.Channel
	2, // 1: plugin.GRPCStdio.StreamStdio:input_type -> google.protobuf.Empty
	1, // 2: plugin.GRPCStdio.StreamStdio:output_type -> plugin.StdioData
	2, // [2:3] is the sub-list for method output_type
	1, // [1:2] is the sub-list for method input_type
	1, // [1:1] is the sub-list for extension type_name
	1, // [1:1] is the sub-list for extension extendee
	0, // [0:1] is the sub-list for field type_name
	}
	
	func init() { file_internal_plugin_grpc_stdio_proto_init() }
	func file_internal_plugin_grpc_stdio_proto_init() {
	if File_internal_plugin_grpc_stdio_proto != nil {
	return
	}
	if !protoimpl.UnsafeEnabled {
	file_internal_plugin_grpc_stdio_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
	switch v := v.(*StdioData); i {
	case 0:
	return &v.state
	case 1:
	return &v.sizeCache
	case 2:
	return &v.unknownFields
	default:
	return nil
	}
	}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
	File: protoimpl.DescBuilder{
	GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
	RawDescriptor: file_internal_plugin_grpc_stdio_proto_rawDesc,
	NumEnums:      1,
	NumMessages:   1,
	NumExtensions: 0,
	NumServices:   1,
	},
	GoTypes:           file_internal_plugin_grpc_stdio_proto_goTypes,
	DependencyIndexes: file_internal_plugin_grpc_stdio_proto_depIdxs,
	EnumInfos:         file_internal_plugin_grpc_stdio_proto_enumTypes,
	MessageInfos:      file_internal_plugin_grpc_stdio_proto_msgTypes,
	}.Build()
	File_internal_plugin_grpc_stdio_proto = out.File
	file_internal_plugin_grpc_stdio_proto_rawDesc = nil
	file_internal_plugin_grpc_stdio_proto_goTypes = nil
	file_internal_plugin_grpc_stdio_proto_depIdxs = nil
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_stdio.proto:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	syntax = "proto3";
	package plugin;
	option go_package = "./plugin";
	
	import "google/protobuf/empty.proto";
	
	// GRPCStdio is a service that is automatically run by the plugin process
	// to stream any stdout/err data so that it can be mirrored on the plugin
	// host side.
	service GRPCStdio {
	// StreamStdio returns a stream that contains all the stdout/stderr.
	// This RPC endpoint must only be called ONCE. Once stdio data is consumed
	// it is not sent again.
	//
	// Callers should connect early to prevent blocking on the plugin process.
	rpc StreamStdio(google.protobuf.Empty) returns (stream StdioData);
	}
	
	// StdioData is a single chunk of stdout or stderr data that is streamed
	// from GRPCStdio.
	message StdioData {
	enum Channel {
	INVALID = 0;
	STDOUT = 1;
	STDERR = 2;
	}
	
	Channel channel = 1;
	bytes data = 2;
	}

github.com/hashicorp/go-plugin/internal/plugin/grpc_stdio_grpc.pb.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
	// versions:
	// - protoc-gen-go-grpc v1.3.0
	// - protoc             (unknown)
	// source: internal/plugin/grpc_stdio.proto
	
	package plugin
	
	import (
	context "context"
	grpc "google.golang.org/grpc"
	codes "google.golang.org/grpc/codes"
	status "google.golang.org/grpc/status"
	emptypb "google.golang.org/protobuf/types/known/emptypb"
	)
	
	// This is a compile-time assertion to ensure that this generated file
	// is compatible with the grpc package it is being compiled against.
	// Requires gRPC-Go v1.32.0 or later.
	const _ = grpc.SupportPackageIsVersion7
	
	const (
	GRPCStdio_StreamStdio_FullMethodName = "/plugin.GRPCStdio/StreamStdio"
	)
	
	// GRPCStdioClient is the client API for GRPCStdio service.
	//
	// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
	type GRPCStdioClient interface {
	// StreamStdio returns a stream that contains all the stdout/stderr.
	// This RPC endpoint must only be called ONCE. Once stdio data is consumed
	// it is not sent again.
	//
	// Callers should connect early to prevent blocking on the plugin process.
	StreamStdio(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (GRPCStdio_StreamStdioClient, error)
	}
	
	type gRPCStdioClient struct {
	cc grpc.ClientConnInterface
	}
	
	func NewGRPCStdioClient(cc grpc.ClientConnInterface) GRPCStdioClient {
	return &gRPCStdioClient{cc}
	}
	
	func (c *gRPCStdioClient) StreamStdio(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (GRPCStdio_StreamStdioClient, error) {
	stream, err := c.cc.NewStream(ctx, &GRPCStdio_ServiceDesc.Streams[0], GRPCStdio_StreamStdio_FullMethodName, opts...)
	if err != nil {
	return nil, err
	}
	x := &gRPCStdioStreamStdioClient{stream}
	if err := x.ClientStream.SendMsg(in); err != nil {
	return nil, err
	}
	if err := x.ClientStream.CloseSend(); err != nil {
	return nil, err
	}
	return x, nil
	}
	
	type GRPCStdio_StreamStdioClient interface {
	Recv() (*StdioData, error)
	grpc.ClientStream
	}
	
	type gRPCStdioStreamStdioClient struct {
	grpc.ClientStream
	}
	
	func (x *gRPCStdioStreamStdioClient) Recv() (*StdioData, error) {
	m := new(StdioData)
	if err := x.ClientStream.RecvMsg(m); err != nil {
	return nil, err
	}
	return m, nil
	}
	
	// GRPCStdioServer is the server API for GRPCStdio service.
	// All implementations should embed UnimplementedGRPCStdioServer
	// for forward compatibility
	type GRPCStdioServer interface {
	// StreamStdio returns a stream that contains all the stdout/stderr.
	// This RPC endpoint must only be called ONCE. Once stdio data is consumed
	// it is not sent again.
	//
	// Callers should connect early to prevent blocking on the plugin process.
	StreamStdio(*emptypb.Empty, GRPCStdio_StreamStdioServer) error
	}
	
	// UnimplementedGRPCStdioServer should be embedded to have forward compatible implementations.
	type UnimplementedGRPCStdioServer struct {
	}
	
	func (UnimplementedGRPCStdioServer) StreamStdio(*emptypb.Empty, GRPCStdio_StreamStdioServer) error {
	return status.Errorf(codes.Unimplemented, "method StreamStdio not implemented")
	}
	
	// UnsafeGRPCStdioServer may be embedded to opt out of forward compatibility for this service.
	// Use of this interface is not recommended, as added methods to GRPCStdioServer will
	// result in compilation errors.
	type UnsafeGRPCStdioServer interface {
	mustEmbedUnimplementedGRPCStdioServer()
	}
	
	func RegisterGRPCStdioServer(s grpc.ServiceRegistrar, srv GRPCStdioServer) {
	s.RegisterService(&GRPCStdio_ServiceDesc, srv)
	}
	
	func _GRPCStdio_StreamStdio_Handler(srv interface{}, stream grpc.ServerStream) error {
	m := new(emptypb.Empty)
	if err := stream.RecvMsg(m); err != nil {
	return err
	}
	return srv.(GRPCStdioServer).StreamStdio(m, &gRPCStdioStreamStdioServer{stream})
	}
	
	type GRPCStdio_StreamStdioServer interface {
	Send(*StdioData) error
	grpc.ServerStream
	}
	
	type gRPCStdioStreamStdioServer struct {
	grpc.ServerStream
	}
	
	func (x *gRPCStdioStreamStdioServer) Send(m *StdioData) error {
	return x.ServerStream.SendMsg(m)
	}
	
	// GRPCStdio_ServiceDesc is the grpc.ServiceDesc for GRPCStdio service.
	// It's only intended for direct use with grpc.RegisterService,
	// and not to be introspected or modified (even as a copy)
	var GRPCStdio_ServiceDesc = grpc.ServiceDesc{
	ServiceName: "plugin.GRPCStdio",
	HandlerType: (*GRPCStdioServer)(nil),
	Methods:     []grpc.MethodDesc{},
	Streams: []grpc.StreamDesc{
	{
	StreamName:    "StreamStdio",
	Handler:       _GRPCStdio_StreamStdio_Handler,
	ServerStreams: true,
	},
	},
	Metadata: "internal/plugin/grpc_stdio.proto",
	}

github.com/hashicorp/go-plugin/log_entry.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"encoding/json"
	"time"
	)
	
	// logEntry is the JSON payload that gets sent to Stderr from the plugin to the host
	type logEntry struct {
	Message   string        `json:"@message"`
	Level     string        `json:"@level"`
	Timestamp time.Time     `json:"timestamp"`
	KVPairs   []*logEntryKV `json:"kv_pairs"`
	}
	
	// logEntryKV is a key value pair within the Output payload
	type logEntryKV struct {
	Key   string      `json:"key"`
	Value interface{} `json:"value"`
	}
	
	// flattenKVPairs is used to flatten KVPair slice into []interface{}
	// for hclog consumption.
	func flattenKVPairs(kvs []*logEntryKV) []interface{} {
	var result []interface{}
	for _, kv := range kvs {
	result = append(result, kv.Key)
	result = append(result, kv.Value)
	}
	
	return result
	}
	
	// parseJSON handles parsing JSON output
	func parseJSON(input []byte) (*logEntry, error) {
	var raw map[string]interface{}
	entry := &logEntry{}
	
	err := json.Unmarshal(input, &raw)
	if err != nil {
	return nil, err
	}
	
	// Parse hclog-specific objects
	if v, ok := raw["@message"]; ok {
	entry.Message = v.(string)
	delete(raw, "@message")
	}
	
	if v, ok := raw["@level"]; ok {
	entry.Level = v.(string)
	delete(raw, "@level")
	}
	
	if v, ok := raw["@timestamp"]; ok {
	t, err := time.Parse("2006-01-02T15:04:05.000000Z07:00", v.(string))
	if err != nil {
	return nil, err
	}
	entry.Timestamp = t
	delete(raw, "@timestamp")
	}
	
	// Parse dynamic KV args from the hclog payload.
	for k, v := range raw {
	entry.KVPairs = append(entry.KVPairs, &logEntryKV{
	Key:   k,
	Value: v,
	})
	}
	
	return entry, nil
	}

github.com/hashicorp/go-plugin/mtls.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"bytes"
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"math/big"
	"time"
	)
	
	// generateCert generates a temporary certificate for plugin authentication. The
	// certificate and private key are returns in PEM format.
	func generateCert() (cert []byte, privateKey []byte, err error) {
	key, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
	if err != nil {
	return nil, nil, err
	}
	
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	sn, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
	return nil, nil, err
	}
	
	host := "localhost"
	
	template := &x509.Certificate{
	Subject: pkix.Name{
	CommonName:   host,
	Organization: []string{"HashiCorp"},
	},
	DNSNames: []string{host},
	ExtKeyUsage: []x509.ExtKeyUsage{
	x509.ExtKeyUsageClientAuth,
	x509.ExtKeyUsageServerAuth,
	},
	KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement | x509.KeyUsageCertSign,
	BasicConstraintsValid: true,
	SerialNumber:          sn,
	NotBefore:             time.Now().Add(-30 * time.Second),
	NotAfter:              time.Now().Add(262980 * time.Hour),
	IsCA:                  true,
	}
	
	der, err := x509.CreateCertificate(rand.Reader, template, template, key.Public(), key)
	if err != nil {
	return nil, nil, err
	}
	
	var certOut bytes.Buffer
	if err := pem.Encode(&certOut, &pem.Block{Type: "CERTIFICATE", Bytes: der}); err != nil {
	return nil, nil, err
	}
	
	keyBytes, err := x509.MarshalECPrivateKey(key)
	if err != nil {
	return nil, nil, err
	}
	
	var keyOut bytes.Buffer
	if err := pem.Encode(&keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}); err != nil {
	return nil, nil, err
	}
	
	cert = certOut.Bytes()
	privateKey = keyOut.Bytes()
	
	return cert, privateKey, nil
	}

github.com/hashicorp/go-plugin/mux_broker.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"encoding/binary"
	"fmt"
	"log"
	"net"
	"sync"
	"sync/atomic"
	"time"
	
	"github.com/hashicorp/yamux"
	)
	
	// MuxBroker is responsible for brokering multiplexed connections by unique ID.
	//
	// It is used by plugins to multiplex multiple RPC connections and data
	// streams on top of a single connection between the plugin process and the
	// host process.
	//
	// This allows a plugin to request a channel with a specific ID to connect to
	// or accept a connection from, and the broker handles the details of
	// holding these channels open while they're being negotiated.
	//
	// The Plugin interface has access to these for both Server and Client.
	// The broker can be used by either (optionally) to reserve and connect to
	// new multiplexed streams. This is useful for complex args and return values,
	// or anything else you might need a data stream for.
	type MuxBroker struct {
	nextId  uint32
	session *yamux.Session
	streams map[uint32]*muxBrokerPending
	
	sync.Mutex
	}
	
	type muxBrokerPending struct {
	ch     chan net.Conn
	doneCh chan struct{}
	}
	
	func newMuxBroker(s *yamux.Session) *MuxBroker {
	return &MuxBroker{
	session: s,
	streams: make(map[uint32]*muxBrokerPending),
	}
	}
	
	// Accept accepts a connection by ID.
	//
	// This should not be called multiple times with the same ID at one time.
	func (m *MuxBroker) Accept(id uint32) (net.Conn, error) {
	var c net.Conn
	p := m.getStream(id)
	select {
	case c = <-p.ch:
	close(p.doneCh)
	case <-time.After(5 * time.Second):
	m.Lock()
	defer m.Unlock()
	delete(m.streams, id)
	
	return nil, fmt.Errorf("timeout waiting for accept")
	}
	
	// Ack our connection
	if err := binary.Write(c, binary.LittleEndian, id); err != nil {
	c.Close()
	return nil, err
	}
	
	return c, nil
	}
	
	// AcceptAndServe is used to accept a specific stream ID and immediately
	// serve an RPC server on that stream ID. This is used to easily serve
	// complex arguments.
	//
	// The served interface is always registered to the "Plugin" name.
	func (m *MuxBroker) AcceptAndServe(id uint32, v interface{}) {
	conn, err := m.Accept(id)
	if err != nil {
	log.Printf("[ERR] plugin: plugin acceptAndServe error: %s", err)
	return
	}
	
	serve(conn, "Plugin", v)
	}
	
	// Close closes the connection and all sub-connections.
	func (m *MuxBroker) Close() error {
	return m.session.Close()
	}
	
	// Dial opens a connection by ID.
	func (m *MuxBroker) Dial(id uint32) (net.Conn, error) {
	// Open the stream
	stream, err := m.session.OpenStream()
	if err != nil {
	return nil, err
	}
	
	// Write the stream ID onto the wire.
	if err := binary.Write(stream, binary.LittleEndian, id); err != nil {
	stream.Close()
	return nil, err
	}
	
	// Read the ack that we connected. Then we're off!
	var ack uint32
	if err := binary.Read(stream, binary.LittleEndian, &ack); err != nil {
	stream.Close()
	return nil, err
	}
	if ack != id {
	stream.Close()
	return nil, fmt.Errorf("bad ack: %d (expected %d)", ack, id)
	}
	
	return stream, nil
	}
	
	// NextId returns a unique ID to use next.
	//
	// It is possible for very long-running plugin hosts to wrap this value,
	// though it would require a very large amount of RPC calls. In practice
	// we've never seen it happen.
	func (m *MuxBroker) NextId() uint32 {
	return atomic.AddUint32(&m.nextId, 1)
	}
	
	// Run starts the brokering and should be executed in a goroutine, since it
	// blocks forever, or until the session closes.
	//
	// Uses of MuxBroker never need to call this. It is called internally by
	// the plugin host/client.
	func (m *MuxBroker) Run() {
	for {
	stream, err := m.session.AcceptStream()
	if err != nil {
	// Once we receive an error, just exit
	break
	}
	
	// Read the stream ID from the stream
	var id uint32
	if err := binary.Read(stream, binary.LittleEndian, &id); err != nil {
	stream.Close()
	continue
	}
	
	// Initialize the waiter
	p := m.getStream(id)
	select {
	case p.ch <- stream:
	default:
	}
	
	// Wait for a timeout
	go m.timeoutWait(id, p)
	}
	}
	
	func (m *MuxBroker) getStream(id uint32) *muxBrokerPending {
	m.Lock()
	defer m.Unlock()
	
	p, ok := m.streams[id]
	if ok {
	return p
	}
	
	m.streams[id] = &muxBrokerPending{
	ch:     make(chan net.Conn, 1),
	doneCh: make(chan struct{}),
	}
	return m.streams[id]
	}
	
	func (m *MuxBroker) timeoutWait(id uint32, p *muxBrokerPending) {
	// Wait for the stream to either be picked up and connected, or
	// for a timeout.
	timeout := false
	select {
	case <-p.doneCh:
	case <-time.After(5 * time.Second):
	timeout = true
	}
	
	m.Lock()
	defer m.Unlock()
	
	// Delete the stream so no one else can grab it
	delete(m.streams, id)
	
	// If we timed out, then check if we have a channel in the buffer,
	// and if so, close it.
	if timeout {
	select {
	case s := <-p.ch:
	s.Close()
	}
	}
	}

github.com/hashicorp/go-plugin/plugin.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	// The plugin package exposes functions and helpers for communicating to
	// plugins which are implemented as standalone binary applications.
	//
	// plugin.Client fully manages the lifecycle of executing the application,
	// connecting to it, and returning the RPC client for dispensing plugins.
	//
	// plugin.Serve fully manages listeners to expose an RPC server from a binary
	// that plugin.Client can connect to.
	package plugin
	
	import (
	"context"
	"errors"
	"net/rpc"
	
	"google.golang.org/grpc"
	)
	
	// Plugin is the interface that is implemented to serve/connect to an
	// inteface implementation.
	type Plugin interface {
	// Server should return the RPC server compatible struct to serve
	// the methods that the Client calls over net/rpc.
	Server(*MuxBroker) (interface{}, error)
	
	// Client returns an interface implementation for the plugin you're
	// serving that communicates to the server end of the plugin.
	Client(*MuxBroker, *rpc.Client) (interface{}, error)
	}
	
	// GRPCPlugin is the interface that is implemented to serve/connect to
	// a plugin over gRPC.
	type GRPCPlugin interface {
	// GRPCServer should register this plugin for serving with the
	// given GRPCServer. Unlike Plugin.Server, this is only called once
	// since gRPC plugins serve singletons.
	GRPCServer(*GRPCBroker, *grpc.Server) error
	
	// GRPCClient should return the interface implementation for the plugin
	// you're serving via gRPC. The provided context will be canceled by
	// go-plugin in the event of the plugin process exiting.
	GRPCClient(context.Context, *GRPCBroker, *grpc.ClientConn) (interface{}, error)
	}
	
	// NetRPCUnsupportedPlugin implements Plugin but returns errors for the
	// Server and Client functions. This will effectively disable support for
	// net/rpc based plugins.
	//
	// This struct can be embedded in your struct.
	type NetRPCUnsupportedPlugin struct{}
	
	func (p NetRPCUnsupportedPlugin) Server(*MuxBroker) (interface{}, error) {
	return nil, errors.New("net/rpc plugin protocol not supported")
	}
	
	func (p NetRPCUnsupportedPlugin) Client(*MuxBroker, *rpc.Client) (interface{}, error) {
	return nil, errors.New("net/rpc plugin protocol not supported")
	}

github.com/hashicorp/go-plugin/process.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin

github.com/hashicorp/go-plugin/protocol.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"io"
	"net"
	)
	
	// Protocol is an enum representing the types of protocols.
	type Protocol string
	
	const (
	ProtocolInvalid Protocol = ""
	ProtocolNetRPC  Protocol = "netrpc"
	ProtocolGRPC    Protocol = "grpc"
	)
	
	// ServerProtocol is an interface that must be implemented for new plugin
	// protocols to be servers.
	type ServerProtocol interface {
	// Init is called once to configure and initialize the protocol, but
	// not start listening. This is the point at which all validation should
	// be done and errors returned.
	Init() error
	
	// Config is extra configuration to be outputted to stdout. This will
	// be automatically base64 encoded to ensure it can be parsed properly.
	// This can be an empty string if additional configuration is not needed.
	Config() string
	
	// Serve is called to serve connections on the given listener. This should
	// continue until the listener is closed.
	Serve(net.Listener)
	}
	
	// ClientProtocol is an interface that must be implemented for new plugin
	// protocols to be clients.
	type ClientProtocol interface {
	io.Closer
	
	// Dispense dispenses a new instance of the plugin with the given name.
	Dispense(string) (interface{}, error)
	
	// Ping checks that the client connection is still healthy.
	Ping() error
	}

github.com/hashicorp/go-plugin/rpc_client.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/rpc"
	
	"github.com/hashicorp/yamux"
	)
	
	// RPCClient connects to an RPCServer over net/rpc to dispense plugin types.
	type RPCClient struct {
	broker  *MuxBroker
	control *rpc.Client
	plugins map[string]Plugin
	
	// These are the streams used for the various stdout/err overrides
	stdout, stderr net.Conn
	}
	
	// newRPCClient creates a new RPCClient. The Client argument is expected
	// to be successfully started already with a lock held.
	func newRPCClient(c *Client) (*RPCClient, error) {
	// Connect to the client
	conn, err := net.Dial(c.address.Network(), c.address.String())
	if err != nil {
	return nil, err
	}
	if tcpConn, ok := conn.(*net.TCPConn); ok {
	// Make sure to set keep alive so that the connection doesn't die
	tcpConn.SetKeepAlive(true)
	}
	
	if c.config.TLSConfig != nil {
	conn = tls.Client(conn, c.config.TLSConfig)
	}
	
	// Create the actual RPC client
	result, err := NewRPCClient(conn, c.config.Plugins)
	if err != nil {
	conn.Close()
	return nil, err
	}
	
	// Begin the stream syncing so that stdin, out, err work properly
	err = result.SyncStreams(
	c.config.SyncStdout,
	c.config.SyncStderr)
	if err != nil {
	result.Close()
	return nil, err
	}
	
	return result, nil
	}
	
	// NewRPCClient creates a client from an already-open connection-like value.
	// Dial is typically used instead.
	func NewRPCClient(conn io.ReadWriteCloser, plugins map[string]Plugin) (*RPCClient, error) {
	// Create the yamux client so we can multiplex
	mux, err := yamux.Client(conn, nil)
	if err != nil {
	conn.Close()
	return nil, err
	}
	
	// Connect to the control stream.
	control, err := mux.Open()
	if err != nil {
	mux.Close()
	return nil, err
	}
	
	// Connect stdout, stderr streams
	stdstream := make([]net.Conn, 2)
	for i, _ := range stdstream {
	stdstream[i], err = mux.Open()
	if err != nil {
	mux.Close()
	return nil, err
	}
	}
	
	// Create the broker and start it up
	broker := newMuxBroker(mux)
	go broker.Run()
	
	// Build the client using our broker and control channel.
	return &RPCClient{
	broker:  broker,
	control: rpc.NewClient(control),
	plugins: plugins,
	stdout:  stdstream[0],
	stderr:  stdstream[1],
	}, nil
	}
	
	// SyncStreams should be called to enable syncing of stdout,
	// stderr with the plugin.
	//
	// This will return immediately and the syncing will continue to happen
	// in the background. You do not need to launch this in a goroutine itself.
	//
	// This should never be called multiple times.
	func (c *RPCClient) SyncStreams(stdout io.Writer, stderr io.Writer) error {
	go copyStream("stdout", stdout, c.stdout)
	go copyStream("stderr", stderr, c.stderr)
	return nil
	}
	
	// Close closes the connection. The client is no longer usable after this
	// is called.
	func (c *RPCClient) Close() error {
	// Call the control channel and ask it to gracefully exit. If this
	// errors, then we save it so that we always return an error but we
	// want to try to close the other channels anyways.
	var empty struct{}
	returnErr := c.control.Call("Control.Quit", true, &empty)
	
	// Close the other streams we have
	if err := c.control.Close(); err != nil {
	return err
	}
	if err := c.stdout.Close(); err != nil {
	return err
	}
	if err := c.stderr.Close(); err != nil {
	return err
	}
	if err := c.broker.Close(); err != nil {
	return err
	}
	
	// Return back the error we got from Control.Quit. This is very important
	// since we MUST return non-nil error if this fails so that Client.Kill
	// will properly try a process.Kill.
	return returnErr
	}
	
	func (c *RPCClient) Dispense(name string) (interface{}, error) {
	p, ok := c.plugins[name]
	if !ok {
	return nil, fmt.Errorf("unknown plugin type: %s", name)
	}
	
	var id uint32
	if err := c.control.Call(
	"Dispenser.Dispense", name, &id); err != nil {
	return nil, err
	}
	
	conn, err := c.broker.Dial(id)
	if err != nil {
	return nil, err
	}
	
	return p.Client(c.broker, rpc.NewClient(conn))
	}
	
	// Ping pings the connection to ensure it is still alive.
	//
	// The error from the RPC call is returned exactly if you want to inspect
	// it for further error analysis. Any error returned from here would indicate
	// that the connection to the plugin is not healthy.
	func (c *RPCClient) Ping() error {
	var empty struct{}
	return c.control.Call("Control.Ping", true, &empty)
	}

github.com/hashicorp/go-plugin/rpc_server.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"net/rpc"
	"sync"
	
	"github.com/hashicorp/yamux"
	)
	
	// RPCServer listens for network connections and then dispenses interface
	// implementations over net/rpc.
	//
	// After setting the fields below, they shouldn't be read again directly
	// from the structure which may be reading/writing them concurrently.
	type RPCServer struct {
	Plugins map[string]Plugin
	
	// Stdout, Stderr are what this server will use instead of the
	// normal stdin/out/err. This is because due to the multi-process nature
	// of our plugin system, we can't use the normal process values so we
	// make our own custom one we pipe across.
	Stdout io.Reader
	Stderr io.Reader
	
	// DoneCh should be set to a non-nil channel that will be closed
	// when the control requests the RPC server to end.
	DoneCh chan<- struct{}
	
	lock sync.Mutex
	}
	
	// ServerProtocol impl.
	func (s *RPCServer) Init() error { return nil }
	
	// ServerProtocol impl.
	func (s *RPCServer) Config() string { return "" }
	
	// ServerProtocol impl.
	func (s *RPCServer) Serve(lis net.Listener) {
	defer s.done()
	
	for {
	conn, err := lis.Accept()
	if err != nil {
	severity := "ERR"
	if errors.Is(err, net.ErrClosed) {
	severity = "DEBUG"
	}
	log.Printf("[%s] plugin: plugin server: %s", severity, err)
	return
	}
	
	go s.ServeConn(conn)
	}
	}
	
	// ServeConn runs a single connection.
	//
	// ServeConn blocks, serving the connection until the client hangs up.
	func (s *RPCServer) ServeConn(conn io.ReadWriteCloser) {
	// First create the yamux server to wrap this connection
	mux, err := yamux.Server(conn, nil)
	if err != nil {
	conn.Close()
	log.Printf("[ERR] plugin: error creating yamux server: %s", err)
	return
	}
	
	// Accept the control connection
	control, err := mux.Accept()
	if err != nil {
	mux.Close()
	if err != io.EOF {
	log.Printf("[ERR] plugin: error accepting control connection: %s", err)
	}
	
	return
	}
	
	// Connect the stdstreams (in, out, err)
	stdstream := make([]net.Conn, 2)
	for i := range stdstream {
	stdstream[i], err = mux.Accept()
	if err != nil {
	mux.Close()
	log.Printf("[ERR] plugin: accepting stream %d: %s", i, err)
	return
	}
	}
	
	// Copy std streams out to the proper place
	go copyStream("stdout", stdstream[0], s.Stdout)
	go copyStream("stderr", stdstream[1], s.Stderr)
	
	// Create the broker and start it up
	broker := newMuxBroker(mux)
	go broker.Run()
	
	// Use the control connection to build the dispenser and serve the
	// connection.
	server := rpc.NewServer()
	server.RegisterName("Control", &controlServer{
	server: s,
	})
	server.RegisterName("Dispenser", &dispenseServer{
	broker:  broker,
	plugins: s.Plugins,
	})
	server.ServeConn(control)
	}
	
	// done is called internally by the control server to trigger the
	// doneCh to close which is listened to by the main process to cleanly
	// exit.
	func (s *RPCServer) done() {
	s.lock.Lock()
	defer s.lock.Unlock()
	
	if s.DoneCh != nil {
	close(s.DoneCh)
	s.DoneCh = nil
	}
	}
	
	// dispenseServer dispenses variousinterface implementations for Terraform.
	type controlServer struct {
	server *RPCServer
	}
	
	// Ping can be called to verify the connection (and likely the binary)
	// is still alive to a plugin.
	func (c *controlServer) Ping(
	null bool, response *struct{},
	) error {
	*response = struct{}{}
	return nil
	}
	
	func (c *controlServer) Quit(
	null bool, response *struct{},
	) error {
	// End the server
	c.server.done()
	
	// Always return true
	*response = struct{}{}
	
	return nil
	}
	
	// dispenseServer dispenses variousinterface implementations for Terraform.
	type dispenseServer struct {
	broker  *MuxBroker
	plugins map[string]Plugin
	}
	
	func (d *dispenseServer) Dispense(
	name string, response *uint32,
	) error {
	// Find the function to create this implementation
	p, ok := d.plugins[name]
	if !ok {
	return fmt.Errorf("unknown plugin type: %s", name)
	}
	
	// Create the implementation first so we know if there is an error.
	impl, err := p.Server(d.broker)
	if err != nil {
	// We turn the error into an errors error so that it works across RPC
	return errors.New(err.Error())
	}
	
	// Reserve an ID for our implementation
	id := d.broker.NextId()
	*response = id
	
	// Run the rest in a goroutine since it can only happen once this RPC
	// call returns. We wait for a connection for the plugin implementation
	// and serve it.
	go func() {
	conn, err := d.broker.Accept(id)
	if err != nil {
	log.Printf("[ERR] go-plugin: plugin dispense error: %s: %s", name, err)
	return
	}
	
	serve(conn, "Plugin", impl)
	}()
	
	return nil
	}
	
	func serve(conn io.ReadWriteCloser, name string, v interface{}) {
	server := rpc.NewServer()
	if err := server.RegisterName(name, v); err != nil {
	log.Printf("[ERR] go-plugin: plugin dispense error: %s", err)
	return
	}
	
	server.ServeConn(conn)
	}

github.com/hashicorp/go-plugin/runner/runner.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package runner
	
	import (
	"context"
	"io"
	)
	
	// Runner defines the interface required by go-plugin to manage the lifecycle of
	// of a plugin and attempt to negotiate a connection with it. Note that this
	// is orthogonal to the protocol and transport used, which is negotiated over stdout.
	type Runner interface {
	// Start should start the plugin and ensure any work required for servicing
	// other interface methods is done. If the context is cancelled, it should
	// only abort any attempts to _start_ the plugin. Waiting and shutdown are
	// handled separately.
	Start(ctx context.Context) error
	
	// Diagnose makes a best-effort attempt to return any debug information that
	// might help users understand why a plugin failed to start and negotiate a
	// connection.
	Diagnose(ctx context.Context) string
	
	// Stdout is used to negotiate the go-plugin protocol.
	Stdout() io.ReadCloser
	
	// Stderr is used for forwarding plugin logs to the host process logger.
	Stderr() io.ReadCloser
	
	// Name is a human-friendly name for the plugin, such as the path to the
	// executable. It does not have to be unique.
	Name() string
	
	AttachedRunner
	}
	
	// AttachedRunner defines a limited subset of Runner's interface to represent the
	// reduced responsibility for plugin lifecycle when attaching to an already running
	// plugin.
	type AttachedRunner interface {
	// Wait should wait until the plugin stops running, whether in response to
	// an out of band signal or in response to calling Kill().
	Wait(ctx context.Context) error
	
	// Kill should stop the plugin and perform any cleanup required.
	Kill(ctx context.Context) error
	
	// ID is a unique identifier to represent the running plugin. e.g. pid or
	// container ID.
	ID() string
	
	AddrTranslator
	}
	
	// AddrTranslator translates addresses between the execution context of the host
	// process and the plugin. For example, if the plugin is in a container, the file
	// path for a Unix socket may be different between the host and the container.
	//
	// It is only intended to be used by the host process.
	type AddrTranslator interface {
	// Called before connecting on any addresses received back from the plugin.
	PluginToHost(pluginNet, pluginAddr string) (hostNet string, hostAddr string, err error)
	
	// Called on any host process addresses before they are sent to the plugin.
	HostToPlugin(hostNet, hostAddr string) (pluginNet string, pluginAddr string, err error)
	}
	
	// ReattachFunc can be passed to a client's reattach config to reattach to an
	// already running plugin instead of starting it ourselves.
	type ReattachFunc func() (AttachedRunner, error)

github.com/hashicorp/go-plugin/server.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/base64"
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"os/signal"
	"os/user"
	"runtime"
	"sort"
	"strconv"
	"strings"
	
	hclog "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/go-plugin/internal/grpcmux"
	"google.golang.org/grpc"
	)
	
	// CoreProtocolVersion is the ProtocolVersion of the plugin system itself.
	// We will increment this whenever we change any protocol behavior. This
	// will invalidate any prior plugins but will at least allow us to iterate
	// on the core in a safe way. We will do our best to do this very
	// infrequently.
	const CoreProtocolVersion = 1
	
	// HandshakeConfig is the configuration used by client and servers to
	// handshake before starting a plugin connection. This is embedded by
	// both ServeConfig and ClientConfig.
	//
	// In practice, the plugin host creates a HandshakeConfig that is exported
	// and plugins then can easily consume it.
	type HandshakeConfig struct {
	// ProtocolVersion is the version that clients must match on to
	// agree they can communicate. This should match the ProtocolVersion
	// set on ClientConfig when using a plugin.
	// This field is not required if VersionedPlugins are being used in the
	// Client or Server configurations.
	ProtocolVersion uint
	
	// MagicCookieKey and value are used as a very basic verification
	// that a plugin is intended to be launched. This is not a security
	// measure, just a UX feature. If the magic cookie doesn't match,
	// we show human-friendly output.
	MagicCookieKey   string
	MagicCookieValue string
	}
	
	// PluginSet is a set of plugins provided to be registered in the plugin
	// server.
	type PluginSet map[string]Plugin
	
	// ServeConfig configures what sorts of plugins are served.
	type ServeConfig struct {
	// HandshakeConfig is the configuration that must match clients.
	HandshakeConfig
	
	// TLSProvider is a function that returns a configured tls.Config.
	TLSProvider func() (*tls.Config, error)
	
	// Plugins are the plugins that are served.
	// The implied version of this PluginSet is the Handshake.ProtocolVersion.
	Plugins PluginSet
	
	// VersionedPlugins is a map of PluginSets for specific protocol versions.
	// These can be used to negotiate a compatible version between client and
	// server. If this is set, Handshake.ProtocolVersion is not required.
	VersionedPlugins map[int]PluginSet
	
	// GRPCServer should be non-nil to enable serving the plugins over
	// gRPC. This is a function to create the server when needed with the
	// given server options. The server options populated by go-plugin will
	// be for TLS if set. You may modify the input slice.
	//
	// Note that the grpc.Server will automatically be registered with
	// the gRPC health checking service. This is not optional since go-plugin
	// relies on this to implement Ping().
	GRPCServer func([]grpc.ServerOption) *grpc.Server
	
	// Logger is used to pass a logger into the server. If none is provided the
	// server will create a default logger.
	Logger hclog.Logger
	
	// Test, if non-nil, will put plugin serving into "test mode". This is
	// meant to be used as part of `go test` within a plugin's codebase to
	// launch the plugin in-process and output a ReattachConfig.
	//
	// This changes the behavior of the server in a number of ways to
	// accomodate the expectation of running in-process:
	//
	//   * The handshake cookie is not validated.
	//   * Stdout/stderr will receive plugin reads and writes
	//   * Connection information will not be sent to stdout
	//
	Test *ServeTestConfig
	}
	
	// ServeTestConfig configures plugin serving for test mode. See ServeConfig.Test.
	type ServeTestConfig struct {
	// Context, if set, will force the plugin serving to end when cancelled.
	// This is only a test configuration because the non-test configuration
	// expects to take over the process and therefore end on an interrupt or
	// kill signal. For tests, we need to kill the plugin serving routinely
	// and this provides a way to do so.
	//
	// If you want to wait for the plugin process to close before moving on,
	// you can wait on CloseCh.
	Context context.Context
	
	// If this channel is non-nil, we will send the ReattachConfig via
	// this channel. This can be encoded (via JSON recommended) to the
	// plugin client to attach to this plugin.
	ReattachConfigCh chan<- *ReattachConfig
	
	// CloseCh, if non-nil, will be closed when serving exits. This can be
	// used along with Context to determine when the server is fully shut down.
	// If this is not set, you can still use Context on its own, but note there
	// may be a period of time between canceling the context and the plugin
	// server being shut down.
	CloseCh chan<- struct{}
	
	// SyncStdio, if true, will enable the client side "SyncStdout/Stderr"
	// functionality to work. This defaults to false because the implementation
	// of making this work within test environments is particularly messy
	// and SyncStdio functionality is fairly rare, so we default to the simple
	// scenario.
	SyncStdio bool
	}
	
	func unixSocketConfigFromEnv() UnixSocketConfig {
	return UnixSocketConfig{
	Group:     os.Getenv(EnvUnixSocketGroup),
	socketDir: os.Getenv(EnvUnixSocketDir),
	}
	}
	
	// protocolVersion determines the protocol version and plugin set to be used by
	// the server. In the event that there is no suitable version, the last version
	// in the config is returned leaving the client to report the incompatibility.
	func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
	protoVersion := int(opts.ProtocolVersion)
	pluginSet := opts.Plugins
	protoType := ProtocolNetRPC
	// Check if the client sent a list of acceptable versions
	var clientVersions []int
	if vs := os.Getenv("PLUGIN_PROTOCOL_VERSIONS"); vs != "" {
	for _, s := range strings.Split(vs, ",") {
	v, err := strconv.Atoi(s)
	if err != nil {
	fmt.Fprintf(os.Stderr, "server sent invalid plugin version %q", s)
	continue
	}
	clientVersions = append(clientVersions, v)
	}
	}
	
	// We want to iterate in reverse order, to ensure we match the newest
	// compatible plugin version.
	sort.Sort(sort.Reverse(sort.IntSlice(clientVersions)))
	
	// set the old un-versioned fields as if they were versioned plugins
	if opts.VersionedPlugins == nil {
	opts.VersionedPlugins = make(map[int]PluginSet)
	}
	
	if pluginSet != nil {
	opts.VersionedPlugins[protoVersion] = pluginSet
	}
	
	// Sort the version to make sure we match the latest first
	var versions []int
	for v := range opts.VersionedPlugins {
	versions = append(versions, v)
	}
	
	sort.Sort(sort.Reverse(sort.IntSlice(versions)))
	
	// See if we have multiple versions of Plugins to choose from
	for _, version := range versions {
	// Record each version, since we guarantee that this returns valid
	// values even if they are not a protocol match.
	protoVersion = version
	pluginSet = opts.VersionedPlugins[version]
	
	// If we have a configured gRPC server we should select a protocol
	if opts.GRPCServer != nil {
	// All plugins in a set must use the same transport, so check the first
	// for the protocol type
	for _, p := range pluginSet {
	switch p.(type) {
	case GRPCPlugin:
	protoType = ProtocolGRPC
	default:
	protoType = ProtocolNetRPC
	}
	break
	}
	}
	
	for _, clientVersion := range clientVersions {
	if clientVersion == protoVersion {
	return protoVersion, protoType, pluginSet
	}
	}
	}
	
	// Return the lowest version as the fallback.
	// Since we iterated over all the versions in reverse order above, these
	// values are from the lowest version number plugins (which may be from
	// a combination of the Handshake.ProtocolVersion and ServeConfig.Plugins
	// fields). This allows serving the oldest version of our plugins to a
	// legacy client that did not send a PLUGIN_PROTOCOL_VERSIONS list.
	return protoVersion, protoType, pluginSet
	}
	
	// Serve serves the plugins given by ServeConfig.
	//
	// Serve doesn't return until the plugin is done being executed. Any
	// fixable errors will be output to os.Stderr and the process will
	// exit with a status code of 1. Serve will panic for unexpected
	// conditions where a user's fix is unknown.
	//
	// This is the method that plugins should call in their main() functions.
	func Serve(opts *ServeConfig) {
	exitCode := -1
	// We use this to trigger an `os.Exit` so that we can execute our other
	// deferred functions. In test mode, we just output the err to stderr
	// and return.
	defer func() {
	if opts.Test == nil && exitCode >= 0 {
	os.Exit(exitCode)
	}
	
	if opts.Test != nil && opts.Test.CloseCh != nil {
	close(opts.Test.CloseCh)
	}
	}()
	
	if opts.Test == nil {
	// Validate the handshake config
	if opts.MagicCookieKey == "" || opts.MagicCookieValue == "" {
	fmt.Fprintf(os.Stderr,
	"Misconfigured ServeConfig given to serve this plugin: no magic cookie\n"+
	"key or value was set. Please notify the plugin author and report\n"+
	"this as a bug.\n")
	exitCode = 1
	return
	}
	
	// First check the cookie
	if os.Getenv(opts.MagicCookieKey) != opts.MagicCookieValue {
	fmt.Fprintf(os.Stderr,
	"This binary is a plugin. These are not meant to be executed directly.\n"+
	"Please execute the program that consumes these plugins, which will\n"+
	"load any plugins automatically\n")
	exitCode = 1
	return
	}
	}
	
	// negotiate the version and plugins
	// start with default version in the handshake config
	protoVersion, protoType, pluginSet := protocolVersion(opts)
	
	logger := opts.Logger
	if logger == nil {
	// internal logger to os.Stderr
	logger = hclog.New(&hclog.LoggerOptions{
	Level:      hclog.Trace,
	Output:     os.Stderr,
	JSONFormat: true,
	})
	}
	
	// Register a listener so we can accept a connection
	listener, err := serverListener(unixSocketConfigFromEnv())
	if err != nil {
	logger.Error("plugin init error", "error", err)
	return
	}
	
	// Close the listener on return. We wrap this in a func() on purpose
	// because the "listener" reference may change to TLS.
	defer func() {
	listener.Close()
	}()
	
	var tlsConfig *tls.Config
	if opts.TLSProvider != nil {
	tlsConfig, err = opts.TLSProvider()
	if err != nil {
	logger.Error("plugin tls init", "error", err)
	return
	}
	}
	
	var serverCert string
	clientCert := os.Getenv("PLUGIN_CLIENT_CERT")
	// If the client is configured using AutoMTLS, the certificate will be here,
	// and we need to generate our own in response.
	if tlsConfig == nil && clientCert != "" {
	logger.Info("configuring server automatic mTLS")
	clientCertPool := x509.NewCertPool()
	if !clientCertPool.AppendCertsFromPEM([]byte(clientCert)) {
	logger.Error("client cert provided but failed to parse", "cert", clientCert)
	}
	
	certPEM, keyPEM, err := generateCert()
	if err != nil {
	logger.Error("failed to generate server certificate", "error", err)
	panic(err)
	}
	
	cert, err := tls.X509KeyPair(certPEM, keyPEM)
	if err != nil {
	logger.Error("failed to parse server certificate", "error", err)
	panic(err)
	}
	
	tlsConfig = &tls.Config{
	Certificates: []tls.Certificate{cert},
	ClientAuth:   tls.RequireAndVerifyClientCert,
	ClientCAs:    clientCertPool,
	MinVersion:   tls.VersionTLS12,
	RootCAs:      clientCertPool,
	ServerName:   "localhost",
	}
	
	// We send back the raw leaf cert data for the client rather than the
	// PEM, since the protocol can't handle newlines.
	serverCert = base64.RawStdEncoding.EncodeToString(cert.Certificate[0])
	}
	
	// Create the channel to tell us when we're done
	doneCh := make(chan struct{})
	
	// Create our new stdout, stderr files. These will override our built-in
	// stdout/stderr so that it works across the stream boundary.
	var stdout_r, stderr_r io.Reader
	stdout_r, stdout_w, err := os.Pipe()
	if err != nil {
	fmt.Fprintf(os.Stderr, "Error preparing plugin: %s\n", err)
	os.Exit(1)
	}
	stderr_r, stderr_w, err := os.Pipe()
	if err != nil {
	fmt.Fprintf(os.Stderr, "Error preparing plugin: %s\n", err)
	os.Exit(1)
	}
	
	// If we're in test mode, we tee off the reader and write the data
	// as-is to our normal Stdout and Stderr so that they continue working
	// while stdio works. This is because in test mode, we assume we're running
	// in `go test` or some equivalent and we want output to go to standard
	// locations.
	if opts.Test != nil {
	// TODO(mitchellh): This isn't super ideal because a TeeReader
	// only works if the reader side is actively read. If we never
	// connect via a plugin client, the output still gets swallowed.
	stdout_r = io.TeeReader(stdout_r, os.Stdout)
	stderr_r = io.TeeReader(stderr_r, os.Stderr)
	}
	
	// Build the server type
	var server ServerProtocol
	switch protoType {
	case ProtocolNetRPC:
	// If we have a TLS configuration then we wrap the listener
	// ourselves and do it at that level.
	if tlsConfig != nil {
	listener = tls.NewListener(listener, tlsConfig)
	}
	
	// Create the RPC server to dispense
	server = &RPCServer{
	Plugins: pluginSet,
	Stdout:  stdout_r,
	Stderr:  stderr_r,
	DoneCh:  doneCh,
	}
	
	case ProtocolGRPC:
	var muxer *grpcmux.GRPCServerMuxer
	if multiplex, _ := strconv.ParseBool(os.Getenv(envMultiplexGRPC)); multiplex {
	muxer = grpcmux.NewGRPCServerMuxer(logger, listener)
	listener = muxer
	}
	
	// Create the gRPC server
	server = &GRPCServer{
	Plugins: pluginSet,
	Server:  opts.GRPCServer,
	TLS:     tlsConfig,
	Stdout:  stdout_r,
	Stderr:  stderr_r,
	DoneCh:  doneCh,
	logger:  logger,
	muxer:   muxer,
	}
	
	default:
	panic("unknown server protocol: " + protoType)
	}
	
	// Initialize the servers
	if err := server.Init(); err != nil {
	logger.Error("protocol init", "error", err)
	return
	}
	
	logger.Debug("plugin address", "network", listener.Addr().Network(), "address", listener.Addr().String())
	
	// Output the address and service name to stdout so that the client can
	// bring it up. In test mode, we don't do this because clients will
	// attach via a reattach config.
	if opts.Test == nil {
	const grpcBrokerMultiplexingSupported = true
	protocolLine := fmt.Sprintf("%d|%d|%s|%s|%s|%s",
	CoreProtocolVersion,
	protoVersion,
	listener.Addr().Network(),
	listener.Addr().String(),
	protoType,
	serverCert)
	
	// Old clients will error with new plugins if we blindly append the
	// seventh segment for gRPC broker multiplexing support, because old
	// client code uses strings.SplitN(line, "|", 6), which means a seventh
	// segment will get appended to the sixth segment as "sixthpart|true".
	//
	// If the environment variable is set, we assume the client is new enough
	// to handle a seventh segment, as it should now use
	// strings.Split(line, "|") and always handle each segment individually.
	if os.Getenv(envMultiplexGRPC) != "" {
	protocolLine += fmt.Sprintf("|%v", grpcBrokerMultiplexingSupported)
	}
	fmt.Printf("%s\n", protocolLine)
	os.Stdout.Sync()
	} else if ch := opts.Test.ReattachConfigCh; ch != nil {
	// Send back the reattach config that can be used. This isn't
	// quite ready if they connect immediately but the client should
	// retry a few times.
	ch <- &ReattachConfig{
	Protocol:        protoType,
	ProtocolVersion: protoVersion,
	Addr:            listener.Addr(),
	Pid:             os.Getpid(),
	Test:            true,
	}
	}
	
	// Eat the interrupts. In test mode we disable this so that go test
	// can be cancelled properly.
	if opts.Test == nil {
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt)
	go func() {
	count := 0
	for {
	<-ch
	count++
	logger.Trace("plugin received interrupt signal, ignoring", "count", count)
	}
	}()
	}
	
	// Set our stdout, stderr to the stdio stream that clients can retrieve
	// using ClientConfig.SyncStdout/err. We only do this for non-test mode
	// or if the test mode explicitly requests it.
	//
	// In test mode, we use a multiwriter so that the data continues going
	// to the normal stdout/stderr so output can show up in test logs. We
	// also send to the stdio stream so that clients can continue working
	// if they depend on that.
	if opts.Test == nil || opts.Test.SyncStdio {
	if opts.Test != nil {
	// In test mode we need to maintain the original values so we can
	// reset it.
	defer func(out, err *os.File) {
	os.Stdout = out
	os.Stderr = err
	}(os.Stdout, os.Stderr)
	}
	os.Stdout = stdout_w
	os.Stderr = stderr_w
	}
	
	// Accept connections and wait for completion
	go server.Serve(listener)
	
	ctx := context.Background()
	if opts.Test != nil && opts.Test.Context != nil {
	ctx = opts.Test.Context
	}
	select {
	case <-ctx.Done():
	// Cancellation. We can stop the server by closing the listener.
	// This isn't graceful at all but this is currently only used by
	// tests and its our only way to stop.
	listener.Close()
	
	// If this is a grpc server, then we also ask the server itself to
	// end which will kill all connections. There isn't an easy way to do
	// this for net/rpc currently but net/rpc is more and more unused.
	if s, ok := server.(*GRPCServer); ok {
	s.Stop()
	}
	
	// Wait for the server itself to shut down
	<-doneCh
	
	case <-doneCh:
	// Note that given the documentation of Serve we should probably be
	// setting exitCode = 0 and using os.Exit here. That's how it used to
	// work before extracting this library. However, for years we've done
	// this so we'll keep this functionality.
	}
	}
	
	func serverListener(unixSocketCfg UnixSocketConfig) (net.Listener, error) {
	if runtime.GOOS == "windows" {
	return serverListener_tcp()
	}
	
	return serverListener_unix(unixSocketCfg)
	}
	
	func serverListener_tcp() (net.Listener, error) {
	envMinPort := os.Getenv("PLUGIN_MIN_PORT")
	envMaxPort := os.Getenv("PLUGIN_MAX_PORT")
	
	var minPort, maxPort int64
	var err error
	
	switch {
	case len(envMinPort) == 0:
	minPort = 0
	default:
	minPort, err = strconv.ParseInt(envMinPort, 10, 32)
	if err != nil {
	return nil, fmt.Errorf("Couldn't get value from PLUGIN_MIN_PORT: %v", err)
	}
	}
	
	switch {
	case len(envMaxPort) == 0:
	maxPort = 0
	default:
	maxPort, err = strconv.ParseInt(envMaxPort, 10, 32)
	if err != nil {
	return nil, fmt.Errorf("Couldn't get value from PLUGIN_MAX_PORT: %v", err)
	}
	}
	
	if minPort > maxPort {
	return nil, fmt.Errorf("PLUGIN_MIN_PORT value of %d is greater than PLUGIN_MAX_PORT value of %d", minPort, maxPort)
	}
	
	for port := minPort; port <= maxPort; port++ {
	address := fmt.Sprintf("127.0.0.1:%d", port)
	listener, err := net.Listen("tcp", address)
	if err == nil {
	return listener, nil
	}
	}
	
	return nil, errors.New("Couldn't bind plugin TCP listener")
	}
	
	func serverListener_unix(unixSocketCfg UnixSocketConfig) (net.Listener, error) {
	tf, err := os.CreateTemp(unixSocketCfg.socketDir, "plugin")
	if err != nil {
	return nil, err
	}
	path := tf.Name()
	
	// Close the file and remove it because it has to not exist for
	// the domain socket.
	if err := tf.Close(); err != nil {
	return nil, err
	}
	if err := os.Remove(path); err != nil {
	return nil, err
	}
	
	l, err := net.Listen("unix", path)
	if err != nil {
	return nil, err
	}
	
	// By default, unix sockets are only writable by the owner. Set up a custom
	// group owner and group write permissions if configured.
	if unixSocketCfg.Group != "" {
	err = setGroupWritable(path, unixSocketCfg.Group, 0o660)
	if err != nil {
	return nil, err
	}
	}
	
	// Wrap the listener in rmListener so that the Unix domain socket file
	// is removed on close.
	return newDeleteFileListener(l, path), nil
	}
	
	func setGroupWritable(path, groupString string, mode os.FileMode) error {
	groupID, err := strconv.Atoi(groupString)
	if err != nil {
	group, err := user.LookupGroup(groupString)
	if err != nil {
	return fmt.Errorf("failed to find gid from %q: %w", groupString, err)
	}
	groupID, err = strconv.Atoi(group.Gid)
	if err != nil {
	return fmt.Errorf("failed to parse %q group's gid as an integer: %w", groupString, err)
	}
	}
	
	err = os.Chown(path, -1, groupID)
	if err != nil {
	return err
	}
	
	err = os.Chmod(path, mode)
	if err != nil {
	return err
	}
	
	return nil
	}
	
	// rmListener is an implementation of net.Listener that forwards most
	// calls to the listener but also calls an additional close function. We
	// use this to cleanup the unix domain socket on close, as well as clean
	// up multiplexed listeners.
	type rmListener struct {
	net.Listener
	close func() error
	}
	
	func newDeleteFileListener(ln net.Listener, path string) *rmListener {
	return &rmListener{
	Listener: ln,
	close: func() error {
	return os.Remove(path)
	},
	}
	}
	
	func (l *rmListener) Close() error {
	// Close the listener itself
	if err := l.Listener.Close(); err != nil {
	return err
	}
	
	// Remove the file
	return l.close()
	}

github.com/hashicorp/go-plugin/server_mux.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"fmt"
	"os"
	)
	
	// ServeMuxMap is the type that is used to configure ServeMux
	type ServeMuxMap map[string]*ServeConfig
	
	// ServeMux is like Serve, but serves multiple types of plugins determined
	// by the argument given on the command-line.
	//
	// This command doesn't return until the plugin is done being executed. Any
	// errors are logged or output to stderr.
	func ServeMux(m ServeMuxMap) {
	if len(os.Args) != 2 {
	fmt.Fprintf(os.Stderr,
	"Invoked improperly. This is an internal command that shouldn't\n"+
	"be manually invoked.\n")
	os.Exit(1)
	}
	
	opts, ok := m[os.Args[1]]
	if !ok {
	fmt.Fprintf(os.Stderr, "Unknown plugin: %s\n", os.Args[1])
	os.Exit(1)
	}
	
	Serve(opts)
	}

github.com/hashicorp/go-plugin/stream.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"io"
	"log"
	)
	
	func copyStream(name string, dst io.Writer, src io.Reader) {
	if src == nil {
	panic(name + ": src is nil")
	}
	if dst == nil {
	panic(name + ": dst is nil")
	}
	if _, err := io.Copy(dst, src); err != nil && err != io.EOF {
	log.Printf("[ERR] plugin: stream copy '%s' error: %s", name, err)
	}
	}

github.com/hashicorp/go-plugin/testing.go:

	// Copyright (c) HashiCorp, Inc.
	// SPDX-License-Identifier: MPL-2.0
	
	package plugin
	
	import (
	"bytes"
	"context"
	"io"
	"net"
	"net/rpc"
	
	hclog "github.com/hashicorp/go-hclog"
	"github.com/hashicorp/go-plugin/internal/grpcmux"
	"github.com/mitchellh/go-testing-interface"
	"google.golang.org/grpc"
	)
	
	// TestOptions allows specifying options that can affect the behavior of the
	// test functions
	type TestOptions struct {
	//ServerStdout causes the given value to be used in place of a blank buffer
	//for RPCServer's Stdout
	ServerStdout io.ReadCloser
	
	//ServerStderr causes the given value to be used in place of a blank buffer
	//for RPCServer's Stderr
	ServerStderr io.ReadCloser
	}
	
	// The testing file contains test helpers that you can use outside of
	// this package for making it easier to test plugins themselves.
	
	// TestConn is a helper function for returning a client and server
	// net.Conn connected to each other.
	func TestConn(t testing.T) (net.Conn, net.Conn) {
	// Listen to any local port. This listener will be closed
	// after a single connection is established.
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
	t.Fatalf("err: %s", err)
	}
	
	// Start a goroutine to accept our client connection
	var serverConn net.Conn
	doneCh := make(chan struct{})
	go func() {
	defer close(doneCh)
	defer l.Close()
	var err error
	serverConn, err = l.Accept()
	if err != nil {
	t.Fatalf("err: %s", err)
	}
	}()
	
	// Connect to the server
	clientConn, err := net.Dial("tcp", l.Addr().String())
	if err != nil {
	t.Fatalf("err: %s", err)
	}
	
	// Wait for the server side to acknowledge it has connected
	<-doneCh
	
	return clientConn, serverConn
	}
	
	// TestRPCConn returns a rpc client and server connected to each other.
	func TestRPCConn(t testing.T) (*rpc.Client, *rpc.Server) {
	clientConn, serverConn := TestConn(t)
	
	server := rpc.NewServer()
	go server.ServeConn(serverConn)
	
	client := rpc.NewClient(clientConn)
	return client, server
	}
	
	// TestPluginRPCConn returns a plugin RPC client and server that are connected
	// together and configured.
	func TestPluginRPCConn(t testing.T, ps map[string]Plugin, opts *TestOptions) (*RPCClient, *RPCServer) {
	// Create two net.Conns we can use to shuttle our control connection
	clientConn, serverConn := TestConn(t)
	
	// Start up the server
	server := &RPCServer{Plugins: ps, Stdout: new(bytes.Buffer), Stderr: new(bytes.Buffer)}
	if opts != nil {
	if opts.ServerStdout != nil {
	server.Stdout = opts.ServerStdout
	}
	if opts.ServerStderr != nil {
	server.Stderr = opts.ServerStderr
	}
	}
	go server.ServeConn(serverConn)
	
	// Connect the client to the server
	client, err := NewRPCClient(clientConn, ps)
	if err != nil {
	t.Fatalf("err: %s", err)
	}
	
	return client, server
	}
	
	// TestGRPCConn returns a gRPC client conn and grpc server that are connected
	// together and configured. The register function is used to register services
	// prior to the Serve call. This is used to test gRPC connections.
	func TestGRPCConn(t testing.T, register func(*grpc.Server)) (*grpc.ClientConn, *grpc.Server) {
	// Create a listener
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
	t.Fatalf("err: %s", err)
	}
	
	server := grpc.NewServer()
	register(server)
	go server.Serve(l)
	
	// Connect to the server
	conn, err := grpc.Dial(
	l.Addr().String(),
	grpc.WithBlock(),
	grpc.WithInsecure())
	if err != nil {
	t.Fatalf("err: %s", err)
	}
	
	// Connection successful, close the listener
	l.Close()
	
	return conn, server
	}
	
	// TestPluginGRPCConn returns a plugin gRPC client and server that are connected
	// together and configured. This is used to test gRPC connections.
	func TestPluginGRPCConn(t testing.T, multiplex bool, ps map[string]Plugin) (*GRPCClient, *GRPCServer) {
	// Create a listener
	ln, err := serverListener(UnixSocketConfig{})
	if err != nil {
	t.Fatal(err)
	}
	
	logger := hclog.New(&hclog.LoggerOptions{
	Level: hclog.Debug,
	})
	
	// Start up the server
	var muxer *grpcmux.GRPCServerMuxer
	if multiplex {
	muxer = grpcmux.NewGRPCServerMuxer(logger, ln)
	ln = muxer
	}
	server := &GRPCServer{
	Plugins: ps,
	DoneCh:  make(chan struct{}),
	Server:  DefaultGRPCServer,
	Stdout:  new(bytes.Buffer),
	Stderr:  new(bytes.Buffer),
	logger:  logger,
	muxer:   muxer,
	}
	if err := server.Init(); err != nil {
	t.Fatalf("err: %s", err)
	}
	go server.Serve(ln)
	
	client := &Client{
	address:  ln.Addr(),
	protocol: ProtocolGRPC,
	config: &ClientConfig{
	Plugins:             ps,
	GRPCBrokerMultiplex: multiplex,
	},
	logger: logger,
	}
	
	grpcClient, err := newGRPCClient(context.Background(), client)
	if err != nil {
	t.Fatal(err)
	}
	
	return grpcClient, server
	}

github.com/hashicorp/go-uuid/.travis.yml:

	language: go
	
	sudo: false
	
	go:
	- 1.4
	- 1.5
	- 1.6
	- tip
	
	script:
	- go test -bench . -benchmem -v ./...

github.com/hashicorp/go-uuid/LICENSE:

	Copyright © 2015-2022 HashiCorp, Inc.
	
	Mozilla Public License, version 2.0
	
	1. Definitions
	
	1.1. "Contributor"
	
	means each individual or legal entity that creates, contributes to the
	creation of, or owns Covered Software.
	
	1.2. "Contributor Version"
	
	means the combination of the Contributions of others (if any) used by a
	Contributor and that particular Contributor's Contribution.
	
	1.3. "Contribution"
	
	means Covered Software of a particular Contributor.
	
	1.4. "Covered Software"
	
	means Source Code Form to which the initial Contributor has attached the
	notice in Exhibit A, the Executable Form of such Source Code Form, and
	Modifications of such Source Code Form, in each case including portions
	thereof.
	
	1.5. "Incompatible With Secondary Licenses"
	means
	
	a. that the initial Contributor has attached the notice described in
	Exhibit B to the Covered Software; or
	
	b. that the Covered Software was made available under the terms of
	version 1.1 or earlier of the License, but not also under the terms of
	a Secondary License.
	
	1.6. "Executable Form"
	
	means any form of the work other than Source Code Form.
	
	1.7. "Larger Work"
	
	means a work that combines Covered Software with other material, in a
	separate file or files, that is not Covered Software.
	
	1.8. "License"
	
	means this document.
	
	1.9. "Licensable"
	
	means having the right to grant, to the maximum extent possible, whether
	at the time of the initial grant or subsequently, any and all of the
	rights conveyed by this License.
	
	1.10. "Modifications"
	
	means any of the following:
	
	a. any file in Source Code Form that results from an addition to,
	deletion from, or modification of the contents of Covered Software; or
	
	b. any new file in Source Code Form that contains any Covered Software.
	
	1.11. "Patent Claims" of a Contributor
	
	means any patent claim(s), including without limitation, method,
	process, and apparatus claims, in any patent Licensable by such
	Contributor that would be infringed, but for the grant of the License,
	by the making, using, selling, offering for sale, having made, import,
	or transfer of either its Contributions or its Contributor Version.
	
	1.12. "Secondary License"
	
	means either the GNU General Public License, Version 2.0, the GNU Lesser
	General Public License, Version 2.1, the GNU Affero General Public
	License, Version 3.0, or any later versions of those licenses.
	
	1.13. "Source Code Form"
	
	means the form of the work preferred for making modifications.
	
	1.14. "You" (or "Your")
	
	means an individual or a legal entity exercising rights under this
	License. For legal entities, "You" includes any entity that controls, is
	controlled by, or is under common control with You. For purposes of this
	definition, "control" means (a) the power, direct or indirect, to cause
	the direction or management of such entity, whether by contract or
	otherwise, or (b) ownership of more than fifty percent (50%) of the
	outstanding shares or beneficial ownership of such entity.
	
	
	2. License Grants and Conditions
	
	2.1. Grants
	
	Each Contributor hereby grants You a world-wide, royalty-free,
	non-exclusive license:
	
	a. under intellectual property rights (other than patent or trademark)
	Licensable by such Contributor to use, reproduce, make available,
	modify, display, perform, distribute, and otherwise exploit its
	Contributions, either on an unmodified basis, with Modifications, or
	as part of a Larger Work; and
	
	b. under Patent Claims of such Contributor to make, use, sell, offer for
	sale, have made, import, and otherwise transfer either its
	Contributions or its Contributor Version.
	
	2.2. Effective Date
	
	The licenses granted in Section 2.1 with respect to any Contribution
	become effective for each Contribution on the date the Contributor first
	distributes such Contribution.
	
	2.3. Limitations on Grant Scope
	
	The licenses granted in this Section 2 are the only rights granted under
	this License. No additional rights or licenses will be implied from the
	distribution or licensing of Covered Software under this License.
	Notwithstanding Section 2.1(b) above, no patent license is granted by a
	Contributor:
	
	a. for any code that a Contributor has removed from Covered Software; or
	
	b. for infringements caused by: (i) Your and any other third party's
	modifications of Covered Software, or (ii) the combination of its
	Contributions with other software (except as part of its Contributor
	Version); or
	
	c. under Patent Claims infringed by Covered Software in the absence of
	its Contributions.
	
	This License does not grant any rights in the trademarks, service marks,
	or logos of any Contributor (except as may be necessary to comply with
	the notice requirements in Section 3.4).
	
	2.4. Subsequent Licenses
	
	No Contributor makes additional grants as a result of Your choice to
	distribute the Covered Software under a subsequent version of this
	License (see Section 10.2) or under the terms of a Secondary License (if
	permitted under the terms of Section 3.3).
	
	2.5. Representation
	
	Each Contributor represents that the Contributor believes its
	Contributions are its original creation(s) or it has sufficient rights to
	grant the rights to its Contributions conveyed by this License.
	
	2.6. Fair Use
	
	This License is not intended to limit any rights You have under
	applicable copyright doctrines of fair use, fair dealing, or other
	equivalents.
	
	2.7. Conditions
	
	Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
	Section 2.1.
	
	
	3. Responsibilities
	
	3.1. Distribution of Source Form
	
	All distribution of Covered Software in Source Code Form, including any
	Modifications that You create or to which You contribute, must be under
	the terms of this License. You must inform recipients that the Source
	Code Form of the Covered Software is governed by the terms of this
	License, and how they can obtain a copy of this License. You may not
	attempt to alter or restrict the recipients' rights in the Source Code
	Form.
	
	3.2. Distribution of Executable Form
	
	If You distribute Covered Software in Executable Form then:
	
	a. such Covered Software must also be made available in Source Code Form,
	as described in Section 3.1, and You must inform recipients of the
	Executable Form how they can obtain a copy of such Source Code Form by
	reasonable means in a timely manner, at a charge no more than the cost
	of distribution to the recipient; and
	
	b. You may distribute such Executable Form under the terms of this
	License, or sublicense it under different terms, provided that the
	license for the Executable Form does not attempt to limit or alter the
	recipients' rights in the Source Code Form under this License.
	
	3.3. Distribution of a Larger Work
	
	You may create and distribute a Larger Work under terms of Your choice,
	provided that You also comply with the requirements of this License for
	the Covered Software. If the Larger Work is a combination of Covered
	Software with a work governed by one or more Secondary Licenses, and the
	Covered Software is not Incompatible With Secondary Licenses, this
	License permits You to additionally distribute such Covered Software
	under the terms of such Secondary License(s), so that the recipient of
	the Larger Work may, at their option, further distribute the Covered
	Software under the terms of either this License or such Secondary
	License(s).
	
	3.4. Notices
	
	You may not remove or alter the substance of any license notices
	(including copyright notices, patent notices, disclaimers of warranty, or
	limitations of liability) contained within the Source Code Form of the
	Covered Software, except that You may alter any license notices to the
	extent required to remedy known factual inaccuracies.
	
	3.5. Application of Additional Terms
	
	You may choose to offer, and to charge a fee for, warranty, support,
	indemnity or liability obligations to one or more recipients of Covered
	Software. However, You may do so only on Your own behalf, and not on
	behalf of any Contributor. You must make it absolutely clear that any
	such warranty, support, indemnity, or liability obligation is offered by
	You alone, and You hereby agree to indemnify every Contributor for any
	liability incurred by such Contributor as a result of warranty, support,
	indemnity or liability terms You offer. You may include additional
	disclaimers of warranty and limitations of liability specific to any
	jurisdiction.
	
	4. Inability to Comply Due to Statute or Regulation
	
	If it is impossible for You to comply with any of the terms of this License
	with respect to some or all of the Covered Software due to statute,
	judicial order, or regulation then You must: (a) comply with the terms of
	this License to the maximum extent possible; and (b) describe the
	limitations and the code they affect. Such description must be placed in a
	text file included with all distributions of the Covered Software under
	this License. Except to the extent prohibited by statute or regulation,
	such description must be sufficiently detailed for a recipient of ordinary
	skill to be able to understand it.
	
	5. Termination
	
	5.1. The rights granted under this License will terminate automatically if You
	fail to comply with any of its terms. However, if You become compliant,
	then the rights granted under this License from a particular Contributor
	are reinstated (a) provisionally, unless and until such Contributor
	explicitly and finally terminates Your grants, and (b) on an ongoing
	basis, if such Contributor fails to notify You of the non-compliance by
	some reasonable means prior to 60 days after You have come back into
	compliance. Moreover, Your grants from a particular Contributor are
	reinstated on an ongoing basis if such Contributor notifies You of the
	non-compliance by some reasonable means, this is the first time You have
	received notice of non-compliance with this License from such
	Contributor, and You become compliant prior to 30 days after Your receipt
	of the notice.
	
	5.2. If You initiate litigation against any entity by asserting a patent
	infringement claim (excluding declaratory judgment actions,
	counter-claims, and cross-claims) alleging that a Contributor Version
	directly or indirectly infringes any patent, then the rights granted to
	You by any and all Contributors for the Covered Software under Section
	2.1 of this License shall terminate.
	
	5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
	license agreements (excluding distributors and resellers) which have been
	validly granted by You or Your distributors under this License prior to
	termination shall survive termination.
	
	6. Disclaimer of Warranty
	
	Covered Software is provided under this License on an "as is" basis,
	without warranty of any kind, either expressed, implied, or statutory,
	including, without limitation, warranties that the Covered Software is free
	of defects, merchantable, fit for a particular purpose or non-infringing.
	The entire risk as to the quality and performance of the Covered Software
	is with You. Should any Covered Software prove defective in any respect,
	You (not any Contributor) assume the cost of any necessary servicing,
	repair, or correction. This disclaimer of warranty constitutes an essential
	part of this License. No use of  any Covered Software is authorized under
	this License except under this disclaimer.
	
	7. Limitation of Liability
	
	Under no circumstances and under no legal theory, whether tort (including
	negligence), contract, or otherwise, shall any Contributor, or anyone who
	distributes Covered Software as permitted above, be liable to You for any
	direct, indirect, special, incidental, or consequential damages of any
	character including, without limitation, damages for lost profits, loss of
	goodwill, work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses, even if such party shall have been
	informed of the possibility of such damages. This limitation of liability
	shall not apply to liability for death or personal injury resulting from
	such party's negligence to the extent applicable law prohibits such
	limitation. Some jurisdictions do not allow the exclusion or limitation of
	incidental or consequential damages, so this exclusion and limitation may
	not apply to You.
	
	8. Litigation
	
	Any litigation relating to this License may be brought only in the courts
	of a jurisdiction where the defendant maintains its principal place of
	business and such litigation shall be governed by laws of that
	jurisdiction, without reference to its conflict-of-law provisions. Nothing
	in this Section shall prevent a party's ability to bring cross-claims or
	counter-claims.
	
	9. Miscellaneous
	
	This License represents the complete agreement concerning the subject
	matter hereof. If any provision of this License is held to be
	unenforceable, such provision shall be reformed only to the extent
	necessary to make it enforceable. Any law or regulation which provides that
	the language of a contract shall be construed against the drafter shall not
	be used to construe this License against a Contributor.
	
	
	10. Versions of the License
	
	10.1. New Versions
	
	Mozilla Foundation is the license steward. Except as provided in Section
	10.3, no one other than the license steward has the right to modify or
	publish new versions of this License. Each version will be given a
	distinguishing version number.
	
	10.2. Effect of New Versions
	
	You may distribute the Covered Software under the terms of the version
	of the License under which You originally received the Covered Software,
	or under the terms of any subsequent version published by the license
	steward.
	
	10.3. Modified Versions
	
	If you create software not governed by this License, and you want to
	create a new license for such software, you may create and use a
	modified version of this License if you rename the license and remove
	any references to the name of the license steward (except to note that
	such modified license differs from this License).
	
	10.4. Distributing Source Code Form that is Incompatible With Secondary
	Licenses If You choose to distribute Source Code Form that is
	Incompatible With Secondary Licenses under the terms of this version of
	the License, the notice described in Exhibit B of this License must be
	attached.
	
	Exhibit A - Source Code Form License Notice
	
	This Source Code Form is subject to the
	terms of the Mozilla Public License, v.
	2.0. If a copy of the MPL was not
	distributed with this file, You can
	obtain one at
	http://mozilla.org/MPL/2.0/.
	
	If it is not possible or desirable to put the notice in a particular file,
	then You may include the notice in a location (such as a LICENSE file in a
	relevant directory) where a recipient would be likely to look for such a
	notice.
	
	You may add additional accurate notices of copyright ownership.
	
	Exhibit B - "Incompatible With Secondary Licenses" Notice
	
	This Source Code Form is "Incompatible
	With Secondary Licenses", as defined by
	the Mozilla Public License, v. 2.0.
	

github.com/hashicorp/go-uuid/README.md:

	# uuid [![Build Status](https://travis-ci.org/hashicorp/go-uuid.svg?branch=master)](https://travis-ci.org/hashicorp/go-uuid)
	
	Generates UUID-format strings using high quality, _purely random_ bytes. It is **not** intended to be RFC compliant, merely to use a well-understood string representation of a 128-bit value. It can also parse UUID-format strings into their component bytes.
	
	Documentation
	=============
	
	The full documentation is available on [Godoc](http://godoc.org/github.com/hashicorp/go-uuid).

github.com/hashicorp/go-uuid/uuid.go:

	package uuid
	
	import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io"
	)
	
	// GenerateRandomBytes is used to generate random bytes of given size.
	func GenerateRandomBytes(size int) ([]byte, error) {
	return GenerateRandomBytesWithReader(size, rand.Reader)
	}
	
	// GenerateRandomBytesWithReader is used to generate random bytes of given size read from a given reader.
	func GenerateRandomBytesWithReader(size int, reader io.Reader) ([]byte, error) {
	if reader == nil {
	return nil, fmt.Errorf("provided reader is nil")
	}
	buf := make([]byte, size)
	if _, err := io.ReadFull(reader, buf); err != nil {
	return nil, fmt.Errorf("failed to read random bytes: %v", err)
	}
	return buf, nil
	}
	
	
	const uuidLen = 16
	
	// GenerateUUID is used to generate a random UUID
	func GenerateUUID() (string, error) {
	return GenerateUUIDWithReader(rand.Reader)
	}
	
	// GenerateUUIDWithReader is used to generate a random UUID with a given Reader
	func GenerateUUIDWithReader(reader io.Reader) (string, error) {
	if reader == nil {
	return "", fmt.Errorf("provided reader is nil")
	}
	buf, err := GenerateRandomBytesWithReader(uuidLen, reader)
	if err != nil {
	return "", err
	}
	return FormatUUID(buf)
	}
	
	func FormatUUID(buf []byte) (string, error) {
	if buflen := len(buf); buflen != uuidLen {
	return "", fmt.Errorf("wrong length byte slice (%d)", buflen)
	}
	
	return fmt.Sprintf("%x-%x-%x-%x-%x",
	buf[0:4],
	buf[4:6],
	buf[6:8],
	buf[8:10],
	buf[10:16]), nil
	}
	
	func ParseUUID(uuid string) ([]byte, error) {
	if len(uuid) != 2 * uuidLen + 4 {
	return nil, fmt.Errorf("uuid string is wrong length")
	}
	
	if uuid[8] != '-' ||
	uuid[13] != '-' ||
	uuid[18] != '-' ||
	uuid[23] != '-' {
	return nil, fmt.Errorf("uuid is improperly formatted")
	}
	
	hexStr := uuid[0:8] + uuid[9:13] + uuid[14:18] + uuid[19:23] + uuid[24:36]
	
	ret, err := hex.DecodeString(hexStr)
	if err != nil {
	return nil, err
	}
	if len(ret) != uuidLen {
	return nil, fmt.Errorf("decoded hex is the wrong length")
	}
	
	return ret, nil
	}

github.com/hashicorp/yamux/.gitignore:

	# Compiled Object files, Static and Dynamic libs (Shared Objects)
	*.o
	*.a
	*.so
	
	# Folders
	_obj
	_test
	
	# Architecture specific extensions/prefixes
	*.[568vq]
	[568vq].out
	
	*.cgo1.go
	*.cgo2.c
	_cgo_defun.c
	_cgo_gotypes.go
	_cgo_export.*
	
	_testmain.go
	
	*.exe
	*.test

github.com/hashicorp/yamux/LICENSE:

	Mozilla Public License, version 2.0
	
	1. Definitions
	
	1.1. "Contributor"
	
	means each individual or legal entity that creates, contributes to the
	creation of, or owns Covered Software.
	
	1.2. "Contributor Version"
	
	means the combination of the Contributions of others (if any) used by a
	Contributor and that particular Contributor's Contribution.
	
	1.3. "Contribution"
	
	means Covered Software of a particular Contributor.
	
	1.4. "Covered Software"
	
	means Source Code Form to which the initial Contributor has attached the
	notice in Exhibit A, the Executable Form of such Source Code Form, and
	Modifications of such Source Code Form, in each case including portions
	thereof.
	
	1.5. "Incompatible With Secondary Licenses"
	means
	
	a. that the initial Contributor has attached the notice described in
	Exhibit B to the Covered Software; or
	
	b. that the Covered Software was made available under the terms of
	version 1.1 or earlier of the License, but not also under the terms of
	a Secondary License.
	
	1.6. "Executable Form"
	
	means any form of the work other than Source Code Form.
	
	1.7. "Larger Work"
	
	means a work that combines Covered Software with other material, in a
	separate file or files, that is not Covered Software.
	
	1.8. "License"
	
	means this document.
	
	1.9. "Licensable"
	
	means having the right to grant, to the maximum extent possible, whether
	at the time of the initial grant or subsequently, any and all of the
	rights conveyed by this License.
	
	1.10. "Modifications"
	
	means any of the following:
	
	a. any file in Source Code Form that results from an addition to,
	deletion from, or modification of the contents of Covered Software; or
	
	b. any new file in Source Code Form that contains any Covered Software.
	
	1.11. "Patent Claims" of a Contributor
	
	means any patent claim(s), including without limitation, method,
	process, and apparatus claims, in any patent Licensable by such
	Contributor that would be infringed, but for the grant of the License,
	by the making, using, selling, offering for sale, having made, import,
	or transfer of either its Contributions or its Contributor Version.
	
	1.12. "Secondary License"
	
	means either the GNU General Public License, Version 2.0, the GNU Lesser
	General Public License, Version 2.1, the GNU Affero General Public
	License, Version 3.0, or any later versions of those licenses.
	
	1.13. "Source Code Form"
	
	means the form of the work preferred for making modifications.
	
	1.14. "You" (or "Your")
	
	means an individual or a legal entity exercising rights under this
	License. For legal entities, "You" includes any entity that controls, is
	controlled by, or is under common control with You. For purposes of this
	definition, "control" means (a) the power, direct or indirect, to cause
	the direction or management of such entity, whether by contract or
	otherwise, or (b) ownership of more than fifty percent (50%) of the
	outstanding shares or beneficial ownership of such entity.
	
	
	2. License Grants and Conditions
	
	2.1. Grants
	
	Each Contributor hereby grants You a world-wide, royalty-free,
	non-exclusive license:
	
	a. under intellectual property rights (other than patent or trademark)
	Licensable by such Contributor to use, reproduce, make available,
	modify, display, perform, distribute, and otherwise exploit its
	Contributions, either on an unmodified basis, with Modifications, or
	as part of a Larger Work; and
	
	b. under Patent Claims of such Contributor to make, use, sell, offer for
	sale, have made, import, and otherwise transfer either its
	Contributions or its Contributor Version.
	
	2.2. Effective Date
	
	The licenses granted in Section 2.1 with respect to any Contribution
	become effective for each Contribution on the date the Contributor first
	distributes such Contribution.
	
	2.3. Limitations on Grant Scope
	
	The licenses granted in this Section 2 are the only rights granted under
	this License. No additional rights or licenses will be implied from the
	distribution or licensing of Covered Software under this License.
	Notwithstanding Section 2.1(b) above, no patent license is granted by a
	Contributor:
	
	a. for any code that a Contributor has removed from Covered Software; or
	
	b. for infringements caused by: (i) Your and any other third party's
	modifications of Covered Software, or (ii) the combination of its
	Contributions with other software (except as part of its Contributor
	Version); or
	
	c. under Patent Claims infringed by Covered Software in the absence of
	its Contributions.
	
	This License does not grant any rights in the trademarks, service marks,
	or logos of any Contributor (except as may be necessary to comply with
	the notice requirements in Section 3.4).
	
	2.4. Subsequent Licenses
	
	No Contributor makes additional grants as a result of Your choice to
	distribute the Covered Software under a subsequent version of this
	License (see Section 10.2) or under the terms of a Secondary License (if
	permitted under the terms of Section 3.3).
	
	2.5. Representation
	
	Each Contributor represents that the Contributor believes its
	Contributions are its original creation(s) or it has sufficient rights to
	grant the rights to its Contributions conveyed by this License.
	
	2.6. Fair Use
	
	This License is not intended to limit any rights You have under
	applicable copyright doctrines of fair use, fair dealing, or other
	equivalents.
	
	2.7. Conditions
	
	Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
	Section 2.1.
	
	
	3. Responsibilities
	
	3.1. Distribution of Source Form
	
	All distribution of Covered Software in Source Code Form, including any
	Modifications that You create or to which You contribute, must be under
	the terms of this License. You must inform recipients that the Source
	Code Form of the Covered Software is governed by the terms of this
	License, and how they can obtain a copy of this License. You may not
	attempt to alter or restrict the recipients' rights in the Source Code
	Form.
	
	3.2. Distribution of Executable Form
	
	If You distribute Covered Software in Executable Form then:
	
	a. such Covered Software must also be made available in Source Code Form,
	as described in Section 3.1, and You must inform recipients of the
	Executable Form how they can obtain a copy of such Source Code Form by
	reasonable means in a timely manner, at a charge no more than the cost
	of distribution to the recipient; and
	
	b. You may distribute such Executable Form under the terms of this
	License, or sublicense it under different terms, provided that the
	license for the Executable Form does not attempt to limit or alter the
	recipients' rights in the Source Code Form under this License.
	
	3.3. Distribution of a Larger Work
	
	You may create and distribute a Larger Work under terms of Your choice,
	provided that You also comply with the requirements of this License for
	the Covered Software. If the Larger Work is a combination of Covered
	Software with a work governed by one or more Secondary Licenses, and the
	Covered Software is not Incompatible With Secondary Licenses, this
	License permits You to additionally distribute such Covered Software
	under the terms of such Secondary License(s), so that the recipient of
	the Larger Work may, at their option, further distribute the Covered
	Software under the terms of either this License or such Secondary
	License(s).
	
	3.4. Notices
	
	You may not remove or alter the substance of any license notices
	(including copyright notices, patent notices, disclaimers of warranty, or
	limitations of liability) contained within the Source Code Form of the
	Covered Software, except that You may alter any license notices to the
	extent required to remedy known factual inaccuracies.
	
	3.5. Application of Additional Terms
	
	You may choose to offer, and to charge a fee for, warranty, support,
	indemnity or liability obligations to one or more recipients of Covered
	Software. However, You may do so only on Your own behalf, and not on
	behalf of any Contributor. You must make it absolutely clear that any
	such warranty, support, indemnity, or liability obligation is offered by
	You alone, and You hereby agree to indemnify every Contributor for any
	liability incurred by such Contributor as a result of warranty, support,
	indemnity or liability terms You offer. You may include additional
	disclaimers of warranty and limitations of liability specific to any
	jurisdiction.
	
	4. Inability to Comply Due to Statute or Regulation
	
	If it is impossible for You to comply with any of the terms of this License
	with respect to some or all of the Covered Software due to statute,
	judicial order, or regulation then You must: (a) comply with the terms of
	this License to the maximum extent possible; and (b) describe the
	limitations and the code they affect. Such description must be placed in a
	text file included with all distributions of the Covered Software under
	this License. Except to the extent prohibited by statute or regulation,
	such description must be sufficiently detailed for a recipient of ordinary
	skill to be able to understand it.
	
	5. Termination
	
	5.1. The rights granted under this License will terminate automatically if You
	fail to comply with any of its terms. However, if You become compliant,
	then the rights granted under this License from a particular Contributor
	are reinstated (a) provisionally, unless and until such Contributor
	explicitly and finally terminates Your grants, and (b) on an ongoing
	basis, if such Contributor fails to notify You of the non-compliance by
	some reasonable means prior to 60 days after You have come back into
	compliance. Moreover, Your grants from a particular Contributor are
	reinstated on an ongoing basis if such Contributor notifies You of the
	non-compliance by some reasonable means, this is the first time You have
	received notice of non-compliance with this License from such
	Contributor, and You become compliant prior to 30 days after Your receipt
	of the notice.
	
	5.2. If You initiate litigation against any entity by asserting a patent
	infringement claim (excluding declaratory judgment actions,
	counter-claims, and cross-claims) alleging that a Contributor Version
	directly or indirectly infringes any patent, then the rights granted to
	You by any and all Contributors for the Covered Software under Section
	2.1 of this License shall terminate.
	
	5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
	license agreements (excluding distributors and resellers) which have been
	validly granted by You or Your distributors under this License prior to
	termination shall survive termination.
	
	6. Disclaimer of Warranty
	
	Covered Software is provided under this License on an "as is" basis,
	without warranty of any kind, either expressed, implied, or statutory,
	including, without limitation, warranties that the Covered Software is free
	of defects, merchantable, fit for a particular purpose or non-infringing.
	The entire risk as to the quality and performance of the Covered Software
	is with You. Should any Covered Software prove defective in any respect,
	You (not any Contributor) assume the cost of any necessary servicing,
	repair, or correction. This disclaimer of warranty constitutes an essential
	part of this License. No use of  any Covered Software is authorized under
	this License except under this disclaimer.
	
	7. Limitation of Liability
	
	Under no circumstances and under no legal theory, whether tort (including
	negligence), contract, or otherwise, shall any Contributor, or anyone who
	distributes Covered Software as permitted above, be liable to You for any
	direct, indirect, special, incidental, or consequential damages of any
	character including, without limitation, damages for lost profits, loss of
	goodwill, work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses, even if such party shall have been
	informed of the possibility of such damages. This limitation of liability
	shall not apply to liability for death or personal injury resulting from
	such party's negligence to the extent applicable law prohibits such
	limitation. Some jurisdictions do not allow the exclusion or limitation of
	incidental or consequential damages, so this exclusion and limitation may
	not apply to You.
	
	8. Litigation
	
	Any litigation relating to this License may be brought only in the courts
	of a jurisdiction where the defendant maintains its principal place of
	business and such litigation shall be governed by laws of that
	jurisdiction, without reference to its conflict-of-law provisions. Nothing
	in this Section shall prevent a party's ability to bring cross-claims or
	counter-claims.
	
	9. Miscellaneous
	
	This License represents the complete agreement concerning the subject
	matter hereof. If any provision of this License is held to be
	unenforceable, such provision shall be reformed only to the extent
	necessary to make it enforceable. Any law or regulation which provides that
	the language of a contract shall be construed against the drafter shall not
	be used to construe this License against a Contributor.
	
	
	10. Versions of the License
	
	10.1. New Versions
	
	Mozilla Foundation is the license steward. Except as provided in Section
	10.3, no one other than the license steward has the right to modify or
	publish new versions of this License. Each version will be given a
	distinguishing version number.
	
	10.2. Effect of New Versions
	
	You may distribute the Covered Software under the terms of the version
	of the License under which You originally received the Covered Software,
	or under the terms of any subsequent version published by the license
	steward.
	
	10.3. Modified Versions
	
	If you create software not governed by this License, and you want to
	create a new license for such software, you may create and use a
	modified version of this License if you rename the license and remove
	any references to the name of the license steward (except to note that
	such modified license differs from this License).
	
	10.4. Distributing Source Code Form that is Incompatible With Secondary
	Licenses If You choose to distribute Source Code Form that is
	Incompatible With Secondary Licenses under the terms of this version of
	the License, the notice described in Exhibit B of this License must be
	attached.
	
	Exhibit A - Source Code Form License Notice
	
	This Source Code Form is subject to the
	terms of the Mozilla Public License, v.
	2.0. If a copy of the MPL was not
	distributed with this file, You can
	obtain one at
	http://mozilla.org/MPL/2.0/.
	
	If it is not possible or desirable to put the notice in a particular file,
	then You may include the notice in a location (such as a LICENSE file in a
	relevant directory) where a recipient would be likely to look for such a
	notice.
	
	You may add additional accurate notices of copyright ownership.
	
	Exhibit B - "Incompatible With Secondary Licenses" Notice
	
	This Source Code Form is "Incompatible
	With Secondary Licenses", as defined by

github.com/hashicorp/yamux/README.md:

	# Yamux
	
	Yamux (Yet another Multiplexer) is a multiplexing library for Golang.
	It relies on an underlying connection to provide reliability
	and ordering, such as TCP or Unix domain sockets, and provides
	stream-oriented multiplexing. It is inspired by SPDY but is not
	interoperable with it.
	
	Yamux features include:
	
	* Bi-directional streams
	* Streams can be opened by either client or server
	* Useful for NAT traversal
	* Server-side push support
	* Flow control
	* Avoid starvation
	* Back-pressure to prevent overwhelming a receiver
	* Keep Alives
	* Enables persistent connections over a load balancer
	* Efficient
	* Enables thousands of logical streams with low overhead
	
	## Documentation
	
	For complete documentation, see the associated [Godoc](http://godoc.org/github.com/hashicorp/yamux).
	
	## Specification
	
	The full specification for Yamux is provided in the `spec.md` file.
	It can be used as a guide to implementors of interoperable libraries.
	
	## Usage
	
	Using Yamux is remarkably simple:
	
	```go
	
	func client() {
	// Get a TCP connection
	conn, err := net.Dial(...)
	if err != nil {
	panic(err)
	}
	
	// Setup client side of yamux
	session, err := yamux.Client(conn, nil)
	if err != nil {
	panic(err)
	}
	
	// Open a new stream
	stream, err := session.Open()
	if err != nil {
	panic(err)
	}
	
	// Stream implements net.Conn
	stream.Write([]byte("ping"))
	}
	
	func server() {
	// Accept a TCP connection
	conn, err := listener.Accept()
	if err != nil {
	panic(err)
	}
	
	// Setup server side of yamux
	session, err := yamux.Server(conn, nil)
	if err != nil {
	panic(err)
	}
	
	// Accept a stream
	stream, err := session.Accept()
	if err != nil {
	panic(err)
	}
	
	// Listen for a message
	buf := make([]byte, 4)
	stream.Read(buf)
	}
	
	```
	

github.com/hashicorp/yamux/addr.go:

	package yamux
	
	import (
	"fmt"
	"net"
	)
	
	// hasAddr is used to get the address from the underlying connection
	type hasAddr interface {
	LocalAddr() net.Addr
	RemoteAddr() net.Addr
	}
	
	// yamuxAddr is used when we cannot get the underlying address
	type yamuxAddr struct {
	Addr string
	}
	
	func (*yamuxAddr) Network() string {
	return "yamux"
	}
	
	func (y *yamuxAddr) String() string {
	return fmt.Sprintf("yamux:%s", y.Addr)
	}
	
	// Addr is used to get the address of the listener.
	func (s *Session) Addr() net.Addr {
	return s.LocalAddr()
	}
	
	// LocalAddr is used to get the local address of the
	// underlying connection.
	func (s *Session) LocalAddr() net.Addr {
	addr, ok := s.conn.(hasAddr)
	if !ok {
	return &yamuxAddr{"local"}
	}
	return addr.LocalAddr()
	}
	
	// RemoteAddr is used to get the address of remote end
	// of the underlying connection
	func (s *Session) RemoteAddr() net.Addr {
	addr, ok := s.conn.(hasAddr)
	if !ok {
	return &yamuxAddr{"remote"}
	}
	return addr.RemoteAddr()
	}
	
	// LocalAddr returns the local address
	func (s *Stream) LocalAddr() net.Addr {
	return s.session.LocalAddr()
	}
	
	// RemoteAddr returns the remote address
	func (s *Stream) RemoteAddr() net.Addr {
	return s.session.RemoteAddr()
	}

github.com/hashicorp/yamux/const.go:

	package yamux
	
	import (
	"encoding/binary"
	"fmt"
	)
	
	// NetError implements net.Error
	type NetError struct {
	err       error
	timeout   bool
	temporary bool
	}
	
	func (e *NetError) Error() string {
	return e.err.Error()
	}
	
	func (e *NetError) Timeout() bool {
	return e.timeout
	}
	
	func (e *NetError) Temporary() bool {
	return e.temporary
	}
	
	var (
	// ErrInvalidVersion means we received a frame with an
	// invalid version
	ErrInvalidVersion = fmt.Errorf("invalid protocol version")
	
	// ErrInvalidMsgType means we received a frame with an
	// invalid message type
	ErrInvalidMsgType = fmt.Errorf("invalid msg type")
	
	// ErrSessionShutdown is used if there is a shutdown during
	// an operation
	ErrSessionShutdown = fmt.Errorf("session shutdown")
	
	// ErrStreamsExhausted is returned if we have no more
	// stream ids to issue
	ErrStreamsExhausted = fmt.Errorf("streams exhausted")
	
	// ErrDuplicateStream is used if a duplicate stream is
	// opened inbound
	ErrDuplicateStream = fmt.Errorf("duplicate stream initiated")
	
	// ErrReceiveWindowExceeded indicates the window was exceeded
	ErrRecvWindowExceeded = fmt.Errorf("recv window exceeded")
	
	// ErrTimeout is used when we reach an IO deadline
	ErrTimeout = &NetError{
	err: fmt.Errorf("i/o deadline reached"),
	
	// Error should meet net.Error interface for timeouts for compatability
	// with standard library expectations, such as http servers.
	timeout: true,
	}
	
	// ErrStreamClosed is returned when using a closed stream
	ErrStreamClosed = fmt.Errorf("stream closed")
	
	// ErrUnexpectedFlag is set when we get an unexpected flag
	ErrUnexpectedFlag = fmt.Errorf("unexpected flag")
	
	// ErrRemoteGoAway is used when we get a go away from the other side
	ErrRemoteGoAway = fmt.Errorf("remote end is not accepting connections")
	
	// ErrConnectionReset is sent if a stream is reset. This can happen
	// if the backlog is exceeded, or if there was a remote GoAway.
	ErrConnectionReset = fmt.Errorf("connection reset")
	
	// ErrConnectionWriteTimeout indicates that we hit the "safety valve"
	// timeout writing to the underlying stream connection.
	ErrConnectionWriteTimeout = fmt.Errorf("connection write timeout")
	
	// ErrKeepAliveTimeout is sent if a missed keepalive caused the stream close
	ErrKeepAliveTimeout = fmt.Errorf("keepalive timeout")
	)
	
	const (
	// protoVersion is the only version we support
	protoVersion uint8 = 0
	)
	
	const (
	// Data is used for data frames. They are followed
	// by length bytes worth of payload.
	typeData uint8 = iota
	
	// WindowUpdate is used to change the window of
	// a given stream. The length indicates the delta
	// update to the window.
	typeWindowUpdate
	
	// Ping is sent as a keep-alive or to measure
	// the RTT. The StreamID and Length value are echoed
	// back in the response.
	typePing
	
	// GoAway is sent to terminate a session. The StreamID
	// should be 0 and the length is an error code.
	typeGoAway
	)
	
	const (
	// SYN is sent to signal a new stream. May
	// be sent with a data payload
	flagSYN uint16 = 1 << iota
	
	// ACK is sent to acknowledge a new stream. May
	// be sent with a data payload
	flagACK
	
	// FIN is sent to half-close the given stream.
	// May be sent with a data payload.
	flagFIN
	
	// RST is used to hard close a given stream.
	flagRST
	)
	
	const (
	// initialStreamWindow is the initial stream window size
	initialStreamWindow uint32 = 256 * 1024
	)
	
	const (
	// goAwayNormal is sent on a normal termination
	goAwayNormal uint32 = iota
	
	// goAwayProtoErr sent on a protocol error
	goAwayProtoErr
	
	// goAwayInternalErr sent on an internal error
	goAwayInternalErr
	)
	
	const (
	sizeOfVersion  = 1
	sizeOfType     = 1
	sizeOfFlags    = 2
	sizeOfStreamID = 4
	sizeOfLength   = 4
	headerSize     = sizeOfVersion + sizeOfType + sizeOfFlags +
	sizeOfStreamID + sizeOfLength
	)
	
	type header []byte
	
	func (h header) Version() uint8 {
	return h[0]
	}
	
	func (h header) MsgType() uint8 {
	return h[1]
	}
	
	func (h header) Flags() uint16 {
	return binary.BigEndian.Uint16(h[2:4])
	}
	
	func (h header) StreamID() uint32 {
	return binary.BigEndian.Uint32(h[4:8])
	}
	
	func (h header) Length() uint32 {
	return binary.BigEndian.Uint32(h[8:12])
	}
	
	func (h header) String() string {
	return fmt.Sprintf("Vsn:%d Type:%d Flags:%d StreamID:%d Length:%d",
	h.Version(), h.MsgType(), h.Flags(), h.StreamID(), h.Length())
	}
	
	func (h header) encode(msgType uint8, flags uint16, streamID uint32, length uint32) {
	h[0] = protoVersion
	h[1] = msgType
	binary.BigEndian.PutUint16(h[2:4], flags)
	binary.BigEndian.PutUint32(h[4:8], streamID)
	binary.BigEndian.PutUint32(h[8:12], length)
	}

github.com/hashicorp/yamux/mux.go:

	package yamux
	
	import (
	"fmt"
	"io"
	"log"
	"os"
	"time"
	)
	
	// Config is used to tune the Yamux session
	type Config struct {
	// AcceptBacklog is used to limit how many streams may be
	// waiting an accept.
	AcceptBacklog int
	
	// EnableKeepalive is used to do a period keep alive
	// messages using a ping.
	EnableKeepAlive bool
	
	// KeepAliveInterval is how often to perform the keep alive
	KeepAliveInterval time.Duration
	
	// ConnectionWriteTimeout is meant to be a "safety valve" timeout after
	// we which will suspect a problem with the underlying connection and
	// close it. This is only applied to writes, where's there's generally
	// an expectation that things will move along quickly.
	ConnectionWriteTimeout time.Duration
	
	// MaxStreamWindowSize is used to control the maximum
	// window size that we allow for a stream.
	MaxStreamWindowSize uint32
	
	// StreamOpenTimeout is the maximum amount of time that a stream will
	// be allowed to remain in pending state while waiting for an ack from the peer.
	// Once the timeout is reached the session will be gracefully closed.
	// A zero value disables the StreamOpenTimeout allowing unbounded
	// blocking on OpenStream calls.
	StreamOpenTimeout time.Duration
	
	// StreamCloseTimeout is the maximum time that a stream will allowed to
	// be in a half-closed state when `Close` is called before forcibly
	// closing the connection. Forcibly closed connections will empty the
	// receive buffer, drop any future packets received for that stream,
	// and send a RST to the remote side.
	StreamCloseTimeout time.Duration
	
	// LogOutput is used to control the log destination. Either Logger or
	// LogOutput can be set, not both.
	LogOutput io.Writer
	
	// Logger is used to pass in the logger to be used. Either Logger or
	// LogOutput can be set, not both.
	Logger *log.Logger
	}
	
	// DefaultConfig is used to return a default configuration
	func DefaultConfig() *Config {
	return &Config{
	AcceptBacklog:          256,
	EnableKeepAlive:        true,
	KeepAliveInterval:      30 * time.Second,
	ConnectionWriteTimeout: 10 * time.Second,
	MaxStreamWindowSize:    initialStreamWindow,
	StreamCloseTimeout:     5 * time.Minute,
	StreamOpenTimeout:      75 * time.Second,
	LogOutput:              os.Stderr,
	}
	}
	
	// VerifyConfig is used to verify the sanity of configuration
	func VerifyConfig(config *Config) error {
	if config.AcceptBacklog <= 0 {
	return fmt.Errorf("backlog must be positive")
	}
	if config.KeepAliveInterval == 0 {
	return fmt.Errorf("keep-alive interval must be positive")
	}
	if config.MaxStreamWindowSize < initialStreamWindow {
	return fmt.Errorf("MaxStreamWindowSize must be larger than %d", initialStreamWindow)
	}
	if config.LogOutput != nil && config.Logger != nil {
	return fmt.Errorf("both Logger and LogOutput may not be set, select one")
	} else if config.LogOutput == nil && config.Logger == nil {
	return fmt.Errorf("one of Logger or LogOutput must be set, select one")
	}
	return nil
	}
	
	// Server is used to initialize a new server-side connection.
	// There must be at most one server-side connection. If a nil config is
	// provided, the DefaultConfiguration will be used.
	func Server(conn io.ReadWriteCloser, config *Config) (*Session, error) {
	if config == nil {
	config = DefaultConfig()
	}
	if err := VerifyConfig(config); err != nil {
	return nil, err
	}
	return newSession(config, conn, false), nil
	}
	
	// Client is used to initialize a new client-side connection.
	// There must be at most one client-side connection.
	func Client(conn io.ReadWriteCloser, config *Config) (*Session, error) {
	if config == nil {
	config = DefaultConfig()
	}
	
	if err := VerifyConfig(config); err != nil {
	return nil, err
	}
	return newSession(config, conn, true), nil
	}

github.com/hashicorp/yamux/session.go:

	package yamux
	
	import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math"
	"net"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	)
	
	// Session is used to wrap a reliable ordered connection and to
	// multiplex it into multiple streams.
	type Session struct {
	// remoteGoAway indicates the remote side does
	// not want futher connections. Must be first for alignment.
	remoteGoAway int32
	
	// localGoAway indicates that we should stop
	// accepting futher connections. Must be first for alignment.
	localGoAway int32
	
	// nextStreamID is the next stream we should
	// send. This depends if we are a client/server.
	nextStreamID uint32
	
	// config holds our configuration
	config *Config
	
	// logger is used for our logs
	logger *log.Logger
	
	// conn is the underlying connection
	conn io.ReadWriteCloser
	
	// bufRead is a buffered reader
	bufRead *bufio.Reader
	
	// pings is used to track inflight pings
	pings    map[uint32]chan struct{}
	pingID   uint32
	pingLock sync.Mutex
	
	// streams maps a stream id to a stream, and inflight has an entry
	// for any outgoing stream that has not yet been established. Both are
	// protected by streamLock.
	streams    map[uint32]*Stream
	inflight   map[uint32]struct{}
	streamLock sync.Mutex
	
	// synCh acts like a semaphore. It is sized to the AcceptBacklog which
	// is assumed to be symmetric between the client and server. This allows
	// the client to avoid exceeding the backlog and instead blocks the open.
	synCh chan struct{}
	
	// acceptCh is used to pass ready streams to the client
	acceptCh chan *Stream
	
	// sendCh is used to mark a stream as ready to send,
	// or to send a header out directly.
	sendCh chan *sendReady
	
	// recvDoneCh is closed when recv() exits to avoid a race
	// between stream registration and stream shutdown
	recvDoneCh chan struct{}
	sendDoneCh chan struct{}
	
	// shutdown is used to safely close a session
	shutdown        bool
	shutdownErr     error
	shutdownCh      chan struct{}
	shutdownLock    sync.Mutex
	shutdownErrLock sync.Mutex
	}
	
	// sendReady is used to either mark a stream as ready
	// or to directly send a header
	type sendReady struct {
	Hdr  []byte
	mu   sync.Mutex // Protects Body from unsafe reads.
	Body []byte
	Err  chan error
	}
	
	// newSession is used to construct a new session
	func newSession(config *Config, conn io.ReadWriteCloser, client bool) *Session {
	logger := config.Logger
	if logger == nil {
	logger = log.New(config.LogOutput, "", log.LstdFlags)
	}
	
	s := &Session{
	config:     config,
	logger:     logger,
	conn:       conn,
	bufRead:    bufio.NewReader(conn),
	pings:      make(map[uint32]chan struct{}),
	streams:    make(map[uint32]*Stream),
	inflight:   make(map[uint32]struct{}),
	synCh:      make(chan struct{}, config.AcceptBacklog),
	acceptCh:   make(chan *Stream, config.AcceptBacklog),
	sendCh:     make(chan *sendReady, 64),
	recvDoneCh: make(chan struct{}),
	sendDoneCh: make(chan struct{}),
	shutdownCh: make(chan struct{}),
	}
	if client {
	s.nextStreamID = 1
	} else {
	s.nextStreamID = 2
	}
	go s.recv()
	go s.send()
	if config.EnableKeepAlive {
	go s.keepalive()
	}
	return s
	}
	
	// IsClosed does a safe check to see if we have shutdown
	func (s *Session) IsClosed() bool {
	select {
	case <-s.shutdownCh:
	return true
	default:
	return false
	}
	}
	
	// CloseChan returns a read-only channel which is closed as
	// soon as the session is closed.
	func (s *Session) CloseChan() <-chan struct{} {
	return s.shutdownCh
	}
	
	// NumStreams returns the number of currently open streams
	func (s *Session) NumStreams() int {
	s.streamLock.Lock()
	num := len(s.streams)
	s.streamLock.Unlock()
	return num
	}
	
	// Open is used to create a new stream as a net.Conn
	func (s *Session) Open() (net.Conn, error) {
	conn, err := s.OpenStream()
	if err != nil {
	return nil, err
	}
	return conn, nil
	}
	
	// OpenStream is used to create a new stream
	func (s *Session) OpenStream() (*Stream, error) {
	if s.IsClosed() {
	return nil, ErrSessionShutdown
	}
	if atomic.LoadInt32(&s.remoteGoAway) == 1 {
	return nil, ErrRemoteGoAway
	}
	
	// Block if we have too many inflight SYNs
	select {
	case s.synCh <- struct{}{}:
	case <-s.shutdownCh:
	return nil, ErrSessionShutdown
	}
	
	GET_ID:
	// Get an ID, and check for stream exhaustion
	id := atomic.LoadUint32(&s.nextStreamID)
	if id >= math.MaxUint32-1 {
	return nil, ErrStreamsExhausted
	}
	if !atomic.CompareAndSwapUint32(&s.nextStreamID, id, id+2) {
	goto GET_ID
	}
	
	// Register the stream
	stream := newStream(s, id, streamInit)
	s.streamLock.Lock()
	s.streams[id] = stream
	s.inflight[id] = struct{}{}
	s.streamLock.Unlock()
	
	if s.config.StreamOpenTimeout > 0 {
	go s.setOpenTimeout(stream)
	}
	
	// Send the window update to create
	if err := stream.sendWindowUpdate(); err != nil {
	select {
	case <-s.synCh:
	default:
	s.logger.Printf("[ERR] yamux: aborted stream open without inflight syn semaphore")
	}
	return nil, err
	}
	return stream, nil
	}
	
	// setOpenTimeout implements a timeout for streams that are opened but not established.
	// If the StreamOpenTimeout is exceeded we assume the peer is unable to ACK,
	// and close the session.
	// The number of running timers is bounded by the capacity of the synCh.
	func (s *Session) setOpenTimeout(stream *Stream) {
	timer := time.NewTimer(s.config.StreamOpenTimeout)
	defer timer.Stop()
	
	select {
	case <-stream.establishCh:
	return
	case <-s.shutdownCh:
	return
	case <-timer.C:
	// Timeout reached while waiting for ACK.
	// Close the session to force connection re-establishment.
	s.logger.Printf("[ERR] yamux: aborted stream open (destination=%s): %v", s.RemoteAddr().String(), ErrTimeout.err)
	s.Close()
	}
	}
	
	// Accept is used to block until the next available stream
	// is ready to be accepted.
	func (s *Session) Accept() (net.Conn, error) {
	conn, err := s.AcceptStream()
	if err != nil {
	return nil, err
	}
	return conn, err
	}
	
	// AcceptStream is used to block until the next available stream
	// is ready to be accepted.
	func (s *Session) AcceptStream() (*Stream, error) {
	select {
	case stream := <-s.acceptCh:
	if err := stream.sendWindowUpdate(); err != nil {
	return nil, err
	}
	return stream, nil
	case <-s.shutdownCh:
	return nil, s.shutdownErr
	}
	}
	
	// Close is used to close the session and all streams.
	// Attempts to send a GoAway before closing the connection.
	func (s *Session) Close() error {
	s.shutdownLock.Lock()
	defer s.shutdownLock.Unlock()
	
	if s.shutdown {
	return nil
	}
	s.shutdown = true
	
	s.shutdownErrLock.Lock()
	if s.shutdownErr == nil {
	s.shutdownErr = ErrSessionShutdown
	}
	s.shutdownErrLock.Unlock()
	
	close(s.shutdownCh)
	
	s.conn.Close()
	<-s.recvDoneCh
	
	s.streamLock.Lock()
	defer s.streamLock.Unlock()
	for _, stream := range s.streams {
	stream.forceClose()
	}
	<-s.sendDoneCh
	return nil
	}
	
	// exitErr is used to handle an error that is causing the
	// session to terminate.
	func (s *Session) exitErr(err error) {
	s.shutdownErrLock.Lock()
	if s.shutdownErr == nil {
	s.shutdownErr = err
	}
	s.shutdownErrLock.Unlock()
	s.Close()
	}
	
	// GoAway can be used to prevent accepting further
	// connections. It does not close the underlying conn.
	func (s *Session) GoAway() error {
	return s.waitForSend(s.goAway(goAwayNormal), nil)
	}
	
	// goAway is used to send a goAway message
	func (s *Session) goAway(reason uint32) header {
	atomic.SwapInt32(&s.localGoAway, 1)
	hdr := header(make([]byte, headerSize))
	hdr.encode(typeGoAway, 0, 0, reason)
	return hdr
	}
	
	// Ping is used to measure the RTT response time
	func (s *Session) Ping() (time.Duration, error) {
	// Get a channel for the ping
	ch := make(chan struct{})
	
	// Get a new ping id, mark as pending
	s.pingLock.Lock()
	id := s.pingID
	s.pingID++
	s.pings[id] = ch
	s.pingLock.Unlock()
	
	// Send the ping request
	hdr := header(make([]byte, headerSize))
	hdr.encode(typePing, flagSYN, 0, id)
	if err := s.waitForSend(hdr, nil); err != nil {
	return 0, err
	}
	
	// Wait for a response
	start := time.Now()
	select {
	case <-ch:
	case <-time.After(s.config.ConnectionWriteTimeout):
	s.pingLock.Lock()
	delete(s.pings, id) // Ignore it if a response comes later.
	s.pingLock.Unlock()
	return 0, ErrTimeout
	case <-s.shutdownCh:
	return 0, ErrSessionShutdown
	}
	
	// Compute the RTT
	return time.Now().Sub(start), nil
	}
	
	// keepalive is a long running goroutine that periodically does
	// a ping to keep the connection alive.
	func (s *Session) keepalive() {
	for {
	select {
	case <-time.After(s.config.KeepAliveInterval):
	_, err := s.Ping()
	if err != nil {
	if err != ErrSessionShutdown {
	s.logger.Printf("[ERR] yamux: keepalive failed: %v", err)
	s.exitErr(ErrKeepAliveTimeout)
	}
	return
	}
	case <-s.shutdownCh:
	return
	}
	}
	}
	
	// waitForSendErr waits to send a header, checking for a potential shutdown
	func (s *Session) waitForSend(hdr header, body []byte) error {
	errCh := make(chan error, 1)
	return s.waitForSendErr(hdr, body, errCh)
	}
	
	// waitForSendErr waits to send a header with optional data, checking for a
	// potential shutdown. Since there's the expectation that sends can happen
	// in a timely manner, we enforce the connection write timeout here.
	func (s *Session) waitForSendErr(hdr header, body []byte, errCh chan error) error {
	t := timerPool.Get()
	timer := t.(*time.Timer)
	timer.Reset(s.config.ConnectionWriteTimeout)
	defer func() {
	timer.Stop()
	select {
	case <-timer.C:
	default:
	}
	timerPool.Put(t)
	}()
	
	ready := &sendReady{Hdr: hdr, Body: body, Err: errCh}
	select {
	case s.sendCh <- ready:
	case <-s.shutdownCh:
	return ErrSessionShutdown
	case <-timer.C:
	return ErrConnectionWriteTimeout
	}
	
	bodyCopy := func() {
	if body == nil {
	return // A nil body is ignored.
	}
	
	// In the event of session shutdown or connection write timeout,
	// we need to prevent `send` from reading the body buffer after
	// returning from this function since the caller may re-use the
	// underlying array.
	ready.mu.Lock()
	defer ready.mu.Unlock()
	
	if ready.Body == nil {
	return // Body was already copied in `send`.
	}
	newBody := make([]byte, len(body))
	copy(newBody, body)
	ready.Body = newBody
	}
	
	select {
	case err := <-errCh:
	return err
	case <-s.shutdownCh:
	bodyCopy()
	return ErrSessionShutdown
	case <-timer.C:
	bodyCopy()
	return ErrConnectionWriteTimeout
	}
	}
	
	// sendNoWait does a send without waiting. Since there's the expectation that
	// the send happens right here, we enforce the connection write timeout if we
	// can't queue the header to be sent.
	func (s *Session) sendNoWait(hdr header) error {
	t := timerPool.Get()
	timer := t.(*time.Timer)
	timer.Reset(s.config.ConnectionWriteTimeout)
	defer func() {
	timer.Stop()
	select {
	case <-timer.C:
	default:
	}
	timerPool.Put(t)
	}()
	
	select {
	case s.sendCh <- &sendReady{Hdr: hdr}:
	return nil
	case <-s.shutdownCh:
	return ErrSessionShutdown
	case <-timer.C:
	return ErrConnectionWriteTimeout
	}
	}
	
	// send is a long running goroutine that sends data
	func (s *Session) send() {
	if err := s.sendLoop(); err != nil {
	s.exitErr(err)
	}
	}
	
	func (s *Session) sendLoop() error {
	defer close(s.sendDoneCh)
	var bodyBuf bytes.Buffer
	for {
	bodyBuf.Reset()
	
	select {
	case ready := <-s.sendCh:
	// Send a header if ready
	if ready.Hdr != nil {
	_, err := s.conn.Write(ready.Hdr)
	if err != nil {
	s.logger.Printf("[ERR] yamux: Failed to write header: %v", err)
	asyncSendErr(ready.Err, err)
	return err
	}
	}
	
	ready.mu.Lock()
	if ready.Body != nil {
	// Copy the body into the buffer to avoid
	// holding a mutex lock during the write.
	_, err := bodyBuf.Write(ready.Body)
	if err != nil {
	ready.Body = nil
	ready.mu.Unlock()
	s.logger.Printf("[ERR] yamux: Failed to copy body into buffer: %v", err)
	asyncSendErr(ready.Err, err)
	return err
	}
	ready.Body = nil
	}
	ready.mu.Unlock()
	
	if bodyBuf.Len() > 0 {
	// Send data from a body if given
	_, err := s.conn.Write(bodyBuf.Bytes())
	if err != nil {
	s.logger.Printf("[ERR] yamux: Failed to write body: %v", err)
	asyncSendErr(ready.Err, err)
	return err
	}
	}
	
	// No error, successful send
	asyncSendErr(ready.Err, nil)
	case <-s.shutdownCh:
	return nil
	}
	}
	}
	
	// recv is a long running goroutine that accepts new data
	func (s *Session) recv() {
	if err := s.recvLoop(); err != nil {
	s.exitErr(err)
	}
	}
	
	// Ensure that the index of the handler (typeData/typeWindowUpdate/etc) matches the message type
	var (
	handlers = []func(*Session, header) error{
	typeData:         (*Session).handleStreamMessage,
	typeWindowUpdate: (*Session).handleStreamMessage,
	typePing:         (*Session).handlePing,
	typeGoAway:       (*Session).handleGoAway,
	}
	)
	
	// recvLoop continues to receive data until a fatal error is encountered
	func (s *Session) recvLoop() error {
	defer close(s.recvDoneCh)
	hdr := header(make([]byte, headerSize))
	for {
	// Read the header
	if _, err := io.ReadFull(s.bufRead, hdr); err != nil {
	if err != io.EOF && !strings.Contains(err.Error(), "closed") && !strings.Contains(err.Error(), "reset by peer") {
	s.logger.Printf("[ERR] yamux: Failed to read header: %v", err)
	}
	return err
	}
	
	// Verify the version
	if hdr.Version() != protoVersion {
	s.logger.Printf("[ERR] yamux: Invalid protocol version: %d", hdr.Version())
	return ErrInvalidVersion
	}
	
	mt := hdr.MsgType()
	if mt < typeData || mt > typeGoAway {
	return ErrInvalidMsgType
	}
	
	if err := handlers[mt](s, hdr); err != nil {
	return err
	}
	}
	}
	
	// handleStreamMessage handles either a data or window update frame
	func (s *Session) handleStreamMessage(hdr header) error {
	// Check for a new stream creation
	id := hdr.StreamID()
	flags := hdr.Flags()
	if flags&flagSYN == flagSYN {
	if err := s.incomingStream(id); err != nil {
	return err
	}
	}
	
	// Get the stream
	s.streamLock.Lock()
	stream := s.streams[id]
	s.streamLock.Unlock()
	
	// If we do not have a stream, likely we sent a RST
	if stream == nil {
	// Drain any data on the wire
	if hdr.MsgType() == typeData && hdr.Length() > 0 {
	s.logger.Printf("[WARN] yamux: Discarding data for stream: %d", id)
	if _, err := io.CopyN(ioutil.Discard, s.bufRead, int64(hdr.Length())); err != nil {
	s.logger.Printf("[ERR] yamux: Failed to discard data: %v", err)
	return nil
	}
	} else {
	s.logger.Printf("[WARN] yamux: frame for missing stream: %v", hdr)
	}
	return nil
	}
	
	// Check if this is a window update
	if hdr.MsgType() == typeWindowUpdate {
	if err := stream.incrSendWindow(hdr, flags); err != nil {
	if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil {
	s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr)
	}
	return err
	}
	return nil
	}
	
	// Read the new data
	if err := stream.readData(hdr, flags, s.bufRead); err != nil {
	if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil {
	s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr)
	}
	return err
	}
	return nil
	}
	
	// handlePing is invokde for a typePing frame
	func (s *Session) handlePing(hdr header) error {
	flags := hdr.Flags()
	pingID := hdr.Length()
	
	// Check if this is a query, respond back in a separate context so we
	// don't interfere with the receiving thread blocking for the write.
	if flags&flagSYN == flagSYN {
	go func() {
	hdr := header(make([]byte, headerSize))
	hdr.encode(typePing, flagACK, 0, pingID)
	if err := s.sendNoWait(hdr); err != nil {
	s.logger.Printf("[WARN] yamux: failed to send ping reply: %v", err)
	}
	}()
	return nil
	}
	
	// Handle a response
	s.pingLock.Lock()
	ch := s.pings[pingID]
	if ch != nil {
	delete(s.pings, pingID)
	close(ch)
	}
	s.pingLock.Unlock()
	return nil
	}
	
	// handleGoAway is invokde for a typeGoAway frame
	func (s *Session) handleGoAway(hdr header) error {
	code := hdr.Length()
	switch code {
	case goAwayNormal:
	atomic.SwapInt32(&s.remoteGoAway, 1)
	case goAwayProtoErr:
	s.logger.Printf("[ERR] yamux: received protocol error go away")
	return fmt.Errorf("yamux protocol error")
	case goAwayInternalErr:
	s.logger.Printf("[ERR] yamux: received internal error go away")
	return fmt.Errorf("remote yamux internal error")
	default:
	s.logger.Printf("[ERR] yamux: received unexpected go away")
	return fmt.Errorf("unexpected go away received")
	}
	return nil
	}
	
	// incomingStream is used to create a new incoming stream
	func (s *Session) incomingStream(id uint32) error {
	// Reject immediately if we are doing a go away
	if atomic.LoadInt32(&s.localGoAway) == 1 {
	hdr := header(make([]byte, headerSize))
	hdr.encode(typeWindowUpdate, flagRST, id, 0)
	return s.sendNoWait(hdr)
	}
	
	// Allocate a new stream
	stream := newStream(s, id, streamSYNReceived)
	
	s.streamLock.Lock()
	defer s.streamLock.Unlock()
	
	// Check if stream already exists
	if _, ok := s.streams[id]; ok {
	s.logger.Printf("[ERR] yamux: duplicate stream declared")
	if sendErr := s.sendNoWait(s.goAway(goAwayProtoErr)); sendErr != nil {
	s.logger.Printf("[WARN] yamux: failed to send go away: %v", sendErr)
	}
	return ErrDuplicateStream
	}
	
	// Register the stream
	s.streams[id] = stream
	
	// Check if we've exceeded the backlog
	select {
	case s.acceptCh <- stream:
	return nil
	default:
	// Backlog exceeded! RST the stream
	s.logger.Printf("[WARN] yamux: backlog exceeded, forcing connection reset")
	delete(s.streams, id)
	hdr := header(make([]byte, headerSize))
	hdr.encode(typeWindowUpdate, flagRST, id, 0)
	return s.sendNoWait(hdr)
	}
	}
	
	// closeStream is used to close a stream once both sides have
	// issued a close. If there was an in-flight SYN and the stream
	// was not yet established, then this will give the credit back.
	func (s *Session) closeStream(id uint32) {
	s.streamLock.Lock()
	if _, ok := s.inflight[id]; ok {
	select {
	case <-s.synCh:
	default:
	s.logger.Printf("[ERR] yamux: SYN tracking out of sync")
	}
	}
	delete(s.streams, id)
	s.streamLock.Unlock()
	}
	
	// establishStream is used to mark a stream that was in the
	// SYN Sent state as established.
	func (s *Session) establishStream(id uint32) {
	s.streamLock.Lock()
	if _, ok := s.inflight[id]; ok {
	delete(s.inflight, id)
	} else {
	s.logger.Printf("[ERR] yamux: established stream without inflight SYN (no tracking entry)")
	}
	select {
	case <-s.synCh:
	default:
	s.logger.Printf("[ERR] yamux: established stream without inflight SYN (didn't have semaphore)")
	}
	s.streamLock.Unlock()
	}

github.com/hashicorp/yamux/spec.md:

	# Specification
	
	We use this document to detail the internal specification of Yamux.
	This is used both as a guide for implementing Yamux, but also for
	alternative interoperable libraries to be built.
	
	# Framing
	
	Yamux uses a streaming connection underneath, but imposes a message
	framing so that it can be shared between many logical streams. Each
	frame contains a header like:
	
	* Version (8 bits)
	* Type (8 bits)
	* Flags (16 bits)
	* StreamID (32 bits)
	* Length (32 bits)
	
	This means that each header has a 12 byte overhead.
	All fields are encoded in network order (big endian).
	Each field is described below:
	
	## Version Field
	
	The version field is used for future backward compatibility. At the
	current time, the field is always set to 0, to indicate the initial
	version.
	
	## Type Field
	
	The type field is used to switch the frame message type. The following
	message types are supported:
	
	* 0x0 Data - Used to transmit data. May transmit zero length payloads
	depending on the flags.
	
	* 0x1 Window Update - Used to updated the senders receive window size.
	This is used to implement per-session flow control.
	
	* 0x2 Ping - Used to measure RTT. It can also be used to heart-beat
	and do keep-alives over TCP.
	
	* 0x3 Go Away - Used to close a session.
	
	## Flag Field
	
	The flags field is used to provide additional information related
	to the message type. The following flags are supported:
	
	* 0x1 SYN - Signals the start of a new stream. May be sent with a data or
	window update message. Also sent with a ping to indicate outbound.
	
	* 0x2 ACK - Acknowledges the start of a new stream. May be sent with a data
	or window update message. Also sent with a ping to indicate response.
	
	* 0x4 FIN - Performs a half-close of a stream. May be sent with a data
	message or window update.
	
	* 0x8 RST - Reset a stream immediately. May be sent with a data or
	window update message.
	
	## StreamID Field
	
	The StreamID field is used to identify the logical stream the frame
	is addressing. The client side should use odd ID's, and the server even.
	This prevents any collisions. Additionally, the 0 ID is reserved to represent
	the session.
	
	Both Ping and Go Away messages should always use the 0 StreamID.
	
	## Length Field
	
	The meaning of the length field depends on the message type:
	
	* Data - provides the length of bytes following the header
	* Window update - provides a delta update to the window size
	* Ping - Contains an opaque value, echoed back
	* Go Away - Contains an error code
	
	# Message Flow
	
	There is no explicit connection setup, as Yamux relies on an underlying
	transport to be provided. However, there is a distinction between client
	and server side of the connection.
	
	## Opening a stream
	
	To open a stream, an initial data or window update frame is sent
	with a new StreamID. The SYN flag should be set to signal a new stream.
	
	The receiver must then reply with either a data or window update frame
	with the StreamID along with the ACK flag to accept the stream or with
	the RST flag to reject the stream.
	
	Because we are relying on the reliable stream underneath, a connection
	can begin sending data once the SYN flag is sent. The corresponding
	ACK does not need to be received. This is particularly well suited
	for an RPC system where a client wants to open a stream and immediately
	fire a request without waiting for the RTT of the ACK.
	
	This does introduce the possibility of a connection being rejected
	after data has been sent already. This is a slight semantic difference
	from TCP, where the conection cannot be refused after it is opened.
	Clients should be prepared to handle this by checking for an error
	that indicates a RST was received.
	
	## Closing a stream
	
	To close a stream, either side sends a data or window update frame
	along with the FIN flag. This does a half-close indicating the sender
	will send no further data.
	
	Once both sides have closed the connection, the stream is closed.
	
	Alternatively, if an error occurs, the RST flag can be used to
	hard close a stream immediately.
	
	## Flow Control
	
	When Yamux is initially starts each stream with a 256KB window size.
	There is no window size for the session.
	
	To prevent the streams from stalling, window update frames should be
	sent regularly. Yamux can be configured to provide a larger limit for
	windows sizes. Both sides assume the initial 256KB window, but can
	immediately send a window update as part of the SYN/ACK indicating a
	larger window.
	
	Both sides should track the number of bytes sent in Data frames
	only, as only they are tracked as part of the window size.
	
	## Session termination
	
	When a session is being terminated, the Go Away message should
	be sent. The Length should be set to one of the following to
	provide an error code:
	
	* 0x0 Normal termination
	* 0x1 Protocol error
	* 0x2 Internal error

github.com/hashicorp/yamux/stream.go:

	package yamux
	
	import (
	"bytes"
	"errors"
	"io"
	"sync"
	"sync/atomic"
	"time"
	)
	
	type streamState int
	
	const (
	streamInit streamState = iota
	streamSYNSent
	streamSYNReceived
	streamEstablished
	streamLocalClose
	streamRemoteClose
	streamClosed
	streamReset
	)
	
	// Stream is used to represent a logical stream
	// within a session.
	type Stream struct {
	recvWindow uint32
	sendWindow uint32
	
	id      uint32
	session *Session
	
	state     streamState
	stateLock sync.Mutex
	
	recvBuf  *bytes.Buffer
	recvLock sync.Mutex
	
	controlHdr     header
	controlErr     chan error
	controlHdrLock sync.Mutex
	
	sendHdr  header
	sendErr  chan error
	sendLock sync.Mutex
	
	recvNotifyCh chan struct{}
	sendNotifyCh chan struct{}
	
	readDeadline  atomic.Value // time.Time
	writeDeadline atomic.Value // time.Time
	
	// establishCh is notified if the stream is established or being closed.
	establishCh chan struct{}
	
	// closeTimer is set with stateLock held to honor the StreamCloseTimeout
	// setting on Session.
	closeTimer *time.Timer
	}
	
	// newStream is used to construct a new stream within
	// a given session for an ID
	func newStream(session *Session, id uint32, state streamState) *Stream {
	s := &Stream{
	id:           id,
	session:      session,
	state:        state,
	controlHdr:   header(make([]byte, headerSize)),
	controlErr:   make(chan error, 1),
	sendHdr:      header(make([]byte, headerSize)),
	sendErr:      make(chan error, 1),
	recvWindow:   initialStreamWindow,
	sendWindow:   initialStreamWindow,
	recvNotifyCh: make(chan struct{}, 1),
	sendNotifyCh: make(chan struct{}, 1),
	establishCh:  make(chan struct{}, 1),
	}
	s.readDeadline.Store(time.Time{})
	s.writeDeadline.Store(time.Time{})
	return s
	}
	
	// Session returns the associated stream session
	func (s *Stream) Session() *Session {
	return s.session
	}
	
	// StreamID returns the ID of this stream
	func (s *Stream) StreamID() uint32 {
	return s.id
	}
	
	// Read is used to read from the stream
	func (s *Stream) Read(b []byte) (n int, err error) {
	defer asyncNotify(s.recvNotifyCh)
	START:
	s.stateLock.Lock()
	switch s.state {
	case streamLocalClose:
	fallthrough
	case streamRemoteClose:
	fallthrough
	case streamClosed:
	s.recvLock.Lock()
	if s.recvBuf == nil || s.recvBuf.Len() == 0 {
	s.recvLock.Unlock()
	s.stateLock.Unlock()
	return 0, io.EOF
	}
	s.recvLock.Unlock()
	case streamReset:
	s.stateLock.Unlock()
	return 0, ErrConnectionReset
	}
	s.stateLock.Unlock()
	
	// If there is no data available, block
	s.recvLock.Lock()
	if s.recvBuf == nil || s.recvBuf.Len() == 0 {
	s.recvLock.Unlock()
	goto WAIT
	}
	
	// Read any bytes
	n, _ = s.recvBuf.Read(b)
	s.recvLock.Unlock()
	
	// Send a window update potentially
	err = s.sendWindowUpdate()
	if err == ErrSessionShutdown {
	err = nil
	}
	return n, err
	
	WAIT:
	var timeout <-chan time.Time
	var timer *time.Timer
	readDeadline := s.readDeadline.Load().(time.Time)
	if !readDeadline.IsZero() {
	delay := readDeadline.Sub(time.Now())
	timer = time.NewTimer(delay)
	timeout = timer.C
	}
	select {
	case <-s.recvNotifyCh:
	if timer != nil {
	timer.Stop()
	}
	goto START
	case <-timeout:
	return 0, ErrTimeout
	}
	}
	
	// Write is used to write to the stream
	func (s *Stream) Write(b []byte) (n int, err error) {
	s.sendLock.Lock()
	defer s.sendLock.Unlock()
	total := 0
	for total < len(b) {
	n, err := s.write(b[total:])
	total += n
	if err != nil {
	return total, err
	}
	}
	return total, nil
	}
	
	// write is used to write to the stream, may return on
	// a short write.
	func (s *Stream) write(b []byte) (n int, err error) {
	var flags uint16
	var max uint32
	var body []byte
	START:
	s.stateLock.Lock()
	switch s.state {
	case streamLocalClose:
	fallthrough
	case streamClosed:
	s.stateLock.Unlock()
	return 0, ErrStreamClosed
	case streamReset:
	s.stateLock.Unlock()
	return 0, ErrConnectionReset
	}
	s.stateLock.Unlock()
	
	// If there is no data available, block
	window := atomic.LoadUint32(&s.sendWindow)
	if window == 0 {
	goto WAIT
	}
	
	// Determine the flags if any
	flags = s.sendFlags()
	
	// Send up to our send window
	max = min(window, uint32(len(b)))
	body = b[:max]
	
	// Send the header
	s.sendHdr.encode(typeData, flags, s.id, max)
	if err = s.session.waitForSendErr(s.sendHdr, body, s.sendErr); err != nil {
	if errors.Is(err, ErrSessionShutdown) || errors.Is(err, ErrConnectionWriteTimeout) {
	// Message left in ready queue, header re-use is unsafe.
	s.sendHdr = header(make([]byte, headerSize))
	}
	return 0, err
	}
	
	// Reduce our send window
	atomic.AddUint32(&s.sendWindow, ^uint32(max-1))
	
	// Unlock
	return int(max), err
	
	WAIT:
	var timeout <-chan time.Time
	writeDeadline := s.writeDeadline.Load().(time.Time)
	if !writeDeadline.IsZero() {
	delay := writeDeadline.Sub(time.Now())
	timeout = time.After(delay)
	}
	select {
	case <-s.sendNotifyCh:
	goto START
	case <-timeout:
	return 0, ErrTimeout
	}
	return 0, nil
	}
	
	// sendFlags determines any flags that are appropriate
	// based on the current stream state
	func (s *Stream) sendFlags() uint16 {
	s.stateLock.Lock()
	defer s.stateLock.Unlock()
	var flags uint16
	switch s.state {
	case streamInit:
	flags |= flagSYN
	s.state = streamSYNSent
	case streamSYNReceived:
	flags |= flagACK
	s.state = streamEstablished
	}
	return flags
	}
	
	// sendWindowUpdate potentially sends a window update enabling
	// further writes to take place. Must be invoked with the lock.
	func (s *Stream) sendWindowUpdate() error {
	s.controlHdrLock.Lock()
	defer s.controlHdrLock.Unlock()
	
	// Determine the delta update
	max := s.session.config.MaxStreamWindowSize
	var bufLen uint32
	s.recvLock.Lock()
	if s.recvBuf != nil {
	bufLen = uint32(s.recvBuf.Len())
	}
	delta := (max - bufLen) - s.recvWindow
	
	// Determine the flags if any
	flags := s.sendFlags()
	
	// Check if we can omit the update
	if delta < (max/2) && flags == 0 {
	s.recvLock.Unlock()
	return nil
	}
	
	// Update our window
	s.recvWindow += delta
	s.recvLock.Unlock()
	
	// Send the header
	s.controlHdr.encode(typeWindowUpdate, flags, s.id, delta)
	if err := s.session.waitForSendErr(s.controlHdr, nil, s.controlErr); err != nil {
	if errors.Is(err, ErrSessionShutdown) || errors.Is(err, ErrConnectionWriteTimeout) {
	// Message left in ready queue, header re-use is unsafe.
	s.controlHdr = header(make([]byte, headerSize))
	}
	return err
	}
	return nil
	}
	
	// sendClose is used to send a FIN
	func (s *Stream) sendClose() error {
	s.controlHdrLock.Lock()
	defer s.controlHdrLock.Unlock()
	
	flags := s.sendFlags()
	flags |= flagFIN
	s.controlHdr.encode(typeWindowUpdate, flags, s.id, 0)
	if err := s.session.waitForSendErr(s.controlHdr, nil, s.controlErr); err != nil {
	if errors.Is(err, ErrSessionShutdown) || errors.Is(err, ErrConnectionWriteTimeout) {
	// Message left in ready queue, header re-use is unsafe.
	s.controlHdr = header(make([]byte, headerSize))
	}
	return err
	}
	return nil
	}
	
	// Close is used to close the stream
	func (s *Stream) Close() error {
	closeStream := false
	s.stateLock.Lock()
	switch s.state {
	// Opened means we need to signal a close
	case streamSYNSent:
	fallthrough
	case streamSYNReceived:
	fallthrough
	case streamEstablished:
	s.state = streamLocalClose
	goto SEND_CLOSE
	
	case streamLocalClose:
	case streamRemoteClose:
	s.state = streamClosed
	closeStream = true
	goto SEND_CLOSE
	
	case streamClosed:
	case streamReset:
	default:
	panic("unhandled state")
	}
	s.stateLock.Unlock()
	return nil
	SEND_CLOSE:
	// This shouldn't happen (the more realistic scenario to cancel the
	// timer is via processFlags) but just in case this ever happens, we
	// cancel the timer to prevent dangling timers.
	if s.closeTimer != nil {
	s.closeTimer.Stop()
	s.closeTimer = nil
	}
	
	// If we have a StreamCloseTimeout set we start the timeout timer.
	// We do this only if we're not already closing the stream since that
	// means this was a graceful close.
	//
	// This prevents memory leaks if one side (this side) closes and the
	// remote side poorly behaves and never responds with a FIN to complete
	// the close. After the specified timeout, we clean our resources up no
	// matter what.
	if !closeStream && s.session.config.StreamCloseTimeout > 0 {
	s.closeTimer = time.AfterFunc(
	s.session.config.StreamCloseTimeout, s.closeTimeout)
	}
	
	s.stateLock.Unlock()
	s.sendClose()
	s.notifyWaiting()
	if closeStream {
	s.session.closeStream(s.id)
	}
	return nil
	}
	
	// closeTimeout is called after StreamCloseTimeout during a close to
	// close this stream.
	func (s *Stream) closeTimeout() {
	// Close our side forcibly
	s.forceClose()
	
	// Free the stream from the session map
	s.session.closeStream(s.id)
	
	// Send a RST so the remote side closes too.
	s.sendLock.Lock()
	defer s.sendLock.Unlock()
	hdr := header(make([]byte, headerSize))
	hdr.encode(typeWindowUpdate, flagRST, s.id, 0)
	s.session.sendNoWait(hdr)
	}
	
	// forceClose is used for when the session is exiting
	func (s *Stream) forceClose() {
	s.stateLock.Lock()
	s.state = streamClosed
	s.stateLock.Unlock()
	s.notifyWaiting()
	}
	
	// processFlags is used to update the state of the stream
	// based on set flags, if any. Lock must be held
	func (s *Stream) processFlags(flags uint16) error {
	s.stateLock.Lock()
	defer s.stateLock.Unlock()
	
	// Close the stream without holding the state lock
	closeStream := false
	defer func() {
	if closeStream {
	if s.closeTimer != nil {
	// Stop our close timeout timer since we gracefully closed
	s.closeTimer.Stop()
	}
	
	s.session.closeStream(s.id)
	}
	}()
	
	if flags&flagACK == flagACK {
	if s.state == streamSYNSent {
	s.state = streamEstablished
	}
	asyncNotify(s.establishCh)
	s.session.establishStream(s.id)
	}
	if flags&flagFIN == flagFIN {
	switch s.state {
	case streamSYNSent:
	fallthrough
	case streamSYNReceived:
	fallthrough
	case streamEstablished:
	s.state = streamRemoteClose
	s.notifyWaiting()
	case streamLocalClose:
	s.state = streamClosed
	closeStream = true
	s.notifyWaiting()
	default:
	s.session.logger.Printf("[ERR] yamux: unexpected FIN flag in state %d", s.state)
	return ErrUnexpectedFlag
	}
	}
	if flags&flagRST == flagRST {
	s.state = streamReset
	closeStream = true
	s.notifyWaiting()
	}
	return nil
	}
	
	// notifyWaiting notifies all the waiting channels
	func (s *Stream) notifyWaiting() {
	asyncNotify(s.recvNotifyCh)
	asyncNotify(s.sendNotifyCh)
	asyncNotify(s.establishCh)
	}
	
	// incrSendWindow updates the size of our send window
	func (s *Stream) incrSendWindow(hdr header, flags uint16) error {
	if err := s.processFlags(flags); err != nil {
	return err
	}
	
	// Increase window, unblock a sender
	atomic.AddUint32(&s.sendWindow, hdr.Length())
	asyncNotify(s.sendNotifyCh)
	return nil
	}
	
	// readData is used to handle a data frame
	func (s *Stream) readData(hdr header, flags uint16, conn io.Reader) error {
	if err := s.processFlags(flags); err != nil {
	return err
	}
	
	// Check that our recv window is not exceeded
	length := hdr.Length()
	if length == 0 {
	return nil
	}
	
	// Wrap in a limited reader
	conn = &io.LimitedReader{R: conn, N: int64(length)}
	
	// Copy into buffer
	s.recvLock.Lock()
	
	if length > s.recvWindow {
	s.session.logger.Printf("[ERR] yamux: receive window exceeded (stream: %d, remain: %d, recv: %d)", s.id, s.recvWindow, length)
	s.recvLock.Unlock()
	return ErrRecvWindowExceeded
	}
	
	if s.recvBuf == nil {
	// Allocate the receive buffer just-in-time to fit the full data frame.
	// This way we can read in the whole packet without further allocations.
	s.recvBuf = bytes.NewBuffer(make([]byte, 0, length))
	}
	copiedLength, err := io.Copy(s.recvBuf, conn)
	if err != nil {
	s.session.logger.Printf("[ERR] yamux: Failed to read stream data: %v", err)
	s.recvLock.Unlock()
	return err
	}
	
	// Decrement the receive window
	s.recvWindow -= uint32(copiedLength)
	s.recvLock.Unlock()
	
	// Unblock any readers
	asyncNotify(s.recvNotifyCh)
	return nil
	}
	
	// SetDeadline sets the read and write deadlines
	func (s *Stream) SetDeadline(t time.Time) error {
	if err := s.SetReadDeadline(t); err != nil {
	return err
	}
	if err := s.SetWriteDeadline(t); err != nil {
	return err
	}
	return nil
	}
	
	// SetReadDeadline sets the deadline for blocked and future Read calls.
	func (s *Stream) SetReadDeadline(t time.Time) error {
	s.readDeadline.Store(t)
	asyncNotify(s.recvNotifyCh)
	return nil
	}
	
	// SetWriteDeadline sets the deadline for blocked and future Write calls
	func (s *Stream) SetWriteDeadline(t time.Time) error {
	s.writeDeadline.Store(t)
	asyncNotify(s.sendNotifyCh)
	return nil
	}
	
	// Shrink is used to compact the amount of buffers utilized
	// This is useful when using Yamux in a connection pool to reduce
	// the idle memory utilization.
	func (s *Stream) Shrink() {
	s.recvLock.Lock()
	if s.recvBuf != nil && s.recvBuf.Len() == 0 {
	s.recvBuf = nil
	}
	s.recvLock.Unlock()
	}

github.com/hashicorp/yamux/util.go:

	package yamux
	
	import (
	"sync"
	"time"
	)
	
	var (
	timerPool = &sync.Pool{
	New: func() interface{} {
	timer := time.NewTimer(time.Hour * 1e6)
	timer.Stop()
	return timer
	},
	}
	)
	
	// asyncSendErr is used to try an async send of an error
	func asyncSendErr(ch chan error, err error) {
	if ch == nil {
	return
	}
	select {
	case ch <- err:
	default:
	}
	}
	
	// asyncNotify is used to signal a waiting goroutine
	func asyncNotify(ch chan struct{}) {
	select {
	case ch <- struct{}{}:
	default:
	}
	}
	
	// min computes the minimum of two values
	func min(a, b uint32) uint32 {
	if a < b {
	return a
	}
	return b
	}

github.com/jcmturner/aescts/v2/LICENSE:

	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "{}"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright {yyyy} {name of copyright owner}
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/jcmturner/dnsutils/v2/LICENSE:

	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "[]"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright [yyyy] [name of copyright owner]
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/jcmturner/gofork/LICENSE:

	Copyright (c) 2009 The Go Authors. All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google Inc. nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

github.com/jcmturner/goidentity/v6/LICENSE:

	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "{}"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright {yyyy} {name of copyright owner}
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/jcmturner/gokrb5/v8/LICENSE:

	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "{}"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright {yyyy} {name of copyright owner}
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/jcmturner/rpc/v2/LICENSE:

	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "[]"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright [yyyy] [name of copyright owner]
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/jinzhu/copier/License:

	The MIT License (MIT)
	
	Copyright (c) 2015 Jinzhu
	
	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
	the Software, and to permit persons to whom the Software is furnished to do so,
	subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
	FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
	COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
	IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
	CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

github.com/lukask32/fleeting-plugin-proxmox/LICENSE:

	MIT License
	
	Copyright (c) 2024 Łukasz Kirylak
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.

github.com/luthermonson/go-proxmox/LICENSE:

	
	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	

github.com/masterzen/simplexml/dom/LICENSE:

	
	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "[]"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright [yyyy] [name of copyright owner]
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/masterzen/winrm/LICENSE:

	
	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "[]"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright [yyyy] [name of copyright owner]
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/mattn/go-colorable/LICENSE:

	The MIT License (MIT)
	
	Copyright (c) 2016 Yasuhiro Matsumoto
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.

github.com/mattn/go-isatty/LICENSE:

	Copyright (c) Yasuhiro MATSUMOTO <mattn.jp@gmail.com>
	
	MIT License (Expat)
	
	Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

github.com/mitchellh/go-testing-interface/LICENSE:

	The MIT License (MIT)
	
	Copyright (c) 2016 Mitchell Hashimoto
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.

github.com/oklog/run/LICENSE:

	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "[]"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright [yyyy] [name of copyright owner]
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

github.com/pmezard/go-difflib/difflib/LICENSE:

	Copyright (c) 2013, Patrick Mezard
	All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	Redistributions in binary form must reproduce the above copyright
	notice, this list of conditions and the following disclaimer in the
	documentation and/or other materials provided with the distribution.
	The names of its contributors may not be used to endorse or promote
	products derived from this software without specific prior written
	permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
	IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
	PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
	TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
	PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
	LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
	NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
	SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

github.com/stretchr/testify/LICENSE:

	MIT License
	
	Copyright (c) 2012-2020 Mat Ryer, Tyler Bunnell and contributors.
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.

github.com/tidwall/transform/LICENSE:

	ISC License
	
	Copyright (c) 2017, Joshua J Baker
	
	Permission to use, copy, modify, and/or distribute this software for any purpose
	with or without fee is hereby granted, provided that the above copyright notice
	and this permission notice appear in all copies.
	
	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
	FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
	OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
	TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
	THIS SOFTWARE.

gitlab.com/gitlab-org/fleeting/fleeting/LICENSE:

	The MIT License (MIT)
	
	Copyright (c) 2015-present GitLab B.V.
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
	

gitlab.com/gitlab-org/fleeting/fleeting/NOTICE:

	With regard to the GitLab Software:
	
	The MIT License (MIT)
	
	Copyright (c) 2015-present GitLab B.V.
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
	
	---
	
	For all third party components incorporated into the GitLab Software, those
	components are licensed under the original license provided by the owner of the
	applicable component.
	
	---
	
	All Documentation content that resides under the docs/ directory of this
	repository is licensed under Creative Commons: CC BY-SA 4.0.

golang.org/x/crypto/LICENSE:

	Copyright 2009 The Go Authors.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google LLC nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

golang.org/x/mod/LICENSE:

	Copyright (c) 2009 The Go Authors. All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google Inc. nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

golang.org/x/net/LICENSE:

	Copyright (c) 2009 The Go Authors. All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google Inc. nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

golang.org/x/sync/errgroup/LICENSE:

	Copyright 2009 The Go Authors.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google LLC nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

golang.org/x/sys/unix/LICENSE:

	Copyright 2009 The Go Authors.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google LLC nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

golang.org/x/text/LICENSE:

	Copyright 2009 The Go Authors.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google LLC nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

google.golang.org/genproto/googleapis/rpc/status/LICENSE:

	
	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "[]"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright [yyyy] [name of copyright owner]
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

google.golang.org/grpc/LICENSE:

	
	Apache License
	Version 2.0, January 2004
	http://www.apache.org/licenses/
	
	TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
	
	1. Definitions.
	
	"License" shall mean the terms and conditions for use, reproduction,
	and distribution as defined by Sections 1 through 9 of this document.
	
	"Licensor" shall mean the copyright owner or entity authorized by
	the copyright owner that is granting the License.
	
	"Legal Entity" shall mean the union of the acting entity and all
	other entities that control, are controlled by, or are under common
	control with that entity. For the purposes of this definition,
	"control" means (i) the power, direct or indirect, to cause the
	direction or management of such entity, whether by contract or
	otherwise, or (ii) ownership of fifty percent (50%) or more of the
	outstanding shares, or (iii) beneficial ownership of such entity.
	
	"You" (or "Your") shall mean an individual or Legal Entity
	exercising permissions granted by this License.
	
	"Source" form shall mean the preferred form for making modifications,
	including but not limited to software source code, documentation
	source, and configuration files.
	
	"Object" form shall mean any form resulting from mechanical
	transformation or translation of a Source form, including but
	not limited to compiled object code, generated documentation,
	and conversions to other media types.
	
	"Work" shall mean the work of authorship, whether in Source or
	Object form, made available under the License, as indicated by a
	copyright notice that is included in or attached to the work
	(an example is provided in the Appendix below).
	
	"Derivative Works" shall mean any work, whether in Source or Object
	form, that is based on (or derived from) the Work and for which the
	editorial revisions, annotations, elaborations, or other modifications
	represent, as a whole, an original work of authorship. For the purposes
	of this License, Derivative Works shall not include works that remain
	separable from, or merely link (or bind by name) to the interfaces of,
	the Work and Derivative Works thereof.
	
	"Contribution" shall mean any work of authorship, including
	the original version of the Work and any modifications or additions
	to that Work or Derivative Works thereof, that is intentionally
	submitted to Licensor for inclusion in the Work by the copyright owner
	or by an individual or Legal Entity authorized to submit on behalf of
	the copyright owner. For the purposes of this definition, "submitted"
	means any form of electronic, verbal, or written communication sent
	to the Licensor or its representatives, including but not limited to
	communication on electronic mailing lists, source code control systems,
	and issue tracking systems that are managed by, or on behalf of, the
	Licensor for the purpose of discussing and improving the Work, but
	excluding communication that is conspicuously marked or otherwise
	designated in writing by the copyright owner as "Not a Contribution."
	
	"Contributor" shall mean Licensor and any individual or Legal Entity
	on behalf of whom a Contribution has been received by Licensor and
	subsequently incorporated within the Work.
	
	2. Grant of Copyright License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	copyright license to reproduce, prepare Derivative Works of,
	publicly display, publicly perform, sublicense, and distribute the
	Work and such Derivative Works in Source or Object form.
	
	3. Grant of Patent License. Subject to the terms and conditions of
	this License, each Contributor hereby grants to You a perpetual,
	worldwide, non-exclusive, no-charge, royalty-free, irrevocable
	(except as stated in this section) patent license to make, have made,
	use, offer to sell, sell, import, and otherwise transfer the Work,
	where such license applies only to those patent claims licensable
	by such Contributor that are necessarily infringed by their
	Contribution(s) alone or by combination of their Contribution(s)
	with the Work to which such Contribution(s) was submitted. If You
	institute patent litigation against any entity (including a
	cross-claim or counterclaim in a lawsuit) alleging that the Work
	or a Contribution incorporated within the Work constitutes direct
	or contributory patent infringement, then any patent licenses
	granted to You under this License for that Work shall terminate
	as of the date such litigation is filed.
	
	4. Redistribution. You may reproduce and distribute copies of the
	Work or Derivative Works thereof in any medium, with or without
	modifications, and in Source or Object form, provided that You
	meet the following conditions:
	
	(a) You must give any other recipients of the Work or
	Derivative Works a copy of this License; and
	
	(b) You must cause any modified files to carry prominent notices
	stating that You changed the files; and
	
	(c) You must retain, in the Source form of any Derivative Works
	that You distribute, all copyright, patent, trademark, and
	attribution notices from the Source form of the Work,
	excluding those notices that do not pertain to any part of
	the Derivative Works; and
	
	(d) If the Work includes a "NOTICE" text file as part of its
	distribution, then any Derivative Works that You distribute must
	include a readable copy of the attribution notices contained
	within such NOTICE file, excluding those notices that do not
	pertain to any part of the Derivative Works, in at least one
	of the following places: within a NOTICE text file distributed
	as part of the Derivative Works; within the Source form or
	documentation, if provided along with the Derivative Works; or,
	within a display generated by the Derivative Works, if and
	wherever such third-party notices normally appear. The contents
	of the NOTICE file are for informational purposes only and
	do not modify the License. You may add Your own attribution
	notices within Derivative Works that You distribute, alongside
	or as an addendum to the NOTICE text from the Work, provided
	that such additional attribution notices cannot be construed
	as modifying the License.
	
	You may add Your own copyright statement to Your modifications and
	may provide additional or different license terms and conditions
	for use, reproduction, or distribution of Your modifications, or
	for any such Derivative Works as a whole, provided Your use,
	reproduction, and distribution of the Work otherwise complies with
	the conditions stated in this License.
	
	5. Submission of Contributions. Unless You explicitly state otherwise,
	any Contribution intentionally submitted for inclusion in the Work
	by You to the Licensor shall be under the terms and conditions of
	this License, without any additional terms or conditions.
	Notwithstanding the above, nothing herein shall supersede or modify
	the terms of any separate license agreement you may have executed
	with Licensor regarding such Contributions.
	
	6. Trademarks. This License does not grant permission to use the trade
	names, trademarks, service marks, or product names of the Licensor,
	except as required for reasonable and customary use in describing the
	origin of the Work and reproducing the content of the NOTICE file.
	
	7. Disclaimer of Warranty. Unless required by applicable law or
	agreed to in writing, Licensor provides the Work (and each
	Contributor provides its Contributions) on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
	implied, including, without limitation, any warranties or conditions
	of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
	PARTICULAR PURPOSE. You are solely responsible for determining the
	appropriateness of using or redistributing the Work and assume any
	risks associated with Your exercise of permissions under this License.
	
	8. Limitation of Liability. In no event and under no legal theory,
	whether in tort (including negligence), contract, or otherwise,
	unless required by applicable law (such as deliberate and grossly
	negligent acts) or agreed to in writing, shall any Contributor be
	liable to You for damages, including any direct, indirect, special,
	incidental, or consequential damages of any character arising as a
	result of this License or out of the use or inability to use the
	Work (including but not limited to damages for loss of goodwill,
	work stoppage, computer failure or malfunction, or any and all
	other commercial damages or losses), even if such Contributor
	has been advised of the possibility of such damages.
	
	9. Accepting Warranty or Additional Liability. While redistributing
	the Work or Derivative Works thereof, You may choose to offer,
	and charge a fee for, acceptance of support, warranty, indemnity,
	or other liability obligations and/or rights consistent with this
	License. However, in accepting such obligations, You may act only
	on Your own behalf and on Your sole responsibility, not on behalf
	of any other Contributor, and only if You agree to indemnify,
	defend, and hold each Contributor harmless for any liability
	incurred by, or claims asserted against, such Contributor by reason
	of your accepting any such warranty or additional liability.
	
	END OF TERMS AND CONDITIONS
	
	APPENDIX: How to apply the Apache License to your work.
	
	To apply the Apache License to your work, attach the following
	boilerplate notice, with the fields enclosed by brackets "[]"
	replaced with your own identifying information. (Don't include
	the brackets!)  The text should be enclosed in the appropriate
	comment syntax for the file format. We also recommend that a
	file or class name and description of purpose be included on the
	same "printed page" as the copyright notice for easier
	identification within third-party archives.
	
	Copyright [yyyy] [name of copyright owner]
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

google.golang.org/grpc/NOTICE.txt:

	Copyright 2014 gRPC authors.
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

google.golang.org/protobuf/LICENSE:

	Copyright (c) 2018 The Go Authors. All rights reserved.
	
	Redistribution and use in source and binary forms, with or without
	modification, are permitted provided that the following conditions are
	met:
	
	* Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
	* Redistributions in binary form must reproduce the above
	copyright notice, this list of conditions and the following disclaimer
	in the documentation and/or other materials provided with the
	distribution.
	* Neither the name of Google Inc. nor the names of its
	contributors may be used to endorse or promote products derived from
	this software without specific prior written permission.
	
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
	LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
	A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
	OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
	LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

gopkg.in/djherbis/times.v1/LICENSE:

	The MIT License (MIT)
	
	Copyright (c) 2015 Dustin H
	
	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.
	

gopkg.in/yaml.v3/LICENSE:

	
	This project is covered by two different licenses: MIT and Apache.
	
	#### MIT License ####
	
	The following files were ported to Go from C files of libyaml, and thus
	are still covered by their original MIT license, with the additional
	copyright staring in 2011 when the project was ported over:
	
	apic.go emitterc.go parserc.go readerc.go scannerc.go
	writerc.go yamlh.go yamlprivateh.go
	
	Copyright (c) 2006-2010 Kirill Simonov
	Copyright (c) 2006-2011 Kirill Simonov
	
	Permission is hereby granted, free of charge, to any person obtaining a copy of
	this software and associated documentation files (the "Software"), to deal in
	the Software without restriction, including without limitation the rights to
	use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
	of the Software, and to permit persons to whom the Software is furnished to do
	so, subject to the following conditions:
	
	The above copyright notice and this permission notice shall be included in all
	copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
	SOFTWARE.
	
	### Apache License ###
	
	All the remaining project files are covered by the Apache license:
	
	Copyright (c) 2011-2019 Canonical Ltd
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

gopkg.in/yaml.v3/NOTICE:

	Copyright 2011-2016 Canonical Ltd.
	
	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at
	
	http://www.apache.org/licenses/LICENSE-2.0
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.

