adds byteexec to run the embedded wireguard-go
This commit is contained in:
parent
6286af0891
commit
e736942f01
1
.gitignore
vendored
1
.gitignore
vendored
@ -83,3 +83,4 @@ fabric.properties
|
||||
wg-quicker
|
||||
assets/*
|
||||
dist/*
|
||||
bin/*
|
||||
|
6
Makefile
6
Makefile
@ -16,17 +16,19 @@ all: clean wg-quicker
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
# rm wg-quicker || true
|
||||
rm wg-quicker || true
|
||||
rm -rf assets || true
|
||||
rm -rf /tmp/wireguard-go || true
|
||||
rm -rf bin || true
|
||||
|
||||
.PHONY: wireguard-go
|
||||
wireguard-go: clean
|
||||
mkdir bin
|
||||
cd /tmp; \
|
||||
git clone $(WIREGUARD-GO_REPO); \
|
||||
cd wireguard-go; \
|
||||
git checkout -b $(WIREGUARD-GO_VERSION) $(WIREGUARD-GO_VERSION); \
|
||||
GOOS=linux GOARCH=$(GOARCH) $(GOARMLINE) $(GO) build -v -o wireguard-go $(GOFLAGS) .
|
||||
mv /tmp/wireguard-go/wireguard-go bin/wireguard-go
|
||||
|
||||
.PHONY: generate
|
||||
generate: wireguard-go
|
||||
|
2
gen.go
2
gen.go
@ -1,3 +1,3 @@
|
||||
package wgquick
|
||||
|
||||
//go:generate go-bindata -pkg assets -o assets/bindata.go -nomemcopy /tmp/wireguard-go/wireguard-go
|
||||
//go:generate go-bindata -pkg assets -o assets/bindata.go -nomemcopy bin/wireguard-go
|
||||
|
3
go.mod
3
go.mod
@ -3,6 +3,9 @@ module go.xsfx.dev/wg-quicker
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/getlantern/byteexec v0.0.0-20170405023437-4cfb26ec74f4
|
||||
github.com/getlantern/filepersist v0.0.0-20160317154340-c5f0cd24e799 // indirect
|
||||
github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9 // indirect
|
||||
github.com/sirupsen/logrus v1.4.0
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/vishvananda/netlink v1.0.0
|
||||
|
20
go.sum
20
go.sum
@ -2,6 +2,24 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/getlantern/byteexec v0.0.0-20170405023437-4cfb26ec74f4 h1:Nqmy8i81dzokjNHpyOg24gnQBeGRF7D51m8HmBRNn0Y=
|
||||
github.com/getlantern/byteexec v0.0.0-20170405023437-4cfb26ec74f4/go.mod h1:4WCQkaCIwta0KlF9bQZA1jYqp8bzIS2PeCqjnef8nZ8=
|
||||
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4=
|
||||
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
|
||||
github.com/getlantern/errors v1.0.1 h1:XukU2whlh7OdpxnkXhNH9VTLVz0EVPGKDV5K0oWhvzw=
|
||||
github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
|
||||
github.com/getlantern/filepersist v0.0.0-20160317154340-c5f0cd24e799 h1:FhkPUYCQYmoxS02r2GRrIV7dahUIncRl36xzs3/mnjA=
|
||||
github.com/getlantern/filepersist v0.0.0-20160317154340-c5f0cd24e799/go.mod h1:8DGAx0LNUfXNnEH+fXI0s3OCBA/351kZCiz/8YSK3i8=
|
||||
github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9 h1:8MYJU90rB1bsavemKSAuDKBjtAKo5xq95bEPOnzV7CE=
|
||||
github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9/go.mod h1:ZyIjgH/1wTCl+B+7yH1DqrWp6MPJqESmwmEQ89ZfhvA=
|
||||
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 h1:micT5vkcr9tOVk1FiH8SWKID8ultN44Z+yzd2y/Vyb0=
|
||||
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o=
|
||||
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 h1:XYzSdCbkzOC0FDNrgJqGRo8PCMFOBFL9py72DRs7bmc=
|
||||
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
|
||||
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA=
|
||||
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
@ -18,6 +36,8 @@ github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b h1:W3er9pI7mt2gOq
|
||||
github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws=
|
||||
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE=
|
||||
|
14
vendor/github.com/getlantern/byteexec/.travis.yml
generated
vendored
Normal file
14
vendor/github.com/getlantern/byteexec/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.4.1
|
||||
|
||||
install:
|
||||
- go get -d -t -v ./...
|
||||
- go build -v ./...
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get -v github.com/axw/gocov/gocov
|
||||
- go get -v github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- $HOME/gopath/bin/goveralls -v -service travis-ci github.com/getlantern/byteexec
|
202
vendor/github.com/getlantern/byteexec/LICENSE
generated
vendored
Normal file
202
vendor/github.com/getlantern/byteexec/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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 2014 Brave New Software Project, Inc.
|
||||
|
||||
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.
|
27
vendor/github.com/getlantern/byteexec/LICENSE_miniupnpc
generated
vendored
Normal file
27
vendor/github.com/getlantern/byteexec/LICENSE_miniupnpc
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
MiniUPnPc
|
||||
Copyright (c) 2005-2011, Thomas BERNARD
|
||||
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 name of the author 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 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.
|
||||
|
14
vendor/github.com/getlantern/byteexec/README.md
generated
vendored
Normal file
14
vendor/github.com/getlantern/byteexec/README.md
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
byteexec [![Travis CI Status](https://travis-ci.org/getlantern/byteexec.svg?branch=master)](https://travis-ci.org/getlantern/byteexec) [![Coverage Status](https://coveralls.io/repos/getlantern/byteexec/badge.png)](https://coveralls.io/r/getlantern/byteexec) [![GoDoc](https://godoc.org/github.com/getlantern/byteexec?status.png)](http://godoc.org/github.com/getlantern/byteexec)
|
||||
==========
|
||||
byteexec provides a Golang package that allows executing files that are stored
|
||||
as Go byte arrays. This is handy when combined with
|
||||
[go-bindata](https://github.com/jteeuwen/go-bindata).
|
||||
|
||||
To install:
|
||||
|
||||
`go get github.com/getlantern/byteexec`
|
||||
|
||||
For docs:
|
||||
|
||||
`godoc github.com/getlantern/byteexec`
|
||||
|
118
vendor/github.com/getlantern/byteexec/byteexec.go
generated
vendored
Normal file
118
vendor/github.com/getlantern/byteexec/byteexec.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
// Package byteexec provides a very basic facility for running executables
|
||||
// supplied as byte arrays, which is handy when used with
|
||||
// github.com/jteeuwen/go-bindata.
|
||||
//
|
||||
// byteexec works by storing the provided command in a file.
|
||||
//
|
||||
// Example Usage:
|
||||
//
|
||||
// programBytes := // read bytes from somewhere
|
||||
// be, err := byteexec.New(programBytes, "new/path/to/executable")
|
||||
// if err != nil {
|
||||
// log.Fatalf("Uh oh: %s", err)
|
||||
// }
|
||||
// cmd := be.Command("arg1", "arg2")
|
||||
// // cmd is an os/exec.Cmd
|
||||
// err = cmd.Run()
|
||||
//
|
||||
// Note - byteexec.New is somewhat expensive, and Exec is safe for concurrent
|
||||
// use, so it's advisable to create only one Exec for each executable.
|
||||
package byteexec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/getlantern/filepersist"
|
||||
"github.com/getlantern/golog"
|
||||
)
|
||||
|
||||
var (
|
||||
log = golog.LoggerFor("Exec")
|
||||
|
||||
fileMode = os.FileMode(0744)
|
||||
|
||||
initMutex sync.Mutex
|
||||
)
|
||||
|
||||
// Exec is a handle to an executable that can be used to create an exec.Cmd
|
||||
// using the Command method. Exec is safe for concurrent use.
|
||||
type Exec struct {
|
||||
Filename string
|
||||
}
|
||||
|
||||
// New creates a new Exec using the program stored in the provided data, at the
|
||||
// provided filename (relative or absolute path allowed). If the path given is
|
||||
// a relative path, the executable will be placed in one of the following
|
||||
// locations:
|
||||
//
|
||||
// On Windows - %APPDATA%/byteexec
|
||||
// On OSX - ~/Library/Application Support/byteexec
|
||||
// All Others - ~/.byteexec
|
||||
//
|
||||
// Creating a new Exec can be somewhat expensive, so it's best to create only
|
||||
// one Exec per executable and reuse that.
|
||||
//
|
||||
// WARNING - if a file already exists at this location and its contents differ
|
||||
// from data, Exec will attempt to overwrite it.
|
||||
func New(data []byte, filename string) (*Exec, error) {
|
||||
log.Tracef("Creating new at %v", filename)
|
||||
// Use initMutex to synchronize file operations by this process
|
||||
initMutex.Lock()
|
||||
defer initMutex.Unlock()
|
||||
|
||||
var err error
|
||||
if !filepath.IsAbs(filename) {
|
||||
filename, err = inStandardDir(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
filename = renameExecutable(filename)
|
||||
log.Tracef("Placing executable in %s", filename)
|
||||
|
||||
err = filepersist.Save(filename, data, fileMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Trace("File saved, returning new Exec")
|
||||
return newExec(filename)
|
||||
}
|
||||
|
||||
// Command creates an exec.Cmd using the supplied args.
|
||||
func (be *Exec) Command(args ...string) *exec.Cmd {
|
||||
return exec.Command(be.Filename, args...)
|
||||
}
|
||||
|
||||
func newExec(filename string) (*Exec, error) {
|
||||
absolutePath, err := filepath.Abs(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Exec{Filename: absolutePath}, nil
|
||||
}
|
||||
|
||||
func inStandardDir(filename string) (string, error) {
|
||||
folder, err := pathForRelativeFiles()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = os.MkdirAll(folder, fileMode)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to make folder %s: %s", folder, err)
|
||||
}
|
||||
return filepath.Join(folder, filename), nil
|
||||
}
|
||||
|
||||
func inHomeDir(filename string) (string, error) {
|
||||
log.Tracef("Determining user's home directory")
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Unable to determine user's home directory: %s", err)
|
||||
}
|
||||
return filepath.Join(usr.HomeDir, filename), nil
|
||||
}
|
5
vendor/github.com/getlantern/byteexec/byteexec_test_stub.go
generated
vendored
Normal file
5
vendor/github.com/getlantern/byteexec/byteexec_test_stub.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// +build !windows
|
||||
|
||||
package byteexec
|
||||
|
||||
const linefeed = "\n"
|
3
vendor/github.com/getlantern/byteexec/byteexec_test_windows.go
generated
vendored
Normal file
3
vendor/github.com/getlantern/byteexec/byteexec_test_windows.go
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
package byteexec
|
||||
|
||||
const linefeed = "\r\n"
|
120
vendor/github.com/getlantern/byteexec/helloworld_darwin.go
generated
vendored
Normal file
120
vendor/github.com/getlantern/byteexec/helloworld_darwin.go
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
120
vendor/github.com/getlantern/byteexec/helloworld_linux_386.go
generated
vendored
Normal file
120
vendor/github.com/getlantern/byteexec/helloworld_linux_386.go
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
120
vendor/github.com/getlantern/byteexec/helloworld_linux_amd64.go
generated
vendored
Normal file
120
vendor/github.com/getlantern/byteexec/helloworld_linux_amd64.go
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
120
vendor/github.com/getlantern/byteexec/helloworld_windows.go
generated
vendored
Normal file
120
vendor/github.com/getlantern/byteexec/helloworld_windows.go
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
11
vendor/github.com/getlantern/byteexec/rename_darwin.go
generated
vendored
Normal file
11
vendor/github.com/getlantern/byteexec/rename_darwin.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// +build !windows
|
||||
|
||||
package byteexec
|
||||
|
||||
func renameExecutable(orig string) string {
|
||||
return orig
|
||||
}
|
||||
|
||||
func pathForRelativeFiles() (string, error) {
|
||||
return inHomeDir("Library/Application Support/byteexec")
|
||||
}
|
11
vendor/github.com/getlantern/byteexec/rename_stub.go
generated
vendored
Normal file
11
vendor/github.com/getlantern/byteexec/rename_stub.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// +build !windows,!darwin
|
||||
|
||||
package byteexec
|
||||
|
||||
func renameExecutable(orig string) string {
|
||||
return orig
|
||||
}
|
||||
|
||||
func pathForRelativeFiles() (string, error) {
|
||||
return inHomeDir(".byteexec")
|
||||
}
|
14
vendor/github.com/getlantern/byteexec/rename_windows.go
generated
vendored
Normal file
14
vendor/github.com/getlantern/byteexec/rename_windows.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package byteexec
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func renameExecutable(orig string) string {
|
||||
return orig + ".exe"
|
||||
}
|
||||
|
||||
func pathForRelativeFiles() (string, error) {
|
||||
return filepath.Join(os.Getenv("APPDATA"), "byteexec"), nil
|
||||
}
|
15
vendor/github.com/getlantern/context/.travis.yml
generated
vendored
Normal file
15
vendor/github.com/getlantern/context/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.6.2
|
||||
|
||||
install:
|
||||
- go get -d -t -v ./...
|
||||
- go build -v ./...
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get -v github.com/axw/gocov/gocov
|
||||
- go get -v github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- go test -race -v -covermode=atomic -coverprofile=profile.cov
|
||||
- $HOME/gopath/bin/goveralls -coverprofile=profile.cov -service=travis-ci
|
202
vendor/github.com/getlantern/context/LICENSE
generated
vendored
Normal file
202
vendor/github.com/getlantern/context/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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 2016 Brave New Software Project, Inc.
|
||||
|
||||
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.
|
6
vendor/github.com/getlantern/context/README.md
generated
vendored
Normal file
6
vendor/github.com/getlantern/context/README.md
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# context [![Travis CI Status](https://travis-ci.org/getlantern/context.svg?branch=master)](https://travis-ci.org/getlantern/context) [![Coverage Status](https://coveralls.io/repos/getlantern/context/badge.png?branch=master)](https://coveralls.io/r/getlantern/context)
|
||||
|
||||
Provides goroutine-based context state inspired by https://github.com/tylerb/gls
|
||||
and https://github.com/jtolds/gls. It uses the same basic hack as tylerb's
|
||||
library, but adds a stack abstraction that allows nested contexts similar to
|
||||
jtolds' library, but using `Enter()` and `Exit()` instead of callback functions.
|
309
vendor/github.com/getlantern/context/context.go
generated
vendored
Normal file
309
vendor/github.com/getlantern/context/context.go
generated
vendored
Normal file
@ -0,0 +1,309 @@
|
||||
// Package context provides a mechanism for transparently tracking contextual
|
||||
// state associated to the current goroutine and even across goroutines.
|
||||
package context
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Manager provides the ability to create and access Contexts.
|
||||
type Manager interface {
|
||||
// Enter enters a new level on the current Context stack, creating a new Context
|
||||
// if necessary.
|
||||
Enter() Context
|
||||
|
||||
// Go starts the given function on a new goroutine but sharing the context of
|
||||
// the current goroutine (if it has one).
|
||||
Go(func())
|
||||
|
||||
// PutGlobal puts the given key->value pair into the global context.
|
||||
PutGlobal(key string, value interface{})
|
||||
|
||||
// PutGlobalDynamic puts a key->value pair into the global context where the
|
||||
// value is generated by a function that gets evaluated at every Read. If the
|
||||
// value is a map[string]interface{}, we will unpack the map and set each
|
||||
// contained key->value pair independently.
|
||||
PutGlobalDynamic(key string, valueFN func() interface{})
|
||||
|
||||
// AsMap returns a map containing all values from the supplied obj if it is a
|
||||
// Contextual, plus any addition values from along the stack, plus globals if so
|
||||
// specified.
|
||||
AsMap(obj interface{}, includeGlobals bool) Map
|
||||
}
|
||||
|
||||
type manager struct {
|
||||
contexts map[uint64]*context
|
||||
mxContexts sync.RWMutex
|
||||
global Map
|
||||
mxGlobal sync.RWMutex
|
||||
}
|
||||
|
||||
// NewManager creates a new Manager
|
||||
func NewManager() Manager {
|
||||
return &manager{
|
||||
contexts: make(map[uint64]*context),
|
||||
global: make(Map),
|
||||
}
|
||||
}
|
||||
|
||||
// Contextual is an interface for anything that maintains its own context.
|
||||
type Contextual interface {
|
||||
// Fill fills the given Map with all of this Contextual's context
|
||||
Fill(m Map)
|
||||
}
|
||||
|
||||
// Map is a map of key->value pairs.
|
||||
type Map map[string]interface{}
|
||||
|
||||
// Fill implements the method from the Contextual interface.
|
||||
func (_m Map) Fill(m Map) {
|
||||
for key, value := range _m {
|
||||
m[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
// Context is a context containing key->value pairs
|
||||
type Context interface {
|
||||
// Enter enters a new level on this Context stack.
|
||||
Enter() Context
|
||||
|
||||
// Go starts the given function on a new goroutine.
|
||||
Go(fn func())
|
||||
|
||||
// Exit exits the current level on this Context stack.
|
||||
Exit()
|
||||
|
||||
// Put puts a key->value pair into the current level of the context stack.
|
||||
Put(key string, value interface{}) Context
|
||||
|
||||
// PutIfAbsent puts the given key->value pair into the current level of the
|
||||
// context stack if and only if that key is defined nowhere within the context
|
||||
// stack (including parent contexts).
|
||||
PutIfAbsent(key string, value interface{}) Context
|
||||
|
||||
// PutDynamic puts a key->value pair into the current level of the context
|
||||
// stack where the value is generated by a function that gets evaluated at
|
||||
// every Read. If the value is a map[string]interface{}, we will unpack the
|
||||
// map and set each contained key->value pair independently.
|
||||
PutDynamic(key string, valueFN func() interface{}) Context
|
||||
|
||||
// Fill fills the given map with data from this Context
|
||||
Fill(m Map)
|
||||
|
||||
// AsMap returns a map containing all values from the supplied obj if it is a
|
||||
// Contextual, plus any addition values from along the stack, plus globals if
|
||||
// so specified.
|
||||
AsMap(obj interface{}, includeGlobals bool) Map
|
||||
}
|
||||
|
||||
type context struct {
|
||||
cm *manager
|
||||
id uint64
|
||||
parent *context
|
||||
branchedFrom *context
|
||||
data Map
|
||||
mx sync.RWMutex
|
||||
}
|
||||
|
||||
type dynval struct {
|
||||
fn func() interface{}
|
||||
}
|
||||
|
||||
func (cm *manager) Enter() Context {
|
||||
return cm.enter(curGoroutineID())
|
||||
}
|
||||
|
||||
func (cm *manager) enter(id uint64) *context {
|
||||
cm.mxContexts.Lock()
|
||||
parentOrNil := cm.contexts[id]
|
||||
c := cm.makeContext(id, parentOrNil, nil)
|
||||
cm.contexts[id] = c
|
||||
cm.mxContexts.Unlock()
|
||||
return c
|
||||
}
|
||||
|
||||
func (cm *manager) exit(id uint64, parent *context) {
|
||||
cm.mxContexts.Lock()
|
||||
if parent == nil {
|
||||
delete(cm.contexts, id)
|
||||
} else {
|
||||
cm.contexts[id] = parent
|
||||
}
|
||||
cm.mxContexts.Unlock()
|
||||
}
|
||||
|
||||
func (cm *manager) branch(id uint64, from *context) {
|
||||
next := cm.makeContext(id, nil, from)
|
||||
cm.mxContexts.Lock()
|
||||
cm.contexts[id] = next
|
||||
cm.mxContexts.Unlock()
|
||||
}
|
||||
|
||||
func (cm *manager) merge(id uint64) {
|
||||
cm.mxContexts.Lock()
|
||||
delete(cm.contexts, id)
|
||||
cm.mxContexts.Unlock()
|
||||
}
|
||||
|
||||
func (c *context) Enter() Context {
|
||||
c.mx.RLock()
|
||||
id := c.id
|
||||
c.mx.RUnlock()
|
||||
return c.cm.enter(id)
|
||||
}
|
||||
|
||||
func (c *context) Go(fn func()) {
|
||||
go func() {
|
||||
id := curGoroutineID()
|
||||
c.cm.branch(id, c)
|
||||
fn()
|
||||
c.cm.merge(id)
|
||||
}()
|
||||
}
|
||||
|
||||
func (cm *manager) Go(fn func()) {
|
||||
c := cm.currentContext()
|
||||
if c != nil {
|
||||
c.Go(fn)
|
||||
} else {
|
||||
go fn()
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *manager) makeContext(id uint64, parent *context, branchedFrom *context) *context {
|
||||
return &context{
|
||||
cm: cm,
|
||||
id: id,
|
||||
parent: parent,
|
||||
branchedFrom: branchedFrom,
|
||||
data: make(Map),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *context) Exit() {
|
||||
c.mx.RLock()
|
||||
id := c.id
|
||||
parent := c.parent
|
||||
c.mx.RUnlock()
|
||||
c.cm.exit(id, parent)
|
||||
}
|
||||
|
||||
func (c *context) Put(key string, value interface{}) Context {
|
||||
c.mx.Lock()
|
||||
c.data[key] = value
|
||||
c.mx.Unlock()
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *context) PutIfAbsent(key string, value interface{}) Context {
|
||||
for ctx := c; ctx != nil; {
|
||||
ctx.mx.RLock()
|
||||
_, exists := ctx.data[key]
|
||||
next := ctx.parent
|
||||
if next == nil {
|
||||
next = ctx.branchedFrom
|
||||
}
|
||||
ctx.mx.RUnlock()
|
||||
if exists {
|
||||
return c
|
||||
}
|
||||
ctx = next
|
||||
}
|
||||
|
||||
// Value not set, set it
|
||||
return c.Put(key, value)
|
||||
}
|
||||
|
||||
func (c *context) PutDynamic(key string, valueFN func() interface{}) Context {
|
||||
value := &dynval{valueFN}
|
||||
c.mx.Lock()
|
||||
c.data[key] = value
|
||||
c.mx.Unlock()
|
||||
return c
|
||||
}
|
||||
|
||||
func (cm *manager) PutGlobal(key string, value interface{}) {
|
||||
cm.mxGlobal.Lock()
|
||||
cm.global[key] = value
|
||||
cm.mxGlobal.Unlock()
|
||||
}
|
||||
|
||||
func (cm *manager) PutGlobalDynamic(key string, valueFN func() interface{}) {
|
||||
value := &dynval{valueFN}
|
||||
cm.mxGlobal.Lock()
|
||||
cm.global[key] = value
|
||||
cm.mxGlobal.Unlock()
|
||||
}
|
||||
|
||||
func (c *context) Fill(m Map) {
|
||||
for ctx := c; ctx != nil; {
|
||||
ctx.mx.RLock()
|
||||
fill(m, ctx.data)
|
||||
next := ctx.parent
|
||||
if next == nil {
|
||||
next = ctx.branchedFrom
|
||||
}
|
||||
ctx.mx.RUnlock()
|
||||
ctx = next
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *manager) AsMap(obj interface{}, includeGlobals bool) Map {
|
||||
return cm.currentContext().asMap(cm, obj, includeGlobals)
|
||||
}
|
||||
|
||||
func (c *context) AsMap(obj interface{}, includeGlobals bool) Map {
|
||||
return c.asMap(c.cm, obj, includeGlobals)
|
||||
}
|
||||
|
||||
func (c *context) asMap(cm *manager, obj interface{}, includeGlobals bool) Map {
|
||||
result := make(Map, 0)
|
||||
cl, ok := obj.(Contextual)
|
||||
if ok {
|
||||
cl.Fill(result)
|
||||
}
|
||||
if c != nil {
|
||||
c.Fill(result)
|
||||
}
|
||||
if includeGlobals {
|
||||
cm.mxGlobal.RLock()
|
||||
fill(result, cm.global)
|
||||
cm.mxGlobal.RUnlock()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func fill(m Map, from Map) {
|
||||
if m != nil {
|
||||
doFill := func(key string, _value interface{}) {
|
||||
switch value := _value.(type) {
|
||||
case map[string]interface{}:
|
||||
for k, v := range value {
|
||||
m[k] = v
|
||||
}
|
||||
default:
|
||||
m[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
for key, value := range from {
|
||||
_, alreadyRead := m[key]
|
||||
if !alreadyRead {
|
||||
switch v := value.(type) {
|
||||
case *dynval:
|
||||
doFill(key, v.fn())
|
||||
default:
|
||||
doFill(key, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (cm *manager) currentContext() *context {
|
||||
id := curGoroutineID()
|
||||
cm.mxContexts.RLock()
|
||||
c := cm.contexts[id]
|
||||
cm.mxContexts.RUnlock()
|
||||
return c
|
||||
}
|
130
vendor/github.com/getlantern/context/gotrack.go
generated
vendored
Normal file
130
vendor/github.com/getlantern/context/gotrack.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Sourced https://github.com/bradfitz/http2/blob/dc0c5c000ec33e263612939744d51a3b68b9cece/gotrack.go
|
||||
var goroutineSpace = []byte("goroutine ")
|
||||
var littleBuf = sync.Pool{
|
||||
New: func() interface{} {
|
||||
buf := make([]byte, 64)
|
||||
return &buf
|
||||
},
|
||||
}
|
||||
|
||||
func curGoroutineID() uint64 {
|
||||
bp := littleBuf.Get().(*[]byte)
|
||||
defer littleBuf.Put(bp)
|
||||
b := *bp
|
||||
b = b[:runtime.Stack(b, false)]
|
||||
// Parse the 4707 out of "goroutine 4707 ["
|
||||
b = bytes.TrimPrefix(b, goroutineSpace)
|
||||
i := bytes.IndexByte(b, ' ')
|
||||
if i < 0 {
|
||||
panic(fmt.Sprintf("No space found in %q", b))
|
||||
}
|
||||
b = b[:i]
|
||||
n, err := parseUintBytes(b, 10, 64)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// parseUintBytes is like strconv.ParseUint, but using a []byte.
|
||||
func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) {
|
||||
var cutoff, maxVal uint64
|
||||
|
||||
if bitSize == 0 {
|
||||
bitSize = int(strconv.IntSize)
|
||||
}
|
||||
|
||||
s0 := s
|
||||
switch {
|
||||
case len(s) < 1:
|
||||
err = strconv.ErrSyntax
|
||||
return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
|
||||
|
||||
case 2 <= base && base <= 36:
|
||||
// valid base; nothing to do
|
||||
|
||||
case base == 0:
|
||||
// Look for octal, hex prefix.
|
||||
switch {
|
||||
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
|
||||
base = 16
|
||||
s = s[2:]
|
||||
if len(s) < 1 {
|
||||
err = strconv.ErrSyntax
|
||||
return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
|
||||
}
|
||||
case s[0] == '0':
|
||||
base = 8
|
||||
default:
|
||||
base = 10
|
||||
}
|
||||
|
||||
default:
|
||||
err = errors.New("invalid base " + strconv.Itoa(base))
|
||||
return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
|
||||
}
|
||||
|
||||
n = 0
|
||||
cutoff = cutoff64(base)
|
||||
maxVal = 1<<uint(bitSize) - 1
|
||||
|
||||
for i := 0; i < len(s); i++ {
|
||||
var v byte
|
||||
d := s[i]
|
||||
switch {
|
||||
case '0' <= d && d <= '9':
|
||||
v = d - '0'
|
||||
case 'a' <= d && d <= 'z':
|
||||
v = d - 'a' + 10
|
||||
case 'A' <= d && d <= 'Z':
|
||||
v = d - 'A' + 10
|
||||
default:
|
||||
n = 0
|
||||
err = strconv.ErrSyntax
|
||||
return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
|
||||
}
|
||||
if int(v) >= base {
|
||||
n = 0
|
||||
err = strconv.ErrSyntax
|
||||
return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
|
||||
}
|
||||
|
||||
if n >= cutoff {
|
||||
// n*base overflows
|
||||
n = 1<<64 - 1
|
||||
err = strconv.ErrRange
|
||||
return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
|
||||
}
|
||||
n *= uint64(base)
|
||||
|
||||
n1 := n + uint64(v)
|
||||
if n1 < n || n1 > maxVal {
|
||||
// n+v overflows
|
||||
n = 1<<64 - 1
|
||||
err = strconv.ErrRange
|
||||
return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
|
||||
}
|
||||
n = n1
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// Return the first number n such that n*base >= 1<<64.
|
||||
func cutoff64(base int) uint64 {
|
||||
if base < 2 {
|
||||
return 0
|
||||
}
|
||||
return (1<<64-1)/uint64(base) + 1
|
||||
}
|
202
vendor/github.com/getlantern/errors/LICENSE
generated
vendored
Normal file
202
vendor/github.com/getlantern/errors/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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 2018 Brave New Software Project, Inc.
|
||||
|
||||
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.
|
646
vendor/github.com/getlantern/errors/errors.go
generated
vendored
Normal file
646
vendor/github.com/getlantern/errors/errors.go
generated
vendored
Normal file
@ -0,0 +1,646 @@
|
||||
/*
|
||||
Package errors defines error types used across Lantern project.
|
||||
|
||||
n, err := Foo()
|
||||
if err != nil {
|
||||
return n, errors.New("Unable to do Foo: %v", err)
|
||||
}
|
||||
|
||||
or
|
||||
|
||||
n, err := Foo()
|
||||
return n, errors.Wrap(err)
|
||||
|
||||
New() method will create a new error with err as its cause. Wrap will wrap err,
|
||||
returning nil if err is nil. If err is an error from Go's standard library,
|
||||
errors will extract details from that error, at least the Go type name and the
|
||||
return value of err.Error().
|
||||
|
||||
One can record the operation on which the error occurred using Op():
|
||||
|
||||
return n, errors.New("Unable to do Foo: %v", err).Op("FooDooer")
|
||||
|
||||
One can also record additional data:
|
||||
|
||||
return n, errors.
|
||||
New("Unable to do Foo: %v", err).
|
||||
Op("FooDooer").
|
||||
With("mydata", "myvalue").
|
||||
With("moredata", 5)
|
||||
|
||||
When used with github.com/getlantern/ops, Error captures its current context
|
||||
and propagates that data for use in calling layers.
|
||||
|
||||
When used with github.com/getlantern/golog, Error provides stacktraces:
|
||||
|
||||
Hello World
|
||||
at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999)
|
||||
at testing.tRunner (testing.go:999)
|
||||
at runtime.goexit (asm_amd999.s:999)
|
||||
Caused by: World
|
||||
at github.com/getlantern/errors.buildCause (errors_test.go:999)
|
||||
at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999)
|
||||
at testing.tRunner (testing.go:999)
|
||||
at runtime.goexit (asm_amd999.s:999)
|
||||
Caused by: orld
|
||||
Caused by: ld
|
||||
at github.com/getlantern/errors.buildSubSubCause (errors_test.go:999)
|
||||
at github.com/getlantern/errors.buildSubCause (errors_test.go:999)
|
||||
at github.com/getlantern/errors.buildCause (errors_test.go:999)
|
||||
at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999)
|
||||
at testing.tRunner (testing.go:999)
|
||||
at runtime.goexit (asm_amd999.s:999)
|
||||
Caused by: d
|
||||
|
||||
It's the caller's responsibility to avoid race conditions accessing the same
|
||||
error instance from multiple goroutines.
|
||||
*/
|
||||
package errors
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/getlantern/context"
|
||||
"github.com/getlantern/hidden"
|
||||
"github.com/getlantern/ops"
|
||||
"github.com/go-stack/stack"
|
||||
)
|
||||
|
||||
// Error wraps system and application defined errors in unified structure for
|
||||
// reporting and logging. It's not meant to be created directly. User New(),
|
||||
// Wrap() and Report() instead.
|
||||
type Error interface {
|
||||
error
|
||||
context.Contextual
|
||||
|
||||
// ErrorClean returns a non-parameterized version of the error whenever
|
||||
// possible. For example, if the error text is:
|
||||
//
|
||||
// unable to dial www.google.com caused by: i/o timeout
|
||||
//
|
||||
// ErrorClean might return:
|
||||
//
|
||||
// unable to dial %v caused by: %v
|
||||
//
|
||||
// This can be useful when performing analytics on the error.
|
||||
ErrorClean() string
|
||||
|
||||
// MultiLinePrinter implements the interface golog.MultiLine
|
||||
MultiLinePrinter() func(buf *bytes.Buffer) bool
|
||||
|
||||
// Op attaches a hint of the operation triggers this Error. Many error types
|
||||
// returned by net and os package have Op pre-filled.
|
||||
Op(op string) Error
|
||||
|
||||
// With attaches arbitrary field to the error. keys will be normalized as
|
||||
// underscore_divided_words, so all characters except letters and numbers will
|
||||
// be replaced with underscores, and all letters will be lowercased.
|
||||
With(key string, value interface{}) Error
|
||||
|
||||
// RootCause returns the bottom-most cause of this Error. If the Error
|
||||
// resulted from wrapping a plain error, the wrapped error will be returned as
|
||||
// the cause.
|
||||
RootCause() error
|
||||
}
|
||||
|
||||
type baseError struct {
|
||||
errID uint64
|
||||
hiddenID string
|
||||
data context.Map
|
||||
context context.Map
|
||||
callStack stack.CallStack
|
||||
}
|
||||
|
||||
// New creates an Error with supplied description and format arguments to the
|
||||
// description. If any of the arguments is an error, we use that as the cause.
|
||||
func New(desc string, args ...interface{}) Error {
|
||||
return NewOffset(1, desc, args...)
|
||||
}
|
||||
|
||||
// NewOffset is like New but offsets the stack by the given offset. This is
|
||||
// useful for utilities like golog that may create errors on behalf of others.
|
||||
func NewOffset(offset int, desc string, args ...interface{}) Error {
|
||||
e := buildError(desc, fmt.Sprintf(desc, args...))
|
||||
e.attachStack(2 + offset)
|
||||
for _, arg := range args {
|
||||
wrapped, isError := arg.(error)
|
||||
if isError {
|
||||
op, _, _, extraData := parseError(wrapped)
|
||||
if op != "" {
|
||||
e.Op(op)
|
||||
}
|
||||
for k, v := range extraData {
|
||||
e.data[k] = v
|
||||
}
|
||||
we := &wrappingError{e, wrapped}
|
||||
bufferError(we)
|
||||
return we
|
||||
}
|
||||
}
|
||||
bufferError(e)
|
||||
return e
|
||||
}
|
||||
|
||||
// Wrap creates an Error based on the information in an error instance. It
|
||||
// returns nil if the error passed in is nil, so we can simply call
|
||||
// errors.Wrap(s.l.Close()) regardless there's an error or not. If the error is
|
||||
// already wrapped, it is returned as is.
|
||||
func Wrap(err error) Error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if e, ok := err.(Error); ok {
|
||||
return e
|
||||
}
|
||||
|
||||
op, goType, desc, extraData := parseError(err)
|
||||
if desc == "" {
|
||||
desc = err.Error()
|
||||
}
|
||||
e := buildError(desc, desc)
|
||||
e.attachStack(2)
|
||||
if op != "" {
|
||||
e.Op(op)
|
||||
}
|
||||
e.data["error_type"] = goType
|
||||
for k, v := range extraData {
|
||||
e.data[k] = v
|
||||
}
|
||||
if cause := getCause(err); cause != nil {
|
||||
we := &wrappingError{e, cause}
|
||||
bufferError(we)
|
||||
return we
|
||||
}
|
||||
bufferError(e)
|
||||
return e
|
||||
}
|
||||
|
||||
// Fill implements the method from the context.Contextual interface.
|
||||
func (e *baseError) Fill(m context.Map) {
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Include the context, which supercedes the cause
|
||||
for key, value := range e.context {
|
||||
m[key] = value
|
||||
}
|
||||
// Now include the error's data, which supercedes everything
|
||||
for key, value := range e.data {
|
||||
m[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
func (e *baseError) Op(op string) Error {
|
||||
e.data["error_op"] = op
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *baseError) With(key string, value interface{}) Error {
|
||||
parts := strings.FieldsFunc(key, func(c rune) bool {
|
||||
return !unicode.IsLetter(c) && !unicode.IsNumber(c)
|
||||
})
|
||||
k := strings.ToLower(strings.Join(parts, "_"))
|
||||
if k == "error" || k == "error_op" {
|
||||
// Never overwrite these
|
||||
return e
|
||||
}
|
||||
switch actual := value.(type) {
|
||||
case string, int, bool, time.Time:
|
||||
e.data[k] = actual
|
||||
default:
|
||||
e.data[k] = fmt.Sprint(actual)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *baseError) RootCause() error {
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *baseError) ErrorClean() string {
|
||||
return e.data["error"].(string)
|
||||
}
|
||||
|
||||
// Error satisfies the error interface
|
||||
func (e *baseError) Error() string {
|
||||
return e.data["error_text"].(string) + e.hiddenID
|
||||
}
|
||||
|
||||
func (e *baseError) MultiLinePrinter() func(*bytes.Buffer) bool {
|
||||
return e.topLevelPrinter()
|
||||
}
|
||||
|
||||
func (e *baseError) topLevelPrinter() func(*bytes.Buffer) bool {
|
||||
printingStack := false
|
||||
stackPosition := 0
|
||||
return func(buf *bytes.Buffer) bool {
|
||||
if !printingStack {
|
||||
buf.WriteString(e.Error())
|
||||
printingStack = true
|
||||
return len(e.callStack) > 0
|
||||
}
|
||||
call := e.callStack[stackPosition]
|
||||
fmt.Fprintf(buf, " at %+n (%s:%d)", call, call, call)
|
||||
stackPosition++
|
||||
return stackPosition < len(e.callStack)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *baseError) attachStack(skip int) {
|
||||
call := stack.Caller(skip)
|
||||
e.callStack = stack.Trace().TrimBelow(call)
|
||||
e.data["error_location"] = fmt.Sprintf("%+n (%s:%d)", call, call, call)
|
||||
}
|
||||
|
||||
func (e *baseError) id() uint64 {
|
||||
return e.errID
|
||||
}
|
||||
|
||||
func (e *baseError) setID(id uint64) {
|
||||
e.errID = id
|
||||
}
|
||||
|
||||
func (e *baseError) setHiddenID(id string) {
|
||||
e.hiddenID = id
|
||||
}
|
||||
|
||||
func buildError(desc string, fullText string) *baseError {
|
||||
e := &baseError{
|
||||
data: make(context.Map),
|
||||
// We capture the current context to allow it to propagate to higher layers.
|
||||
context: ops.AsMap(nil, false),
|
||||
}
|
||||
|
||||
cleanedDesc := hidden.Clean(desc)
|
||||
e.data["error"] = cleanedDesc
|
||||
if fullText != "" {
|
||||
e.data["error_text"] = hidden.Clean(fullText)
|
||||
} else {
|
||||
e.data["error_text"] = cleanedDesc
|
||||
}
|
||||
e.data["error_type"] = "errors.Error"
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
type topLevelPrinter interface {
|
||||
// Returns a printer which prints only the top-level error and any associated stack trace. The
|
||||
// output of this printer will be a prefix of the output from MultiLinePrinter().
|
||||
topLevelPrinter() func(*bytes.Buffer) bool
|
||||
}
|
||||
|
||||
type unwrapper interface {
|
||||
Unwrap() error
|
||||
}
|
||||
|
||||
type wrappingError struct {
|
||||
*baseError
|
||||
wrapped error
|
||||
}
|
||||
|
||||
// Implements error unwrapping as described in the standard library's errors package:
|
||||
// https://golang.org/pkg/errors/#pkg-overview
|
||||
func (e *wrappingError) Unwrap() error {
|
||||
return e.wrapped
|
||||
}
|
||||
|
||||
func (e *wrappingError) Fill(m context.Map) {
|
||||
type filler interface{ Fill(context.Map) }
|
||||
|
||||
applyToChain(e.wrapped, func(err error) {
|
||||
if f, ok := err.(filler); ok {
|
||||
f.Fill(m)
|
||||
}
|
||||
})
|
||||
e.baseError.Fill(m)
|
||||
}
|
||||
|
||||
func (e *wrappingError) RootCause() error {
|
||||
return unwrapToRoot(e)
|
||||
}
|
||||
|
||||
func (e *wrappingError) MultiLinePrinter() func(*bytes.Buffer) bool {
|
||||
var (
|
||||
currentPrinter = e.baseError.topLevelPrinter()
|
||||
nextErr = e.wrapped
|
||||
prefix = ""
|
||||
)
|
||||
return func(buf *bytes.Buffer) bool {
|
||||
fmt.Fprint(buf, prefix)
|
||||
if currentPrinter(buf) {
|
||||
prefix = ""
|
||||
return true
|
||||
}
|
||||
if nextErr == nil {
|
||||
return false
|
||||
}
|
||||
currentPrinter = getTopLevelPrinter(nextErr)
|
||||
prefix = "Caused by: "
|
||||
if uw, ok := nextErr.(unwrapper); ok {
|
||||
nextErr = uw.Unwrap()
|
||||
} else {
|
||||
nextErr = nil
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// We have to implement these two methods or the fluid syntax will result in the embedded *baseError
|
||||
// being returned, not the *wrappingError.
|
||||
|
||||
func (e *wrappingError) Op(op string) Error {
|
||||
e.baseError = e.baseError.Op(op).(*baseError)
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *wrappingError) With(key string, value interface{}) Error {
|
||||
e.baseError = e.baseError.With(key, value).(*baseError)
|
||||
return e
|
||||
}
|
||||
|
||||
func getTopLevelPrinter(err error) func(*bytes.Buffer) bool {
|
||||
if tlp, ok := err.(topLevelPrinter); ok {
|
||||
return tlp.topLevelPrinter()
|
||||
}
|
||||
return func(buf *bytes.Buffer) bool {
|
||||
fmt.Fprint(buf, err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func getCause(e error) error {
|
||||
if uw, ok := e.(unwrapper); ok {
|
||||
return uw.Unwrap()
|
||||
}
|
||||
// Look for hidden *baseErrors
|
||||
hiddenIDs, extractErr := hidden.Extract(e.Error())
|
||||
if extractErr == nil && len(hiddenIDs) > 0 {
|
||||
// Take the first hidden ID as our cause
|
||||
return get(hiddenIDs[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func unwrapToRoot(e error) error {
|
||||
if uw, ok := e.(unwrapper); ok {
|
||||
return unwrapToRoot(uw.Unwrap())
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Applies f to the chain of errors unwrapped from err. The function is applied to the root cause
|
||||
// first and err last.
|
||||
func applyToChain(err error, f func(error)) {
|
||||
if uw, ok := err.(unwrapper); ok {
|
||||
applyToChain(uw.Unwrap(), f)
|
||||
}
|
||||
f(err)
|
||||
}
|
||||
|
||||
func parseError(err error) (op string, goType string, desc string, extra map[string]string) {
|
||||
extra = make(map[string]string)
|
||||
|
||||
// interfaces
|
||||
if _, ok := err.(net.Error); ok {
|
||||
if opError, ok := err.(*net.OpError); ok {
|
||||
op = opError.Op
|
||||
if opError.Source != nil {
|
||||
extra["remote_addr"] = opError.Source.String()
|
||||
}
|
||||
if opError.Addr != nil {
|
||||
extra["local_addr"] = opError.Addr.String()
|
||||
}
|
||||
extra["network"] = opError.Net
|
||||
err = opError.Err
|
||||
}
|
||||
switch actual := err.(type) {
|
||||
case *net.AddrError:
|
||||
goType = "net.AddrError"
|
||||
desc = actual.Err
|
||||
extra["addr"] = actual.Addr
|
||||
case *net.DNSError:
|
||||
goType = "net.DNSError"
|
||||
desc = actual.Err
|
||||
extra["domain"] = actual.Name
|
||||
if actual.Server != "" {
|
||||
extra["dns_server"] = actual.Server
|
||||
}
|
||||
case *net.InvalidAddrError:
|
||||
goType = "net.InvalidAddrError"
|
||||
desc = actual.Error()
|
||||
case *net.ParseError:
|
||||
goType = "net.ParseError"
|
||||
desc = "invalid " + actual.Type
|
||||
extra["text_to_parse"] = actual.Text
|
||||
case net.UnknownNetworkError:
|
||||
goType = "net.UnknownNetworkError"
|
||||
desc = "unknown network"
|
||||
case syscall.Errno:
|
||||
goType = "syscall.Errno"
|
||||
desc = actual.Error()
|
||||
case *url.Error:
|
||||
goType = "url.Error"
|
||||
desc = actual.Err.Error()
|
||||
op = actual.Op
|
||||
default:
|
||||
goType = reflect.TypeOf(err).String()
|
||||
desc = err.Error()
|
||||
}
|
||||
return
|
||||
}
|
||||
if _, ok := err.(runtime.Error); ok {
|
||||
desc = err.Error()
|
||||
switch err.(type) {
|
||||
case *runtime.TypeAssertionError:
|
||||
goType = "runtime.TypeAssertionError"
|
||||
default:
|
||||
goType = reflect.TypeOf(err).String()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// structs
|
||||
switch actual := err.(type) {
|
||||
case *http.ProtocolError:
|
||||
desc = actual.ErrorString
|
||||
if name, ok := httpProtocolErrors[err]; ok {
|
||||
goType = name
|
||||
} else {
|
||||
goType = "http.ProtocolError"
|
||||
}
|
||||
case url.EscapeError, *url.EscapeError:
|
||||
goType = "url.EscapeError"
|
||||
desc = "invalid URL escape"
|
||||
case url.InvalidHostError, *url.InvalidHostError:
|
||||
goType = "url.InvalidHostError"
|
||||
desc = "invalid character in host name"
|
||||
case *textproto.Error:
|
||||
goType = "textproto.Error"
|
||||
desc = actual.Error()
|
||||
case textproto.ProtocolError, *textproto.ProtocolError:
|
||||
goType = "textproto.ProtocolError"
|
||||
desc = actual.Error()
|
||||
|
||||
case tls.RecordHeaderError:
|
||||
goType = "tls.RecordHeaderError"
|
||||
desc = actual.Msg
|
||||
extra["header"] = hex.EncodeToString(actual.RecordHeader[:])
|
||||
case x509.CertificateInvalidError:
|
||||
goType = "x509.CertificateInvalidError"
|
||||
desc = actual.Error()
|
||||
case x509.ConstraintViolationError:
|
||||
goType = "x509.ConstraintViolationError"
|
||||
desc = actual.Error()
|
||||
case x509.HostnameError:
|
||||
goType = "x509.HostnameError"
|
||||
desc = actual.Error()
|
||||
extra["host"] = actual.Host
|
||||
case x509.InsecureAlgorithmError:
|
||||
goType = "x509.InsecureAlgorithmError"
|
||||
desc = actual.Error()
|
||||
case x509.SystemRootsError:
|
||||
goType = "x509.SystemRootsError"
|
||||
desc = actual.Error()
|
||||
case x509.UnhandledCriticalExtension:
|
||||
goType = "x509.UnhandledCriticalExtension"
|
||||
desc = actual.Error()
|
||||
case x509.UnknownAuthorityError:
|
||||
goType = "x509.UnknownAuthorityError"
|
||||
desc = actual.Error()
|
||||
case hex.InvalidByteError:
|
||||
goType = "hex.InvalidByteError"
|
||||
desc = "invalid byte"
|
||||
case *json.InvalidUTF8Error:
|
||||
goType = "json.InvalidUTF8Error"
|
||||
desc = "invalid UTF-8 in string"
|
||||
case *json.InvalidUnmarshalError:
|
||||
goType = "json.InvalidUnmarshalError"
|
||||
desc = actual.Error()
|
||||
case *json.MarshalerError:
|
||||
goType = "json.MarshalerError"
|
||||
desc = actual.Error()
|
||||
case *json.SyntaxError:
|
||||
goType = "json.SyntaxError"
|
||||
desc = actual.Error()
|
||||
case *json.UnmarshalFieldError:
|
||||
goType = "json.UnmarshalFieldError"
|
||||
desc = actual.Error()
|
||||
case *json.UnmarshalTypeError:
|
||||
goType = "json.UnmarshalTypeError"
|
||||
desc = actual.Error()
|
||||
case *json.UnsupportedTypeError:
|
||||
goType = "json.UnsupportedTypeError"
|
||||
desc = actual.Error()
|
||||
case *json.UnsupportedValueError:
|
||||
goType = "json.UnsupportedValueError"
|
||||
desc = actual.Error()
|
||||
|
||||
case *os.LinkError:
|
||||
goType = "os.LinkError"
|
||||
desc = actual.Error()
|
||||
case *os.PathError:
|
||||
goType = "os.PathError"
|
||||
op = actual.Op
|
||||
desc = actual.Err.Error()
|
||||
case *os.SyscallError:
|
||||
goType = "os.SyscallError"
|
||||
op = actual.Syscall
|
||||
desc = actual.Err.Error()
|
||||
case *exec.Error:
|
||||
goType = "exec.Error"
|
||||
desc = actual.Err.Error()
|
||||
case *exec.ExitError:
|
||||
goType = "exec.ExitError"
|
||||
desc = actual.Error()
|
||||
// TODO: limit the length
|
||||
extra["stderr"] = string(actual.Stderr)
|
||||
case *strconv.NumError:
|
||||
goType = "strconv.NumError"
|
||||
desc = actual.Err.Error()
|
||||
extra["function"] = actual.Func
|
||||
case *time.ParseError:
|
||||
goType = "time.ParseError"
|
||||
desc = actual.Message
|
||||
default:
|
||||
desc = err.Error()
|
||||
if t, ok := miscErrors[err]; ok {
|
||||
goType = t
|
||||
return
|
||||
}
|
||||
goType = reflect.TypeOf(err).String()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var httpProtocolErrors = map[error]string{
|
||||
http.ErrHeaderTooLong: "http.ErrHeaderTooLong",
|
||||
http.ErrShortBody: "http.ErrShortBody",
|
||||
http.ErrNotSupported: "http.ErrNotSupported",
|
||||
http.ErrUnexpectedTrailer: "http.ErrUnexpectedTrailer",
|
||||
http.ErrMissingContentLength: "http.ErrMissingContentLength",
|
||||
http.ErrNotMultipart: "http.ErrNotMultipart",
|
||||
http.ErrMissingBoundary: "http.ErrMissingBoundary",
|
||||
}
|
||||
|
||||
var miscErrors = map[error]string{
|
||||
bufio.ErrInvalidUnreadByte: "bufio.ErrInvalidUnreadByte",
|
||||
bufio.ErrInvalidUnreadRune: "bufio.ErrInvalidUnreadRune",
|
||||
bufio.ErrBufferFull: "bufio.ErrBufferFull",
|
||||
bufio.ErrNegativeCount: "bufio.ErrNegativeCount",
|
||||
bufio.ErrTooLong: "bufio.ErrTooLong",
|
||||
bufio.ErrNegativeAdvance: "bufio.ErrNegativeAdvance",
|
||||
bufio.ErrAdvanceTooFar: "bufio.ErrAdvanceTooFar",
|
||||
bufio.ErrFinalToken: "bufio.ErrFinalToken",
|
||||
|
||||
http.ErrWriteAfterFlush: "http.ErrWriteAfterFlush",
|
||||
http.ErrBodyNotAllowed: "http.ErrBodyNotAllowed",
|
||||
http.ErrHijacked: "http.ErrHijacked",
|
||||
http.ErrContentLength: "http.ErrContentLength",
|
||||
http.ErrBodyReadAfterClose: "http.ErrBodyReadAfterClose",
|
||||
http.ErrHandlerTimeout: "http.ErrHandlerTimeout",
|
||||
http.ErrLineTooLong: "http.ErrLineTooLong",
|
||||
http.ErrMissingFile: "http.ErrMissingFile",
|
||||
http.ErrNoCookie: "http.ErrNoCookie",
|
||||
http.ErrNoLocation: "http.ErrNoLocation",
|
||||
http.ErrSkipAltProtocol: "http.ErrSkipAltProtocol",
|
||||
|
||||
io.EOF: "io.EOF",
|
||||
io.ErrClosedPipe: "io.ErrClosedPipe",
|
||||
io.ErrNoProgress: "io.ErrNoProgress",
|
||||
io.ErrShortBuffer: "io.ErrShortBuffer",
|
||||
io.ErrShortWrite: "io.ErrShortWrite",
|
||||
io.ErrUnexpectedEOF: "io.ErrUnexpectedEOF",
|
||||
|
||||
os.ErrInvalid: "os.ErrInvalid",
|
||||
os.ErrPermission: "os.ErrPermission",
|
||||
os.ErrExist: "os.ErrExist",
|
||||
os.ErrNotExist: "os.ErrNotExist",
|
||||
|
||||
exec.ErrNotFound: "exec.ErrNotFound",
|
||||
|
||||
x509.ErrUnsupportedAlgorithm: "x509.ErrUnsupportedAlgorithm",
|
||||
x509.IncorrectPasswordError: "x509.IncorrectPasswordError",
|
||||
|
||||
hex.ErrLength: "hex.ErrLength",
|
||||
}
|
57
vendor/github.com/getlantern/errors/hide.go
generated
vendored
Normal file
57
vendor/github.com/getlantern/errors/hide.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"sync"
|
||||
|
||||
"github.com/getlantern/hidden"
|
||||
)
|
||||
|
||||
var (
|
||||
hiddenErrors = make([]hideableError, 100)
|
||||
nextID = uint64(0)
|
||||
hiddenMutex sync.RWMutex
|
||||
)
|
||||
|
||||
type hideableError interface {
|
||||
Error
|
||||
id() uint64
|
||||
setID(uint64)
|
||||
setHiddenID(string)
|
||||
}
|
||||
|
||||
// This trick saves the error to a ring buffer and embeds a non-printing
|
||||
// hiddenID in the error's description, so that if the error is later wrapped
|
||||
// by a standard error using something like
|
||||
// fmt.Errorf("An error occurred: %v", thisError), we can subsequently extract
|
||||
// the error simply using the hiddenID in the string.
|
||||
func bufferError(e hideableError) {
|
||||
hiddenMutex.Lock()
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, nextID)
|
||||
e.setID(nextID)
|
||||
e.setHiddenID(hidden.ToString(b))
|
||||
hiddenErrors[idxForID(nextID)] = e
|
||||
nextID++
|
||||
hiddenMutex.Unlock()
|
||||
}
|
||||
|
||||
func get(hiddenID []byte) Error {
|
||||
if len(hiddenID) != 8 {
|
||||
return nil
|
||||
}
|
||||
id := binary.BigEndian.Uint64(hiddenID)
|
||||
hiddenMutex.RLock()
|
||||
err := hiddenErrors[idxForID(id)]
|
||||
hiddenMutex.RUnlock()
|
||||
if err != nil && err.id() == id {
|
||||
// Found it!
|
||||
return err
|
||||
}
|
||||
// buffer has rolled over
|
||||
return nil
|
||||
}
|
||||
|
||||
func idxForID(id uint64) int {
|
||||
return int(id % uint64(len(hiddenErrors)))
|
||||
}
|
122
vendor/github.com/getlantern/filepersist/filepersist.go
generated
vendored
Normal file
122
vendor/github.com/getlantern/filepersist/filepersist.go
generated
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
// package filepersist provdies a mechanism for persisting data to a file at a
|
||||
// permanent location
|
||||
package filepersist
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/getlantern/golog"
|
||||
)
|
||||
|
||||
var (
|
||||
log = golog.LoggerFor("filepersist")
|
||||
)
|
||||
|
||||
// Save saves the given data to the file at filename. If an existing file at
|
||||
// that filename already exists, this simply chmods the existing file to match
|
||||
// the given fileMode and otherwise leaves it alone.
|
||||
func Save(filename string, data []byte, fileMode os.FileMode) error {
|
||||
log.Tracef("Attempting to open %v for creating, but only if it doesn't already exist", filename)
|
||||
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_EXCL, fileMode)
|
||||
if err != nil {
|
||||
if !os.IsExist(err) {
|
||||
return fmt.Errorf("Unexpected error opening %s: %s", filename, err)
|
||||
}
|
||||
|
||||
log.Tracef("%s already exists, check to make sure contents is the same", filename)
|
||||
if dataMatches(filename, data) {
|
||||
log.Tracef("Data in %s matches expected, using existing", filename)
|
||||
chmod(filename, fileMode)
|
||||
// TODO - maybe don't swallow the error, but returning something
|
||||
// unique so the caller can decide whether or not to ignore it.
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Tracef("Data in %s doesn't match expected, truncating file", filename)
|
||||
file, err = openAndTruncate(filename, fileMode, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to truncate %s: %s", filename, err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Tracef("Created new file at %s, writing data", filename)
|
||||
_, err = file.Write(data)
|
||||
if err != nil {
|
||||
if err := os.Remove(filename); err != nil {
|
||||
log.Debugf("Unable to remove file: %v", err)
|
||||
}
|
||||
return fmt.Errorf("Unable to write to file at %s: %s", filename, err)
|
||||
}
|
||||
if err := file.Sync(); err != nil {
|
||||
log.Debugf("Unable to sync file: %v", err)
|
||||
}
|
||||
if err := file.Close(); err != nil {
|
||||
log.Debugf("Unable to close file: %v", err)
|
||||
}
|
||||
|
||||
log.Trace("File saved")
|
||||
return nil
|
||||
}
|
||||
|
||||
func openAndTruncate(filename string, fileMode os.FileMode, removeIfNecessary bool) (*os.File, error) {
|
||||
file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, fileMode)
|
||||
if err != nil && os.IsPermission(err) && removeIfNecessary {
|
||||
log.Tracef("Permission denied truncating file %v, try to remove", filename)
|
||||
err = os.Remove(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to remove file %v: %v", filename, err)
|
||||
}
|
||||
return openAndTruncate(filename, fileMode, false)
|
||||
}
|
||||
|
||||
return file, err
|
||||
}
|
||||
|
||||
// dataMatches compares the file at filename byte for byte with the given data
|
||||
func dataMatches(filename string, data []byte) bool {
|
||||
file, err := os.OpenFile(filename, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
log.Tracef("Unable to open existing file at %s for reading: %s", filename, err)
|
||||
return false
|
||||
}
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
log.Tracef("Unable to stat file %s", filename)
|
||||
return false
|
||||
}
|
||||
if fileInfo.Size() != int64(len(data)) {
|
||||
return false
|
||||
}
|
||||
b := make([]byte, 65536)
|
||||
i := 0
|
||||
for {
|
||||
n, err := file.Read(b)
|
||||
if err != nil && err != io.EOF {
|
||||
log.Tracef("Error reading %s for comparison: %s", filename, err)
|
||||
return false
|
||||
}
|
||||
for j := 0; j < n; j++ {
|
||||
if b[j] != data[i] {
|
||||
return false
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func chmod(filename string, fileMode os.FileMode) {
|
||||
fi, err := os.Stat(filename)
|
||||
if err != nil || fi.Mode() != fileMode {
|
||||
log.Tracef("Chmodding %v", filename)
|
||||
err = os.Chmod(filename, fileMode)
|
||||
if err != nil {
|
||||
log.Debugf("Warning - unable to chmod %v: %v", filename, err)
|
||||
}
|
||||
}
|
||||
}
|
14
vendor/github.com/getlantern/golog/.travis.yml
generated
vendored
Normal file
14
vendor/github.com/getlantern/golog/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.4.1
|
||||
|
||||
install:
|
||||
- go get -d -t -v ./...
|
||||
- go build -v ./...
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get -v github.com/axw/gocov/gocov
|
||||
- go get -v github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- $HOME/gopath/bin/goveralls -v -service travis-ci github.com/getlantern/golog
|
202
vendor/github.com/getlantern/golog/LICENSE
generated
vendored
Normal file
202
vendor/github.com/getlantern/golog/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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 2014 Brave New Software Project, Inc.
|
||||
|
||||
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.
|
6
vendor/github.com/getlantern/golog/README.md
generated
vendored
Normal file
6
vendor/github.com/getlantern/golog/README.md
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
golog [![Travis CI Status](https://travis-ci.org/getlantern/golog.svg?branch=master)](https://travis-ci.org/getlantern/golog) [![Coverage Status](https://coveralls.io/repos/getlantern/golog/badge.png)](https://coveralls.io/r/getlantern/golog) [![GoDoc](https://godoc.org/github.com/getlantern/golog?status.png)](http://godoc.org/github.com/getlantern/golog)
|
||||
==========
|
||||
Provides logging used in many getlantern components.
|
||||
|
||||
[GoDoc](https://godoc.org/github.com/getlantern/golog)
|
||||
|
14
vendor/github.com/getlantern/golog/go.mod
generated
vendored
Normal file
14
vendor/github.com/getlantern/golog/go.mod
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
module github.com/getlantern/golog
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 // indirect
|
||||
github.com/getlantern/errors v1.0.1
|
||||
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 // indirect
|
||||
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55
|
||||
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f
|
||||
github.com/go-stack/stack v1.8.0 // indirect
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c
|
||||
github.com/stretchr/testify v1.3.0
|
||||
)
|
21
vendor/github.com/getlantern/golog/go.sum
generated
vendored
Normal file
21
vendor/github.com/getlantern/golog/go.sum
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520 h1:NRUJuo3v3WGC/g5YiyF790gut6oQr5f3FBI88Wv0dx4=
|
||||
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
|
||||
github.com/getlantern/errors v1.0.1 h1:XukU2whlh7OdpxnkXhNH9VTLVz0EVPGKDV5K0oWhvzw=
|
||||
github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
|
||||
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7 h1:micT5vkcr9tOVk1FiH8SWKID8ultN44Z+yzd2y/Vyb0=
|
||||
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o=
|
||||
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55 h1:XYzSdCbkzOC0FDNrgJqGRo8PCMFOBFL9py72DRs7bmc=
|
||||
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
|
||||
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f h1:wrYrQttPS8FHIRSlsrcuKazukx/xqO/PpLZzZXsF+EA=
|
||||
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
|
||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
480
vendor/github.com/getlantern/golog/golog.go
generated
vendored
Normal file
480
vendor/github.com/getlantern/golog/golog.go
generated
vendored
Normal file
@ -0,0 +1,480 @@
|
||||
// Package golog implements logging functions that log errors to stderr and
|
||||
// debug messages to stdout. Trace logging is also supported.
|
||||
// Trace logs go to stdout as well, but they are only written if the program
|
||||
// is run with environment variable "TRACE=true".
|
||||
// A stack dump will be printed after the message if "PRINT_STACK=true".
|
||||
package golog
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/getlantern/errors"
|
||||
"github.com/getlantern/hidden"
|
||||
"github.com/getlantern/ops"
|
||||
"github.com/oxtoacart/bpool"
|
||||
)
|
||||
|
||||
const (
|
||||
// ERROR is an error Severity
|
||||
ERROR = 500
|
||||
|
||||
// FATAL is an error Severity
|
||||
FATAL = 600
|
||||
)
|
||||
|
||||
var (
|
||||
outs atomic.Value
|
||||
prepender atomic.Value
|
||||
reporters []ErrorReporter
|
||||
reportersMutex sync.RWMutex
|
||||
|
||||
bufferPool = bpool.NewBufferPool(200)
|
||||
|
||||
onFatal atomic.Value
|
||||
)
|
||||
|
||||
// Severity is a level of error (higher values are more severe)
|
||||
type Severity int
|
||||
|
||||
func (s Severity) String() string {
|
||||
switch s {
|
||||
case ERROR:
|
||||
return "ERROR"
|
||||
case FATAL:
|
||||
return "FATAL"
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
DefaultOnFatal()
|
||||
ResetOutputs()
|
||||
ResetPrepender()
|
||||
}
|
||||
|
||||
// SetPrepender sets a function to write something, e.g., the timestamp, before
|
||||
// each line of the log.
|
||||
func SetPrepender(p func(io.Writer)) {
|
||||
prepender.Store(p)
|
||||
}
|
||||
|
||||
func ResetPrepender() {
|
||||
SetPrepender(func(io.Writer) {})
|
||||
}
|
||||
|
||||
func GetPrepender() func(io.Writer) {
|
||||
return prepender.Load().(func(io.Writer))
|
||||
}
|
||||
|
||||
// SetOutputs sets the outputs for error and debug logs to use the given writers.
|
||||
// Returns a function that resets outputs to their original values prior to calling SetOutputs.
|
||||
func SetOutputs(errorOut io.Writer, debugOut io.Writer) (reset func()) {
|
||||
oldOuts := outs.Load()
|
||||
outs.Store(&outputs{
|
||||
ErrorOut: errorOut,
|
||||
DebugOut: debugOut,
|
||||
})
|
||||
return func() {
|
||||
outs.Store(oldOuts)
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated: instead of calling ResetOutputs, use the reset function returned by SetOutputs.
|
||||
func ResetOutputs() {
|
||||
SetOutputs(os.Stderr, os.Stdout)
|
||||
}
|
||||
|
||||
func GetOutputs() *outputs {
|
||||
return outs.Load().(*outputs)
|
||||
}
|
||||
|
||||
// RegisterReporter registers the given ErrorReporter. All logged Errors are
|
||||
// sent to this reporter.
|
||||
func RegisterReporter(reporter ErrorReporter) {
|
||||
reportersMutex.Lock()
|
||||
reporters = append(reporters, reporter)
|
||||
reportersMutex.Unlock()
|
||||
}
|
||||
|
||||
// OnFatal configures golog to call the given function on any FATAL error. By
|
||||
// default, golog calls os.Exit(1) on any FATAL error.
|
||||
func OnFatal(fn func(err error)) {
|
||||
onFatal.Store(fn)
|
||||
}
|
||||
|
||||
// DefaultOnFatal enables the default behavior for OnFatal
|
||||
func DefaultOnFatal() {
|
||||
onFatal.Store(func(err error) {
|
||||
os.Exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
type outputs struct {
|
||||
ErrorOut io.Writer
|
||||
DebugOut io.Writer
|
||||
}
|
||||
|
||||
// MultiLine is an interface for arguments that support multi-line output.
|
||||
type MultiLine interface {
|
||||
// MultiLinePrinter returns a function that can be used to print the
|
||||
// multi-line output. The returned function writes one line to the buffer and
|
||||
// returns true if there are more lines to write. This function does not need
|
||||
// to take care of trailing carriage returns, golog handles that
|
||||
// automatically.
|
||||
MultiLinePrinter() func(buf *bytes.Buffer) bool
|
||||
}
|
||||
|
||||
// ErrorReporter is a function to which the logger will report errors.
|
||||
// It the given error and corresponding message along with associated ops
|
||||
// context. This should return quickly as it executes on the critical code
|
||||
// path. The recommended approach is to buffer as much as possible and discard
|
||||
// new reports if the buffer becomes saturated.
|
||||
type ErrorReporter func(err error, severity Severity, ctx map[string]interface{})
|
||||
|
||||
type Logger interface {
|
||||
// Debug logs to stdout
|
||||
Debug(arg interface{})
|
||||
// Debugf logs to stdout
|
||||
Debugf(message string, args ...interface{})
|
||||
|
||||
// Error logs to stderr
|
||||
Error(arg interface{}) error
|
||||
// Errorf logs to stderr. It returns the first argument that's an error, or
|
||||
// a new error built using fmt.Errorf if none of the arguments are errors.
|
||||
Errorf(message string, args ...interface{}) error
|
||||
|
||||
// Fatal logs to stderr and then exits with status 1
|
||||
Fatal(arg interface{})
|
||||
// Fatalf logs to stderr and then exits with status 1
|
||||
Fatalf(message string, args ...interface{})
|
||||
|
||||
// Trace logs to stderr only if TRACE=true
|
||||
Trace(arg interface{})
|
||||
// Tracef logs to stderr only if TRACE=true
|
||||
Tracef(message string, args ...interface{})
|
||||
|
||||
// TraceOut provides access to an io.Writer to which trace information can
|
||||
// be streamed. If running with environment variable "TRACE=true", TraceOut
|
||||
// will point to os.Stderr, otherwise it will point to a ioutil.Discared.
|
||||
// Each line of trace information will be prefixed with this Logger's
|
||||
// prefix.
|
||||
TraceOut() io.Writer
|
||||
|
||||
// IsTraceEnabled() indicates whether or not tracing is enabled for this
|
||||
// logger.
|
||||
IsTraceEnabled() bool
|
||||
|
||||
// AsStdLogger returns an standard logger
|
||||
AsStdLogger() *log.Logger
|
||||
}
|
||||
|
||||
func LoggerFor(prefix string) Logger {
|
||||
l := &logger{
|
||||
prefix: prefix + ": ",
|
||||
pc: make([]uintptr, 10),
|
||||
}
|
||||
|
||||
trace := os.Getenv("TRACE")
|
||||
l.traceOn, _ = strconv.ParseBool(trace)
|
||||
if !l.traceOn {
|
||||
prefixes := strings.Split(trace, ",")
|
||||
for _, p := range prefixes {
|
||||
if prefix == strings.Trim(p, " ") {
|
||||
l.traceOn = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if l.traceOn {
|
||||
l.traceOut = l.newTraceWriter()
|
||||
} else {
|
||||
l.traceOut = ioutil.Discard
|
||||
}
|
||||
|
||||
printStack := os.Getenv("PRINT_STACK")
|
||||
l.printStack, _ = strconv.ParseBool(printStack)
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
prefix string
|
||||
traceOn bool
|
||||
traceOut io.Writer
|
||||
printStack bool
|
||||
outs atomic.Value
|
||||
pc []uintptr
|
||||
funcForPc *runtime.Func
|
||||
}
|
||||
|
||||
// attaches the file and line number corresponding to
|
||||
// the log message
|
||||
func (l *logger) linePrefix(skipFrames int) string {
|
||||
runtime.Callers(skipFrames, l.pc)
|
||||
funcForPc := runtime.FuncForPC(l.pc[0])
|
||||
file, line := funcForPc.FileLine(l.pc[0] - 1)
|
||||
return fmt.Sprintf("%s%s:%d ", l.prefix, filepath.Base(file), line)
|
||||
}
|
||||
|
||||
func (l *logger) print(out io.Writer, skipFrames int, severity string, arg interface{}) {
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
|
||||
GetPrepender()(buf)
|
||||
linePrefix := l.linePrefix(skipFrames)
|
||||
writeHeader := func() {
|
||||
buf.WriteString(severity)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(linePrefix)
|
||||
}
|
||||
if arg != nil {
|
||||
ml, isMultiline := arg.(MultiLine)
|
||||
if !isMultiline {
|
||||
writeHeader()
|
||||
fmt.Fprintf(buf, "%v", arg)
|
||||
printContext(buf, arg)
|
||||
buf.WriteByte('\n')
|
||||
} else {
|
||||
mlp := ml.MultiLinePrinter()
|
||||
first := true
|
||||
for {
|
||||
writeHeader()
|
||||
more := mlp(buf)
|
||||
if first {
|
||||
printContext(buf, arg)
|
||||
first = false
|
||||
}
|
||||
buf.WriteByte('\n')
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
b := []byte(hidden.Clean(buf.String()))
|
||||
_, err := out.Write(b)
|
||||
if err != nil {
|
||||
errorOnLogging(err)
|
||||
}
|
||||
if l.printStack {
|
||||
l.doPrintStack()
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logger) printf(out io.Writer, skipFrames int, severity string, err error, message string, args ...interface{}) {
|
||||
buf := bufferPool.Get()
|
||||
defer bufferPool.Put(buf)
|
||||
|
||||
GetPrepender()(buf)
|
||||
linePrefix := l.linePrefix(skipFrames)
|
||||
buf.WriteString(severity)
|
||||
buf.WriteString(" ")
|
||||
buf.WriteString(linePrefix)
|
||||
fmt.Fprintf(buf, message, args...)
|
||||
printContext(buf, err)
|
||||
buf.WriteByte('\n')
|
||||
b := []byte(hidden.Clean(buf.String()))
|
||||
_, err2 := out.Write(b)
|
||||
if err2 != nil {
|
||||
errorOnLogging(err2)
|
||||
}
|
||||
if l.printStack {
|
||||
l.doPrintStack()
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logger) Debug(arg interface{}) {
|
||||
l.print(GetOutputs().DebugOut, 4, "DEBUG", arg)
|
||||
}
|
||||
|
||||
func (l *logger) Debugf(message string, args ...interface{}) {
|
||||
l.printf(GetOutputs().DebugOut, 4, "DEBUG", nil, message, args...)
|
||||
}
|
||||
|
||||
func (l *logger) Error(arg interface{}) error {
|
||||
return l.errorSkipFrames(arg, 1, ERROR)
|
||||
}
|
||||
|
||||
func (l *logger) Errorf(message string, args ...interface{}) error {
|
||||
return l.errorSkipFrames(errors.NewOffset(1, message, args...), 1, ERROR)
|
||||
}
|
||||
|
||||
func (l *logger) Fatal(arg interface{}) {
|
||||
fatal(l.errorSkipFrames(arg, 1, FATAL))
|
||||
}
|
||||
|
||||
func (l *logger) Fatalf(message string, args ...interface{}) {
|
||||
fatal(l.errorSkipFrames(errors.NewOffset(1, message, args...), 1, FATAL))
|
||||
}
|
||||
|
||||
func fatal(err error) {
|
||||
fn := onFatal.Load().(func(err error))
|
||||
fn(err)
|
||||
}
|
||||
|
||||
func (l *logger) errorSkipFrames(arg interface{}, skipFrames int, severity Severity) error {
|
||||
var err error
|
||||
switch e := arg.(type) {
|
||||
case error:
|
||||
err = e
|
||||
default:
|
||||
err = fmt.Errorf("%v", e)
|
||||
}
|
||||
l.print(GetOutputs().ErrorOut, skipFrames+4, severity.String(), err)
|
||||
return report(err, severity)
|
||||
}
|
||||
|
||||
func (l *logger) Trace(arg interface{}) {
|
||||
if l.traceOn {
|
||||
l.print(GetOutputs().DebugOut, 4, "TRACE", arg)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logger) Tracef(message string, args ...interface{}) {
|
||||
if l.traceOn {
|
||||
l.printf(GetOutputs().DebugOut, 4, "TRACE", nil, message, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logger) TraceOut() io.Writer {
|
||||
return l.traceOut
|
||||
}
|
||||
|
||||
func (l *logger) IsTraceEnabled() bool {
|
||||
return l.traceOn
|
||||
}
|
||||
|
||||
func (l *logger) newTraceWriter() io.Writer {
|
||||
pr, pw := io.Pipe()
|
||||
br := bufio.NewReader(pr)
|
||||
|
||||
if !l.traceOn {
|
||||
return pw
|
||||
}
|
||||
go func() {
|
||||
defer func() {
|
||||
if err := pr.Close(); err != nil {
|
||||
errorOnLogging(err)
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
if err := pw.Close(); err != nil {
|
||||
errorOnLogging(err)
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
line, err := br.ReadString('\n')
|
||||
if err == nil {
|
||||
// Log the line (minus the trailing newline)
|
||||
l.print(GetOutputs().DebugOut, 6, "TRACE", line[:len(line)-1])
|
||||
} else {
|
||||
l.printf(GetOutputs().DebugOut, 6, "TRACE", nil, "TraceWriter closed due to unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return pw
|
||||
}
|
||||
|
||||
type errorWriter struct {
|
||||
l *logger
|
||||
}
|
||||
|
||||
// Write implements method of io.Writer, due to different call depth,
|
||||
// it will not log correct file and line prefix
|
||||
func (w *errorWriter) Write(p []byte) (n int, err error) {
|
||||
s := string(p)
|
||||
if s[len(s)-1] == '\n' {
|
||||
s = s[:len(s)-1]
|
||||
}
|
||||
w.l.print(GetOutputs().ErrorOut, 6, "ERROR", s)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (l *logger) AsStdLogger() *log.Logger {
|
||||
return log.New(&errorWriter{l}, "", 0)
|
||||
}
|
||||
|
||||
func (l *logger) doPrintStack() {
|
||||
var b []byte
|
||||
buf := bytes.NewBuffer(b)
|
||||
for _, pc := range l.pc {
|
||||
funcForPc := runtime.FuncForPC(pc)
|
||||
if funcForPc == nil {
|
||||
break
|
||||
}
|
||||
name := funcForPc.Name()
|
||||
if strings.HasPrefix(name, "runtime.") {
|
||||
break
|
||||
}
|
||||
file, line := funcForPc.FileLine(pc)
|
||||
fmt.Fprintf(buf, "\t%s\t%s: %d\n", name, file, line)
|
||||
}
|
||||
if _, err := buf.WriteTo(os.Stderr); err != nil {
|
||||
errorOnLogging(err)
|
||||
}
|
||||
}
|
||||
|
||||
func errorOnLogging(err error) {
|
||||
fmt.Fprintf(os.Stderr, "Unable to log: %v\n", err)
|
||||
}
|
||||
|
||||
func printContext(buf *bytes.Buffer, err interface{}) {
|
||||
// Note - we don't include globals when printing in order to avoid polluting the text log
|
||||
values := ops.AsMap(err, false)
|
||||
if len(values) == 0 {
|
||||
return
|
||||
}
|
||||
buf.WriteString(" [")
|
||||
var keys []string
|
||||
for key := range values {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for i, key := range keys {
|
||||
value := values[key]
|
||||
if i > 0 {
|
||||
buf.WriteString(" ")
|
||||
}
|
||||
buf.WriteString(key)
|
||||
buf.WriteString("=")
|
||||
fmt.Fprintf(buf, "%v", value)
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
}
|
||||
|
||||
func report(err error, severity Severity) error {
|
||||
var reportersCopy []ErrorReporter
|
||||
reportersMutex.RLock()
|
||||
if len(reporters) > 0 {
|
||||
reportersCopy = make([]ErrorReporter, len(reporters))
|
||||
copy(reportersCopy, reporters)
|
||||
}
|
||||
reportersMutex.RUnlock()
|
||||
|
||||
if len(reportersCopy) > 0 {
|
||||
ctx := ops.AsMap(err, true)
|
||||
ctx["severity"] = severity.String()
|
||||
for _, reporter := range reportersCopy {
|
||||
// We include globals when reporting
|
||||
reporter(err, severity, ctx)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
29
vendor/github.com/getlantern/hex/LICENSE
generated
vendored
Normal file
29
vendor/github.com/getlantern/hex/LICENSE
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
Copyright (c) 2009 The Go Authors.
|
||||
Copyright (c) 2016 Brave New Software Project, Inc.
|
||||
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.
|
110
vendor/github.com/getlantern/hex/hex.go
generated
vendored
Normal file
110
vendor/github.com/getlantern/hex/hex.go
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright 2009 The Go Authors.
|
||||
// Copyright 2016 Brave New Software Project, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package hex implements hexadecimal encoding and decoding. It's taken almost
|
||||
// verbatim from golang/encoding/hex, however it allows using a different set
|
||||
// of encoding characters than the standard 0-F.
|
||||
package hex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// DefaultEncoding behaves just like golang/encoding/hex.
|
||||
var DefaultEncoding = NewEncoding("0123456789abcdef")
|
||||
|
||||
// An Encoding that uses a specific table of encoding characters.
|
||||
type Encoding struct {
|
||||
hextable string
|
||||
}
|
||||
|
||||
// NewEncoding constructs an Encoding using the given hextable.
|
||||
func NewEncoding(hextable string) *Encoding {
|
||||
return &Encoding{hextable}
|
||||
}
|
||||
|
||||
// EncodedLen returns the length of an encoding of n source bytes.
|
||||
func EncodedLen(n int) int { return n * 2 }
|
||||
|
||||
// Encode encodes src into EncodedLen(len(src))
|
||||
// bytes of dst. As a convenience, it returns the number
|
||||
// of bytes written to dst, but this value is always EncodedLen(len(src)).
|
||||
// Encode implements hexadecimal encoding.
|
||||
func (e *Encoding) Encode(dst, src []byte) int {
|
||||
for i, v := range src {
|
||||
dst[i*2] = e.hextable[v>>4]
|
||||
dst[i*2+1] = e.hextable[v&0x0f]
|
||||
}
|
||||
|
||||
return len(src) * 2
|
||||
}
|
||||
|
||||
// ErrLength results from decoding an odd length slice.
|
||||
var ErrLength = errors.New("encoding/hex: odd length hex string")
|
||||
|
||||
// InvalidByteError values describe errors resulting from an invalid byte in a hex string.
|
||||
type InvalidByteError byte
|
||||
|
||||
func (e InvalidByteError) Error() string {
|
||||
return fmt.Sprintf("encoding/hex: invalid byte: %#U", rune(e))
|
||||
}
|
||||
|
||||
func DecodedLen(x int) int { return x / 2 }
|
||||
|
||||
// Decode decodes src into DecodedLen(len(src)) bytes, returning the actual
|
||||
// number of bytes written to dst.
|
||||
//
|
||||
// If Decode encounters invalid input, it returns an error describing the failure.
|
||||
func (e *Encoding) Decode(dst, src []byte) (int, error) {
|
||||
if len(src)%2 == 1 {
|
||||
return 0, ErrLength
|
||||
}
|
||||
|
||||
for i := 0; i < len(src)/2; i++ {
|
||||
a, ok := e.fromHexChar(src[i*2])
|
||||
if !ok {
|
||||
return 0, InvalidByteError(src[i*2])
|
||||
}
|
||||
b, ok := e.fromHexChar(src[i*2+1])
|
||||
if !ok {
|
||||
return 0, InvalidByteError(src[i*2+1])
|
||||
}
|
||||
dst[i] = (a << 4) | b
|
||||
}
|
||||
|
||||
return len(src) / 2, nil
|
||||
}
|
||||
|
||||
// fromHexChar converts a hex character into its value and a success flag.
|
||||
func (e *Encoding) fromHexChar(c byte) (byte, bool) {
|
||||
for i, ch := range []byte(e.hextable) {
|
||||
if ch == c {
|
||||
return byte(i), true
|
||||
}
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// EncodeToString returns the hexadecimal encoding of src.
|
||||
func (e *Encoding) EncodeToString(src []byte) string {
|
||||
dst := make([]byte, EncodedLen(len(src)))
|
||||
e.Encode(dst, src)
|
||||
return string(dst)
|
||||
}
|
||||
|
||||
// DecodeString returns the bytes represented by the hexadecimal string s.
|
||||
func (e *Encoding) DecodeString(s string) ([]byte, error) {
|
||||
src := []byte(s)
|
||||
dst := make([]byte, DecodedLen(len(src)))
|
||||
_, err := e.Decode(dst, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dst, nil
|
||||
}
|
202
vendor/github.com/getlantern/hidden/LICENSE
generated
vendored
Normal file
202
vendor/github.com/getlantern/hidden/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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 2016 Brave New Software Project, Inc.
|
||||
|
||||
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.
|
66
vendor/github.com/getlantern/hidden/hidden.go
generated
vendored
Normal file
66
vendor/github.com/getlantern/hidden/hidden.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
// Package hidden provides the ability to "hide" binary data in a string using
|
||||
// a hex encoding with non-printing characters. Hidden data is demarcated with
|
||||
// a leading and trailing NUL character.
|
||||
package hidden
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/getlantern/hex"
|
||||
)
|
||||
|
||||
// 16 non-printing characters
|
||||
const hextable = "\x01\x02\x03\x04\x05\x06\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17"
|
||||
|
||||
var (
|
||||
hexencoding = hex.NewEncoding(hextable)
|
||||
|
||||
re *regexp.Regexp
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
re, err = regexp.Compile(fmt.Sprintf("\x00[%v]+\x00", hextable))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// ToString encodes the given data as a hidden string, including leadnig and
|
||||
// trailing NULs.
|
||||
func ToString(data []byte) string {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 2+hex.EncodedLen(len(data))))
|
||||
// Leading NUL
|
||||
buf.WriteByte(0)
|
||||
buf.WriteString(hexencoding.EncodeToString(data))
|
||||
// Trailing NUL
|
||||
buf.WriteByte(0)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// FromString extracts the hidden data from a string, which is expected to
|
||||
// contain leading and trailing NULs.
|
||||
func FromString(str string) ([]byte, error) {
|
||||
return hexencoding.DecodeString(str[1 : len(str)-1])
|
||||
}
|
||||
|
||||
// Extract extracts all hidden data from an arbitrary string.
|
||||
func Extract(str string) ([][]byte, error) {
|
||||
m := re.FindAllString(str, -1)
|
||||
result := make([][]byte, 0, len(m))
|
||||
for _, s := range m {
|
||||
b, err := FromString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = append(result, b)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Clean removes any hidden data from an arbitrary string.
|
||||
func Clean(str string) string {
|
||||
return re.ReplaceAllString(str, "")
|
||||
}
|
202
vendor/github.com/getlantern/ops/LICENSE
generated
vendored
Normal file
202
vendor/github.com/getlantern/ops/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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 2017 Brave New Software Project, Inc.
|
||||
|
||||
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.
|
154
vendor/github.com/getlantern/ops/ops.go
generated
vendored
Normal file
154
vendor/github.com/getlantern/ops/ops.go
generated
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
// Package ops provides a facility for tracking the processing of operations,
|
||||
// including contextual metadata about the operation and their final success or
|
||||
// failure. An op is assumed to have succeeded if by the time of calling Exit()
|
||||
// no errors have been reported. The final status can be reported to a metrics
|
||||
// facility.
|
||||
package ops
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/getlantern/context"
|
||||
)
|
||||
|
||||
var (
|
||||
cm = context.NewManager()
|
||||
reporters []Reporter
|
||||
reportersMutex sync.RWMutex
|
||||
)
|
||||
|
||||
// Reporter is a function that reports the success or failure of an Op. If
|
||||
// failure is nil, the Op can be considered successful.
|
||||
type Reporter func(failure error, ctx map[string]interface{})
|
||||
|
||||
// Op represents an operation that's being performed. It mimics the API of
|
||||
// context.Context.
|
||||
type Op interface {
|
||||
// Begin marks the beginning of an Op under this Op.
|
||||
Begin(name string) Op
|
||||
|
||||
// Go starts the given function on a new goroutine.
|
||||
Go(fn func())
|
||||
|
||||
// End marks the end of this op, at which point the Op will report its success
|
||||
// or failure to all registered Reporters.
|
||||
End()
|
||||
|
||||
// Cancel cancels this op so that even if End() is called later, it will not
|
||||
// report its success or failure.
|
||||
Cancel()
|
||||
|
||||
// Set puts a key->value pair into the current Op's context.
|
||||
Set(key string, value interface{}) Op
|
||||
|
||||
// SetDynamic puts a key->value pair into the current Op's context, where the
|
||||
// value is generated by a function that gets evaluated at every Read.
|
||||
SetDynamic(key string, valueFN func() interface{}) Op
|
||||
|
||||
// FailIf marks this Op as failed if the given err is not nil. If FailIf is
|
||||
// called multiple times, the latest error will be reported as the failure.
|
||||
// Returns the original error for convenient chaining.
|
||||
FailIf(err error) error
|
||||
}
|
||||
|
||||
type op struct {
|
||||
ctx context.Context
|
||||
canceled bool
|
||||
failure atomic.Value
|
||||
}
|
||||
|
||||
// RegisterReporter registers the given reporter.
|
||||
func RegisterReporter(reporter Reporter) {
|
||||
reportersMutex.Lock()
|
||||
reporters = append(reporters, reporter)
|
||||
reportersMutex.Unlock()
|
||||
}
|
||||
|
||||
// Begin marks the beginning of a new Op.
|
||||
func Begin(name string) Op {
|
||||
return &op{ctx: cm.Enter().Put("op", name).PutIfAbsent("root_op", name)}
|
||||
}
|
||||
|
||||
func (o *op) Begin(name string) Op {
|
||||
return &op{ctx: o.ctx.Enter().Put("op", name).PutIfAbsent("root_op", name)}
|
||||
}
|
||||
|
||||
func (o *op) Go(fn func()) {
|
||||
o.ctx.Go(fn)
|
||||
}
|
||||
|
||||
// Go mimics the method from context.Manager.
|
||||
func Go(fn func()) {
|
||||
cm.Go(fn)
|
||||
}
|
||||
|
||||
func (o *op) Cancel() {
|
||||
o.canceled = true
|
||||
}
|
||||
|
||||
func (o *op) End() {
|
||||
if o.canceled {
|
||||
return
|
||||
}
|
||||
|
||||
var reportersCopy []Reporter
|
||||
reportersMutex.RLock()
|
||||
if len(reporters) > 0 {
|
||||
reportersCopy = make([]Reporter, len(reporters))
|
||||
copy(reportersCopy, reporters)
|
||||
}
|
||||
reportersMutex.RUnlock()
|
||||
|
||||
if len(reportersCopy) > 0 {
|
||||
var failure error
|
||||
_failure := o.failure.Load()
|
||||
ctx := o.ctx.AsMap(_failure, true)
|
||||
if _failure != nil {
|
||||
failure = _failure.(error)
|
||||
_, errorSet := ctx["error"]
|
||||
if !errorSet {
|
||||
ctx["error"] = failure.Error()
|
||||
}
|
||||
}
|
||||
for _, reporter := range reportersCopy {
|
||||
reporter(failure, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
o.ctx.Exit()
|
||||
}
|
||||
|
||||
func (o *op) Set(key string, value interface{}) Op {
|
||||
o.ctx.Put(key, value)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetGlobal puts a key->value pair into the global context, which is inherited
|
||||
// by all Ops.
|
||||
func SetGlobal(key string, value interface{}) {
|
||||
cm.PutGlobal(key, value)
|
||||
}
|
||||
|
||||
func (o *op) SetDynamic(key string, valueFN func() interface{}) Op {
|
||||
o.ctx.PutDynamic(key, valueFN)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetGlobalDynamic is like SetGlobal but uses a function to derive the value
|
||||
// at read time.
|
||||
func SetGlobalDynamic(key string, valueFN func() interface{}) {
|
||||
cm.PutGlobalDynamic(key, valueFN)
|
||||
}
|
||||
|
||||
// AsMap mimics the method from context.Manager.
|
||||
func AsMap(obj interface{}, includeGlobals bool) context.Map {
|
||||
return cm.AsMap(obj, includeGlobals)
|
||||
}
|
||||
|
||||
func (o *op) FailIf(err error) error {
|
||||
if err != nil {
|
||||
o.failure.Store(err)
|
||||
}
|
||||
return err
|
||||
}
|
15
vendor/github.com/go-stack/stack/.travis.yml
generated
vendored
Normal file
15
vendor/github.com/go-stack/stack/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
language: go
|
||||
sudo: false
|
||||
go:
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- tip
|
||||
|
||||
before_install:
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- goveralls -service=travis-ci
|
21
vendor/github.com/go-stack/stack/LICENSE.md
generated
vendored
Normal file
21
vendor/github.com/go-stack/stack/LICENSE.md
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Chris Hines
|
||||
|
||||
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.
|
38
vendor/github.com/go-stack/stack/README.md
generated
vendored
Normal file
38
vendor/github.com/go-stack/stack/README.md
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
[![GoDoc](https://godoc.org/github.com/go-stack/stack?status.svg)](https://godoc.org/github.com/go-stack/stack)
|
||||
[![Go Report Card](https://goreportcard.com/badge/go-stack/stack)](https://goreportcard.com/report/go-stack/stack)
|
||||
[![TravisCI](https://travis-ci.org/go-stack/stack.svg?branch=master)](https://travis-ci.org/go-stack/stack)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/go-stack/stack/badge.svg?branch=master)](https://coveralls.io/github/go-stack/stack?branch=master)
|
||||
|
||||
# stack
|
||||
|
||||
Package stack implements utilities to capture, manipulate, and format call
|
||||
stacks. It provides a simpler API than package runtime.
|
||||
|
||||
The implementation takes care of the minutia and special cases of interpreting
|
||||
the program counter (pc) values returned by runtime.Callers.
|
||||
|
||||
## Versioning
|
||||
|
||||
Package stack publishes releases via [semver](http://semver.org/) compatible Git
|
||||
tags prefixed with a single 'v'. The master branch always contains the latest
|
||||
release. The develop branch contains unreleased commits.
|
||||
|
||||
## Formatting
|
||||
|
||||
Package stack's types implement fmt.Formatter, which provides a simple and
|
||||
flexible way to declaratively configure formatting when used with logging or
|
||||
error tracking packages.
|
||||
|
||||
```go
|
||||
func DoTheThing() {
|
||||
c := stack.Caller(0)
|
||||
log.Print(c) // "source.go:10"
|
||||
log.Printf("%+v", c) // "pkg/path/source.go:10"
|
||||
log.Printf("%n", c) // "DoTheThing"
|
||||
|
||||
s := stack.Trace().TrimRuntime()
|
||||
log.Print(s) // "[source.go:15 caller.go:42 main.go:14]"
|
||||
}
|
||||
```
|
||||
|
||||
See the docs for all of the supported formatting options.
|
1
vendor/github.com/go-stack/stack/go.mod
generated
vendored
Normal file
1
vendor/github.com/go-stack/stack/go.mod
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module github.com/go-stack/stack
|
400
vendor/github.com/go-stack/stack/stack.go
generated
vendored
Normal file
400
vendor/github.com/go-stack/stack/stack.go
generated
vendored
Normal file
@ -0,0 +1,400 @@
|
||||
// +build go1.7
|
||||
|
||||
// Package stack implements utilities to capture, manipulate, and format call
|
||||
// stacks. It provides a simpler API than package runtime.
|
||||
//
|
||||
// The implementation takes care of the minutia and special cases of
|
||||
// interpreting the program counter (pc) values returned by runtime.Callers.
|
||||
//
|
||||
// Package stack's types implement fmt.Formatter, which provides a simple and
|
||||
// flexible way to declaratively configure formatting when used with logging
|
||||
// or error tracking packages.
|
||||
package stack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Call records a single function invocation from a goroutine stack.
|
||||
type Call struct {
|
||||
frame runtime.Frame
|
||||
}
|
||||
|
||||
// Caller returns a Call from the stack of the current goroutine. The argument
|
||||
// skip is the number of stack frames to ascend, with 0 identifying the
|
||||
// calling function.
|
||||
func Caller(skip int) Call {
|
||||
// As of Go 1.9 we need room for up to three PC entries.
|
||||
//
|
||||
// 0. An entry for the stack frame prior to the target to check for
|
||||
// special handling needed if that prior entry is runtime.sigpanic.
|
||||
// 1. A possible second entry to hold metadata about skipped inlined
|
||||
// functions. If inline functions were not skipped the target frame
|
||||
// PC will be here.
|
||||
// 2. A third entry for the target frame PC when the second entry
|
||||
// is used for skipped inline functions.
|
||||
var pcs [3]uintptr
|
||||
n := runtime.Callers(skip+1, pcs[:])
|
||||
frames := runtime.CallersFrames(pcs[:n])
|
||||
frame, _ := frames.Next()
|
||||
frame, _ = frames.Next()
|
||||
|
||||
return Call{
|
||||
frame: frame,
|
||||
}
|
||||
}
|
||||
|
||||
// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c).
|
||||
func (c Call) String() string {
|
||||
return fmt.Sprint(c)
|
||||
}
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler. It formats the Call the same
|
||||
// as fmt.Sprintf("%v", c).
|
||||
func (c Call) MarshalText() ([]byte, error) {
|
||||
if c.frame == (runtime.Frame{}) {
|
||||
return nil, ErrNoFunc
|
||||
}
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
fmt.Fprint(&buf, c)
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// ErrNoFunc means that the Call has a nil *runtime.Func. The most likely
|
||||
// cause is a Call with the zero value.
|
||||
var ErrNoFunc = errors.New("no call stack information")
|
||||
|
||||
// Format implements fmt.Formatter with support for the following verbs.
|
||||
//
|
||||
// %s source file
|
||||
// %d line number
|
||||
// %n function name
|
||||
// %k last segment of the package path
|
||||
// %v equivalent to %s:%d
|
||||
//
|
||||
// It accepts the '+' and '#' flags for most of the verbs as follows.
|
||||
//
|
||||
// %+s path of source file relative to the compile time GOPATH,
|
||||
// or the module path joined to the path of source file relative
|
||||
// to module root
|
||||
// %#s full path of source file
|
||||
// %+n import path qualified function name
|
||||
// %+k full package path
|
||||
// %+v equivalent to %+s:%d
|
||||
// %#v equivalent to %#s:%d
|
||||
func (c Call) Format(s fmt.State, verb rune) {
|
||||
if c.frame == (runtime.Frame{}) {
|
||||
fmt.Fprintf(s, "%%!%c(NOFUNC)", verb)
|
||||
return
|
||||
}
|
||||
|
||||
switch verb {
|
||||
case 's', 'v':
|
||||
file := c.frame.File
|
||||
switch {
|
||||
case s.Flag('#'):
|
||||
// done
|
||||
case s.Flag('+'):
|
||||
file = pkgFilePath(&c.frame)
|
||||
default:
|
||||
const sep = "/"
|
||||
if i := strings.LastIndex(file, sep); i != -1 {
|
||||
file = file[i+len(sep):]
|
||||
}
|
||||
}
|
||||
io.WriteString(s, file)
|
||||
if verb == 'v' {
|
||||
buf := [7]byte{':'}
|
||||
s.Write(strconv.AppendInt(buf[:1], int64(c.frame.Line), 10))
|
||||
}
|
||||
|
||||
case 'd':
|
||||
buf := [6]byte{}
|
||||
s.Write(strconv.AppendInt(buf[:0], int64(c.frame.Line), 10))
|
||||
|
||||
case 'k':
|
||||
name := c.frame.Function
|
||||
const pathSep = "/"
|
||||
start, end := 0, len(name)
|
||||
if i := strings.LastIndex(name, pathSep); i != -1 {
|
||||
start = i + len(pathSep)
|
||||
}
|
||||
const pkgSep = "."
|
||||
if i := strings.Index(name[start:], pkgSep); i != -1 {
|
||||
end = start + i
|
||||
}
|
||||
if s.Flag('+') {
|
||||
start = 0
|
||||
}
|
||||
io.WriteString(s, name[start:end])
|
||||
|
||||
case 'n':
|
||||
name := c.frame.Function
|
||||
if !s.Flag('+') {
|
||||
const pathSep = "/"
|
||||
if i := strings.LastIndex(name, pathSep); i != -1 {
|
||||
name = name[i+len(pathSep):]
|
||||
}
|
||||
const pkgSep = "."
|
||||
if i := strings.Index(name, pkgSep); i != -1 {
|
||||
name = name[i+len(pkgSep):]
|
||||
}
|
||||
}
|
||||
io.WriteString(s, name)
|
||||
}
|
||||
}
|
||||
|
||||
// Frame returns the call frame infomation for the Call.
|
||||
func (c Call) Frame() runtime.Frame {
|
||||
return c.frame
|
||||
}
|
||||
|
||||
// PC returns the program counter for this call frame; multiple frames may
|
||||
// have the same PC value.
|
||||
//
|
||||
// Deprecated: Use Call.Frame instead.
|
||||
func (c Call) PC() uintptr {
|
||||
return c.frame.PC
|
||||
}
|
||||
|
||||
// CallStack records a sequence of function invocations from a goroutine
|
||||
// stack.
|
||||
type CallStack []Call
|
||||
|
||||
// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", cs).
|
||||
func (cs CallStack) String() string {
|
||||
return fmt.Sprint(cs)
|
||||
}
|
||||
|
||||
var (
|
||||
openBracketBytes = []byte("[")
|
||||
closeBracketBytes = []byte("]")
|
||||
spaceBytes = []byte(" ")
|
||||
)
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler. It formats the CallStack the
|
||||
// same as fmt.Sprintf("%v", cs).
|
||||
func (cs CallStack) MarshalText() ([]byte, error) {
|
||||
buf := bytes.Buffer{}
|
||||
buf.Write(openBracketBytes)
|
||||
for i, pc := range cs {
|
||||
if i > 0 {
|
||||
buf.Write(spaceBytes)
|
||||
}
|
||||
fmt.Fprint(&buf, pc)
|
||||
}
|
||||
buf.Write(closeBracketBytes)
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// Format implements fmt.Formatter by printing the CallStack as square brackets
|
||||
// ([, ]) surrounding a space separated list of Calls each formatted with the
|
||||
// supplied verb and options.
|
||||
func (cs CallStack) Format(s fmt.State, verb rune) {
|
||||
s.Write(openBracketBytes)
|
||||
for i, pc := range cs {
|
||||
if i > 0 {
|
||||
s.Write(spaceBytes)
|
||||
}
|
||||
pc.Format(s, verb)
|
||||
}
|
||||
s.Write(closeBracketBytes)
|
||||
}
|
||||
|
||||
// Trace returns a CallStack for the current goroutine with element 0
|
||||
// identifying the calling function.
|
||||
func Trace() CallStack {
|
||||
var pcs [512]uintptr
|
||||
n := runtime.Callers(1, pcs[:])
|
||||
|
||||
frames := runtime.CallersFrames(pcs[:n])
|
||||
cs := make(CallStack, 0, n)
|
||||
|
||||
// Skip extra frame retrieved just to make sure the runtime.sigpanic
|
||||
// special case is handled.
|
||||
frame, more := frames.Next()
|
||||
|
||||
for more {
|
||||
frame, more = frames.Next()
|
||||
cs = append(cs, Call{frame: frame})
|
||||
}
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// TrimBelow returns a slice of the CallStack with all entries below c
|
||||
// removed.
|
||||
func (cs CallStack) TrimBelow(c Call) CallStack {
|
||||
for len(cs) > 0 && cs[0] != c {
|
||||
cs = cs[1:]
|
||||
}
|
||||
return cs
|
||||
}
|
||||
|
||||
// TrimAbove returns a slice of the CallStack with all entries above c
|
||||
// removed.
|
||||
func (cs CallStack) TrimAbove(c Call) CallStack {
|
||||
for len(cs) > 0 && cs[len(cs)-1] != c {
|
||||
cs = cs[:len(cs)-1]
|
||||
}
|
||||
return cs
|
||||
}
|
||||
|
||||
// pkgIndex returns the index that results in file[index:] being the path of
|
||||
// file relative to the compile time GOPATH, and file[:index] being the
|
||||
// $GOPATH/src/ portion of file. funcName must be the name of a function in
|
||||
// file as returned by runtime.Func.Name.
|
||||
func pkgIndex(file, funcName string) int {
|
||||
// As of Go 1.6.2 there is no direct way to know the compile time GOPATH
|
||||
// at runtime, but we can infer the number of path segments in the GOPATH.
|
||||
// We note that runtime.Func.Name() returns the function name qualified by
|
||||
// the import path, which does not include the GOPATH. Thus we can trim
|
||||
// segments from the beginning of the file path until the number of path
|
||||
// separators remaining is one more than the number of path separators in
|
||||
// the function name. For example, given:
|
||||
//
|
||||
// GOPATH /home/user
|
||||
// file /home/user/src/pkg/sub/file.go
|
||||
// fn.Name() pkg/sub.Type.Method
|
||||
//
|
||||
// We want to produce:
|
||||
//
|
||||
// file[:idx] == /home/user/src/
|
||||
// file[idx:] == pkg/sub/file.go
|
||||
//
|
||||
// From this we can easily see that fn.Name() has one less path separator
|
||||
// than our desired result for file[idx:]. We count separators from the
|
||||
// end of the file path until it finds two more than in the function name
|
||||
// and then move one character forward to preserve the initial path
|
||||
// segment without a leading separator.
|
||||
const sep = "/"
|
||||
i := len(file)
|
||||
for n := strings.Count(funcName, sep) + 2; n > 0; n-- {
|
||||
i = strings.LastIndex(file[:i], sep)
|
||||
if i == -1 {
|
||||
i = -len(sep)
|
||||
break
|
||||
}
|
||||
}
|
||||
// get back to 0 or trim the leading separator
|
||||
return i + len(sep)
|
||||
}
|
||||
|
||||
// pkgFilePath returns the frame's filepath relative to the compile-time GOPATH,
|
||||
// or its module path joined to its path relative to the module root.
|
||||
//
|
||||
// As of Go 1.11 there is no direct way to know the compile time GOPATH or
|
||||
// module paths at runtime, but we can piece together the desired information
|
||||
// from available information. We note that runtime.Frame.Function contains the
|
||||
// function name qualified by the package path, which includes the module path
|
||||
// but not the GOPATH. We can extract the package path from that and append the
|
||||
// last segments of the file path to arrive at the desired package qualified
|
||||
// file path. For example, given:
|
||||
//
|
||||
// GOPATH /home/user
|
||||
// import path pkg/sub
|
||||
// frame.File /home/user/src/pkg/sub/file.go
|
||||
// frame.Function pkg/sub.Type.Method
|
||||
// Desired return pkg/sub/file.go
|
||||
//
|
||||
// It appears that we simply need to trim ".Type.Method" from frame.Function and
|
||||
// append "/" + path.Base(file).
|
||||
//
|
||||
// But there are other wrinkles. Although it is idiomatic to do so, the internal
|
||||
// name of a package is not required to match the last segment of its import
|
||||
// path. In addition, the introduction of modules in Go 1.11 allows working
|
||||
// without a GOPATH. So we also must make these work right:
|
||||
//
|
||||
// GOPATH /home/user
|
||||
// import path pkg/go-sub
|
||||
// package name sub
|
||||
// frame.File /home/user/src/pkg/go-sub/file.go
|
||||
// frame.Function pkg/sub.Type.Method
|
||||
// Desired return pkg/go-sub/file.go
|
||||
//
|
||||
// Module path pkg/v2
|
||||
// import path pkg/v2/go-sub
|
||||
// package name sub
|
||||
// frame.File /home/user/cloned-pkg/go-sub/file.go
|
||||
// frame.Function pkg/v2/sub.Type.Method
|
||||
// Desired return pkg/v2/go-sub/file.go
|
||||
//
|
||||
// We can handle all of these situations by using the package path extracted
|
||||
// from frame.Function up to, but not including, the last segment as the prefix
|
||||
// and the last two segments of frame.File as the suffix of the returned path.
|
||||
// This preserves the existing behavior when working in a GOPATH without modules
|
||||
// and a semantically equivalent behavior when used in module aware project.
|
||||
func pkgFilePath(frame *runtime.Frame) string {
|
||||
pre := pkgPrefix(frame.Function)
|
||||
post := pathSuffix(frame.File)
|
||||
if pre == "" {
|
||||
return post
|
||||
}
|
||||
return pre + "/" + post
|
||||
}
|
||||
|
||||
// pkgPrefix returns the import path of the function's package with the final
|
||||
// segment removed.
|
||||
func pkgPrefix(funcName string) string {
|
||||
const pathSep = "/"
|
||||
end := strings.LastIndex(funcName, pathSep)
|
||||
if end == -1 {
|
||||
return ""
|
||||
}
|
||||
return funcName[:end]
|
||||
}
|
||||
|
||||
// pathSuffix returns the last two segments of path.
|
||||
func pathSuffix(path string) string {
|
||||
const pathSep = "/"
|
||||
lastSep := strings.LastIndex(path, pathSep)
|
||||
if lastSep == -1 {
|
||||
return path
|
||||
}
|
||||
return path[strings.LastIndex(path[:lastSep], pathSep)+1:]
|
||||
}
|
||||
|
||||
var runtimePath string
|
||||
|
||||
func init() {
|
||||
var pcs [3]uintptr
|
||||
runtime.Callers(0, pcs[:])
|
||||
frames := runtime.CallersFrames(pcs[:])
|
||||
frame, _ := frames.Next()
|
||||
file := frame.File
|
||||
|
||||
idx := pkgIndex(frame.File, frame.Function)
|
||||
|
||||
runtimePath = file[:idx]
|
||||
if runtime.GOOS == "windows" {
|
||||
runtimePath = strings.ToLower(runtimePath)
|
||||
}
|
||||
}
|
||||
|
||||
func inGoroot(c Call) bool {
|
||||
file := c.frame.File
|
||||
if len(file) == 0 || file[0] == '?' {
|
||||
return true
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
file = strings.ToLower(file)
|
||||
}
|
||||
return strings.HasPrefix(file, runtimePath) || strings.HasSuffix(file, "/_testmain.go")
|
||||
}
|
||||
|
||||
// TrimRuntime returns a slice of the CallStack with the topmost entries from
|
||||
// the go runtime removed. It considers any calls originating from unknown
|
||||
// files, files under GOROOT, or _testmain.go as part of the runtime.
|
||||
func (cs CallStack) TrimRuntime() CallStack {
|
||||
for len(cs) > 0 && inGoroot(cs[len(cs)-1]) {
|
||||
cs = cs[:len(cs)-1]
|
||||
}
|
||||
return cs
|
||||
}
|
202
vendor/github.com/oxtoacart/bpool/LICENSE
generated
vendored
Normal file
202
vendor/github.com/oxtoacart/bpool/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
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 2014 Percy Wegmann
|
||||
|
||||
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.
|
65
vendor/github.com/oxtoacart/bpool/README.md
generated
vendored
Normal file
65
vendor/github.com/oxtoacart/bpool/README.md
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
# bpool [![GoDoc](https://godoc.org/github.com/oxtoacart/bpool?status.png)](https://godoc.org/github.com/oxtoacart/bpool)
|
||||
|
||||
Package bpool implements leaky pools of byte arrays and Buffers as bounded channels.
|
||||
It is based on the leaky buffer example from the Effective Go documentation: http://golang.org/doc/effective_go.html#leaky_buffer
|
||||
|
||||
bpool provides the following pool types:
|
||||
|
||||
* [bpool.BufferPool](https://godoc.org/github.com/oxtoacart/bpool#BufferPool)
|
||||
which provides a fixed-size pool of
|
||||
[bytes.Buffers](http://golang.org/pkg/bytes/#Buffer).
|
||||
* [bpool.BytePool](https://godoc.org/github.com/oxtoacart/bpool#BytePool) which
|
||||
provides a fixed-size pool of `[]byte` slices with a pre-set width (length).
|
||||
* [bpool.SizedBufferPool](https://godoc.org/github.com/oxtoacart/bpool#SizedBufferPool),
|
||||
which is an alternative to `bpool.BufferPool` that pre-sizes the capacity of
|
||||
buffers issued from the pool and discards buffers that have grown too large
|
||||
upon return.
|
||||
|
||||
A common use case for this package is to use buffers to execute HTML templates
|
||||
against (via ExecuteTemplate) or encode JSON into (via json.NewEncoder). This
|
||||
allows you to catch any rendering or marshalling errors prior to writing to a
|
||||
`http.ResponseWriter`, which helps to avoid writing incomplete or malformed data
|
||||
to the response.
|
||||
|
||||
## Install
|
||||
|
||||
`go get github.com/oxtoacart/bpool`
|
||||
|
||||
## Documentation
|
||||
|
||||
See [godoc.org](http://godoc.org/github.com/oxtoacart/bpool) or use `godoc github.com/oxtoacart/bpool`
|
||||
|
||||
## Example
|
||||
|
||||
Here's a quick example for using `bpool.BufferPool`. We create a pool of the
|
||||
desired size, call the `Get()` method to obtain a buffer for use, and call
|
||||
`Put(buf)` to return the buffer to the pool.
|
||||
|
||||
```go
|
||||
|
||||
var bufpool *bpool.BufferPool
|
||||
|
||||
func main() {
|
||||
|
||||
bufpool = bpool.NewBufferPool(48)
|
||||
|
||||
}
|
||||
|
||||
func someFunction() error {
|
||||
|
||||
// Get a buffer from the pool
|
||||
buf := bufpool.Get()
|
||||
...
|
||||
...
|
||||
...
|
||||
// Return the buffer to the pool
|
||||
bufpool.Put(buf)
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Apache 2.0 Licensed. See the LICENSE file for details.
|
||||
|
6
vendor/github.com/oxtoacart/bpool/bpool.go
generated
vendored
Normal file
6
vendor/github.com/oxtoacart/bpool/bpool.go
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/*
|
||||
Package bpool implements leaky pools of byte arrays and Buffers as bounded
|
||||
channels. It is based on the leaky buffer example from the Effective Go
|
||||
documentation: http://golang.org/doc/effective_go.html#leaky_buffer
|
||||
*/
|
||||
package bpool
|
45
vendor/github.com/oxtoacart/bpool/bufferpool.go
generated
vendored
Normal file
45
vendor/github.com/oxtoacart/bpool/bufferpool.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
package bpool
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// BufferPool implements a pool of bytes.Buffers in the form of a bounded
|
||||
// channel.
|
||||
type BufferPool struct {
|
||||
c chan *bytes.Buffer
|
||||
}
|
||||
|
||||
// NewBufferPool creates a new BufferPool bounded to the given size.
|
||||
func NewBufferPool(size int) (bp *BufferPool) {
|
||||
return &BufferPool{
|
||||
c: make(chan *bytes.Buffer, size),
|
||||
}
|
||||
}
|
||||
|
||||
// Get gets a Buffer from the BufferPool, or creates a new one if none are
|
||||
// available in the pool.
|
||||
func (bp *BufferPool) Get() (b *bytes.Buffer) {
|
||||
select {
|
||||
case b = <-bp.c:
|
||||
// reuse existing buffer
|
||||
default:
|
||||
// create new buffer
|
||||
b = bytes.NewBuffer([]byte{})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Put returns the given Buffer to the BufferPool.
|
||||
func (bp *BufferPool) Put(b *bytes.Buffer) {
|
||||
b.Reset()
|
||||
select {
|
||||
case bp.c <- b:
|
||||
default: // Discard the buffer if the pool is full.
|
||||
}
|
||||
}
|
||||
|
||||
// NumPooled returns the number of items currently pooled.
|
||||
func (bp *BufferPool) NumPooled() int {
|
||||
return len(bp.c)
|
||||
}
|
56
vendor/github.com/oxtoacart/bpool/bytepool.go
generated
vendored
Normal file
56
vendor/github.com/oxtoacart/bpool/bytepool.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
package bpool
|
||||
|
||||
// BytePool implements a leaky pool of []byte in the form of a bounded
|
||||
// channel.
|
||||
type BytePool struct {
|
||||
c chan []byte
|
||||
w int
|
||||
h int
|
||||
}
|
||||
|
||||
// NewBytePool creates a new BytePool bounded to the given maxSize, with new
|
||||
// byte arrays sized based on width.
|
||||
func NewBytePool(maxSize int, width int) (bp *BytePool) {
|
||||
return &BytePool{
|
||||
c: make(chan []byte, maxSize),
|
||||
w: width,
|
||||
}
|
||||
}
|
||||
|
||||
// Get gets a []byte from the BytePool, or creates a new one if none are
|
||||
// available in the pool.
|
||||
func (bp *BytePool) Get() (b []byte) {
|
||||
select {
|
||||
case b = <-bp.c:
|
||||
// reuse existing buffer
|
||||
default:
|
||||
// create new buffer
|
||||
b = make([]byte, bp.w)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Put returns the given Buffer to the BytePool.
|
||||
func (bp *BytePool) Put(b []byte) {
|
||||
if cap(b) < bp.w {
|
||||
// someone tried to put back a too small buffer, discard it
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case bp.c <- b[:bp.w]:
|
||||
// buffer went back into pool
|
||||
default:
|
||||
// buffer didn't go back into pool, just discard
|
||||
}
|
||||
}
|
||||
|
||||
// NumPooled returns the number of items currently pooled.
|
||||
func (bp *BytePool) NumPooled() int {
|
||||
return len(bp.c)
|
||||
}
|
||||
|
||||
// Width returns the width of the byte arrays in this pool.
|
||||
func (bp *BytePool) Width() (n int) {
|
||||
return bp.w
|
||||
}
|
81
vendor/github.com/oxtoacart/bpool/byteslice.go
generated
vendored
Normal file
81
vendor/github.com/oxtoacart/bpool/byteslice.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
package bpool
|
||||
|
||||
// WrapByteSlice wraps a []byte as a ByteSlice
|
||||
func WrapByteSlice(full []byte, headerLength int) ByteSlice {
|
||||
return ByteSlice{
|
||||
full: full,
|
||||
current: full[headerLength:],
|
||||
head: headerLength,
|
||||
end: len(full),
|
||||
}
|
||||
}
|
||||
|
||||
// ByteSlice provides a wrapper around []byte with some added convenience
|
||||
type ByteSlice struct {
|
||||
full []byte
|
||||
current []byte
|
||||
head int
|
||||
end int
|
||||
}
|
||||
|
||||
// ResliceTo reslices the end of the current slice.
|
||||
func (b ByteSlice) ResliceTo(end int) ByteSlice {
|
||||
return ByteSlice{
|
||||
full: b.full,
|
||||
current: b.current[:end],
|
||||
head: b.head,
|
||||
end: b.head + end,
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes returns the current slice
|
||||
func (b ByteSlice) Bytes() []byte {
|
||||
return b.current
|
||||
}
|
||||
|
||||
// BytesWithHeader returns the current slice preceded by the header
|
||||
func (b ByteSlice) BytesWithHeader() []byte {
|
||||
return b.full[:b.end]
|
||||
}
|
||||
|
||||
// Full returns the full original buffer underlying the ByteSlice
|
||||
func (b ByteSlice) Full() []byte {
|
||||
return b.full
|
||||
}
|
||||
|
||||
// ByteSlicePool is a bool of byte slices
|
||||
type ByteSlicePool interface {
|
||||
// Get gets a byte slice from the pool
|
||||
GetSlice() ByteSlice
|
||||
// Put returns a byte slice to the pool
|
||||
PutSlice(ByteSlice)
|
||||
// NumPooled returns the number of currently pooled items
|
||||
NumPooled() int
|
||||
}
|
||||
|
||||
// NewByteSlicePool creates a new ByteSlicePool bounded to the
|
||||
// given maxSize, with new byte arrays sized based on width
|
||||
func NewByteSlicePool(maxSize int, width int) ByteSlicePool {
|
||||
return NewHeaderPreservingByteSlicePool(maxSize, width, 0)
|
||||
}
|
||||
|
||||
// NewHeaderPreservingByteSlicePool creates a new ByteSlicePool bounded to the
|
||||
// given maxSize, with new byte arrays sized based on width and headerLength
|
||||
// preserved at the beginning of the slice.
|
||||
func NewHeaderPreservingByteSlicePool(maxSize int, width int, headerLength int) ByteSlicePool {
|
||||
return &BytePool{
|
||||
c: make(chan []byte, maxSize),
|
||||
w: width + headerLength,
|
||||
h: headerLength,
|
||||
}
|
||||
}
|
||||
|
||||
// GetSlice implements the method from interface ByteSlicePool
|
||||
func (bp *BytePool) GetSlice() ByteSlice {
|
||||
return WrapByteSlice(bp.Get(), bp.h)
|
||||
}
|
||||
|
||||
// PutSlice implements the method from interface ByteSlicePool
|
||||
func (bp *BytePool) PutSlice(b ByteSlice) {
|
||||
bp.Put(b.Full())
|
||||
}
|
5
vendor/github.com/oxtoacart/bpool/go.mod
generated
vendored
Normal file
5
vendor/github.com/oxtoacart/bpool/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/oxtoacart/bpool
|
||||
|
||||
go 1.12
|
||||
|
||||
require github.com/stretchr/testify v1.3.0
|
7
vendor/github.com/oxtoacart/bpool/go.sum
generated
vendored
Normal file
7
vendor/github.com/oxtoacart/bpool/go.sum
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
60
vendor/github.com/oxtoacart/bpool/sizedbufferpool.go
generated
vendored
Normal file
60
vendor/github.com/oxtoacart/bpool/sizedbufferpool.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
package bpool
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// SizedBufferPool implements a pool of bytes.Buffers in the form of a bounded
|
||||
// channel. Buffers are pre-allocated to the requested size.
|
||||
type SizedBufferPool struct {
|
||||
c chan *bytes.Buffer
|
||||
a int
|
||||
}
|
||||
|
||||
// SizedBufferPool creates a new BufferPool bounded to the given size.
|
||||
// size defines the number of buffers to be retained in the pool and alloc sets
|
||||
// the initial capacity of new buffers to minimize calls to make().
|
||||
//
|
||||
// The value of alloc should seek to provide a buffer that is representative of
|
||||
// most data written to the the buffer (i.e. 95th percentile) without being
|
||||
// overly large (which will increase static memory consumption). You may wish to
|
||||
// track the capacity of your last N buffers (i.e. using an []int) prior to
|
||||
// returning them to the pool as input into calculating a suitable alloc value.
|
||||
func NewSizedBufferPool(size int, alloc int) (bp *SizedBufferPool) {
|
||||
return &SizedBufferPool{
|
||||
c: make(chan *bytes.Buffer, size),
|
||||
a: alloc,
|
||||
}
|
||||
}
|
||||
|
||||
// Get gets a Buffer from the SizedBufferPool, or creates a new one if none are
|
||||
// available in the pool. Buffers have a pre-allocated capacity.
|
||||
func (bp *SizedBufferPool) Get() (b *bytes.Buffer) {
|
||||
select {
|
||||
case b = <-bp.c:
|
||||
// reuse existing buffer
|
||||
default:
|
||||
// create new buffer
|
||||
b = bytes.NewBuffer(make([]byte, 0, bp.a))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Put returns the given Buffer to the SizedBufferPool.
|
||||
func (bp *SizedBufferPool) Put(b *bytes.Buffer) {
|
||||
b.Reset()
|
||||
|
||||
// Release buffers over our maximum capacity and re-create a pre-sized
|
||||
// buffer to replace it.
|
||||
// Note that the cap(b.Bytes()) provides the capacity from the read off-set
|
||||
// only, but as we've called b.Reset() the full capacity of the underlying
|
||||
// byte slice is returned.
|
||||
if cap(b.Bytes()) > bp.a {
|
||||
b = bytes.NewBuffer(make([]byte, 0, bp.a))
|
||||
}
|
||||
|
||||
select {
|
||||
case bp.c <- b:
|
||||
default: // Discard the buffer if the pool is full.
|
||||
}
|
||||
}
|
20
vendor/modules.txt
vendored
20
vendor/modules.txt
vendored
@ -1,5 +1,23 @@
|
||||
# github.com/davecgh/go-spew v1.1.1
|
||||
github.com/davecgh/go-spew/spew
|
||||
# github.com/getlantern/byteexec v0.0.0-20170405023437-4cfb26ec74f4
|
||||
github.com/getlantern/byteexec
|
||||
# github.com/getlantern/context v0.0.0-20190109183933-c447772a6520
|
||||
github.com/getlantern/context
|
||||
# github.com/getlantern/errors v1.0.1
|
||||
github.com/getlantern/errors
|
||||
# github.com/getlantern/filepersist v0.0.0-20160317154340-c5f0cd24e799
|
||||
github.com/getlantern/filepersist
|
||||
# github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9
|
||||
github.com/getlantern/golog
|
||||
# github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7
|
||||
github.com/getlantern/hex
|
||||
# github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55
|
||||
github.com/getlantern/hidden
|
||||
# github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f
|
||||
github.com/getlantern/ops
|
||||
# github.com/go-stack/stack v1.8.0
|
||||
github.com/go-stack/stack
|
||||
# github.com/konsorten/go-windows-terminal-sequences v1.0.1
|
||||
github.com/konsorten/go-windows-terminal-sequences
|
||||
# github.com/mdlayher/genetlink v0.0.0-20191008151445-a2cadeac9a63
|
||||
@ -7,6 +25,8 @@ github.com/mdlayher/genetlink
|
||||
# github.com/mdlayher/netlink v0.0.0-20191009155606-de872b0d824b
|
||||
github.com/mdlayher/netlink
|
||||
github.com/mdlayher/netlink/nlenc
|
||||
# github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c
|
||||
github.com/oxtoacart/bpool
|
||||
# github.com/pmezard/go-difflib v1.0.0
|
||||
github.com/pmezard/go-difflib/difflib
|
||||
# github.com/sirupsen/logrus v1.4.0
|
||||
|
33
wg.go
33
wg.go
@ -8,13 +8,34 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/getlantern/byteexec"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
"go.xsfx.dev/wg-quicker/assets"
|
||||
"golang.org/x/sys/unix"
|
||||
"golang.zx2c4.com/wireguard/wgctrl"
|
||||
)
|
||||
|
||||
// wgGo runs a embedded wireguard-go for interface creation.
|
||||
func wgGo(iface string) error {
|
||||
wgob, err := assets.Asset("bin/wireguard-go")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get wireguard-go: %w", err)
|
||||
}
|
||||
|
||||
wgo, err := byteexec.New(wgob, "wireguard-go")
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to build byteexec for wireguard-go: %w", err)
|
||||
}
|
||||
|
||||
cmd := wgo.Command(iface)
|
||||
cmd.Start()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Up sets and configures the wg interface. Mostly equivalent to `wg-quick up iface`
|
||||
func Up(cfg *Config, iface string, logger logrus.FieldLogger) error {
|
||||
log := logger.WithField("iface", iface)
|
||||
@ -172,6 +193,7 @@ func SyncLink(cfg *Config, iface string, log logrus.FieldLogger) (netlink.Link,
|
||||
return nil, err
|
||||
}
|
||||
log.Info("link not found, creating")
|
||||
|
||||
wgLink := &netlink.GenericLink{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: iface,
|
||||
@ -180,11 +202,16 @@ func SyncLink(cfg *Config, iface string, log logrus.FieldLogger) (netlink.Link,
|
||||
LinkType: "wireguard",
|
||||
}
|
||||
if err := netlink.LinkAdd(wgLink); err != nil {
|
||||
log.WithError(err).Error("cannot create link")
|
||||
return nil, err
|
||||
log.WithError(err).Errorf("cannot create link: %w", err)
|
||||
log.Info("trying to use embedded wireguard-go...")
|
||||
if err := wgGo(iface); err != nil {
|
||||
log.WithError(err).Errorf("cannot create link through wireguard-go: %w", err)
|
||||
return nil, fmt.Errorf("cannot create link")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: ADD WIREGUARD-GO HERE!!!1111!!
|
||||
// Needs some sleeping to wait for interface creating.
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
link, err = netlink.LinkByName(iface)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user