15
vendor/cloud.google.com/go/AUTHORS
generated
vendored
15
vendor/cloud.google.com/go/AUTHORS
generated
vendored
@ -1,15 +0,0 @@
|
||||
# This is the official list of cloud authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
|
||||
# Names should be added to this file as:
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
|
||||
Filippo Valsorda <hi@filippo.io>
|
||||
Google Inc.
|
||||
Ingo Oeser <nightlyone@googlemail.com>
|
||||
Palm Stone Games, Inc.
|
||||
Paweł Knap <pawelknap88@gmail.com>
|
||||
Péter Szilágyi <peterke@gmail.com>
|
||||
Tyler Treat <ttreat31@gmail.com>
|
40
vendor/cloud.google.com/go/CONTRIBUTORS
generated
vendored
40
vendor/cloud.google.com/go/CONTRIBUTORS
generated
vendored
@ -1,40 +0,0 @@
|
||||
# People who have agreed to one of the CLAs and can contribute patches.
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees are listed here
|
||||
# but not in AUTHORS, because Google holds the copyright.
|
||||
#
|
||||
# https://developers.google.com/open-source/cla/individual
|
||||
# https://developers.google.com/open-source/cla/corporate
|
||||
#
|
||||
# Names should be added to this file as:
|
||||
# Name <email address>
|
||||
|
||||
# Keep the list alphabetically sorted.
|
||||
|
||||
Alexis Hunt <lexer@google.com>
|
||||
Andreas Litt <andreas.litt@gmail.com>
|
||||
Andrew Gerrand <adg@golang.org>
|
||||
Brad Fitzpatrick <bradfitz@golang.org>
|
||||
Burcu Dogan <jbd@google.com>
|
||||
Dave Day <djd@golang.org>
|
||||
David Sansome <me@davidsansome.com>
|
||||
David Symonds <dsymonds@golang.org>
|
||||
Filippo Valsorda <hi@filippo.io>
|
||||
Glenn Lewis <gmlewis@google.com>
|
||||
Ingo Oeser <nightlyone@googlemail.com>
|
||||
James Hall <james.hall@shopify.com>
|
||||
Johan Euphrosine <proppy@google.com>
|
||||
Jonathan Amsterdam <jba@google.com>
|
||||
Kunpei Sakai <namusyaka@gmail.com>
|
||||
Luna Duclos <luna.duclos@palmstonegames.com>
|
||||
Magnus Hiie <magnus.hiie@gmail.com>
|
||||
Mario Castro <mariocaster@gmail.com>
|
||||
Michael McGreevy <mcgreevy@golang.org>
|
||||
Omar Jarjur <ojarjur@google.com>
|
||||
Paweł Knap <pawelknap88@gmail.com>
|
||||
Péter Szilágyi <peterke@gmail.com>
|
||||
Sarah Adams <shadams@google.com>
|
||||
Thanatat Tamtan <acoshift@gmail.com>
|
||||
Toby Burress <kurin@google.com>
|
||||
Tuo Shan <shantuo@google.com>
|
||||
Tyler Treat <ttreat31@gmail.com>
|
90
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
90
vendor/cloud.google.com/go/compute/metadata/metadata.go
generated
vendored
@ -61,25 +61,14 @@ var (
|
||||
instID = &cachedValue{k: "instance/id", trim: true}
|
||||
)
|
||||
|
||||
var (
|
||||
defaultClient = &Client{hc: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
ResponseHeaderTimeout: 2 * time.Second,
|
||||
},
|
||||
}}
|
||||
subscribeClient = &Client{hc: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
},
|
||||
}}
|
||||
)
|
||||
var defaultClient = &Client{hc: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
},
|
||||
}}
|
||||
|
||||
// NotDefinedError is returned when requested metadata is not defined.
|
||||
//
|
||||
@ -137,7 +126,7 @@ func testOnGCE() bool {
|
||||
resc := make(chan bool, 2)
|
||||
|
||||
// Try two strategies in parallel.
|
||||
// See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194
|
||||
// See https://github.com/googleapis/google-cloud-go/issues/194
|
||||
go func() {
|
||||
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
@ -151,7 +140,7 @@ func testOnGCE() bool {
|
||||
}()
|
||||
|
||||
go func() {
|
||||
addrs, err := net.LookupHost("metadata.google.internal")
|
||||
addrs, err := net.DefaultResolver.LookupHost(ctx, "metadata.google.internal")
|
||||
if err != nil || len(addrs) == 0 {
|
||||
resc <- false
|
||||
return
|
||||
@ -206,10 +195,9 @@ func systemInfoSuggestsGCE() bool {
|
||||
return name == "Google" || name == "Google Compute Engine"
|
||||
}
|
||||
|
||||
// Subscribe calls Client.Subscribe on a client designed for subscribing (one with no
|
||||
// ResponseHeaderTimeout).
|
||||
// Subscribe calls Client.Subscribe on the default client.
|
||||
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
||||
return subscribeClient.Subscribe(suffix, fn)
|
||||
return defaultClient.Subscribe(suffix, fn)
|
||||
}
|
||||
|
||||
// Get calls Client.Get on the default client.
|
||||
@ -227,6 +215,9 @@ func InternalIP() (string, error) { return defaultClient.InternalIP() }
|
||||
// ExternalIP returns the instance's primary external (public) IP address.
|
||||
func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
|
||||
|
||||
// Email calls Client.Email on the default client.
|
||||
func Email(serviceAccount string) (string, error) { return defaultClient.Email(serviceAccount) }
|
||||
|
||||
// Hostname returns the instance's hostname. This will be of the form
|
||||
// "<instanceID>.c.<projID>.internal".
|
||||
func Hostname() (string, error) { return defaultClient.Hostname() }
|
||||
@ -277,9 +268,14 @@ type Client struct {
|
||||
hc *http.Client
|
||||
}
|
||||
|
||||
// NewClient returns a Client that can be used to fetch metadata. All HTTP requests
|
||||
// will use the given http.Client instead of the default client.
|
||||
// NewClient returns a Client that can be used to fetch metadata.
|
||||
// Returns the client that uses the specified http.Client for HTTP requests.
|
||||
// If nil is specified, returns the default client.
|
||||
func NewClient(c *http.Client) *Client {
|
||||
if c == nil {
|
||||
return defaultClient
|
||||
}
|
||||
|
||||
return &Client{hc: c}
|
||||
}
|
||||
|
||||
@ -300,8 +296,12 @@ func (c *Client) getETag(suffix string) (value, etag string, err error) {
|
||||
// being stable anyway.
|
||||
host = metadataIP
|
||||
}
|
||||
url := "http://" + host + "/computeMetadata/v1/" + suffix
|
||||
req, _ := http.NewRequest("GET", url, nil)
|
||||
suffix = strings.TrimLeft(suffix, "/")
|
||||
u := "http://" + host + "/computeMetadata/v1/" + suffix
|
||||
req, err := http.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
req.Header.Set("Metadata-Flavor", "Google")
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
res, err := c.hc.Do(req)
|
||||
@ -312,13 +312,13 @@ func (c *Client) getETag(suffix string) (value, etag string, err error) {
|
||||
if res.StatusCode == http.StatusNotFound {
|
||||
return "", "", NotDefinedError(suffix)
|
||||
}
|
||||
if res.StatusCode != 200 {
|
||||
return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url)
|
||||
}
|
||||
all, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
if res.StatusCode != 200 {
|
||||
return "", "", &Error{Code: res.StatusCode, Message: string(all)}
|
||||
}
|
||||
return string(all), res.Header.Get("Etag"), nil
|
||||
}
|
||||
|
||||
@ -367,6 +367,16 @@ func (c *Client) InternalIP() (string, error) {
|
||||
return c.getTrimmed("instance/network-interfaces/0/ip")
|
||||
}
|
||||
|
||||
// Email returns the email address associated with the service account.
|
||||
// The account may be empty or the string "default" to use the instance's
|
||||
// main account.
|
||||
func (c *Client) Email(serviceAccount string) (string, error) {
|
||||
if serviceAccount == "" {
|
||||
serviceAccount = "default"
|
||||
}
|
||||
return c.getTrimmed("instance/service-accounts/" + serviceAccount + "/email")
|
||||
}
|
||||
|
||||
// ExternalIP returns the instance's primary external (public) IP address.
|
||||
func (c *Client) ExternalIP() (string, error) {
|
||||
return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
|
||||
@ -394,11 +404,7 @@ func (c *Client) InstanceTags() ([]string, error) {
|
||||
|
||||
// InstanceName returns the current VM's instance ID string.
|
||||
func (c *Client) InstanceName() (string, error) {
|
||||
host, err := c.Hostname()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.Split(host, ".")[0], nil
|
||||
return c.getTrimmed("instance/name")
|
||||
}
|
||||
|
||||
// Zone returns the current VM's zone, such as "us-central1-b".
|
||||
@ -499,3 +505,15 @@ func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) erro
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error contains an error response from the server.
|
||||
type Error struct {
|
||||
// Code is the HTTP response status code.
|
||||
Code int
|
||||
// Message is the server response message.
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("compute: Received %d `%s`", e.Code, e.Message)
|
||||
}
|
||||
|
201
vendor/github.com/go-logr/logr/LICENSE
generated
vendored
Normal file
201
vendor/github.com/go-logr/logr/LICENSE
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
183
vendor/github.com/go-logr/logr/README.md
generated
vendored
Normal file
183
vendor/github.com/go-logr/logr/README.md
generated
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
# A more minimal logging API for Go
|
||||
|
||||
Before you consider this package, please read [this blog post by the
|
||||
inimitable Dave Cheney][warning-makes-no-sense]. I really appreciate what
|
||||
he has to say, and it largely aligns with my own experiences. Too many
|
||||
choices of levels means inconsistent logs.
|
||||
|
||||
This package offers a purely abstract interface, based on these ideas but with
|
||||
a few twists. Code can depend on just this interface and have the actual
|
||||
logging implementation be injected from callers. Ideally only `main()` knows
|
||||
what logging implementation is being used.
|
||||
|
||||
# Differences from Dave's ideas
|
||||
|
||||
The main differences are:
|
||||
|
||||
1) Dave basically proposes doing away with the notion of a logging API in favor
|
||||
of `fmt.Printf()`. I disagree, especially when you consider things like output
|
||||
locations, timestamps, file and line decorations, and structured logging. I
|
||||
restrict the API to just 2 types of logs: info and error.
|
||||
|
||||
Info logs are things you want to tell the user which are not errors. Error
|
||||
logs are, well, errors. If your code receives an `error` from a subordinate
|
||||
function call and is logging that `error` *and not returning it*, use error
|
||||
logs.
|
||||
|
||||
2) Verbosity-levels on info logs. This gives developers a chance to indicate
|
||||
arbitrary grades of importance for info logs, without assigning names with
|
||||
semantic meaning such as "warning", "trace", and "debug". Superficially this
|
||||
may feel very similar, but the primary difference is the lack of semantics.
|
||||
Because verbosity is a numerical value, it's safe to assume that an app running
|
||||
with higher verbosity means more (and less important) logs will be generated.
|
||||
|
||||
This is a BETA grade API.
|
||||
|
||||
There are implementations for the following logging libraries:
|
||||
|
||||
- **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr)
|
||||
- **k8s.io/klog**: [klogr](https://git.k8s.io/klog/klogr)
|
||||
- **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr)
|
||||
- **log** (the Go standard library logger):
|
||||
[stdr](https://github.com/go-logr/stdr)
|
||||
- **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
|
||||
- **github.com/wojas/genericr**: [genericr](https://github.com/wojas/genericr) (makes it easy to implement your own backend)
|
||||
- **logfmt** (Heroku style [logging](https://www.brandur.org/logfmt)): [logfmtr](https://github.com/iand/logfmtr)
|
||||
|
||||
# FAQ
|
||||
|
||||
## Conceptual
|
||||
|
||||
## Why structured logging?
|
||||
|
||||
- **Structured logs are more easily queriable**: Since you've got
|
||||
key-value pairs, it's much easier to query your structured logs for
|
||||
particular values by filtering on the contents of a particular key --
|
||||
think searching request logs for error codes, Kubernetes reconcilers for
|
||||
the name and namespace of the reconciled object, etc
|
||||
|
||||
- **Structured logging makes it easier to have cross-referencable logs**:
|
||||
Similarly to searchability, if you maintain conventions around your
|
||||
keys, it becomes easy to gather all log lines related to a particular
|
||||
concept.
|
||||
|
||||
- **Structured logs allow better dimensions of filtering**: if you have
|
||||
structure to your logs, you've got more precise control over how much
|
||||
information is logged -- you might choose in a particular configuration
|
||||
to log certain keys but not others, only log lines where a certain key
|
||||
matches a certain value, etc, instead of just having v-levels and names
|
||||
to key off of.
|
||||
|
||||
- **Structured logs better represent structured data**: sometimes, the
|
||||
data that you want to log is inherently structured (think tuple-link
|
||||
objects). Structured logs allow you to preserve that structure when
|
||||
outputting.
|
||||
|
||||
## Why V-levels?
|
||||
|
||||
**V-levels give operators an easy way to control the chattiness of log
|
||||
operations**. V-levels provide a way for a given package to distinguish
|
||||
the relative importance or verbosity of a given log message. Then, if
|
||||
a particular logger or package is logging too many messages, the user
|
||||
of the package can simply change the v-levels for that library.
|
||||
|
||||
## Why not more named levels, like Warning?
|
||||
|
||||
Read [Dave Cheney's post][warning-makes-no-sense]. Then read [Differences
|
||||
from Dave's ideas](#differences-from-daves-ideas).
|
||||
|
||||
## Why not allow format strings, too?
|
||||
|
||||
**Format strings negate many of the benefits of structured logs**:
|
||||
|
||||
- They're not easily searchable without resorting to fuzzy searching,
|
||||
regular expressions, etc
|
||||
|
||||
- They don't store structured data well, since contents are flattened into
|
||||
a string
|
||||
|
||||
- They're not cross-referencable
|
||||
|
||||
- They don't compress easily, since the message is not constant
|
||||
|
||||
(unless you turn positional parameters into key-value pairs with numerical
|
||||
keys, at which point you've gotten key-value logging with meaningless
|
||||
keys)
|
||||
|
||||
## Practical
|
||||
|
||||
## Why key-value pairs, and not a map?
|
||||
|
||||
Key-value pairs are *much* easier to optimize, especially around
|
||||
allocations. Zap (a structured logger that inspired logr's interface) has
|
||||
[performance measurements](https://github.com/uber-go/zap#performance)
|
||||
that show this quite nicely.
|
||||
|
||||
While the interface ends up being a little less obvious, you get
|
||||
potentially better performance, plus avoid making users type
|
||||
`map[string]string{}` every time they want to log.
|
||||
|
||||
## What if my V-levels differ between libraries?
|
||||
|
||||
That's fine. Control your V-levels on a per-logger basis, and use the
|
||||
`WithName` function to pass different loggers to different libraries.
|
||||
|
||||
Generally, you should take care to ensure that you have relatively
|
||||
consistent V-levels within a given logger, however, as this makes deciding
|
||||
on what verbosity of logs to request easier.
|
||||
|
||||
## But I *really* want to use a format string!
|
||||
|
||||
That's not actually a question. Assuming your question is "how do
|
||||
I convert my mental model of logging with format strings to logging with
|
||||
constant messages":
|
||||
|
||||
1. figure out what the error actually is, as you'd write in a TL;DR style,
|
||||
and use that as a message
|
||||
|
||||
2. For every place you'd write a format specifier, look to the word before
|
||||
it, and add that as a key value pair
|
||||
|
||||
For instance, consider the following examples (all taken from spots in the
|
||||
Kubernetes codebase):
|
||||
|
||||
- `klog.V(4).Infof("Client is returning errors: code %v, error %v",
|
||||
responseCode, err)` becomes `logger.Error(err, "client returned an
|
||||
error", "code", responseCode)`
|
||||
|
||||
- `klog.V(4).Infof("Got a Retry-After %ds response for attempt %d to %v",
|
||||
seconds, retries, url)` becomes `logger.V(4).Info("got a retry-after
|
||||
response when requesting url", "attempt", retries, "after
|
||||
seconds", seconds, "url", url)`
|
||||
|
||||
If you *really* must use a format string, place it as a key value, and
|
||||
call `fmt.Sprintf` yourself -- for instance, `log.Printf("unable to
|
||||
reflect over type %T")` becomes `logger.Info("unable to reflect over
|
||||
type", "type", fmt.Sprintf("%T"))`. In general though, the cases where
|
||||
this is necessary should be few and far between.
|
||||
|
||||
## How do I choose my V-levels?
|
||||
|
||||
This is basically the only hard constraint: increase V-levels to denote
|
||||
more verbose or more debug-y logs.
|
||||
|
||||
Otherwise, you can start out with `0` as "you always want to see this",
|
||||
`1` as "common logging that you might *possibly* want to turn off", and
|
||||
`10` as "I would like to performance-test your log collection stack".
|
||||
|
||||
Then gradually choose levels in between as you need them, working your way
|
||||
down from 10 (for debug and trace style logs) and up from 1 (for chattier
|
||||
info-type logs).
|
||||
|
||||
## How do I choose my keys
|
||||
|
||||
- make your keys human-readable
|
||||
- constant keys are generally a good idea
|
||||
- be consistent across your codebase
|
||||
- keys should naturally match parts of the message string
|
||||
|
||||
While key names are mostly unrestricted (and spaces are acceptable),
|
||||
it's generally a good idea to stick to printable ascii characters, or at
|
||||
least match the general character set of your log lines.
|
||||
|
||||
[warning-makes-no-sense]: http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
35
vendor/github.com/go-logr/logr/discard.go
generated
vendored
Normal file
35
vendor/github.com/go-logr/logr/discard.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package logr
|
||||
|
||||
// Discard returns a valid Logger that discards all messages logged to it.
|
||||
// It can be used whenever the caller is not interested in the logs.
|
||||
func Discard() Logger {
|
||||
return discardLogger{}
|
||||
}
|
||||
|
||||
// discardLogger is a Logger that discards all messages.
|
||||
type discardLogger struct{}
|
||||
|
||||
func (l discardLogger) Enabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (l discardLogger) Info(msg string, keysAndValues ...interface{}) {
|
||||
}
|
||||
|
||||
func (l discardLogger) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||
}
|
||||
|
||||
func (l discardLogger) V(level int) Logger {
|
||||
return l
|
||||
}
|
||||
|
||||
func (l discardLogger) WithValues(keysAndValues ...interface{}) Logger {
|
||||
return l
|
||||
}
|
||||
|
||||
func (l discardLogger) WithName(name string) Logger {
|
||||
return l
|
||||
}
|
||||
|
||||
// Verify that it actually implements the interface
|
||||
var _ Logger = discardLogger{}
|
3
vendor/github.com/go-logr/logr/go.mod
generated
vendored
Normal file
3
vendor/github.com/go-logr/logr/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/go-logr/logr
|
||||
|
||||
go 1.14
|
222
vendor/github.com/go-logr/logr/logr.go
generated
vendored
Normal file
222
vendor/github.com/go-logr/logr/logr.go
generated
vendored
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright 2019 The logr Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package logr defines abstract interfaces for logging. Packages can depend on
|
||||
// these interfaces and callers can implement logging in whatever way is
|
||||
// appropriate.
|
||||
//
|
||||
// This design derives from Dave Cheney's blog:
|
||||
// http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
||||
//
|
||||
// This is a BETA grade API. Until there is a significant 2nd implementation,
|
||||
// I don't really know how it will change.
|
||||
//
|
||||
// The logging specifically makes it non-trivial to use format strings, to encourage
|
||||
// attaching structured information instead of unstructured format strings.
|
||||
//
|
||||
// Usage
|
||||
//
|
||||
// Logging is done using a Logger. Loggers can have name prefixes and named
|
||||
// values attached, so that all log messages logged with that Logger have some
|
||||
// base context associated.
|
||||
//
|
||||
// The term "key" is used to refer to the name associated with a particular
|
||||
// value, to disambiguate it from the general Logger name.
|
||||
//
|
||||
// For instance, suppose we're trying to reconcile the state of an object, and
|
||||
// we want to log that we've made some decision.
|
||||
//
|
||||
// With the traditional log package, we might write:
|
||||
// log.Printf("decided to set field foo to value %q for object %s/%s",
|
||||
// targetValue, object.Namespace, object.Name)
|
||||
//
|
||||
// With logr's structured logging, we'd write:
|
||||
// // elsewhere in the file, set up the logger to log with the prefix of
|
||||
// // "reconcilers", and the named value target-type=Foo, for extra context.
|
||||
// log := mainLogger.WithName("reconcilers").WithValues("target-type", "Foo")
|
||||
//
|
||||
// // later on...
|
||||
// log.Info("setting foo on object", "value", targetValue, "object", object)
|
||||
//
|
||||
// Depending on our logging implementation, we could then make logging decisions
|
||||
// based on field values (like only logging such events for objects in a certain
|
||||
// namespace), or copy the structured information into a structured log store.
|
||||
//
|
||||
// For logging errors, Logger has a method called Error. Suppose we wanted to
|
||||
// log an error while reconciling. With the traditional log package, we might
|
||||
// write:
|
||||
// log.Errorf("unable to reconcile object %s/%s: %v", object.Namespace, object.Name, err)
|
||||
//
|
||||
// With logr, we'd instead write:
|
||||
// // assuming the above setup for log
|
||||
// log.Error(err, "unable to reconcile object", "object", object)
|
||||
//
|
||||
// This functions similarly to:
|
||||
// log.Info("unable to reconcile object", "error", err, "object", object)
|
||||
//
|
||||
// However, it ensures that a standard key for the error value ("error") is used
|
||||
// across all error logging. Furthermore, certain implementations may choose to
|
||||
// attach additional information (such as stack traces) on calls to Error, so
|
||||
// it's preferred to use Error to log errors.
|
||||
//
|
||||
// Parts of a log line
|
||||
//
|
||||
// Each log message from a Logger has four types of context:
|
||||
// logger name, log verbosity, log message, and the named values.
|
||||
//
|
||||
// The Logger name consists of a series of name "segments" added by successive
|
||||
// calls to WithName. These name segments will be joined in some way by the
|
||||
// underlying implementation. It is strongly recommended that name segments
|
||||
// contain simple identifiers (letters, digits, and hyphen), and do not contain
|
||||
// characters that could muddle the log output or confuse the joining operation
|
||||
// (e.g. whitespace, commas, periods, slashes, brackets, quotes, etc).
|
||||
//
|
||||
// Log verbosity represents how little a log matters. Level zero, the default,
|
||||
// matters most. Increasing levels matter less and less. Try to avoid lots of
|
||||
// different verbosity levels, and instead provide useful keys, logger names,
|
||||
// and log messages for users to filter on. It's illegal to pass a log level
|
||||
// below zero.
|
||||
//
|
||||
// The log message consists of a constant message attached to the log line.
|
||||
// This should generally be a simple description of what's occurring, and should
|
||||
// never be a format string.
|
||||
//
|
||||
// Variable information can then be attached using named values (key/value
|
||||
// pairs). Keys are arbitrary strings, while values may be any Go value.
|
||||
//
|
||||
// Key Naming Conventions
|
||||
//
|
||||
// Keys are not strictly required to conform to any specification or regex, but
|
||||
// it is recommended that they:
|
||||
// * be human-readable and meaningful (not auto-generated or simple ordinals)
|
||||
// * be constant (not dependent on input data)
|
||||
// * contain only printable characters
|
||||
// * not contain whitespace or punctuation
|
||||
//
|
||||
// These guidelines help ensure that log data is processed properly regardless
|
||||
// of the log implementation. For example, log implementations will try to
|
||||
// output JSON data or will store data for later database (e.g. SQL) queries.
|
||||
//
|
||||
// While users are generally free to use key names of their choice, it's
|
||||
// generally best to avoid using the following keys, as they're frequently used
|
||||
// by implementations:
|
||||
//
|
||||
// - `"caller"`: the calling information (file/line) of a particular log line.
|
||||
// - `"error"`: the underlying error value in the `Error` method.
|
||||
// - `"level"`: the log level.
|
||||
// - `"logger"`: the name of the associated logger.
|
||||
// - `"msg"`: the log message.
|
||||
// - `"stacktrace"`: the stack trace associated with a particular log line or
|
||||
// error (often from the `Error` message).
|
||||
// - `"ts"`: the timestamp for a log line.
|
||||
//
|
||||
// Implementations are encouraged to make use of these keys to represent the
|
||||
// above concepts, when necessary (for example, in a pure-JSON output form, it
|
||||
// would be necessary to represent at least message and timestamp as ordinary
|
||||
// named values).
|
||||
//
|
||||
// Implementations may choose to give callers access to the underlying
|
||||
// logging implementation. The recommended pattern for this is:
|
||||
// // Underlier exposes access to the underlying logging implementation.
|
||||
// // Since callers only have a logr.Logger, they have to know which
|
||||
// // implementation is in use, so this interface is less of an abstraction
|
||||
// // and more of way to test type conversion.
|
||||
// type Underlier interface {
|
||||
// GetUnderlying() <underlying-type>
|
||||
// }
|
||||
package logr
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// TODO: consider adding back in format strings if they're really needed
|
||||
// TODO: consider other bits of zap/zapcore functionality like ObjectMarshaller (for arbitrary objects)
|
||||
// TODO: consider other bits of glog functionality like Flush, InfoDepth, OutputStats
|
||||
|
||||
// Logger represents the ability to log messages, both errors and not.
|
||||
type Logger interface {
|
||||
// Enabled tests whether this Logger is enabled. For example, commandline
|
||||
// flags might be used to set the logging verbosity and disable some info
|
||||
// logs.
|
||||
Enabled() bool
|
||||
|
||||
// Info logs a non-error message with the given key/value pairs as context.
|
||||
//
|
||||
// The msg argument should be used to add some constant description to
|
||||
// the log line. The key/value pairs can then be used to add additional
|
||||
// variable information. The key/value pairs should alternate string
|
||||
// keys and arbitrary values.
|
||||
Info(msg string, keysAndValues ...interface{})
|
||||
|
||||
// Error logs an error, with the given message and key/value pairs as context.
|
||||
// It functions similarly to calling Info with the "error" named value, but may
|
||||
// have unique behavior, and should be preferred for logging errors (see the
|
||||
// package documentations for more information).
|
||||
//
|
||||
// The msg field should be used to add context to any underlying error,
|
||||
// while the err field should be used to attach the actual error that
|
||||
// triggered this log line, if present.
|
||||
Error(err error, msg string, keysAndValues ...interface{})
|
||||
|
||||
// V returns an Logger value for a specific verbosity level, relative to
|
||||
// this Logger. In other words, V values are additive. V higher verbosity
|
||||
// level means a log message is less important. It's illegal to pass a log
|
||||
// level less than zero.
|
||||
V(level int) Logger
|
||||
|
||||
// WithValues adds some key-value pairs of context to a logger.
|
||||
// See Info for documentation on how key/value pairs work.
|
||||
WithValues(keysAndValues ...interface{}) Logger
|
||||
|
||||
// WithName adds a new element to the logger's name.
|
||||
// Successive calls with WithName continue to append
|
||||
// suffixes to the logger's name. It's strongly recommended
|
||||
// that name segments contain only letters, digits, and hyphens
|
||||
// (see the package documentation for more information).
|
||||
WithName(name string) Logger
|
||||
}
|
||||
|
||||
// InfoLogger provides compatibility with code that relies on the v0.1.0 interface
|
||||
// Deprecated: use Logger instead. This will be removed in a future release.
|
||||
type InfoLogger = Logger
|
||||
|
||||
type contextKey struct{}
|
||||
|
||||
// FromContext returns a Logger constructed from ctx or nil if no
|
||||
// logger details are found.
|
||||
func FromContext(ctx context.Context) Logger {
|
||||
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FromContextOrDiscard returns a Logger constructed from ctx or a Logger
|
||||
// that discards all messages if no logger details are found.
|
||||
func FromContextOrDiscard(ctx context.Context) Logger {
|
||||
if v, ok := ctx.Value(contextKey{}).(Logger); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return discardLogger{}
|
||||
}
|
||||
|
||||
// NewContext returns a new context derived from ctx that embeds the Logger.
|
||||
func NewContext(ctx context.Context, l Logger) context.Context {
|
||||
return context.WithValue(ctx, contextKey{}, l)
|
||||
}
|
16
vendor/github.com/go-ping/ping/.editorconfig
generated
vendored
Normal file
16
vendor/github.com/go-ping/ping/.editorconfig
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
# https://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
2
vendor/github.com/go-ping/ping/.gitignore
generated
vendored
Normal file
2
vendor/github.com/go-ping/ping/.gitignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/ping
|
||||
/dist
|
6
vendor/github.com/go-ping/ping/.golangci.yml
generated
vendored
Normal file
6
vendor/github.com/go-ping/ping/.golangci.yml
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
issues:
|
||||
exclude-rules:
|
||||
- path: _test.go
|
||||
linters:
|
||||
- errcheck
|
46
vendor/github.com/go-ping/ping/.goreleaser.yml
generated
vendored
Normal file
46
vendor/github.com/go-ping/ping/.goreleaser.yml
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
project_name: ping
|
||||
before:
|
||||
hooks:
|
||||
- go mod download
|
||||
builds:
|
||||
- binary: ping
|
||||
dir: cmd/ping
|
||||
goarch:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
goarm:
|
||||
- 6
|
||||
- 7
|
||||
goos:
|
||||
- darwin
|
||||
- freebsd
|
||||
- linux
|
||||
- windows
|
||||
archives:
|
||||
- files:
|
||||
- LICENSE
|
||||
- README.md
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
format: zip
|
||||
wrap_in_directory: true
|
||||
# TODO: Decide if we want packages (name conflcits with /bin/ping?)
|
||||
# nfpms:
|
||||
# homepage: https://github.com/go-ping/ping
|
||||
# maintainer: 'Go Ping Maintainers <go-ping@example.com>'
|
||||
# description: Ping written in Go.
|
||||
# license: MIT
|
||||
# formats:
|
||||
# - deb
|
||||
# - rpm
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
name_template: "{{ .Tag }}-{{ .ShortCommit }}"
|
||||
changelog:
|
||||
sort: asc
|
||||
filters:
|
||||
exclude:
|
||||
- '^docs:'
|
||||
- '^test:'
|
21
vendor/github.com/go-ping/ping/LICENSE
generated
vendored
Normal file
21
vendor/github.com/go-ping/ping/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Cameron Sparr and contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
32
vendor/github.com/go-ping/ping/Makefile
generated
vendored
Normal file
32
vendor/github.com/go-ping/ping/Makefile
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
GO ?= go
|
||||
GOFMT ?= $(GO)fmt
|
||||
GOOPTS ?=
|
||||
GO111MODULE :=
|
||||
pkgs = ./...
|
||||
|
||||
all: style vet build test
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
@echo ">> building ping"
|
||||
GO111MODULE=$(GO111MODULE) $(GO) build $(GOOPTS) ./cmd/ping
|
||||
|
||||
.PHONY: style
|
||||
style:
|
||||
@echo ">> checking code style"
|
||||
@fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \
|
||||
if [ -n "$${fmtRes}" ]; then \
|
||||
echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \
|
||||
echo "Please ensure you are using $$($(GO) version) for formatting code."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
@echo ">> running all tests"
|
||||
GO111MODULE=$(GO111MODULE) $(GO) test -race -cover $(GOOPTS) $(pkgs)
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
@echo ">> vetting code"
|
||||
GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs)
|
130
vendor/github.com/go-ping/ping/README.md
generated
vendored
Normal file
130
vendor/github.com/go-ping/ping/README.md
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
# go-ping
|
||||
[](https://pkg.go.dev/github.com/go-ping/ping)
|
||||
[](https://circleci.com/gh/go-ping/ping)
|
||||
|
||||
A simple but powerful ICMP echo (ping) library for Go, inspired by
|
||||
[go-fastping](https://github.com/tatsushid/go-fastping).
|
||||
|
||||
Here is a very simple example that sends and receives three packets:
|
||||
|
||||
```go
|
||||
pinger, err := ping.NewPinger("www.google.com")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pinger.Count = 3
|
||||
err = pinger.Run() // Blocks until finished.
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
stats := pinger.Statistics() // get send/receive/rtt stats
|
||||
```
|
||||
|
||||
Here is an example that emulates the traditional UNIX ping command:
|
||||
|
||||
```go
|
||||
pinger, err := ping.NewPinger("www.google.com")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Listen for Ctrl-C.
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
go func() {
|
||||
for _ = range c {
|
||||
pinger.Stop()
|
||||
}
|
||||
}()
|
||||
|
||||
pinger.OnRecv = func(pkt *ping.Packet) {
|
||||
fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v\n",
|
||||
pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt)
|
||||
}
|
||||
|
||||
pinger.OnFinish = func(stats *ping.Statistics) {
|
||||
fmt.Printf("\n--- %s ping statistics ---\n", stats.Addr)
|
||||
fmt.Printf("%d packets transmitted, %d packets received, %v%% packet loss\n",
|
||||
stats.PacketsSent, stats.PacketsRecv, stats.PacketLoss)
|
||||
fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n",
|
||||
stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt)
|
||||
}
|
||||
|
||||
fmt.Printf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr())
|
||||
err = pinger.Run()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
It sends ICMP Echo Request packet(s) and waits for an Echo Reply in
|
||||
response. If it receives a response, it calls the `OnRecv` callback.
|
||||
When it's finished, it calls the `OnFinish` callback.
|
||||
|
||||
For a full ping example, see
|
||||
[cmd/ping/ping.go](https://github.com/go-ping/ping/blob/master/cmd/ping/ping.go).
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
go get -u github.com/go-ping/ping
|
||||
```
|
||||
|
||||
To install the native Go ping executable:
|
||||
|
||||
```bash
|
||||
go get -u github.com/go-ping/ping/...
|
||||
$GOPATH/bin/ping
|
||||
```
|
||||
|
||||
## Supported Operating Systems
|
||||
|
||||
### Linux
|
||||
This library attempts to send an "unprivileged" ping via UDP. On Linux,
|
||||
this must be enabled with the following sysctl command:
|
||||
|
||||
```
|
||||
sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"
|
||||
```
|
||||
|
||||
If you do not wish to do this, you can call `pinger.SetPrivileged(true)`
|
||||
in your code and then use setcap on your binary to allow it to bind to
|
||||
raw sockets (or just run it as root):
|
||||
|
||||
```
|
||||
setcap cap_net_raw=+ep /path/to/your/compiled/binary
|
||||
```
|
||||
|
||||
See [this blog](https://sturmflut.github.io/linux/ubuntu/2015/01/17/unprivileged-icmp-sockets-on-linux/)
|
||||
and the Go [x/net/icmp](https://godoc.org/golang.org/x/net/icmp) package
|
||||
for more details.
|
||||
|
||||
### Windows
|
||||
|
||||
You must use `pinger.SetPrivileged(true)`, otherwise you will receive
|
||||
the following error:
|
||||
|
||||
```
|
||||
socket: The requested protocol has not been configured into the system, or no implementation for it exists.
|
||||
```
|
||||
|
||||
Despite the method name, this should work without the need to elevate
|
||||
privileges and has been tested on Windows 10. Please note that accessing
|
||||
packet TTL values is not supported due to limitations in the Go
|
||||
x/net/ipv4 and x/net/ipv6 packages.
|
||||
|
||||
### Plan 9 from Bell Labs
|
||||
|
||||
There is no support for Plan 9. This is because the entire `x/net/ipv4`
|
||||
and `x/net/ipv6` packages are not implemented by the Go programming
|
||||
language.
|
||||
|
||||
## Maintainers and Getting Help:
|
||||
|
||||
This repo was originally in the personal account of
|
||||
[sparrc](https://github.com/sparrc), but is now maintained by the
|
||||
[go-ping organization](https://github.com/go-ping).
|
||||
|
||||
For support and help, you usually find us in the #go-ping channel of
|
||||
Gophers Slack. See https://invite.slack.golangbridge.org/ for an invite
|
||||
to the Gophers Slack org.
|
5
vendor/github.com/go-ping/ping/go.mod
generated
vendored
Normal file
5
vendor/github.com/go-ping/ping/go.mod
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
module github.com/go-ping/ping
|
||||
|
||||
go 1.14
|
||||
|
||||
require golang.org/x/net v0.0.0-20200904194848-62affa334b73
|
10
vendor/github.com/go-ping/ping/go.sum
generated
vendored
Normal file
10
vendor/github.com/go-ping/ping/go.sum
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
669
vendor/github.com/go-ping/ping/ping.go
generated
vendored
Normal file
669
vendor/github.com/go-ping/ping/ping.go
generated
vendored
Normal file
@ -0,0 +1,669 @@
|
||||
// Package ping is a simple but powerful ICMP echo (ping) library.
|
||||
//
|
||||
// Here is a very simple example that sends and receives three packets:
|
||||
//
|
||||
// pinger, err := ping.NewPinger("www.google.com")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// pinger.Count = 3
|
||||
// err = pinger.Run() // blocks until finished
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// stats := pinger.Statistics() // get send/receive/rtt stats
|
||||
//
|
||||
// Here is an example that emulates the traditional UNIX ping command:
|
||||
//
|
||||
// pinger, err := ping.NewPinger("www.google.com")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// // Listen for Ctrl-C.
|
||||
// c := make(chan os.Signal, 1)
|
||||
// signal.Notify(c, os.Interrupt)
|
||||
// go func() {
|
||||
// for _ = range c {
|
||||
// pinger.Stop()
|
||||
// }
|
||||
// }()
|
||||
// pinger.OnRecv = func(pkt *ping.Packet) {
|
||||
// fmt.Printf("%d bytes from %s: icmp_seq=%d time=%v\n",
|
||||
// pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt)
|
||||
// }
|
||||
// pinger.OnFinish = func(stats *ping.Statistics) {
|
||||
// fmt.Printf("\n--- %s ping statistics ---\n", stats.Addr)
|
||||
// fmt.Printf("%d packets transmitted, %d packets received, %v%% packet loss\n",
|
||||
// stats.PacketsSent, stats.PacketsRecv, stats.PacketLoss)
|
||||
// fmt.Printf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n",
|
||||
// stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt)
|
||||
// }
|
||||
// fmt.Printf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr())
|
||||
// err = pinger.Run()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// It sends ICMP Echo Request packet(s) and waits for an Echo Reply in response.
|
||||
// If it receives a response, it calls the OnRecv callback. When it's finished,
|
||||
// it calls the OnFinish callback.
|
||||
//
|
||||
// For a full ping example, see "cmd/ping/ping.go".
|
||||
//
|
||||
package ping
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/icmp"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
const (
|
||||
timeSliceLength = 8
|
||||
trackerLength = 8
|
||||
protocolICMP = 1
|
||||
protocolIPv6ICMP = 58
|
||||
)
|
||||
|
||||
var (
|
||||
ipv4Proto = map[string]string{"icmp": "ip4:icmp", "udp": "udp4"}
|
||||
ipv6Proto = map[string]string{"icmp": "ip6:ipv6-icmp", "udp": "udp6"}
|
||||
)
|
||||
|
||||
// New returns a new Pinger struct pointer.
|
||||
func New(addr string) *Pinger {
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
return &Pinger{
|
||||
Count: -1,
|
||||
Interval: time.Second,
|
||||
RecordRtts: true,
|
||||
Size: timeSliceLength,
|
||||
Timeout: time.Second * 100000,
|
||||
Tracker: r.Int63n(math.MaxInt64),
|
||||
|
||||
addr: addr,
|
||||
done: make(chan bool),
|
||||
id: r.Intn(math.MaxInt16),
|
||||
ipaddr: nil,
|
||||
ipv4: false,
|
||||
network: "ip",
|
||||
protocol: "udp",
|
||||
}
|
||||
}
|
||||
|
||||
// NewPinger returns a new Pinger and resolves the address.
|
||||
func NewPinger(addr string) (*Pinger, error) {
|
||||
p := New(addr)
|
||||
return p, p.Resolve()
|
||||
}
|
||||
|
||||
// Pinger represents a packet sender/receiver.
|
||||
type Pinger struct {
|
||||
// Interval is the wait time between each packet send. Default is 1s.
|
||||
Interval time.Duration
|
||||
|
||||
// Timeout specifies a timeout before ping exits, regardless of how many
|
||||
// packets have been received.
|
||||
Timeout time.Duration
|
||||
|
||||
// Count tells pinger to stop after sending (and receiving) Count echo
|
||||
// packets. If this option is not specified, pinger will operate until
|
||||
// interrupted.
|
||||
Count int
|
||||
|
||||
// Debug runs in debug mode
|
||||
Debug bool
|
||||
|
||||
// Number of packets sent
|
||||
PacketsSent int
|
||||
|
||||
// Number of packets received
|
||||
PacketsRecv int
|
||||
|
||||
// If true, keep a record of rtts of all received packets.
|
||||
// Set to false to avoid memory bloat for long running pings.
|
||||
RecordRtts bool
|
||||
|
||||
// rtts is all of the Rtts
|
||||
rtts []time.Duration
|
||||
|
||||
// OnSend is called when Pinger sends a packet
|
||||
OnSend func(*Packet)
|
||||
|
||||
// OnRecv is called when Pinger receives and processes a packet
|
||||
OnRecv func(*Packet)
|
||||
|
||||
// OnFinish is called when Pinger exits
|
||||
OnFinish func(*Statistics)
|
||||
|
||||
// Size of packet being sent
|
||||
Size int
|
||||
|
||||
// Tracker: Used to uniquely identify packet when non-priviledged
|
||||
Tracker int64
|
||||
|
||||
// Source is the source IP address
|
||||
Source string
|
||||
|
||||
// stop chan bool
|
||||
done chan bool
|
||||
|
||||
ipaddr *net.IPAddr
|
||||
addr string
|
||||
|
||||
ipv4 bool
|
||||
id int
|
||||
sequence int
|
||||
// network is one of "ip", "ip4", or "ip6".
|
||||
network string
|
||||
// protocol is "icmp" or "udp".
|
||||
protocol string
|
||||
}
|
||||
|
||||
type packet struct {
|
||||
bytes []byte
|
||||
nbytes int
|
||||
ttl int
|
||||
}
|
||||
|
||||
// Packet represents a received and processed ICMP echo packet.
|
||||
type Packet struct {
|
||||
// Rtt is the round-trip time it took to ping.
|
||||
Rtt time.Duration
|
||||
|
||||
// IPAddr is the address of the host being pinged.
|
||||
IPAddr *net.IPAddr
|
||||
|
||||
// Addr is the string address of the host being pinged.
|
||||
Addr string
|
||||
|
||||
// NBytes is the number of bytes in the message.
|
||||
Nbytes int
|
||||
|
||||
// Seq is the ICMP sequence number.
|
||||
Seq int
|
||||
|
||||
// TTL is the Time To Live on the packet.
|
||||
Ttl int
|
||||
}
|
||||
|
||||
// Statistics represent the stats of a currently running or finished
|
||||
// pinger operation.
|
||||
type Statistics struct {
|
||||
// PacketsRecv is the number of packets received.
|
||||
PacketsRecv int
|
||||
|
||||
// PacketsSent is the number of packets sent.
|
||||
PacketsSent int
|
||||
|
||||
// PacketLoss is the percentage of packets lost.
|
||||
PacketLoss float64
|
||||
|
||||
// IPAddr is the address of the host being pinged.
|
||||
IPAddr *net.IPAddr
|
||||
|
||||
// Addr is the string address of the host being pinged.
|
||||
Addr string
|
||||
|
||||
// Rtts is all of the round-trip times sent via this pinger.
|
||||
Rtts []time.Duration
|
||||
|
||||
// MinRtt is the minimum round-trip time sent via this pinger.
|
||||
MinRtt time.Duration
|
||||
|
||||
// MaxRtt is the maximum round-trip time sent via this pinger.
|
||||
MaxRtt time.Duration
|
||||
|
||||
// AvgRtt is the average round-trip time sent via this pinger.
|
||||
AvgRtt time.Duration
|
||||
|
||||
// StdDevRtt is the standard deviation of the round-trip times sent via
|
||||
// this pinger.
|
||||
StdDevRtt time.Duration
|
||||
}
|
||||
|
||||
// SetIPAddr sets the ip address of the target host.
|
||||
func (p *Pinger) SetIPAddr(ipaddr *net.IPAddr) {
|
||||
p.ipv4 = isIPv4(ipaddr.IP)
|
||||
|
||||
p.ipaddr = ipaddr
|
||||
p.addr = ipaddr.String()
|
||||
}
|
||||
|
||||
// IPAddr returns the ip address of the target host.
|
||||
func (p *Pinger) IPAddr() *net.IPAddr {
|
||||
return p.ipaddr
|
||||
}
|
||||
|
||||
// Resolve does the DNS lookup for the Pinger address and sets IP protocol.
|
||||
func (p *Pinger) Resolve() error {
|
||||
if len(p.addr) == 0 {
|
||||
return errors.New("addr cannot be empty")
|
||||
}
|
||||
ipaddr, err := net.ResolveIPAddr(p.network, p.addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.ipv4 = isIPv4(ipaddr.IP)
|
||||
|
||||
p.ipaddr = ipaddr
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAddr resolves and sets the ip address of the target host, addr can be a
|
||||
// DNS name like "www.google.com" or IP like "127.0.0.1".
|
||||
func (p *Pinger) SetAddr(addr string) error {
|
||||
oldAddr := p.addr
|
||||
p.addr = addr
|
||||
err := p.Resolve()
|
||||
if err != nil {
|
||||
p.addr = oldAddr
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Addr returns the string ip address of the target host.
|
||||
func (p *Pinger) Addr() string {
|
||||
return p.addr
|
||||
}
|
||||
|
||||
// SetNetwork allows configuration of DNS resolution.
|
||||
// * "ip" will automatically select IPv4 or IPv6.
|
||||
// * "ip4" will select IPv4.
|
||||
// * "ip6" will select IPv6.
|
||||
func (p *Pinger) SetNetwork(n string) {
|
||||
switch n {
|
||||
case "ip4":
|
||||
p.network = "ip4"
|
||||
case "ip6":
|
||||
p.network = "ip6"
|
||||
default:
|
||||
p.network = "ip"
|
||||
}
|
||||
}
|
||||
|
||||
// SetPrivileged sets the type of ping pinger will send.
|
||||
// false means pinger will send an "unprivileged" UDP ping.
|
||||
// true means pinger will send a "privileged" raw ICMP ping.
|
||||
// NOTE: setting to true requires that it be run with super-user privileges.
|
||||
func (p *Pinger) SetPrivileged(privileged bool) {
|
||||
if privileged {
|
||||
p.protocol = "icmp"
|
||||
} else {
|
||||
p.protocol = "udp"
|
||||
}
|
||||
}
|
||||
|
||||
// Privileged returns whether pinger is running in privileged mode.
|
||||
func (p *Pinger) Privileged() bool {
|
||||
return p.protocol == "icmp"
|
||||
}
|
||||
|
||||
// Run runs the pinger. This is a blocking function that will exit when it's
|
||||
// done. If Count or Interval are not specified, it will run continuously until
|
||||
// it is interrupted.
|
||||
func (p *Pinger) Run() error {
|
||||
var conn *icmp.PacketConn
|
||||
var err error
|
||||
if p.ipaddr == nil {
|
||||
err = p.Resolve()
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if p.ipv4 {
|
||||
if conn, err = p.listen(ipv4Proto[p.protocol]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = conn.IPv4PacketConn().SetControlMessage(ipv4.FlagTTL, true); runtime.GOOS != "windows" && err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if conn, err = p.listen(ipv6Proto[p.protocol]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = conn.IPv6PacketConn().SetControlMessage(ipv6.FlagHopLimit, true); runtime.GOOS != "windows" && err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
defer conn.Close()
|
||||
defer p.finish()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
recv := make(chan *packet, 5)
|
||||
defer close(recv)
|
||||
wg.Add(1)
|
||||
//nolint:errcheck
|
||||
go p.recvICMP(conn, recv, &wg)
|
||||
|
||||
err = p.sendICMP(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
timeout := time.NewTicker(p.Timeout)
|
||||
defer timeout.Stop()
|
||||
interval := time.NewTicker(p.Interval)
|
||||
defer interval.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-p.done:
|
||||
wg.Wait()
|
||||
return nil
|
||||
case <-timeout.C:
|
||||
close(p.done)
|
||||
wg.Wait()
|
||||
return nil
|
||||
case <-interval.C:
|
||||
if p.Count > 0 && p.PacketsSent >= p.Count {
|
||||
continue
|
||||
}
|
||||
err = p.sendICMP(conn)
|
||||
if err != nil {
|
||||
// FIXME: this logs as FATAL but continues
|
||||
fmt.Println("FATAL: ", err.Error())
|
||||
}
|
||||
case r := <-recv:
|
||||
err := p.processPacket(r)
|
||||
if err != nil {
|
||||
// FIXME: this logs as FATAL but continues
|
||||
fmt.Println("FATAL: ", err.Error())
|
||||
}
|
||||
}
|
||||
if p.Count > 0 && p.PacketsRecv >= p.Count {
|
||||
close(p.done)
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pinger) Stop() {
|
||||
close(p.done)
|
||||
}
|
||||
|
||||
func (p *Pinger) finish() {
|
||||
handler := p.OnFinish
|
||||
if handler != nil {
|
||||
s := p.Statistics()
|
||||
handler(s)
|
||||
}
|
||||
}
|
||||
|
||||
// Statistics returns the statistics of the pinger. This can be run while the
|
||||
// pinger is running or after it is finished. OnFinish calls this function to
|
||||
// get it's finished statistics.
|
||||
func (p *Pinger) Statistics() *Statistics {
|
||||
loss := float64(p.PacketsSent-p.PacketsRecv) / float64(p.PacketsSent) * 100
|
||||
var min, max, total time.Duration
|
||||
if len(p.rtts) > 0 {
|
||||
min = p.rtts[0]
|
||||
max = p.rtts[0]
|
||||
}
|
||||
for _, rtt := range p.rtts {
|
||||
if rtt < min {
|
||||
min = rtt
|
||||
}
|
||||
if rtt > max {
|
||||
max = rtt
|
||||
}
|
||||
total += rtt
|
||||
}
|
||||
s := Statistics{
|
||||
PacketsSent: p.PacketsSent,
|
||||
PacketsRecv: p.PacketsRecv,
|
||||
PacketLoss: loss,
|
||||
Rtts: p.rtts,
|
||||
Addr: p.addr,
|
||||
IPAddr: p.ipaddr,
|
||||
MaxRtt: max,
|
||||
MinRtt: min,
|
||||
}
|
||||
if len(p.rtts) > 0 {
|
||||
s.AvgRtt = total / time.Duration(len(p.rtts))
|
||||
var sumsquares time.Duration
|
||||
for _, rtt := range p.rtts {
|
||||
sumsquares += (rtt - s.AvgRtt) * (rtt - s.AvgRtt)
|
||||
}
|
||||
s.StdDevRtt = time.Duration(math.Sqrt(
|
||||
float64(sumsquares / time.Duration(len(p.rtts)))))
|
||||
}
|
||||
return &s
|
||||
}
|
||||
|
||||
func (p *Pinger) recvICMP(
|
||||
conn *icmp.PacketConn,
|
||||
recv chan<- *packet,
|
||||
wg *sync.WaitGroup,
|
||||
) error {
|
||||
defer wg.Done()
|
||||
for {
|
||||
select {
|
||||
case <-p.done:
|
||||
return nil
|
||||
default:
|
||||
bytes := make([]byte, 512)
|
||||
if err := conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100)); err != nil {
|
||||
return err
|
||||
}
|
||||
var n, ttl int
|
||||
var err error
|
||||
if p.ipv4 {
|
||||
var cm *ipv4.ControlMessage
|
||||
n, cm, _, err = conn.IPv4PacketConn().ReadFrom(bytes)
|
||||
if cm != nil {
|
||||
ttl = cm.TTL
|
||||
}
|
||||
} else {
|
||||
var cm *ipv6.ControlMessage
|
||||
n, cm, _, err = conn.IPv6PacketConn().ReadFrom(bytes)
|
||||
if cm != nil {
|
||||
ttl = cm.HopLimit
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if neterr, ok := err.(*net.OpError); ok {
|
||||
if neterr.Timeout() {
|
||||
// Read timeout
|
||||
continue
|
||||
} else {
|
||||
close(p.done)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
case <-p.done:
|
||||
return nil
|
||||
case recv <- &packet{bytes: bytes, nbytes: n, ttl: ttl}:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pinger) processPacket(recv *packet) error {
|
||||
receivedAt := time.Now()
|
||||
var proto int
|
||||
if p.ipv4 {
|
||||
proto = protocolICMP
|
||||
} else {
|
||||
proto = protocolIPv6ICMP
|
||||
}
|
||||
|
||||
var m *icmp.Message
|
||||
var err error
|
||||
if m, err = icmp.ParseMessage(proto, recv.bytes); err != nil {
|
||||
return fmt.Errorf("error parsing icmp message: %s", err.Error())
|
||||
}
|
||||
|
||||
if m.Type != ipv4.ICMPTypeEchoReply && m.Type != ipv6.ICMPTypeEchoReply {
|
||||
// Not an echo reply, ignore it
|
||||
return nil
|
||||
}
|
||||
|
||||
outPkt := &Packet{
|
||||
Nbytes: recv.nbytes,
|
||||
IPAddr: p.ipaddr,
|
||||
Addr: p.addr,
|
||||
Ttl: recv.ttl,
|
||||
}
|
||||
|
||||
switch pkt := m.Body.(type) {
|
||||
case *icmp.Echo:
|
||||
// If we are priviledged, we can match icmp.ID
|
||||
if p.protocol == "icmp" {
|
||||
// Check if reply from same ID
|
||||
if pkt.ID != p.id {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(pkt.Data) < timeSliceLength+trackerLength {
|
||||
return fmt.Errorf("insufficient data received; got: %d %v",
|
||||
len(pkt.Data), pkt.Data)
|
||||
}
|
||||
|
||||
tracker := bytesToInt(pkt.Data[timeSliceLength:])
|
||||
timestamp := bytesToTime(pkt.Data[:timeSliceLength])
|
||||
|
||||
if tracker != p.Tracker {
|
||||
return nil
|
||||
}
|
||||
|
||||
outPkt.Rtt = receivedAt.Sub(timestamp)
|
||||
outPkt.Seq = pkt.Seq
|
||||
p.PacketsRecv++
|
||||
default:
|
||||
// Very bad, not sure how this can happen
|
||||
return fmt.Errorf("invalid ICMP echo reply; type: '%T', '%v'", pkt, pkt)
|
||||
}
|
||||
|
||||
if p.RecordRtts {
|
||||
p.rtts = append(p.rtts, outPkt.Rtt)
|
||||
}
|
||||
handler := p.OnRecv
|
||||
if handler != nil {
|
||||
handler(outPkt)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pinger) sendICMP(conn *icmp.PacketConn) error {
|
||||
var typ icmp.Type
|
||||
if p.ipv4 {
|
||||
typ = ipv4.ICMPTypeEcho
|
||||
} else {
|
||||
typ = ipv6.ICMPTypeEchoRequest
|
||||
}
|
||||
|
||||
var dst net.Addr = p.ipaddr
|
||||
if p.protocol == "udp" {
|
||||
dst = &net.UDPAddr{IP: p.ipaddr.IP, Zone: p.ipaddr.Zone}
|
||||
}
|
||||
|
||||
t := append(timeToBytes(time.Now()), intToBytes(p.Tracker)...)
|
||||
if remainSize := p.Size - timeSliceLength - trackerLength; remainSize > 0 {
|
||||
t = append(t, bytes.Repeat([]byte{1}, remainSize)...)
|
||||
}
|
||||
|
||||
body := &icmp.Echo{
|
||||
ID: p.id,
|
||||
Seq: p.sequence,
|
||||
Data: t,
|
||||
}
|
||||
|
||||
msg := &icmp.Message{
|
||||
Type: typ,
|
||||
Code: 0,
|
||||
Body: body,
|
||||
}
|
||||
|
||||
msgBytes, err := msg.Marshal(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
if _, err := conn.WriteTo(msgBytes, dst); err != nil {
|
||||
if neterr, ok := err.(*net.OpError); ok {
|
||||
if neterr.Err == syscall.ENOBUFS {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
handler := p.OnSend
|
||||
if handler != nil {
|
||||
outPkt := &Packet{
|
||||
Nbytes: len(msgBytes),
|
||||
IPAddr: p.ipaddr,
|
||||
Addr: p.addr,
|
||||
Seq: p.sequence,
|
||||
}
|
||||
handler(outPkt)
|
||||
}
|
||||
|
||||
p.PacketsSent++
|
||||
p.sequence++
|
||||
break
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pinger) listen(netProto string) (*icmp.PacketConn, error) {
|
||||
conn, err := icmp.ListenPacket(netProto, p.Source)
|
||||
if err != nil {
|
||||
close(p.done)
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func bytesToTime(b []byte) time.Time {
|
||||
var nsec int64
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
nsec += int64(b[i]) << ((7 - i) * 8)
|
||||
}
|
||||
return time.Unix(nsec/1000000000, nsec%1000000000)
|
||||
}
|
||||
|
||||
func isIPv4(ip net.IP) bool {
|
||||
return len(ip.To4()) == net.IPv4len
|
||||
}
|
||||
|
||||
func timeToBytes(t time.Time) []byte {
|
||||
nsec := t.UnixNano()
|
||||
b := make([]byte, 8)
|
||||
for i := uint8(0); i < 8; i++ {
|
||||
b[i] = byte((nsec >> ((7 - i) * 8)) & 0xff)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func bytesToInt(b []byte) int64 {
|
||||
return int64(binary.BigEndian.Uint64(b))
|
||||
}
|
||||
|
||||
func intToBytes(tracker int64) []byte {
|
||||
b := make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(b, uint64(tracker))
|
||||
return b
|
||||
}
|
11
vendor/github.com/google/gofuzz/.travis.yml
generated
vendored
11
vendor/github.com/google/gofuzz/.travis.yml
generated
vendored
@ -1,13 +1,10 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.4
|
||||
- 1.3
|
||||
- 1.2
|
||||
- tip
|
||||
|
||||
install:
|
||||
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
|
||||
- 1.11.x
|
||||
- 1.12.x
|
||||
- 1.13.x
|
||||
- master
|
||||
|
||||
script:
|
||||
- go test -cover
|
||||
|
2
vendor/github.com/google/gofuzz/CONTRIBUTING.md
generated
vendored
2
vendor/github.com/google/gofuzz/CONTRIBUTING.md
generated
vendored
@ -1,7 +1,7 @@
|
||||
# How to contribute #
|
||||
|
||||
We'd love to accept your patches and contributions to this project. There are
|
||||
a just a few small guidelines you need to follow.
|
||||
just a few small guidelines you need to follow.
|
||||
|
||||
|
||||
## Contributor License Agreement ##
|
||||
|
20
vendor/github.com/google/gofuzz/README.md
generated
vendored
20
vendor/github.com/google/gofuzz/README.md
generated
vendored
@ -3,7 +3,7 @@ gofuzz
|
||||
|
||||
gofuzz is a library for populating go objects with random values.
|
||||
|
||||
[](https://godoc.org/github.com/google/gofuzz)
|
||||
[](https://godoc.org/github.com/google/gofuzz)
|
||||
[](https://travis-ci.org/google/gofuzz)
|
||||
|
||||
This is useful for testing:
|
||||
@ -68,4 +68,22 @@ f.Fuzz(&myObject) // Type will correspond to whether A or B info is set.
|
||||
|
||||
See more examples in ```example_test.go```.
|
||||
|
||||
You can use this library for easier [go-fuzz](https://github.com/dvyukov/go-fuzz)ing.
|
||||
go-fuzz provides the user a byte-slice, which should be converted to different inputs
|
||||
for the tested function. This library can help convert the byte slice. Consider for
|
||||
example a fuzz test for a the function `mypackage.MyFunc` that takes an int arguments:
|
||||
```go
|
||||
// +build gofuzz
|
||||
package mypackage
|
||||
|
||||
import fuzz "github.com/google/gofuzz"
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
var i int
|
||||
fuzz.NewFromGoFuzz(data).Fuzz(&i)
|
||||
MyFunc(i)
|
||||
return 0
|
||||
}
|
||||
```
|
||||
|
||||
Happy testing!
|
||||
|
81
vendor/github.com/google/gofuzz/bytesource/bytesource.go
generated
vendored
Normal file
81
vendor/github.com/google/gofuzz/bytesource/bytesource.go
generated
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Package bytesource provides a rand.Source64 that is determined by a slice of bytes.
|
||||
package bytesource
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
// ByteSource implements rand.Source64 determined by a slice of bytes. The random numbers are
|
||||
// generated from each 8 bytes in the slice, until the last bytes are consumed, from which a
|
||||
// fallback pseudo random source is created in case more random numbers are required.
|
||||
// It also exposes a `bytes.Reader` API, which lets callers consume the bytes directly.
|
||||
type ByteSource struct {
|
||||
*bytes.Reader
|
||||
fallback rand.Source
|
||||
}
|
||||
|
||||
// New returns a new ByteSource from a given slice of bytes.
|
||||
func New(input []byte) *ByteSource {
|
||||
s := &ByteSource{
|
||||
Reader: bytes.NewReader(input),
|
||||
fallback: rand.NewSource(0),
|
||||
}
|
||||
if len(input) > 0 {
|
||||
s.fallback = rand.NewSource(int64(s.consumeUint64()))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *ByteSource) Uint64() uint64 {
|
||||
// Return from input if it was not exhausted.
|
||||
if s.Len() > 0 {
|
||||
return s.consumeUint64()
|
||||
}
|
||||
|
||||
// Input was exhausted, return random number from fallback (in this case fallback should not be
|
||||
// nil). Try first having a Uint64 output (Should work in current rand implementation),
|
||||
// otherwise return a conversion of Int63.
|
||||
if s64, ok := s.fallback.(rand.Source64); ok {
|
||||
return s64.Uint64()
|
||||
}
|
||||
return uint64(s.fallback.Int63())
|
||||
}
|
||||
|
||||
func (s *ByteSource) Int63() int64 {
|
||||
return int64(s.Uint64() >> 1)
|
||||
}
|
||||
|
||||
func (s *ByteSource) Seed(seed int64) {
|
||||
s.fallback = rand.NewSource(seed)
|
||||
s.Reader = bytes.NewReader(nil)
|
||||
}
|
||||
|
||||
// consumeUint64 reads 8 bytes from the input and convert them to a uint64. It assumes that the the
|
||||
// bytes reader is not empty.
|
||||
func (s *ByteSource) consumeUint64() uint64 {
|
||||
var bytes [8]byte
|
||||
_, err := s.Read(bytes[:])
|
||||
if err != nil && err != io.EOF {
|
||||
panic("failed reading source") // Should not happen.
|
||||
}
|
||||
return binary.BigEndian.Uint64(bytes[:])
|
||||
}
|
172
vendor/github.com/google/gofuzz/fuzz.go
generated
vendored
172
vendor/github.com/google/gofuzz/fuzz.go
generated
vendored
@ -20,7 +20,11 @@ import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/google/gofuzz/bytesource"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// fuzzFuncMap is a map from a type to a fuzzFunc that handles that type.
|
||||
@ -28,13 +32,14 @@ type fuzzFuncMap map[reflect.Type]reflect.Value
|
||||
|
||||
// Fuzzer knows how to fill any object with random fields.
|
||||
type Fuzzer struct {
|
||||
fuzzFuncs fuzzFuncMap
|
||||
defaultFuzzFuncs fuzzFuncMap
|
||||
r *rand.Rand
|
||||
nilChance float64
|
||||
minElements int
|
||||
maxElements int
|
||||
maxDepth int
|
||||
fuzzFuncs fuzzFuncMap
|
||||
defaultFuzzFuncs fuzzFuncMap
|
||||
r *rand.Rand
|
||||
nilChance float64
|
||||
minElements int
|
||||
maxElements int
|
||||
maxDepth int
|
||||
skipFieldPatterns []*regexp.Regexp
|
||||
}
|
||||
|
||||
// New returns a new Fuzzer. Customize your Fuzzer further by calling Funcs,
|
||||
@ -59,6 +64,34 @@ func NewWithSeed(seed int64) *Fuzzer {
|
||||
return f
|
||||
}
|
||||
|
||||
// NewFromGoFuzz is a helper function that enables using gofuzz (this
|
||||
// project) with go-fuzz (https://github.com/dvyukov/go-fuzz) for continuous
|
||||
// fuzzing. Essentially, it enables translating the fuzzing bytes from
|
||||
// go-fuzz to any Go object using this library.
|
||||
//
|
||||
// This implementation promises a constant translation from a given slice of
|
||||
// bytes to the fuzzed objects. This promise will remain over future
|
||||
// versions of Go and of this library.
|
||||
//
|
||||
// Note: the returned Fuzzer should not be shared between multiple goroutines,
|
||||
// as its deterministic output will no longer be available.
|
||||
//
|
||||
// Example: use go-fuzz to test the function `MyFunc(int)` in the package
|
||||
// `mypackage`. Add the file: "mypacakge_fuzz.go" with the content:
|
||||
//
|
||||
// // +build gofuzz
|
||||
// package mypacakge
|
||||
// import fuzz "github.com/google/gofuzz"
|
||||
// func Fuzz(data []byte) int {
|
||||
// var i int
|
||||
// fuzz.NewFromGoFuzz(data).Fuzz(&i)
|
||||
// MyFunc(i)
|
||||
// return 0
|
||||
// }
|
||||
func NewFromGoFuzz(data []byte) *Fuzzer {
|
||||
return New().RandSource(bytesource.New(data))
|
||||
}
|
||||
|
||||
// Funcs adds each entry in fuzzFuncs as a custom fuzzing function.
|
||||
//
|
||||
// Each entry in fuzzFuncs must be a function taking two parameters.
|
||||
@ -139,7 +172,7 @@ func (f *Fuzzer) genElementCount() int {
|
||||
}
|
||||
|
||||
func (f *Fuzzer) genShouldFill() bool {
|
||||
return f.r.Float64() > f.nilChance
|
||||
return f.r.Float64() >= f.nilChance
|
||||
}
|
||||
|
||||
// MaxDepth sets the maximum number of recursive fuzz calls that will be made
|
||||
@ -150,6 +183,13 @@ func (f *Fuzzer) MaxDepth(d int) *Fuzzer {
|
||||
return f
|
||||
}
|
||||
|
||||
// Skip fields which match the supplied pattern. Call this multiple times if needed
|
||||
// This is useful to skip XXX_ fields generated by protobuf
|
||||
func (f *Fuzzer) SkipFieldsWithPattern(pattern *regexp.Regexp) *Fuzzer {
|
||||
f.skipFieldPatterns = append(f.skipFieldPatterns, pattern)
|
||||
return f
|
||||
}
|
||||
|
||||
// Fuzz recursively fills all of obj's fields with something random. First
|
||||
// this tries to find a custom fuzz function (see Funcs). If there is no
|
||||
// custom function this tests whether the object implements fuzz.Interface and,
|
||||
@ -231,6 +271,7 @@ func (fc *fuzzerContext) doFuzz(v reflect.Value, flags uint64) {
|
||||
fn(v, fc.fuzzer.r)
|
||||
return
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Map:
|
||||
if fc.fuzzer.genShouldFill() {
|
||||
@ -274,7 +315,17 @@ func (fc *fuzzerContext) doFuzz(v reflect.Value, flags uint64) {
|
||||
v.Set(reflect.Zero(v.Type()))
|
||||
case reflect.Struct:
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
fc.doFuzz(v.Field(i), 0)
|
||||
skipField := false
|
||||
fieldName := v.Type().Field(i).Name
|
||||
for _, pattern := range fc.fuzzer.skipFieldPatterns {
|
||||
if pattern.MatchString(fieldName) {
|
||||
skipField = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !skipField {
|
||||
fc.doFuzz(v.Field(i), 0)
|
||||
}
|
||||
}
|
||||
case reflect.Chan:
|
||||
fallthrough
|
||||
@ -431,10 +482,10 @@ var fillFuncMap = map[reflect.Kind]func(reflect.Value, *rand.Rand){
|
||||
v.SetFloat(r.Float64())
|
||||
},
|
||||
reflect.Complex64: func(v reflect.Value, r *rand.Rand) {
|
||||
panic("unimplemented")
|
||||
v.SetComplex(complex128(complex(r.Float32(), r.Float32())))
|
||||
},
|
||||
reflect.Complex128: func(v reflect.Value, r *rand.Rand) {
|
||||
panic("unimplemented")
|
||||
v.SetComplex(complex(r.Float64(), r.Float64()))
|
||||
},
|
||||
reflect.String: func(v reflect.Value, r *rand.Rand) {
|
||||
v.SetString(randString(r))
|
||||
@ -446,38 +497,105 @@ var fillFuncMap = map[reflect.Kind]func(reflect.Value, *rand.Rand){
|
||||
|
||||
// randBool returns true or false randomly.
|
||||
func randBool(r *rand.Rand) bool {
|
||||
if r.Int()&1 == 1 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return r.Int31()&(1<<30) == 0
|
||||
}
|
||||
|
||||
type charRange struct {
|
||||
first, last rune
|
||||
type int63nPicker interface {
|
||||
Int63n(int64) int64
|
||||
}
|
||||
|
||||
// UnicodeRange describes a sequential range of unicode characters.
|
||||
// Last must be numerically greater than First.
|
||||
type UnicodeRange struct {
|
||||
First, Last rune
|
||||
}
|
||||
|
||||
// UnicodeRanges describes an arbitrary number of sequential ranges of unicode characters.
|
||||
// To be useful, each range must have at least one character (First <= Last) and
|
||||
// there must be at least one range.
|
||||
type UnicodeRanges []UnicodeRange
|
||||
|
||||
// choose returns a random unicode character from the given range, using the
|
||||
// given randomness source.
|
||||
func (r *charRange) choose(rand *rand.Rand) rune {
|
||||
count := int64(r.last - r.first)
|
||||
return r.first + rune(rand.Int63n(count))
|
||||
func (ur UnicodeRange) choose(r int63nPicker) rune {
|
||||
count := int64(ur.Last - ur.First + 1)
|
||||
return ur.First + rune(r.Int63n(count))
|
||||
}
|
||||
|
||||
var unicodeRanges = []charRange{
|
||||
// CustomStringFuzzFunc constructs a FuzzFunc which produces random strings.
|
||||
// Each character is selected from the range ur. If there are no characters
|
||||
// in the range (cr.Last < cr.First), this will panic.
|
||||
func (ur UnicodeRange) CustomStringFuzzFunc() func(s *string, c Continue) {
|
||||
ur.check()
|
||||
return func(s *string, c Continue) {
|
||||
*s = ur.randString(c.Rand)
|
||||
}
|
||||
}
|
||||
|
||||
// check is a function that used to check whether the first of ur(UnicodeRange)
|
||||
// is greater than the last one.
|
||||
func (ur UnicodeRange) check() {
|
||||
if ur.Last < ur.First {
|
||||
panic("The last encoding must be greater than the first one.")
|
||||
}
|
||||
}
|
||||
|
||||
// randString of UnicodeRange makes a random string up to 20 characters long.
|
||||
// Each character is selected form ur(UnicodeRange).
|
||||
func (ur UnicodeRange) randString(r *rand.Rand) string {
|
||||
n := r.Intn(20)
|
||||
sb := strings.Builder{}
|
||||
sb.Grow(n)
|
||||
for i := 0; i < n; i++ {
|
||||
sb.WriteRune(ur.choose(r))
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// defaultUnicodeRanges sets a default unicode range when user do not set
|
||||
// CustomStringFuzzFunc() but wants fuzz string.
|
||||
var defaultUnicodeRanges = UnicodeRanges{
|
||||
{' ', '~'}, // ASCII characters
|
||||
{'\u00a0', '\u02af'}, // Multi-byte encoded characters
|
||||
{'\u4e00', '\u9fff'}, // Common CJK (even longer encodings)
|
||||
}
|
||||
|
||||
// CustomStringFuzzFunc constructs a FuzzFunc which produces random strings.
|
||||
// Each character is selected from one of the ranges of ur(UnicodeRanges).
|
||||
// Each range has an equal probability of being chosen. If there are no ranges,
|
||||
// or a selected range has no characters (.Last < .First), this will panic.
|
||||
// Do not modify any of the ranges in ur after calling this function.
|
||||
func (ur UnicodeRanges) CustomStringFuzzFunc() func(s *string, c Continue) {
|
||||
// Check unicode ranges slice is empty.
|
||||
if len(ur) == 0 {
|
||||
panic("UnicodeRanges is empty.")
|
||||
}
|
||||
// if not empty, each range should be checked.
|
||||
for i := range ur {
|
||||
ur[i].check()
|
||||
}
|
||||
return func(s *string, c Continue) {
|
||||
*s = ur.randString(c.Rand)
|
||||
}
|
||||
}
|
||||
|
||||
// randString of UnicodeRanges makes a random string up to 20 characters long.
|
||||
// Each character is selected form one of the ranges of ur(UnicodeRanges),
|
||||
// and each range has an equal probability of being chosen.
|
||||
func (ur UnicodeRanges) randString(r *rand.Rand) string {
|
||||
n := r.Intn(20)
|
||||
sb := strings.Builder{}
|
||||
sb.Grow(n)
|
||||
for i := 0; i < n; i++ {
|
||||
sb.WriteRune(ur[r.Intn(len(ur))].choose(r))
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// randString makes a random string up to 20 characters long. The returned string
|
||||
// may include a variety of (valid) UTF-8 encodings.
|
||||
func randString(r *rand.Rand) string {
|
||||
n := r.Intn(20)
|
||||
runes := make([]rune, n)
|
||||
for i := range runes {
|
||||
runes[i] = unicodeRanges[r.Intn(len(unicodeRanges))].choose(r)
|
||||
}
|
||||
return string(runes)
|
||||
return defaultUnicodeRanges.randString(r)
|
||||
}
|
||||
|
||||
// randUint64 makes random 64 bit numbers.
|
||||
|
20
vendor/github.com/prometheus/client_golang/prometheus/counter.go
generated
vendored
20
vendor/github.com/prometheus/client_golang/prometheus/counter.go
generated
vendored
@ -163,7 +163,7 @@ func (c *counter) updateExemplar(v float64, l Labels) {
|
||||
// (e.g. number of HTTP requests, partitioned by response code and
|
||||
// method). Create instances with NewCounterVec.
|
||||
type CounterVec struct {
|
||||
*metricVec
|
||||
*MetricVec
|
||||
}
|
||||
|
||||
// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
|
||||
@ -176,11 +176,11 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||
opts.ConstLabels,
|
||||
)
|
||||
return &CounterVec{
|
||||
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
||||
if len(lvs) != len(desc.variableLabels) {
|
||||
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
|
||||
}
|
||||
result := &counter{desc: desc, labelPairs: makeLabelPairs(desc, lvs), now: time.Now}
|
||||
result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: time.Now}
|
||||
result.init(result) // Init self-collection.
|
||||
return result
|
||||
}),
|
||||
@ -188,7 +188,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||
}
|
||||
|
||||
// GetMetricWithLabelValues returns the Counter for the given slice of label
|
||||
// values (same order as the VariableLabels in Desc). If that combination of
|
||||
// values (same order as the variable labels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new Counter is created.
|
||||
//
|
||||
// It is possible to call this method without using the returned Counter to only
|
||||
@ -202,7 +202,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||
// Counter with the same label values is created later.
|
||||
//
|
||||
// An error is returned if the number of label values is not the same as the
|
||||
// number of VariableLabels in Desc (minus any curried labels).
|
||||
// number of variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// Note that for more than one label value, this method is prone to mistakes
|
||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||
@ -211,7 +211,7 @@ func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
|
||||
// with a performance overhead (for creating and processing the Labels map).
|
||||
// See also the GaugeVec example.
|
||||
func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
|
||||
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
|
||||
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
|
||||
if metric != nil {
|
||||
return metric.(Counter), err
|
||||
}
|
||||
@ -219,19 +219,19 @@ func (v *CounterVec) GetMetricWithLabelValues(lvs ...string) (Counter, error) {
|
||||
}
|
||||
|
||||
// GetMetricWith returns the Counter for the given Labels map (the label names
|
||||
// must match those of the VariableLabels in Desc). If that label map is
|
||||
// must match those of the variable labels in Desc). If that label map is
|
||||
// accessed for the first time, a new Counter is created. Implications of
|
||||
// creating a Counter without using it and keeping the Counter for later use are
|
||||
// the same as for GetMetricWithLabelValues.
|
||||
//
|
||||
// An error is returned if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc (minus any curried labels).
|
||||
// with those of the variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// This method is used for the same purpose as
|
||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||
// methods.
|
||||
func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) {
|
||||
metric, err := v.metricVec.getMetricWith(labels)
|
||||
metric, err := v.MetricVec.GetMetricWith(labels)
|
||||
if metric != nil {
|
||||
return metric.(Counter), err
|
||||
}
|
||||
@ -275,7 +275,7 @@ func (v *CounterVec) With(labels Labels) Counter {
|
||||
// registered with a given registry (usually the uncurried version). The Reset
|
||||
// method deletes all metrics, even if called on a curried vector.
|
||||
func (v *CounterVec) CurryWith(labels Labels) (*CounterVec, error) {
|
||||
vec, err := v.curryWith(labels)
|
||||
vec, err := v.MetricVec.CurryWith(labels)
|
||||
if vec != nil {
|
||||
return &CounterVec{vec}, err
|
||||
}
|
||||
|
2
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
@ -51,7 +51,7 @@ type Desc struct {
|
||||
// constLabelPairs contains precalculated DTO label pairs based on
|
||||
// the constant labels.
|
||||
constLabelPairs []*dto.LabelPair
|
||||
// VariableLabels contains names of labels for which the metric
|
||||
// variableLabels contains names of labels for which the metric
|
||||
// maintains variable values.
|
||||
variableLabels []string
|
||||
// id is a hash of the values of the ConstLabels and fqName. This
|
||||
|
20
vendor/github.com/prometheus/client_golang/prometheus/gauge.go
generated
vendored
20
vendor/github.com/prometheus/client_golang/prometheus/gauge.go
generated
vendored
@ -132,7 +132,7 @@ func (g *gauge) Write(out *dto.Metric) error {
|
||||
// (e.g. number of operations queued, partitioned by user and operation
|
||||
// type). Create instances with NewGaugeVec.
|
||||
type GaugeVec struct {
|
||||
*metricVec
|
||||
*MetricVec
|
||||
}
|
||||
|
||||
// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
|
||||
@ -145,11 +145,11 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
||||
opts.ConstLabels,
|
||||
)
|
||||
return &GaugeVec{
|
||||
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
||||
if len(lvs) != len(desc.variableLabels) {
|
||||
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
|
||||
}
|
||||
result := &gauge{desc: desc, labelPairs: makeLabelPairs(desc, lvs)}
|
||||
result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)}
|
||||
result.init(result) // Init self-collection.
|
||||
return result
|
||||
}),
|
||||
@ -157,7 +157,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
||||
}
|
||||
|
||||
// GetMetricWithLabelValues returns the Gauge for the given slice of label
|
||||
// values (same order as the VariableLabels in Desc). If that combination of
|
||||
// values (same order as the variable labels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new Gauge is created.
|
||||
//
|
||||
// It is possible to call this method without using the returned Gauge to only
|
||||
@ -172,7 +172,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
||||
// example.
|
||||
//
|
||||
// An error is returned if the number of label values is not the same as the
|
||||
// number of VariableLabels in Desc (minus any curried labels).
|
||||
// number of variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// Note that for more than one label value, this method is prone to mistakes
|
||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||
@ -180,7 +180,7 @@ func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
|
||||
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
||||
// with a performance overhead (for creating and processing the Labels map).
|
||||
func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
|
||||
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
|
||||
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
|
||||
if metric != nil {
|
||||
return metric.(Gauge), err
|
||||
}
|
||||
@ -188,19 +188,19 @@ func (v *GaugeVec) GetMetricWithLabelValues(lvs ...string) (Gauge, error) {
|
||||
}
|
||||
|
||||
// GetMetricWith returns the Gauge for the given Labels map (the label names
|
||||
// must match those of the VariableLabels in Desc). If that label map is
|
||||
// must match those of the variable labels in Desc). If that label map is
|
||||
// accessed for the first time, a new Gauge is created. Implications of
|
||||
// creating a Gauge without using it and keeping the Gauge for later use are
|
||||
// the same as for GetMetricWithLabelValues.
|
||||
//
|
||||
// An error is returned if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc (minus any curried labels).
|
||||
// with those of the variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// This method is used for the same purpose as
|
||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||
// methods.
|
||||
func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) {
|
||||
metric, err := v.metricVec.getMetricWith(labels)
|
||||
metric, err := v.MetricVec.GetMetricWith(labels)
|
||||
if metric != nil {
|
||||
return metric.(Gauge), err
|
||||
}
|
||||
@ -244,7 +244,7 @@ func (v *GaugeVec) With(labels Labels) Gauge {
|
||||
// registered with a given registry (usually the uncurried version). The Reset
|
||||
// method deletes all metrics, even if called on a curried vector.
|
||||
func (v *GaugeVec) CurryWith(labels Labels) (*GaugeVec, error) {
|
||||
vec, err := v.curryWith(labels)
|
||||
vec, err := v.MetricVec.CurryWith(labels)
|
||||
if vec != nil {
|
||||
return &GaugeVec{vec}, err
|
||||
}
|
||||
|
7
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
7
vendor/github.com/prometheus/client_golang/prometheus/go_collector.go
generated
vendored
@ -58,9 +58,10 @@ type goCollector struct {
|
||||
// collector will use the memstats from a previous collection if
|
||||
// runtime.ReadMemStats takes more than 1s. However, if there are no previously
|
||||
// collected memstats, or their collection is more than 5m ago, the collection
|
||||
// will block until runtime.ReadMemStats succeeds. (The problem might be solved
|
||||
// in Go1.13, see https://github.com/golang/go/issues/19812 for the related Go
|
||||
// issue.)
|
||||
// will block until runtime.ReadMemStats succeeds.
|
||||
//
|
||||
// NOTE: The problem is solved in Go 1.15, see
|
||||
// https://github.com/golang/go/issues/19812 for the related Go issue.
|
||||
func NewGoCollector() Collector {
|
||||
return &goCollector{
|
||||
goroutinesDesc: NewDesc(
|
||||
|
22
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
22
vendor/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
@ -192,7 +192,7 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
|
||||
h := &histogram{
|
||||
desc: desc,
|
||||
upperBounds: opts.Buckets,
|
||||
labelPairs: makeLabelPairs(desc, labelValues),
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
counts: [2]*histogramCounts{{}, {}},
|
||||
now: time.Now,
|
||||
}
|
||||
@ -409,7 +409,7 @@ func (h *histogram) updateExemplar(v float64, bucket int, l Labels) {
|
||||
// (e.g. HTTP request latencies, partitioned by status code and method). Create
|
||||
// instances with NewHistogramVec.
|
||||
type HistogramVec struct {
|
||||
*metricVec
|
||||
*MetricVec
|
||||
}
|
||||
|
||||
// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
|
||||
@ -422,14 +422,14 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
|
||||
opts.ConstLabels,
|
||||
)
|
||||
return &HistogramVec{
|
||||
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
||||
return newHistogram(desc, opts, lvs...)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// GetMetricWithLabelValues returns the Histogram for the given slice of label
|
||||
// values (same order as the VariableLabels in Desc). If that combination of
|
||||
// values (same order as the variable labels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new Histogram is created.
|
||||
//
|
||||
// It is possible to call this method without using the returned Histogram to only
|
||||
@ -444,7 +444,7 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
|
||||
// example.
|
||||
//
|
||||
// An error is returned if the number of label values is not the same as the
|
||||
// number of VariableLabels in Desc (minus any curried labels).
|
||||
// number of variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// Note that for more than one label value, this method is prone to mistakes
|
||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||
@ -453,7 +453,7 @@ func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
|
||||
// with a performance overhead (for creating and processing the Labels map).
|
||||
// See also the GaugeVec example.
|
||||
func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
|
||||
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
|
||||
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
|
||||
if metric != nil {
|
||||
return metric.(Observer), err
|
||||
}
|
||||
@ -461,19 +461,19 @@ func (v *HistogramVec) GetMetricWithLabelValues(lvs ...string) (Observer, error)
|
||||
}
|
||||
|
||||
// GetMetricWith returns the Histogram for the given Labels map (the label names
|
||||
// must match those of the VariableLabels in Desc). If that label map is
|
||||
// must match those of the variable labels in Desc). If that label map is
|
||||
// accessed for the first time, a new Histogram is created. Implications of
|
||||
// creating a Histogram without using it and keeping the Histogram for later use
|
||||
// are the same as for GetMetricWithLabelValues.
|
||||
//
|
||||
// An error is returned if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc (minus any curried labels).
|
||||
// with those of the variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// This method is used for the same purpose as
|
||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||
// methods.
|
||||
func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) {
|
||||
metric, err := v.metricVec.getMetricWith(labels)
|
||||
metric, err := v.MetricVec.GetMetricWith(labels)
|
||||
if metric != nil {
|
||||
return metric.(Observer), err
|
||||
}
|
||||
@ -517,7 +517,7 @@ func (v *HistogramVec) With(labels Labels) Observer {
|
||||
// registered with a given registry (usually the uncurried version). The Reset
|
||||
// method deletes all metrics, even if called on a curried vector.
|
||||
func (v *HistogramVec) CurryWith(labels Labels) (ObserverVec, error) {
|
||||
vec, err := v.curryWith(labels)
|
||||
vec, err := v.MetricVec.CurryWith(labels)
|
||||
if vec != nil {
|
||||
return &HistogramVec{vec}, err
|
||||
}
|
||||
@ -602,7 +602,7 @@ func NewConstHistogram(
|
||||
count: count,
|
||||
sum: sum,
|
||||
buckets: buckets,
|
||||
labelPairs: makeLabelPairs(desc, labelValues),
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/metric.go
generated
vendored
@ -89,7 +89,7 @@ type Opts struct {
|
||||
// better covered by target labels set by the scraping Prometheus
|
||||
// server, or by one specific metric (e.g. a build_info or a
|
||||
// machine_role metric). See also
|
||||
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
|
||||
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
|
||||
ConstLabels Labels
|
||||
}
|
||||
|
||||
|
21
vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
generated
vendored
21
vendor/github.com/prometheus/client_golang/prometheus/process_collector.go
generated
vendored
@ -15,7 +15,11 @@ package prometheus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type processCollector struct {
|
||||
@ -149,3 +153,20 @@ func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error)
|
||||
}
|
||||
ch <- NewInvalidMetric(desc, err)
|
||||
}
|
||||
|
||||
// NewPidFileFn returns a function that retrieves a pid from the specified file.
|
||||
// It is meant to be used for the PidFn field in ProcessCollectorOpts.
|
||||
func NewPidFileFn(pidFilePath string) func() (int, error) {
|
||||
return func() (int, error) {
|
||||
content, err := ioutil.ReadFile(pidFilePath)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("can't read pid file %q: %+v", pidFilePath, err)
|
||||
}
|
||||
pid, err := strconv.Atoi(strings.TrimSpace(string(content)))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("can't parse pid file %q: %+v", pidFilePath, err)
|
||||
}
|
||||
|
||||
return pid, nil
|
||||
}
|
||||
}
|
||||
|
10
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
generated
vendored
10
vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go
generated
vendored
@ -99,7 +99,7 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler {
|
||||
inFlightSem = make(chan struct{}, opts.MaxRequestsInFlight)
|
||||
}
|
||||
if opts.Registry != nil {
|
||||
// Initialize all possibilites that can occur below.
|
||||
// Initialize all possibilities that can occur below.
|
||||
errCnt.WithLabelValues("gathering")
|
||||
errCnt.WithLabelValues("encoding")
|
||||
if err := opts.Registry.Register(errCnt); err != nil {
|
||||
@ -303,8 +303,12 @@ type Logger interface {
|
||||
// HandlerOpts specifies options how to serve metrics via an http.Handler. The
|
||||
// zero value of HandlerOpts is a reasonable default.
|
||||
type HandlerOpts struct {
|
||||
// ErrorLog specifies an optional logger for errors collecting and
|
||||
// serving metrics. If nil, errors are not logged at all.
|
||||
// ErrorLog specifies an optional Logger for errors collecting and
|
||||
// serving metrics. If nil, errors are not logged at all. Note that the
|
||||
// type of a reported error is often prometheus.MultiError, which
|
||||
// formats into a multi-line error string. If you want to avoid the
|
||||
// latter, create a Logger implementation that detects a
|
||||
// prometheus.MultiError and formats the contained errors into one line.
|
||||
ErrorLog Logger
|
||||
// ErrorHandling defines how errors are handled. Note that errors are
|
||||
// logged regardless of the configured ErrorHandling provided ErrorLog
|
||||
|
91
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
91
vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go
generated
vendored
@ -43,14 +43,14 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl
|
||||
|
||||
// InstrumentHandlerDuration is a middleware that wraps the provided
|
||||
// http.Handler to observe the request duration with the provided ObserverVec.
|
||||
// The ObserverVec must have zero, one, or two non-const non-curried labels. For
|
||||
// those, the only allowed label names are "code" and "method". The function
|
||||
// panics otherwise. The Observe method of the Observer in the ObserverVec is
|
||||
// called with the request duration in seconds. Partitioning happens by HTTP
|
||||
// status code and/or HTTP method if the respective instance label names are
|
||||
// present in the ObserverVec. For unpartitioned observations, use an
|
||||
// ObserverVec with zero labels. Note that partitioning of Histograms is
|
||||
// expensive and should be used judiciously.
|
||||
// The ObserverVec must have valid metric and label names and must have zero,
|
||||
// one, or two non-const non-curried labels. For those, the only allowed label
|
||||
// names are "code" and "method". The function panics otherwise. The Observe
|
||||
// method of the Observer in the ObserverVec is called with the request duration
|
||||
// in seconds. Partitioning happens by HTTP status code and/or HTTP method if
|
||||
// the respective instance label names are present in the ObserverVec. For
|
||||
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||
// partitioning of Histograms is expensive and should be used judiciously.
|
||||
//
|
||||
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
||||
//
|
||||
@ -79,12 +79,13 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler) ht
|
||||
}
|
||||
|
||||
// InstrumentHandlerCounter is a middleware that wraps the provided http.Handler
|
||||
// to observe the request result with the provided CounterVec. The CounterVec
|
||||
// must have zero, one, or two non-const non-curried labels. For those, the only
|
||||
// allowed label names are "code" and "method". The function panics
|
||||
// otherwise. Partitioning of the CounterVec happens by HTTP status code and/or
|
||||
// HTTP method if the respective instance label names are present in the
|
||||
// CounterVec. For unpartitioned counting, use a CounterVec with zero labels.
|
||||
// to observe the request result with the provided CounterVec. The CounterVec
|
||||
// must have valid metric and label names and must have zero, one, or two
|
||||
// non-const non-curried labels. For those, the only allowed label names are
|
||||
// "code" and "method". The function panics otherwise. Partitioning of the
|
||||
// CounterVec happens by HTTP status code and/or HTTP method if the respective
|
||||
// instance label names are present in the CounterVec. For unpartitioned
|
||||
// counting, use a CounterVec with zero labels.
|
||||
//
|
||||
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
||||
//
|
||||
@ -110,14 +111,15 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler)
|
||||
|
||||
// InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided
|
||||
// http.Handler to observe with the provided ObserverVec the request duration
|
||||
// until the response headers are written. The ObserverVec must have zero, one,
|
||||
// or two non-const non-curried labels. For those, the only allowed label names
|
||||
// are "code" and "method". The function panics otherwise. The Observe method of
|
||||
// the Observer in the ObserverVec is called with the request duration in
|
||||
// seconds. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||
// respective instance label names are present in the ObserverVec. For
|
||||
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||
// partitioning of Histograms is expensive and should be used judiciously.
|
||||
// until the response headers are written. The ObserverVec must have valid
|
||||
// metric and label names and must have zero, one, or two non-const non-curried
|
||||
// labels. For those, the only allowed label names are "code" and "method". The
|
||||
// function panics otherwise. The Observe method of the Observer in the
|
||||
// ObserverVec is called with the request duration in seconds. Partitioning
|
||||
// happens by HTTP status code and/or HTTP method if the respective instance
|
||||
// label names are present in the ObserverVec. For unpartitioned observations,
|
||||
// use an ObserverVec with zero labels. Note that partitioning of Histograms is
|
||||
// expensive and should be used judiciously.
|
||||
//
|
||||
// If the wrapped Handler panics before calling WriteHeader, no value is
|
||||
// reported.
|
||||
@ -139,15 +141,15 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
|
||||
}
|
||||
|
||||
// InstrumentHandlerRequestSize is a middleware that wraps the provided
|
||||
// http.Handler to observe the request size with the provided ObserverVec. The
|
||||
// ObserverVec must have zero, one, or two non-const non-curried labels. For
|
||||
// those, the only allowed label names are "code" and "method". The function
|
||||
// panics otherwise. The Observe method of the Observer in the ObserverVec is
|
||||
// called with the request size in bytes. Partitioning happens by HTTP status
|
||||
// code and/or HTTP method if the respective instance label names are present in
|
||||
// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
|
||||
// labels. Note that partitioning of Histograms is expensive and should be used
|
||||
// judiciously.
|
||||
// http.Handler to observe the request size with the provided ObserverVec. The
|
||||
// ObserverVec must have valid metric and label names and must have zero, one,
|
||||
// or two non-const non-curried labels. For those, the only allowed label names
|
||||
// are "code" and "method". The function panics otherwise. The Observe method of
|
||||
// the Observer in the ObserverVec is called with the request size in
|
||||
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||
// respective instance label names are present in the ObserverVec. For
|
||||
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||
// partitioning of Histograms is expensive and should be used judiciously.
|
||||
//
|
||||
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
||||
//
|
||||
@ -174,15 +176,15 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler)
|
||||
}
|
||||
|
||||
// InstrumentHandlerResponseSize is a middleware that wraps the provided
|
||||
// http.Handler to observe the response size with the provided ObserverVec. The
|
||||
// ObserverVec must have zero, one, or two non-const non-curried labels. For
|
||||
// those, the only allowed label names are "code" and "method". The function
|
||||
// panics otherwise. The Observe method of the Observer in the ObserverVec is
|
||||
// called with the response size in bytes. Partitioning happens by HTTP status
|
||||
// code and/or HTTP method if the respective instance label names are present in
|
||||
// the ObserverVec. For unpartitioned observations, use an ObserverVec with zero
|
||||
// labels. Note that partitioning of Histograms is expensive and should be used
|
||||
// judiciously.
|
||||
// http.Handler to observe the response size with the provided ObserverVec. The
|
||||
// ObserverVec must have valid metric and label names and must have zero, one,
|
||||
// or two non-const non-curried labels. For those, the only allowed label names
|
||||
// are "code" and "method". The function panics otherwise. The Observe method of
|
||||
// the Observer in the ObserverVec is called with the response size in
|
||||
// bytes. Partitioning happens by HTTP status code and/or HTTP method if the
|
||||
// respective instance label names are present in the ObserverVec. For
|
||||
// unpartitioned observations, use an ObserverVec with zero labels. Note that
|
||||
// partitioning of Histograms is expensive and should be used judiciously.
|
||||
//
|
||||
// If the wrapped Handler does not set a status code, a status code of 200 is assumed.
|
||||
//
|
||||
@ -198,6 +200,11 @@ func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler
|
||||
})
|
||||
}
|
||||
|
||||
// checkLabels returns whether the provided Collector has a non-const,
|
||||
// non-curried label named "code" and/or "method". It panics if the provided
|
||||
// Collector does not have a Desc or has more than one Desc or its Desc is
|
||||
// invalid. It also panics if the Collector has any non-const, non-curried
|
||||
// labels that are not named "code" or "method".
|
||||
func checkLabels(c prometheus.Collector) (code bool, method bool) {
|
||||
// TODO(beorn7): Remove this hacky way to check for instance labels
|
||||
// once Descriptors can have their dimensionality queried.
|
||||
@ -225,6 +232,10 @@ func checkLabels(c prometheus.Collector) (code bool, method bool) {
|
||||
|
||||
close(descc)
|
||||
|
||||
// Make sure the Collector has a valid Desc by registering it with a
|
||||
// temporary registry.
|
||||
prometheus.NewRegistry().MustRegister(c)
|
||||
|
||||
// Create a ConstMetric with the Desc. Since we don't know how many
|
||||
// variable labels there are, try for as long as it needs.
|
||||
for err := errors.New("dummy"); err != nil; lvs = append(lvs, magicString) {
|
||||
|
2
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
2
vendor/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
@ -215,6 +215,8 @@ func (err AlreadyRegisteredError) Error() string {
|
||||
// by a Gatherer to report multiple errors during MetricFamily gathering.
|
||||
type MultiError []error
|
||||
|
||||
// Error formats the contained errors as a bullet point list, preceded by the
|
||||
// total number of errors. Note that this results in a multi-line string.
|
||||
func (errs MultiError) Error() string {
|
||||
if len(errs) == 0 {
|
||||
return ""
|
||||
|
26
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
26
vendor/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
@ -110,7 +110,7 @@ type SummaryOpts struct {
|
||||
// better covered by target labels set by the scraping Prometheus
|
||||
// server, or by one specific metric (e.g. a build_info or a
|
||||
// machine_role metric). See also
|
||||
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels,-not-static-scraped-labels
|
||||
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
|
||||
ConstLabels Labels
|
||||
|
||||
// Objectives defines the quantile rank estimates with their respective
|
||||
@ -208,7 +208,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
||||
// Use the lock-free implementation of a Summary without objectives.
|
||||
s := &noObjectivesSummary{
|
||||
desc: desc,
|
||||
labelPairs: makeLabelPairs(desc, labelValues),
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
counts: [2]*summaryCounts{{}, {}},
|
||||
}
|
||||
s.init(s) // Init self-collection.
|
||||
@ -221,7 +221,7 @@ func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
|
||||
objectives: opts.Objectives,
|
||||
sortedObjectives: make([]float64, 0, len(opts.Objectives)),
|
||||
|
||||
labelPairs: makeLabelPairs(desc, labelValues),
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
|
||||
hotBuf: make([]float64, 0, opts.BufCap),
|
||||
coldBuf: make([]float64, 0, opts.BufCap),
|
||||
@ -513,7 +513,7 @@ func (s quantSort) Less(i, j int) bool {
|
||||
// (e.g. HTTP request latencies, partitioned by status code and method). Create
|
||||
// instances with NewSummaryVec.
|
||||
type SummaryVec struct {
|
||||
*metricVec
|
||||
*MetricVec
|
||||
}
|
||||
|
||||
// NewSummaryVec creates a new SummaryVec based on the provided SummaryOpts and
|
||||
@ -535,14 +535,14 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
||||
opts.ConstLabels,
|
||||
)
|
||||
return &SummaryVec{
|
||||
metricVec: newMetricVec(desc, func(lvs ...string) Metric {
|
||||
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
|
||||
return newSummary(desc, opts, lvs...)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// GetMetricWithLabelValues returns the Summary for the given slice of label
|
||||
// values (same order as the VariableLabels in Desc). If that combination of
|
||||
// values (same order as the variable labels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new Summary is created.
|
||||
//
|
||||
// It is possible to call this method without using the returned Summary to only
|
||||
@ -557,7 +557,7 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
||||
// example.
|
||||
//
|
||||
// An error is returned if the number of label values is not the same as the
|
||||
// number of VariableLabels in Desc (minus any curried labels).
|
||||
// number of variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// Note that for more than one label value, this method is prone to mistakes
|
||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||
@ -566,7 +566,7 @@ func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
|
||||
// with a performance overhead (for creating and processing the Labels map).
|
||||
// See also the GaugeVec example.
|
||||
func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
|
||||
metric, err := v.metricVec.getMetricWithLabelValues(lvs...)
|
||||
metric, err := v.MetricVec.GetMetricWithLabelValues(lvs...)
|
||||
if metric != nil {
|
||||
return metric.(Observer), err
|
||||
}
|
||||
@ -574,19 +574,19 @@ func (v *SummaryVec) GetMetricWithLabelValues(lvs ...string) (Observer, error) {
|
||||
}
|
||||
|
||||
// GetMetricWith returns the Summary for the given Labels map (the label names
|
||||
// must match those of the VariableLabels in Desc). If that label map is
|
||||
// must match those of the variable labels in Desc). If that label map is
|
||||
// accessed for the first time, a new Summary is created. Implications of
|
||||
// creating a Summary without using it and keeping the Summary for later use are
|
||||
// the same as for GetMetricWithLabelValues.
|
||||
//
|
||||
// An error is returned if the number and names of the Labels are inconsistent
|
||||
// with those of the VariableLabels in Desc (minus any curried labels).
|
||||
// with those of the variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// This method is used for the same purpose as
|
||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||
// methods.
|
||||
func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) {
|
||||
metric, err := v.metricVec.getMetricWith(labels)
|
||||
metric, err := v.MetricVec.GetMetricWith(labels)
|
||||
if metric != nil {
|
||||
return metric.(Observer), err
|
||||
}
|
||||
@ -630,7 +630,7 @@ func (v *SummaryVec) With(labels Labels) Observer {
|
||||
// registered with a given registry (usually the uncurried version). The Reset
|
||||
// method deletes all metrics, even if called on a curried vector.
|
||||
func (v *SummaryVec) CurryWith(labels Labels) (ObserverVec, error) {
|
||||
vec, err := v.curryWith(labels)
|
||||
vec, err := v.MetricVec.CurryWith(labels)
|
||||
if vec != nil {
|
||||
return &SummaryVec{vec}, err
|
||||
}
|
||||
@ -716,7 +716,7 @@ func NewConstSummary(
|
||||
count: count,
|
||||
sum: sum,
|
||||
quantiles: quantiles,
|
||||
labelPairs: makeLabelPairs(desc, labelValues),
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
13
vendor/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
13
vendor/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
@ -63,7 +63,7 @@ func newValueFunc(desc *Desc, valueType ValueType, function func() float64) *val
|
||||
desc: desc,
|
||||
valType: valueType,
|
||||
function: function,
|
||||
labelPairs: makeLabelPairs(desc, nil),
|
||||
labelPairs: MakeLabelPairs(desc, nil),
|
||||
}
|
||||
result.init(result)
|
||||
return result
|
||||
@ -95,7 +95,7 @@ func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues
|
||||
desc: desc,
|
||||
valType: valueType,
|
||||
val: value,
|
||||
labelPairs: makeLabelPairs(desc, labelValues),
|
||||
labelPairs: MakeLabelPairs(desc, labelValues),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -145,7 +145,14 @@ func populateMetric(
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
|
||||
// MakeLabelPairs is a helper function to create protobuf LabelPairs from the
|
||||
// variable and constant labels in the provided Desc. The values for the
|
||||
// variable labels are defined by the labelValues slice, which must be in the
|
||||
// same order as the corresponding variable labels in the Desc.
|
||||
//
|
||||
// This function is only needed for custom Metric implementations. See MetricVec
|
||||
// example.
|
||||
func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
|
||||
totalLen := len(desc.variableLabels) + len(desc.constLabelPairs)
|
||||
if totalLen == 0 {
|
||||
// Super fast path.
|
||||
|
112
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
112
vendor/github.com/prometheus/client_golang/prometheus/vec.go
generated
vendored
@ -20,12 +20,20 @@ import (
|
||||
"github.com/prometheus/common/model"
|
||||
)
|
||||
|
||||
// metricVec is a Collector to bundle metrics of the same name that differ in
|
||||
// their label values. metricVec is not used directly (and therefore
|
||||
// unexported). It is used as a building block for implementations of vectors of
|
||||
// a given metric type, like GaugeVec, CounterVec, SummaryVec, and HistogramVec.
|
||||
// It also handles label currying.
|
||||
type metricVec struct {
|
||||
// MetricVec is a Collector to bundle metrics of the same name that differ in
|
||||
// their label values. MetricVec is not used directly but as a building block
|
||||
// for implementations of vectors of a given metric type, like GaugeVec,
|
||||
// CounterVec, SummaryVec, and HistogramVec. It is exported so that it can be
|
||||
// used for custom Metric implementations.
|
||||
//
|
||||
// To create a FooVec for custom Metric Foo, embed a pointer to MetricVec in
|
||||
// FooVec and initialize it with NewMetricVec. Implement wrappers for
|
||||
// GetMetricWithLabelValues and GetMetricWith that return (Foo, error) rather
|
||||
// than (Metric, error). Similarly, create a wrapper for CurryWith that returns
|
||||
// (*FooVec, error) rather than (*MetricVec, error). It is recommended to also
|
||||
// add the convenience methods WithLabelValues, With, and MustCurryWith, which
|
||||
// panic instead of returning errors. See also the MetricVec example.
|
||||
type MetricVec struct {
|
||||
*metricMap
|
||||
|
||||
curry []curriedLabelValue
|
||||
@ -35,9 +43,9 @@ type metricVec struct {
|
||||
hashAddByte func(h uint64, b byte) uint64
|
||||
}
|
||||
|
||||
// newMetricVec returns an initialized metricVec.
|
||||
func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
|
||||
return &metricVec{
|
||||
// NewMetricVec returns an initialized metricVec.
|
||||
func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec {
|
||||
return &MetricVec{
|
||||
metricMap: &metricMap{
|
||||
metrics: map[uint64][]metricWithLabelValues{},
|
||||
desc: desc,
|
||||
@ -63,7 +71,7 @@ func newMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *metricVec {
|
||||
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
||||
// with a performance overhead (for creating and processing the Labels map).
|
||||
// See also the CounterVec example.
|
||||
func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
|
||||
func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
|
||||
h, err := m.hashLabelValues(lvs)
|
||||
if err != nil {
|
||||
return false
|
||||
@ -82,7 +90,7 @@ func (m *metricVec) DeleteLabelValues(lvs ...string) bool {
|
||||
//
|
||||
// This method is used for the same purpose as DeleteLabelValues(...string). See
|
||||
// there for pros and cons of the two methods.
|
||||
func (m *metricVec) Delete(labels Labels) bool {
|
||||
func (m *MetricVec) Delete(labels Labels) bool {
|
||||
h, err := m.hashLabels(labels)
|
||||
if err != nil {
|
||||
return false
|
||||
@ -95,15 +103,32 @@ func (m *metricVec) Delete(labels Labels) bool {
|
||||
// show up in GoDoc.
|
||||
|
||||
// Describe implements Collector.
|
||||
func (m *metricVec) Describe(ch chan<- *Desc) { m.metricMap.Describe(ch) }
|
||||
func (m *MetricVec) Describe(ch chan<- *Desc) { m.metricMap.Describe(ch) }
|
||||
|
||||
// Collect implements Collector.
|
||||
func (m *metricVec) Collect(ch chan<- Metric) { m.metricMap.Collect(ch) }
|
||||
func (m *MetricVec) Collect(ch chan<- Metric) { m.metricMap.Collect(ch) }
|
||||
|
||||
// Reset deletes all metrics in this vector.
|
||||
func (m *metricVec) Reset() { m.metricMap.Reset() }
|
||||
func (m *MetricVec) Reset() { m.metricMap.Reset() }
|
||||
|
||||
func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
|
||||
// CurryWith returns a vector curried with the provided labels, i.e. the
|
||||
// returned vector has those labels pre-set for all labeled operations performed
|
||||
// on it. The cardinality of the curried vector is reduced accordingly. The
|
||||
// order of the remaining labels stays the same (just with the curried labels
|
||||
// taken out of the sequence – which is relevant for the
|
||||
// (GetMetric)WithLabelValues methods). It is possible to curry a curried
|
||||
// vector, but only with labels not yet used for currying before.
|
||||
//
|
||||
// The metrics contained in the MetricVec are shared between the curried and
|
||||
// uncurried vectors. They are just accessed differently. Curried and uncurried
|
||||
// vectors behave identically in terms of collection. Only one must be
|
||||
// registered with a given registry (usually the uncurried version). The Reset
|
||||
// method deletes all metrics, even if called on a curried vector.
|
||||
//
|
||||
// Note that CurryWith is usually not called directly but through a wrapper
|
||||
// around MetricVec, implementing a vector for a specific Metric
|
||||
// implementation, for example GaugeVec.
|
||||
func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
|
||||
var (
|
||||
newCurry []curriedLabelValue
|
||||
oldCurry = m.curry
|
||||
@ -128,7 +153,7 @@ func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
|
||||
return nil, fmt.Errorf("%d unknown label(s) found during currying", l)
|
||||
}
|
||||
|
||||
return &metricVec{
|
||||
return &MetricVec{
|
||||
metricMap: m.metricMap,
|
||||
curry: newCurry,
|
||||
hashAdd: m.hashAdd,
|
||||
@ -136,7 +161,34 @@ func (m *metricVec) curryWith(labels Labels) (*metricVec, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
|
||||
// GetMetricWithLabelValues returns the Metric for the given slice of label
|
||||
// values (same order as the variable labels in Desc). If that combination of
|
||||
// label values is accessed for the first time, a new Metric is created (by
|
||||
// calling the newMetric function provided during construction of the
|
||||
// MetricVec).
|
||||
//
|
||||
// It is possible to call this method without using the returned Metry to only
|
||||
// create the new Metric but leave it in its intitial state.
|
||||
//
|
||||
// Keeping the Metric for later use is possible (and should be considered if
|
||||
// performance is critical), but keep in mind that Reset, DeleteLabelValues and
|
||||
// Delete can be used to delete the Metric from the MetricVec. In that case, the
|
||||
// Metric will still exist, but it will not be exported anymore, even if a
|
||||
// Metric with the same label values is created later.
|
||||
//
|
||||
// An error is returned if the number of label values is not the same as the
|
||||
// number of variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// Note that for more than one label value, this method is prone to mistakes
|
||||
// caused by an incorrect order of arguments. Consider GetMetricWith(Labels) as
|
||||
// an alternative to avoid that type of mistake. For higher label numbers, the
|
||||
// latter has a much more readable (albeit more verbose) syntax, but it comes
|
||||
// with a performance overhead (for creating and processing the Labels map).
|
||||
//
|
||||
// Note that GetMetricWithLabelValues is usually not called directly but through
|
||||
// a wrapper around MetricVec, implementing a vector for a specific Metric
|
||||
// implementation, for example GaugeVec.
|
||||
func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
|
||||
h, err := m.hashLabelValues(lvs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -145,7 +197,23 @@ func (m *metricVec) getMetricWithLabelValues(lvs ...string) (Metric, error) {
|
||||
return m.metricMap.getOrCreateMetricWithLabelValues(h, lvs, m.curry), nil
|
||||
}
|
||||
|
||||
func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
|
||||
// GetMetricWith returns the Metric for the given Labels map (the label names
|
||||
// must match those of the variable labels in Desc). If that label map is
|
||||
// accessed for the first time, a new Metric is created. Implications of
|
||||
// creating a Metric without using it and keeping the Metric for later use
|
||||
// are the same as for GetMetricWithLabelValues.
|
||||
//
|
||||
// An error is returned if the number and names of the Labels are inconsistent
|
||||
// with those of the variable labels in Desc (minus any curried labels).
|
||||
//
|
||||
// This method is used for the same purpose as
|
||||
// GetMetricWithLabelValues(...string). See there for pros and cons of the two
|
||||
// methods.
|
||||
//
|
||||
// Note that GetMetricWith is usually not called directly but through a wrapper
|
||||
// around MetricVec, implementing a vector for a specific Metric implementation,
|
||||
// for example GaugeVec.
|
||||
func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
|
||||
h, err := m.hashLabels(labels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -154,7 +222,7 @@ func (m *metricVec) getMetricWith(labels Labels) (Metric, error) {
|
||||
return m.metricMap.getOrCreateMetricWithLabels(h, labels, m.curry), nil
|
||||
}
|
||||
|
||||
func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
|
||||
func (m *MetricVec) hashLabelValues(vals []string) (uint64, error) {
|
||||
if err := validateLabelValues(vals, len(m.desc.variableLabels)-len(m.curry)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -177,7 +245,7 @@ func (m *metricVec) hashLabelValues(vals []string) (uint64, error) {
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (m *metricVec) hashLabels(labels Labels) (uint64, error) {
|
||||
func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
|
||||
if err := validateValuesInLabels(labels, len(m.desc.variableLabels)-len(m.curry)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -276,7 +344,9 @@ func (m *metricMap) deleteByHashWithLabelValues(
|
||||
}
|
||||
|
||||
if len(metrics) > 1 {
|
||||
old := metrics
|
||||
m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
|
||||
old[len(old)-1] = metricWithLabelValues{}
|
||||
} else {
|
||||
delete(m.metrics, h)
|
||||
}
|
||||
@ -302,7 +372,9 @@ func (m *metricMap) deleteByHashWithLabels(
|
||||
}
|
||||
|
||||
if len(metrics) > 1 {
|
||||
old := metrics
|
||||
m.metrics[h] = append(metrics[:i], metrics[i+1:]...)
|
||||
old[len(old)-1] = metricWithLabelValues{}
|
||||
} else {
|
||||
delete(m.metrics, h)
|
||||
}
|
||||
|
4
vendor/github.com/prometheus/client_golang/prometheus/wrap.go
generated
vendored
4
vendor/github.com/prometheus/client_golang/prometheus/wrap.go
generated
vendored
@ -32,7 +32,9 @@ import (
|
||||
// in a no-op Registerer.
|
||||
//
|
||||
// WrapRegistererWith provides a way to add fixed labels to a subset of
|
||||
// Collectors. It should not be used to add fixed labels to all metrics exposed.
|
||||
// Collectors. It should not be used to add fixed labels to all metrics
|
||||
// exposed. See also
|
||||
// https://prometheus.io/docs/instrumenting/writing_exporters/#target-labels-not-static-scraped-labels
|
||||
//
|
||||
// Conflicts between Collectors registered through the original Registerer with
|
||||
// Collectors registered through the wrapping Registerer will still be
|
||||
|
11
vendor/github.com/prometheus/common/expfmt/text_parse.go
generated
vendored
11
vendor/github.com/prometheus/common/expfmt/text_parse.go
generated
vendored
@ -299,6 +299,17 @@ func (p *TextParser) startLabelName() stateFn {
|
||||
p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
|
||||
return nil
|
||||
}
|
||||
// Check for duplicate label names.
|
||||
labels := make(map[string]struct{})
|
||||
for _, l := range p.currentMetric.Label {
|
||||
lName := l.GetName()
|
||||
if _, exists := labels[lName]; !exists {
|
||||
labels[lName] = struct{}{}
|
||||
} else {
|
||||
p.parseError(fmt.Sprintf("duplicate label names for metric %q", p.currentMF.GetName()))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return p.startLabelValue
|
||||
}
|
||||
|
||||
|
3
vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md
generated
vendored
Normal file
3
vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
## Prometheus Community Code of Conduct
|
||||
|
||||
Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
44
vendor/github.com/prometheus/procfs/cpuinfo.go
generated
vendored
44
vendor/github.com/prometheus/procfs/cpuinfo.go
generated
vendored
@ -407,6 +407,50 @@ func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) {
|
||||
return cpuinfo, nil
|
||||
}
|
||||
|
||||
func parseCPUInfoRISCV(info []byte) ([]CPUInfo, error) {
|
||||
scanner := bufio.NewScanner(bytes.NewReader(info))
|
||||
|
||||
firstLine := firstNonEmptyLine(scanner)
|
||||
if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") {
|
||||
return nil, errors.New("invalid cpuinfo file: " + firstLine)
|
||||
}
|
||||
field := strings.SplitN(firstLine, ": ", 2)
|
||||
v, err := strconv.ParseUint(field[1], 0, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
firstcpu := CPUInfo{Processor: uint(v)}
|
||||
cpuinfo := []CPUInfo{firstcpu}
|
||||
i := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if !strings.Contains(line, ":") {
|
||||
continue
|
||||
}
|
||||
field := strings.SplitN(line, ": ", 2)
|
||||
switch strings.TrimSpace(field[0]) {
|
||||
case "processor":
|
||||
v, err := strconv.ParseUint(field[1], 0, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i = int(v)
|
||||
cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor
|
||||
cpuinfo[i].Processor = uint(v)
|
||||
case "hart":
|
||||
cpuinfo[i].CoreID = field[1]
|
||||
case "isa":
|
||||
cpuinfo[i].ModelName = field[1]
|
||||
}
|
||||
}
|
||||
return cpuinfo, nil
|
||||
}
|
||||
|
||||
func parseCPUInfoDummy(_ []byte) ([]CPUInfo, error) { // nolint:unused,deadcode
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// firstNonEmptyLine advances the scanner to the first non-empty line
|
||||
// and returns the contents of that line
|
||||
func firstNonEmptyLine(scanner *bufio.Scanner) string {
|
||||
|
19
vendor/github.com/prometheus/procfs/cpuinfo_arm64.go
generated
vendored
19
vendor/github.com/prometheus/procfs/cpuinfo_arm64.go
generated
vendored
@ -1,19 +0,0 @@
|
||||
// Copyright 2020 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
// +build arm64
|
||||
|
||||
package procfs
|
||||
|
||||
var parseCPUInfo = parseCPUInfoARM
|
@ -12,6 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
// +build arm arm64
|
||||
|
||||
package procfs
|
||||
|
18
vendor/github.com/prometheus/procfs/cpuinfo_mips64le.go
generated
vendored
18
vendor/github.com/prometheus/procfs/cpuinfo_mips64le.go
generated
vendored
@ -1,18 +0,0 @@
|
||||
// Copyright 2020 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
|
||||
package procfs
|
||||
|
||||
var parseCPUInfo = parseCPUInfoMips
|
18
vendor/github.com/prometheus/procfs/cpuinfo_mipsle.go
generated
vendored
18
vendor/github.com/prometheus/procfs/cpuinfo_mipsle.go
generated
vendored
@ -1,18 +0,0 @@
|
||||
// Copyright 2020 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
|
||||
package procfs
|
||||
|
||||
var parseCPUInfo = parseCPUInfoMips
|
@ -12,6 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
// +build mips mipsle mips64 mips64le
|
||||
|
||||
package procfs
|
||||
|
@ -12,7 +12,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
// +build !386,!amd64,!arm,!arm64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x
|
||||
|
||||
package procfs
|
||||
|
||||
var parseCPUInfo = parseCPUInfoMips
|
||||
var parseCPUInfo = parseCPUInfoDummy
|
18
vendor/github.com/prometheus/procfs/cpuinfo_ppc64le.go
generated
vendored
18
vendor/github.com/prometheus/procfs/cpuinfo_ppc64le.go
generated
vendored
@ -1,18 +0,0 @@
|
||||
// Copyright 2020 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
|
||||
package procfs
|
||||
|
||||
var parseCPUInfo = parseCPUInfoPPC
|
@ -12,6 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
// +build linux
|
||||
// +build ppc64 ppc64le
|
||||
|
||||
package procfs
|
||||
|
75
vendor/github.com/prometheus/procfs/fixtures.ttar
generated
vendored
75
vendor/github.com/prometheus/procfs/fixtures.ttar
generated
vendored
@ -467,7 +467,7 @@ Pid: 26231
|
||||
PPid: 1
|
||||
TracerPid: 0
|
||||
Uid: 1000 1000 1000 0
|
||||
Gid: 0 0 0 0
|
||||
Gid: 1001 1001 1001 0
|
||||
FDSize: 128
|
||||
Groups:
|
||||
NStgid: 1
|
||||
@ -1966,7 +1966,7 @@ Lines: 1
|
||||
Mode: 444
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/proc/mdstat
|
||||
Lines: 56
|
||||
Lines: 60
|
||||
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
|
||||
|
||||
md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] sdd1[10](S) sdd2[11](S)
|
||||
@ -1989,6 +1989,10 @@ md8 : active raid1 sdb1[1] sda1[0] sdc[2](S) sde[3](S)
|
||||
195310144 blocks [2/2] [UU]
|
||||
[=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec
|
||||
|
||||
md201 : active raid1 sda3[0] sdb3[1]
|
||||
1993728 blocks super 1.2 [2/2] [UU]
|
||||
[=>...................] check = 5.7% (114176/1993728) finish=0.2min speed=114176K/sec
|
||||
|
||||
md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1](F)
|
||||
7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU]
|
||||
bitmap: 0/30 pages [0KB], 65536KB chunk
|
||||
@ -3754,6 +3758,73 @@ Path: fixtures/sys/class/powercap/intel-rapl:0:0/uevent
|
||||
Lines: 0
|
||||
Mode: 644
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Directory: fixtures/sys/class/powercap/intel-rapl:a
|
||||
Mode: 755
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_max_power_uw
|
||||
Lines: 1
|
||||
95000000
|
||||
Mode: 444
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_name
|
||||
Lines: 1
|
||||
long_term
|
||||
Mode: 444
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_power_limit_uw
|
||||
Lines: 1
|
||||
4090000000
|
||||
Mode: 644
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_time_window_us
|
||||
Lines: 1
|
||||
999424
|
||||
Mode: 644
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_max_power_uw
|
||||
Lines: 1
|
||||
0
|
||||
Mode: 444
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_name
|
||||
Lines: 1
|
||||
short_term
|
||||
Mode: 444
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_power_limit_uw
|
||||
Lines: 1
|
||||
4090000000
|
||||
Mode: 644
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_time_window_us
|
||||
Lines: 1
|
||||
2440
|
||||
Mode: 644
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/enabled
|
||||
Lines: 1
|
||||
1
|
||||
Mode: 644
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/energy_uj
|
||||
Lines: 1
|
||||
240422366267
|
||||
Mode: 444
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/max_energy_range_uj
|
||||
Lines: 1
|
||||
262143328850
|
||||
Mode: 444
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/name
|
||||
Lines: 1
|
||||
package-10
|
||||
Mode: 444
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Path: fixtures/sys/class/powercap/intel-rapl:a/uevent
|
||||
Lines: 0
|
||||
Mode: 644
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Directory: fixtures/sys/class/thermal
|
||||
Mode: 775
|
||||
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
2
vendor/github.com/prometheus/procfs/kernel_random.go
generated
vendored
2
vendor/github.com/prometheus/procfs/kernel_random.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
type KernelRandom struct {
|
||||
// EntropyAvaliable gives the available entropy, in bits.
|
||||
EntropyAvaliable *uint64
|
||||
// PoolSize gives the size of the entropy pool, in bytes.
|
||||
// PoolSize gives the size of the entropy pool, in bits.
|
||||
PoolSize *uint64
|
||||
// URandomMinReseedSeconds is the number of seconds after which the DRNG will be reseeded.
|
||||
URandomMinReseedSeconds *uint64
|
||||
|
5
vendor/github.com/prometheus/procfs/mdstat.go
generated
vendored
5
vendor/github.com/prometheus/procfs/mdstat.go
generated
vendored
@ -107,11 +107,14 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) {
|
||||
syncedBlocks := size
|
||||
recovering := strings.Contains(lines[syncLineIdx], "recovery")
|
||||
resyncing := strings.Contains(lines[syncLineIdx], "resync")
|
||||
checking := strings.Contains(lines[syncLineIdx], "check")
|
||||
|
||||
// Append recovery and resyncing state info.
|
||||
if recovering || resyncing {
|
||||
if recovering || resyncing || checking {
|
||||
if recovering {
|
||||
state = "recovering"
|
||||
} else if checking {
|
||||
state = "checking"
|
||||
} else {
|
||||
state = "resyncing"
|
||||
}
|
||||
|
6
vendor/github.com/prometheus/procfs/proc_status.go
generated
vendored
6
vendor/github.com/prometheus/procfs/proc_status.go
generated
vendored
@ -72,8 +72,10 @@ type ProcStatus struct {
|
||||
// Number of involuntary context switches.
|
||||
NonVoluntaryCtxtSwitches uint64
|
||||
|
||||
// UIDs of the process (Real, effective, saved set, and filesystem UIDs (GIDs))
|
||||
// UIDs of the process (Real, effective, saved set, and filesystem UIDs)
|
||||
UIDs [4]string
|
||||
// GIDs of the process (Real, effective, saved set, and filesystem GIDs)
|
||||
GIDs [4]string
|
||||
}
|
||||
|
||||
// NewStatus returns the current status information of the process.
|
||||
@ -119,6 +121,8 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
|
||||
s.Name = vString
|
||||
case "Uid":
|
||||
copy(s.UIDs[:], strings.Split(vString, "\t"))
|
||||
case "Gid":
|
||||
copy(s.GIDs[:], strings.Split(vString, "\t"))
|
||||
case "VmPeak":
|
||||
s.VmPeak = vUintBytes
|
||||
case "VmSize":
|
||||
|
7
vendor/github.com/spf13/pflag/.travis.yml
generated
vendored
7
vendor/github.com/spf13/pflag/.travis.yml
generated
vendored
@ -3,8 +3,9 @@ sudo: false
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.7.3
|
||||
- 1.8.1
|
||||
- 1.9.x
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
@ -12,7 +13,7 @@ matrix:
|
||||
- go: tip
|
||||
|
||||
install:
|
||||
- go get github.com/golang/lint/golint
|
||||
- go get golang.org/x/lint/golint
|
||||
- export PATH=$GOPATH/bin:$PATH
|
||||
- go install ./...
|
||||
|
||||
|
4
vendor/github.com/spf13/pflag/README.md
generated
vendored
4
vendor/github.com/spf13/pflag/README.md
generated
vendored
@ -86,8 +86,8 @@ fmt.Println("ip has value ", *ip)
|
||||
fmt.Println("flagvar has value ", flagvar)
|
||||
```
|
||||
|
||||
There are helpers function to get values later if you have the FlagSet but
|
||||
it was difficult to keep up with all of the flag pointers in your code.
|
||||
There are helper functions available to get the value stored in a Flag if you have a FlagSet but find
|
||||
it difficult to keep up with all of the pointers in your code.
|
||||
If you have a pflag.FlagSet with a flag called 'flagname' of type int you
|
||||
can use GetInt() to get the int value. But notice that 'flagname' must exist
|
||||
and it must be an int. GetString("flagname") will fail.
|
||||
|
38
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
38
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
@ -71,6 +71,44 @@ func (s *boolSliceValue) String() string {
|
||||
return "[" + out + "]"
|
||||
}
|
||||
|
||||
func (s *boolSliceValue) fromString(val string) (bool, error) {
|
||||
return strconv.ParseBool(val)
|
||||
}
|
||||
|
||||
func (s *boolSliceValue) toString(val bool) string {
|
||||
return strconv.FormatBool(val)
|
||||
}
|
||||
|
||||
func (s *boolSliceValue) Append(val string) error {
|
||||
i, err := s.fromString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *boolSliceValue) Replace(val []string) error {
|
||||
out := make([]bool, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = s.fromString(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *boolSliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = s.toString(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func boolSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
|
104
vendor/github.com/spf13/pflag/bytes.go
generated
vendored
104
vendor/github.com/spf13/pflag/bytes.go
generated
vendored
@ -1,6 +1,7 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
@ -9,10 +10,12 @@ import (
|
||||
// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded
|
||||
type bytesHexValue []byte
|
||||
|
||||
// String implements pflag.Value.String.
|
||||
func (bytesHex bytesHexValue) String() string {
|
||||
return fmt.Sprintf("%X", []byte(bytesHex))
|
||||
}
|
||||
|
||||
// Set implements pflag.Value.Set.
|
||||
func (bytesHex *bytesHexValue) Set(value string) error {
|
||||
bin, err := hex.DecodeString(strings.TrimSpace(value))
|
||||
|
||||
@ -25,6 +28,7 @@ func (bytesHex *bytesHexValue) Set(value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type implements pflag.Value.Type.
|
||||
func (*bytesHexValue) Type() string {
|
||||
return "bytesHex"
|
||||
}
|
||||
@ -103,3 +107,103 @@ func BytesHex(name string, value []byte, usage string) *[]byte {
|
||||
func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
|
||||
return CommandLine.BytesHexP(name, shorthand, value, usage)
|
||||
}
|
||||
|
||||
// BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded
|
||||
type bytesBase64Value []byte
|
||||
|
||||
// String implements pflag.Value.String.
|
||||
func (bytesBase64 bytesBase64Value) String() string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(bytesBase64))
|
||||
}
|
||||
|
||||
// Set implements pflag.Value.Set.
|
||||
func (bytesBase64 *bytesBase64Value) Set(value string) error {
|
||||
bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*bytesBase64 = bin
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type implements pflag.Value.Type.
|
||||
func (*bytesBase64Value) Type() string {
|
||||
return "bytesBase64"
|
||||
}
|
||||
|
||||
func newBytesBase64Value(val []byte, p *[]byte) *bytesBase64Value {
|
||||
*p = val
|
||||
return (*bytesBase64Value)(p)
|
||||
}
|
||||
|
||||
func bytesBase64ValueConv(sval string) (interface{}, error) {
|
||||
|
||||
bin, err := base64.StdEncoding.DecodeString(sval)
|
||||
if err == nil {
|
||||
return bin, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
|
||||
}
|
||||
|
||||
// GetBytesBase64 return the []byte value of a flag with the given name
|
||||
func (f *FlagSet) GetBytesBase64(name string) ([]byte, error) {
|
||||
val, err := f.getFlagType(name, "bytesBase64", bytesBase64ValueConv)
|
||||
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
|
||||
return val.([]byte), nil
|
||||
}
|
||||
|
||||
// BytesBase64Var defines an []byte flag with specified name, default value, and usage string.
|
||||
// The argument p points to an []byte variable in which to store the value of the flag.
|
||||
func (f *FlagSet) BytesBase64Var(p *[]byte, name string, value []byte, usage string) {
|
||||
f.VarP(newBytesBase64Value(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) {
|
||||
f.VarP(newBytesBase64Value(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// BytesBase64Var defines an []byte flag with specified name, default value, and usage string.
|
||||
// The argument p points to an []byte variable in which to store the value of the flag.
|
||||
func BytesBase64Var(p *[]byte, name string, value []byte, usage string) {
|
||||
CommandLine.VarP(newBytesBase64Value(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||
func BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) {
|
||||
CommandLine.VarP(newBytesBase64Value(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// BytesBase64 defines an []byte flag with specified name, default value, and usage string.
|
||||
// The return value is the address of an []byte variable that stores the value of the flag.
|
||||
func (f *FlagSet) BytesBase64(name string, value []byte, usage string) *[]byte {
|
||||
p := new([]byte)
|
||||
f.BytesBase64VarP(p, name, "", value, usage)
|
||||
return p
|
||||
}
|
||||
|
||||
// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte {
|
||||
p := new([]byte)
|
||||
f.BytesBase64VarP(p, name, shorthand, value, usage)
|
||||
return p
|
||||
}
|
||||
|
||||
// BytesBase64 defines an []byte flag with specified name, default value, and usage string.
|
||||
// The return value is the address of an []byte variable that stores the value of the flag.
|
||||
func BytesBase64(name string, value []byte, usage string) *[]byte {
|
||||
return CommandLine.BytesBase64P(name, "", value, usage)
|
||||
}
|
||||
|
||||
// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash.
|
||||
func BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte {
|
||||
return CommandLine.BytesBase64P(name, shorthand, value, usage)
|
||||
}
|
||||
|
4
vendor/github.com/spf13/pflag/count.go
generated
vendored
4
vendor/github.com/spf13/pflag/count.go
generated
vendored
@ -46,7 +46,7 @@ func (f *FlagSet) GetCount(name string) (int, error) {
|
||||
|
||||
// CountVar defines a count flag with specified name, default value, and usage string.
|
||||
// The argument p points to an int variable in which to store the value of the flag.
|
||||
// A count flag will add 1 to its value evey time it is found on the command line
|
||||
// A count flag will add 1 to its value every time it is found on the command line
|
||||
func (f *FlagSet) CountVar(p *int, name string, usage string) {
|
||||
f.CountVarP(p, name, "", usage)
|
||||
}
|
||||
@ -69,7 +69,7 @@ func CountVarP(p *int, name, shorthand string, usage string) {
|
||||
|
||||
// Count defines a count flag with specified name, default value, and usage string.
|
||||
// The return value is the address of an int variable that stores the value of the flag.
|
||||
// A count flag will add 1 to its value evey time it is found on the command line
|
||||
// A count flag will add 1 to its value every time it is found on the command line
|
||||
func (f *FlagSet) Count(name string, usage string) *int {
|
||||
p := new(int)
|
||||
f.CountVarP(p, name, "", usage)
|
||||
|
38
vendor/github.com/spf13/pflag/duration_slice.go
generated
vendored
38
vendor/github.com/spf13/pflag/duration_slice.go
generated
vendored
@ -51,6 +51,44 @@ func (s *durationSliceValue) String() string {
|
||||
return "[" + strings.Join(out, ",") + "]"
|
||||
}
|
||||
|
||||
func (s *durationSliceValue) fromString(val string) (time.Duration, error) {
|
||||
return time.ParseDuration(val)
|
||||
}
|
||||
|
||||
func (s *durationSliceValue) toString(val time.Duration) string {
|
||||
return fmt.Sprintf("%s", val)
|
||||
}
|
||||
|
||||
func (s *durationSliceValue) Append(val string) error {
|
||||
i, err := s.fromString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *durationSliceValue) Replace(val []string) error {
|
||||
out := make([]time.Duration, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = s.fromString(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *durationSliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = s.toString(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func durationSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
|
26
vendor/github.com/spf13/pflag/flag.go
generated
vendored
26
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -57,9 +57,9 @@ that give one-letter shorthands for flags. You can use these by appending
|
||||
var ip = flag.IntP("flagname", "f", 1234, "help message")
|
||||
var flagvar bool
|
||||
func init() {
|
||||
flag.BoolVarP("boolname", "b", true, "help message")
|
||||
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
|
||||
}
|
||||
flag.VarP(&flagVar, "varname", "v", 1234, "help message")
|
||||
flag.VarP(&flagval, "varname", "v", "help message")
|
||||
Shorthand letters can be used with single dashes on the command line.
|
||||
Boolean shorthand flags can be combined with other shorthand flags.
|
||||
|
||||
@ -190,6 +190,18 @@ type Value interface {
|
||||
Type() string
|
||||
}
|
||||
|
||||
// SliceValue is a secondary interface to all flags which hold a list
|
||||
// of values. This allows full control over the value of list flags,
|
||||
// and avoids complicated marshalling and unmarshalling to csv.
|
||||
type SliceValue interface {
|
||||
// Append adds the specified value to the end of the flag value list.
|
||||
Append(string) error
|
||||
// Replace will fully overwrite any data currently in the flag value list.
|
||||
Replace([]string) error
|
||||
// GetSlice returns the flag value list as an array of strings.
|
||||
GetSlice() []string
|
||||
}
|
||||
|
||||
// sortFlags returns the flags as a slice in lexicographical sorted order.
|
||||
func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
|
||||
list := make(sort.StringSlice, len(flags))
|
||||
@ -925,13 +937,16 @@ func stripUnknownFlagValue(args []string) []string {
|
||||
}
|
||||
|
||||
first := args[0]
|
||||
if first[0] == '-' {
|
||||
if len(first) > 0 && first[0] == '-' {
|
||||
//--unknown --next-flag ...
|
||||
return args
|
||||
}
|
||||
|
||||
//--unknown arg ... (args will be arg ...)
|
||||
return args[1:]
|
||||
if len(args) > 1 {
|
||||
return args[1:]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
|
||||
@ -990,11 +1005,12 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
||||
}
|
||||
|
||||
func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
|
||||
outArgs = args
|
||||
|
||||
if strings.HasPrefix(shorthands, "test.") {
|
||||
return
|
||||
}
|
||||
|
||||
outArgs = args
|
||||
outShorts = shorthands[1:]
|
||||
c := shorthands[0]
|
||||
|
||||
|
174
vendor/github.com/spf13/pflag/float32_slice.go
generated
vendored
Normal file
174
vendor/github.com/spf13/pflag/float32_slice.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- float32Slice Value
|
||||
type float32SliceValue struct {
|
||||
value *[]float32
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newFloat32SliceValue(val []float32, p *[]float32) *float32SliceValue {
|
||||
isv := new(float32SliceValue)
|
||||
isv.value = p
|
||||
*isv.value = val
|
||||
return isv
|
||||
}
|
||||
|
||||
func (s *float32SliceValue) Set(val string) error {
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]float32, len(ss))
|
||||
for i, d := range ss {
|
||||
var err error
|
||||
var temp64 float64
|
||||
temp64, err = strconv.ParseFloat(d, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out[i] = float32(temp64)
|
||||
|
||||
}
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
*s.value = append(*s.value, out...)
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *float32SliceValue) Type() string {
|
||||
return "float32Slice"
|
||||
}
|
||||
|
||||
func (s *float32SliceValue) String() string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = fmt.Sprintf("%f", d)
|
||||
}
|
||||
return "[" + strings.Join(out, ",") + "]"
|
||||
}
|
||||
|
||||
func (s *float32SliceValue) fromString(val string) (float32, error) {
|
||||
t64, err := strconv.ParseFloat(val, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float32(t64), nil
|
||||
}
|
||||
|
||||
func (s *float32SliceValue) toString(val float32) string {
|
||||
return fmt.Sprintf("%f", val)
|
||||
}
|
||||
|
||||
func (s *float32SliceValue) Append(val string) error {
|
||||
i, err := s.fromString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *float32SliceValue) Replace(val []string) error {
|
||||
out := make([]float32, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = s.fromString(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *float32SliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = s.toString(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func float32SliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []float32{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]float32, len(ss))
|
||||
for i, d := range ss {
|
||||
var err error
|
||||
var temp64 float64
|
||||
temp64, err = strconv.ParseFloat(d, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[i] = float32(temp64)
|
||||
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetFloat32Slice return the []float32 value of a flag with the given name
|
||||
func (f *FlagSet) GetFloat32Slice(name string) ([]float32, error) {
|
||||
val, err := f.getFlagType(name, "float32Slice", float32SliceConv)
|
||||
if err != nil {
|
||||
return []float32{}, err
|
||||
}
|
||||
return val.([]float32), nil
|
||||
}
|
||||
|
||||
// Float32SliceVar defines a float32Slice flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []float32 variable in which to store the value of the flag.
|
||||
func (f *FlagSet) Float32SliceVar(p *[]float32, name string, value []float32, usage string) {
|
||||
f.VarP(newFloat32SliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) {
|
||||
f.VarP(newFloat32SliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Float32SliceVar defines a float32[] flag with specified name, default value, and usage string.
|
||||
// The argument p points to a float32[] variable in which to store the value of the flag.
|
||||
func Float32SliceVar(p *[]float32, name string, value []float32, usage string) {
|
||||
CommandLine.VarP(newFloat32SliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) {
|
||||
CommandLine.VarP(newFloat32SliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Float32Slice defines a []float32 flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []float32 variable that stores the value of the flag.
|
||||
func (f *FlagSet) Float32Slice(name string, value []float32, usage string) *[]float32 {
|
||||
p := []float32{}
|
||||
f.Float32SliceVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 {
|
||||
p := []float32{}
|
||||
f.Float32SliceVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// Float32Slice defines a []float32 flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []float32 variable that stores the value of the flag.
|
||||
func Float32Slice(name string, value []float32, usage string) *[]float32 {
|
||||
return CommandLine.Float32SliceP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 {
|
||||
return CommandLine.Float32SliceP(name, shorthand, value, usage)
|
||||
}
|
166
vendor/github.com/spf13/pflag/float64_slice.go
generated
vendored
Normal file
166
vendor/github.com/spf13/pflag/float64_slice.go
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- float64Slice Value
|
||||
type float64SliceValue struct {
|
||||
value *[]float64
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newFloat64SliceValue(val []float64, p *[]float64) *float64SliceValue {
|
||||
isv := new(float64SliceValue)
|
||||
isv.value = p
|
||||
*isv.value = val
|
||||
return isv
|
||||
}
|
||||
|
||||
func (s *float64SliceValue) Set(val string) error {
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]float64, len(ss))
|
||||
for i, d := range ss {
|
||||
var err error
|
||||
out[i], err = strconv.ParseFloat(d, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
*s.value = append(*s.value, out...)
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *float64SliceValue) Type() string {
|
||||
return "float64Slice"
|
||||
}
|
||||
|
||||
func (s *float64SliceValue) String() string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = fmt.Sprintf("%f", d)
|
||||
}
|
||||
return "[" + strings.Join(out, ",") + "]"
|
||||
}
|
||||
|
||||
func (s *float64SliceValue) fromString(val string) (float64, error) {
|
||||
return strconv.ParseFloat(val, 64)
|
||||
}
|
||||
|
||||
func (s *float64SliceValue) toString(val float64) string {
|
||||
return fmt.Sprintf("%f", val)
|
||||
}
|
||||
|
||||
func (s *float64SliceValue) Append(val string) error {
|
||||
i, err := s.fromString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *float64SliceValue) Replace(val []string) error {
|
||||
out := make([]float64, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = s.fromString(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *float64SliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = s.toString(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func float64SliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []float64{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]float64, len(ss))
|
||||
for i, d := range ss {
|
||||
var err error
|
||||
out[i], err = strconv.ParseFloat(d, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetFloat64Slice return the []float64 value of a flag with the given name
|
||||
func (f *FlagSet) GetFloat64Slice(name string) ([]float64, error) {
|
||||
val, err := f.getFlagType(name, "float64Slice", float64SliceConv)
|
||||
if err != nil {
|
||||
return []float64{}, err
|
||||
}
|
||||
return val.([]float64), nil
|
||||
}
|
||||
|
||||
// Float64SliceVar defines a float64Slice flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []float64 variable in which to store the value of the flag.
|
||||
func (f *FlagSet) Float64SliceVar(p *[]float64, name string, value []float64, usage string) {
|
||||
f.VarP(newFloat64SliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) {
|
||||
f.VarP(newFloat64SliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Float64SliceVar defines a float64[] flag with specified name, default value, and usage string.
|
||||
// The argument p points to a float64[] variable in which to store the value of the flag.
|
||||
func Float64SliceVar(p *[]float64, name string, value []float64, usage string) {
|
||||
CommandLine.VarP(newFloat64SliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) {
|
||||
CommandLine.VarP(newFloat64SliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Float64Slice defines a []float64 flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []float64 variable that stores the value of the flag.
|
||||
func (f *FlagSet) Float64Slice(name string, value []float64, usage string) *[]float64 {
|
||||
p := []float64{}
|
||||
f.Float64SliceVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 {
|
||||
p := []float64{}
|
||||
f.Float64SliceVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// Float64Slice defines a []float64 flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []float64 variable that stores the value of the flag.
|
||||
func Float64Slice(name string, value []float64, usage string) *[]float64 {
|
||||
return CommandLine.Float64SliceP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 {
|
||||
return CommandLine.Float64SliceP(name, shorthand, value, usage)
|
||||
}
|
3
vendor/github.com/spf13/pflag/go.mod
generated
vendored
Normal file
3
vendor/github.com/spf13/pflag/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/spf13/pflag
|
||||
|
||||
go 1.12
|
0
vendor/github.com/spf13/pflag/go.sum
generated
vendored
Normal file
0
vendor/github.com/spf13/pflag/go.sum
generated
vendored
Normal file
174
vendor/github.com/spf13/pflag/int32_slice.go
generated
vendored
Normal file
174
vendor/github.com/spf13/pflag/int32_slice.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- int32Slice Value
|
||||
type int32SliceValue struct {
|
||||
value *[]int32
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newInt32SliceValue(val []int32, p *[]int32) *int32SliceValue {
|
||||
isv := new(int32SliceValue)
|
||||
isv.value = p
|
||||
*isv.value = val
|
||||
return isv
|
||||
}
|
||||
|
||||
func (s *int32SliceValue) Set(val string) error {
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]int32, len(ss))
|
||||
for i, d := range ss {
|
||||
var err error
|
||||
var temp64 int64
|
||||
temp64, err = strconv.ParseInt(d, 0, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out[i] = int32(temp64)
|
||||
|
||||
}
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
*s.value = append(*s.value, out...)
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *int32SliceValue) Type() string {
|
||||
return "int32Slice"
|
||||
}
|
||||
|
||||
func (s *int32SliceValue) String() string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = fmt.Sprintf("%d", d)
|
||||
}
|
||||
return "[" + strings.Join(out, ",") + "]"
|
||||
}
|
||||
|
||||
func (s *int32SliceValue) fromString(val string) (int32, error) {
|
||||
t64, err := strconv.ParseInt(val, 0, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(t64), nil
|
||||
}
|
||||
|
||||
func (s *int32SliceValue) toString(val int32) string {
|
||||
return fmt.Sprintf("%d", val)
|
||||
}
|
||||
|
||||
func (s *int32SliceValue) Append(val string) error {
|
||||
i, err := s.fromString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *int32SliceValue) Replace(val []string) error {
|
||||
out := make([]int32, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = s.fromString(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *int32SliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = s.toString(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func int32SliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []int32{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]int32, len(ss))
|
||||
for i, d := range ss {
|
||||
var err error
|
||||
var temp64 int64
|
||||
temp64, err = strconv.ParseInt(d, 0, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[i] = int32(temp64)
|
||||
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetInt32Slice return the []int32 value of a flag with the given name
|
||||
func (f *FlagSet) GetInt32Slice(name string) ([]int32, error) {
|
||||
val, err := f.getFlagType(name, "int32Slice", int32SliceConv)
|
||||
if err != nil {
|
||||
return []int32{}, err
|
||||
}
|
||||
return val.([]int32), nil
|
||||
}
|
||||
|
||||
// Int32SliceVar defines a int32Slice flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []int32 variable in which to store the value of the flag.
|
||||
func (f *FlagSet) Int32SliceVar(p *[]int32, name string, value []int32, usage string) {
|
||||
f.VarP(newInt32SliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) {
|
||||
f.VarP(newInt32SliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Int32SliceVar defines a int32[] flag with specified name, default value, and usage string.
|
||||
// The argument p points to a int32[] variable in which to store the value of the flag.
|
||||
func Int32SliceVar(p *[]int32, name string, value []int32, usage string) {
|
||||
CommandLine.VarP(newInt32SliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) {
|
||||
CommandLine.VarP(newInt32SliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Int32Slice defines a []int32 flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []int32 variable that stores the value of the flag.
|
||||
func (f *FlagSet) Int32Slice(name string, value []int32, usage string) *[]int32 {
|
||||
p := []int32{}
|
||||
f.Int32SliceVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 {
|
||||
p := []int32{}
|
||||
f.Int32SliceVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// Int32Slice defines a []int32 flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []int32 variable that stores the value of the flag.
|
||||
func Int32Slice(name string, value []int32, usage string) *[]int32 {
|
||||
return CommandLine.Int32SliceP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 {
|
||||
return CommandLine.Int32SliceP(name, shorthand, value, usage)
|
||||
}
|
166
vendor/github.com/spf13/pflag/int64_slice.go
generated
vendored
Normal file
166
vendor/github.com/spf13/pflag/int64_slice.go
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- int64Slice Value
|
||||
type int64SliceValue struct {
|
||||
value *[]int64
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newInt64SliceValue(val []int64, p *[]int64) *int64SliceValue {
|
||||
isv := new(int64SliceValue)
|
||||
isv.value = p
|
||||
*isv.value = val
|
||||
return isv
|
||||
}
|
||||
|
||||
func (s *int64SliceValue) Set(val string) error {
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]int64, len(ss))
|
||||
for i, d := range ss {
|
||||
var err error
|
||||
out[i], err = strconv.ParseInt(d, 0, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
*s.value = append(*s.value, out...)
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *int64SliceValue) Type() string {
|
||||
return "int64Slice"
|
||||
}
|
||||
|
||||
func (s *int64SliceValue) String() string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = fmt.Sprintf("%d", d)
|
||||
}
|
||||
return "[" + strings.Join(out, ",") + "]"
|
||||
}
|
||||
|
||||
func (s *int64SliceValue) fromString(val string) (int64, error) {
|
||||
return strconv.ParseInt(val, 0, 64)
|
||||
}
|
||||
|
||||
func (s *int64SliceValue) toString(val int64) string {
|
||||
return fmt.Sprintf("%d", val)
|
||||
}
|
||||
|
||||
func (s *int64SliceValue) Append(val string) error {
|
||||
i, err := s.fromString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *int64SliceValue) Replace(val []string) error {
|
||||
out := make([]int64, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = s.fromString(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *int64SliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = s.toString(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func int64SliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []int64{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make([]int64, len(ss))
|
||||
for i, d := range ss {
|
||||
var err error
|
||||
out[i], err = strconv.ParseInt(d, 0, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetInt64Slice return the []int64 value of a flag with the given name
|
||||
func (f *FlagSet) GetInt64Slice(name string) ([]int64, error) {
|
||||
val, err := f.getFlagType(name, "int64Slice", int64SliceConv)
|
||||
if err != nil {
|
||||
return []int64{}, err
|
||||
}
|
||||
return val.([]int64), nil
|
||||
}
|
||||
|
||||
// Int64SliceVar defines a int64Slice flag with specified name, default value, and usage string.
|
||||
// The argument p points to a []int64 variable in which to store the value of the flag.
|
||||
func (f *FlagSet) Int64SliceVar(p *[]int64, name string, value []int64, usage string) {
|
||||
f.VarP(newInt64SliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) {
|
||||
f.VarP(newInt64SliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Int64SliceVar defines a int64[] flag with specified name, default value, and usage string.
|
||||
// The argument p points to a int64[] variable in which to store the value of the flag.
|
||||
func Int64SliceVar(p *[]int64, name string, value []int64, usage string) {
|
||||
CommandLine.VarP(newInt64SliceValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) {
|
||||
CommandLine.VarP(newInt64SliceValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// Int64Slice defines a []int64 flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []int64 variable that stores the value of the flag.
|
||||
func (f *FlagSet) Int64Slice(name string, value []int64, usage string) *[]int64 {
|
||||
p := []int64{}
|
||||
f.Int64SliceVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 {
|
||||
p := []int64{}
|
||||
f.Int64SliceVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// Int64Slice defines a []int64 flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a []int64 variable that stores the value of the flag.
|
||||
func Int64Slice(name string, value []int64, usage string) *[]int64 {
|
||||
return CommandLine.Int64SliceP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||
func Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 {
|
||||
return CommandLine.Int64SliceP(name, shorthand, value, usage)
|
||||
}
|
30
vendor/github.com/spf13/pflag/int_slice.go
generated
vendored
30
vendor/github.com/spf13/pflag/int_slice.go
generated
vendored
@ -51,6 +51,36 @@ func (s *intSliceValue) String() string {
|
||||
return "[" + strings.Join(out, ",") + "]"
|
||||
}
|
||||
|
||||
func (s *intSliceValue) Append(val string) error {
|
||||
i, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *intSliceValue) Replace(val []string) error {
|
||||
out := make([]int, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = strconv.Atoi(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *intSliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = strconv.Itoa(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func intSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
|
40
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
40
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
@ -72,9 +72,47 @@ func (s *ipSliceValue) String() string {
|
||||
return "[" + out + "]"
|
||||
}
|
||||
|
||||
func (s *ipSliceValue) fromString(val string) (net.IP, error) {
|
||||
return net.ParseIP(strings.TrimSpace(val)), nil
|
||||
}
|
||||
|
||||
func (s *ipSliceValue) toString(val net.IP) string {
|
||||
return val.String()
|
||||
}
|
||||
|
||||
func (s *ipSliceValue) Append(val string) error {
|
||||
i, err := s.fromString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ipSliceValue) Replace(val []string) error {
|
||||
out := make([]net.IP, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = s.fromString(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ipSliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = s.toString(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func ipSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Emtpy string would cause a slice with one (empty) entry
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
if len(val) == 0 {
|
||||
return []net.IP{}, nil
|
||||
}
|
||||
|
26
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
26
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
@ -23,6 +23,32 @@ func (s *stringArrayValue) Set(val string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringArrayValue) Append(val string) error {
|
||||
*s.value = append(*s.value, val)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringArrayValue) Replace(val []string) error {
|
||||
out := make([]string, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i] = d
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringArrayValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = d
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (s *stringArrayValue) Type() string {
|
||||
return "stringArray"
|
||||
}
|
||||
|
22
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
22
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
@ -62,6 +62,20 @@ func (s *stringSliceValue) String() string {
|
||||
return "[" + str + "]"
|
||||
}
|
||||
|
||||
func (s *stringSliceValue) Append(val string) error {
|
||||
*s.value = append(*s.value, val)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringSliceValue) Replace(val []string) error {
|
||||
*s.value = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringSliceValue) GetSlice() []string {
|
||||
return *s.value
|
||||
}
|
||||
|
||||
func stringSliceConv(sval string) (interface{}, error) {
|
||||
sval = sval[1 : len(sval)-1]
|
||||
// An empty string would cause a slice with one (empty) string
|
||||
@ -84,7 +98,7 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
|
||||
// The argument p points to a []string variable in which to store the value of the flag.
|
||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||
// For example:
|
||||
// --ss="v1,v2" -ss="v3"
|
||||
// --ss="v1,v2" --ss="v3"
|
||||
// will result in
|
||||
// []string{"v1", "v2", "v3"}
|
||||
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
|
||||
@ -100,7 +114,7 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s
|
||||
// The argument p points to a []string variable in which to store the value of the flag.
|
||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||
// For example:
|
||||
// --ss="v1,v2" -ss="v3"
|
||||
// --ss="v1,v2" --ss="v3"
|
||||
// will result in
|
||||
// []string{"v1", "v2", "v3"}
|
||||
func StringSliceVar(p *[]string, name string, value []string, usage string) {
|
||||
@ -116,7 +130,7 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage
|
||||
// The return value is the address of a []string variable that stores the value of the flag.
|
||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||
// For example:
|
||||
// --ss="v1,v2" -ss="v3"
|
||||
// --ss="v1,v2" --ss="v3"
|
||||
// will result in
|
||||
// []string{"v1", "v2", "v3"}
|
||||
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
|
||||
@ -136,7 +150,7 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str
|
||||
// The return value is the address of a []string variable that stores the value of the flag.
|
||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||
// For example:
|
||||
// --ss="v1,v2" -ss="v3"
|
||||
// --ss="v1,v2" --ss="v3"
|
||||
// will result in
|
||||
// []string{"v1", "v2", "v3"}
|
||||
func StringSlice(name string, value []string, usage string) *[]string {
|
||||
|
149
vendor/github.com/spf13/pflag/string_to_int.go
generated
vendored
Normal file
149
vendor/github.com/spf13/pflag/string_to_int.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- stringToInt Value
|
||||
type stringToIntValue struct {
|
||||
value *map[string]int
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newStringToIntValue(val map[string]int, p *map[string]int) *stringToIntValue {
|
||||
ssv := new(stringToIntValue)
|
||||
ssv.value = p
|
||||
*ssv.value = val
|
||||
return ssv
|
||||
}
|
||||
|
||||
// Format: a=1,b=2
|
||||
func (s *stringToIntValue) Set(val string) error {
|
||||
ss := strings.Split(val, ",")
|
||||
out := make(map[string]int, len(ss))
|
||||
for _, pair := range ss {
|
||||
kv := strings.SplitN(pair, "=", 2)
|
||||
if len(kv) != 2 {
|
||||
return fmt.Errorf("%s must be formatted as key=value", pair)
|
||||
}
|
||||
var err error
|
||||
out[kv[0]], err = strconv.Atoi(kv[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
for k, v := range out {
|
||||
(*s.value)[k] = v
|
||||
}
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringToIntValue) Type() string {
|
||||
return "stringToInt"
|
||||
}
|
||||
|
||||
func (s *stringToIntValue) String() string {
|
||||
var buf bytes.Buffer
|
||||
i := 0
|
||||
for k, v := range *s.value {
|
||||
if i > 0 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
buf.WriteString(k)
|
||||
buf.WriteRune('=')
|
||||
buf.WriteString(strconv.Itoa(v))
|
||||
i++
|
||||
}
|
||||
return "[" + buf.String() + "]"
|
||||
}
|
||||
|
||||
func stringToIntConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// An empty string would cause an empty map
|
||||
if len(val) == 0 {
|
||||
return map[string]int{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make(map[string]int, len(ss))
|
||||
for _, pair := range ss {
|
||||
kv := strings.SplitN(pair, "=", 2)
|
||||
if len(kv) != 2 {
|
||||
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
|
||||
}
|
||||
var err error
|
||||
out[kv[0]], err = strconv.Atoi(kv[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetStringToInt return the map[string]int value of a flag with the given name
|
||||
func (f *FlagSet) GetStringToInt(name string) (map[string]int, error) {
|
||||
val, err := f.getFlagType(name, "stringToInt", stringToIntConv)
|
||||
if err != nil {
|
||||
return map[string]int{}, err
|
||||
}
|
||||
return val.(map[string]int), nil
|
||||
}
|
||||
|
||||
// StringToIntVar defines a string flag with specified name, default value, and usage string.
|
||||
// The argument p points to a map[string]int variable in which to store the values of the multiple flags.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func (f *FlagSet) StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
|
||||
f.VarP(newStringToIntValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
|
||||
f.VarP(newStringToIntValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// StringToIntVar defines a string flag with specified name, default value, and usage string.
|
||||
// The argument p points to a map[string]int variable in which to store the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
|
||||
CommandLine.VarP(newStringToIntValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
|
||||
CommandLine.VarP(newStringToIntValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// StringToInt defines a string flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a map[string]int variable that stores the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func (f *FlagSet) StringToInt(name string, value map[string]int, usage string) *map[string]int {
|
||||
p := map[string]int{}
|
||||
f.StringToIntVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
|
||||
p := map[string]int{}
|
||||
f.StringToIntVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// StringToInt defines a string flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a map[string]int variable that stores the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func StringToInt(name string, value map[string]int, usage string) *map[string]int {
|
||||
return CommandLine.StringToIntP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
|
||||
func StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
|
||||
return CommandLine.StringToIntP(name, shorthand, value, usage)
|
||||
}
|
149
vendor/github.com/spf13/pflag/string_to_int64.go
generated
vendored
Normal file
149
vendor/github.com/spf13/pflag/string_to_int64.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- stringToInt64 Value
|
||||
type stringToInt64Value struct {
|
||||
value *map[string]int64
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newStringToInt64Value(val map[string]int64, p *map[string]int64) *stringToInt64Value {
|
||||
ssv := new(stringToInt64Value)
|
||||
ssv.value = p
|
||||
*ssv.value = val
|
||||
return ssv
|
||||
}
|
||||
|
||||
// Format: a=1,b=2
|
||||
func (s *stringToInt64Value) Set(val string) error {
|
||||
ss := strings.Split(val, ",")
|
||||
out := make(map[string]int64, len(ss))
|
||||
for _, pair := range ss {
|
||||
kv := strings.SplitN(pair, "=", 2)
|
||||
if len(kv) != 2 {
|
||||
return fmt.Errorf("%s must be formatted as key=value", pair)
|
||||
}
|
||||
var err error
|
||||
out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
for k, v := range out {
|
||||
(*s.value)[k] = v
|
||||
}
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringToInt64Value) Type() string {
|
||||
return "stringToInt64"
|
||||
}
|
||||
|
||||
func (s *stringToInt64Value) String() string {
|
||||
var buf bytes.Buffer
|
||||
i := 0
|
||||
for k, v := range *s.value {
|
||||
if i > 0 {
|
||||
buf.WriteRune(',')
|
||||
}
|
||||
buf.WriteString(k)
|
||||
buf.WriteRune('=')
|
||||
buf.WriteString(strconv.FormatInt(v, 10))
|
||||
i++
|
||||
}
|
||||
return "[" + buf.String() + "]"
|
||||
}
|
||||
|
||||
func stringToInt64Conv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// An empty string would cause an empty map
|
||||
if len(val) == 0 {
|
||||
return map[string]int64{}, nil
|
||||
}
|
||||
ss := strings.Split(val, ",")
|
||||
out := make(map[string]int64, len(ss))
|
||||
for _, pair := range ss {
|
||||
kv := strings.SplitN(pair, "=", 2)
|
||||
if len(kv) != 2 {
|
||||
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
|
||||
}
|
||||
var err error
|
||||
out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetStringToInt64 return the map[string]int64 value of a flag with the given name
|
||||
func (f *FlagSet) GetStringToInt64(name string) (map[string]int64, error) {
|
||||
val, err := f.getFlagType(name, "stringToInt64", stringToInt64Conv)
|
||||
if err != nil {
|
||||
return map[string]int64{}, err
|
||||
}
|
||||
return val.(map[string]int64), nil
|
||||
}
|
||||
|
||||
// StringToInt64Var defines a string flag with specified name, default value, and usage string.
|
||||
// The argument p point64s to a map[string]int64 variable in which to store the values of the multiple flags.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func (f *FlagSet) StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) {
|
||||
f.VarP(newStringToInt64Value(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
|
||||
f.VarP(newStringToInt64Value(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// StringToInt64Var defines a string flag with specified name, default value, and usage string.
|
||||
// The argument p point64s to a map[string]int64 variable in which to store the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) {
|
||||
CommandLine.VarP(newStringToInt64Value(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||
func StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
|
||||
CommandLine.VarP(newStringToInt64Value(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// StringToInt64 defines a string flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a map[string]int64 variable that stores the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func (f *FlagSet) StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 {
|
||||
p := map[string]int64{}
|
||||
f.StringToInt64VarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 {
|
||||
p := map[string]int64{}
|
||||
f.StringToInt64VarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// StringToInt64 defines a string flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a map[string]int64 variable that stores the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 {
|
||||
return CommandLine.StringToInt64P(name, "", value, usage)
|
||||
}
|
||||
|
||||
// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash.
|
||||
func StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 {
|
||||
return CommandLine.StringToInt64P(name, shorthand, value, usage)
|
||||
}
|
160
vendor/github.com/spf13/pflag/string_to_string.go
generated
vendored
Normal file
160
vendor/github.com/spf13/pflag/string_to_string.go
generated
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
package pflag
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// -- stringToString Value
|
||||
type stringToStringValue struct {
|
||||
value *map[string]string
|
||||
changed bool
|
||||
}
|
||||
|
||||
func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue {
|
||||
ssv := new(stringToStringValue)
|
||||
ssv.value = p
|
||||
*ssv.value = val
|
||||
return ssv
|
||||
}
|
||||
|
||||
// Format: a=1,b=2
|
||||
func (s *stringToStringValue) Set(val string) error {
|
||||
var ss []string
|
||||
n := strings.Count(val, "=")
|
||||
switch n {
|
||||
case 0:
|
||||
return fmt.Errorf("%s must be formatted as key=value", val)
|
||||
case 1:
|
||||
ss = append(ss, strings.Trim(val, `"`))
|
||||
default:
|
||||
r := csv.NewReader(strings.NewReader(val))
|
||||
var err error
|
||||
ss, err = r.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
out := make(map[string]string, len(ss))
|
||||
for _, pair := range ss {
|
||||
kv := strings.SplitN(pair, "=", 2)
|
||||
if len(kv) != 2 {
|
||||
return fmt.Errorf("%s must be formatted as key=value", pair)
|
||||
}
|
||||
out[kv[0]] = kv[1]
|
||||
}
|
||||
if !s.changed {
|
||||
*s.value = out
|
||||
} else {
|
||||
for k, v := range out {
|
||||
(*s.value)[k] = v
|
||||
}
|
||||
}
|
||||
s.changed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *stringToStringValue) Type() string {
|
||||
return "stringToString"
|
||||
}
|
||||
|
||||
func (s *stringToStringValue) String() string {
|
||||
records := make([]string, 0, len(*s.value)>>1)
|
||||
for k, v := range *s.value {
|
||||
records = append(records, k+"="+v)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
w := csv.NewWriter(&buf)
|
||||
if err := w.Write(records); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
w.Flush()
|
||||
return "[" + strings.TrimSpace(buf.String()) + "]"
|
||||
}
|
||||
|
||||
func stringToStringConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// An empty string would cause an empty map
|
||||
if len(val) == 0 {
|
||||
return map[string]string{}, nil
|
||||
}
|
||||
r := csv.NewReader(strings.NewReader(val))
|
||||
ss, err := r.Read()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make(map[string]string, len(ss))
|
||||
for _, pair := range ss {
|
||||
kv := strings.SplitN(pair, "=", 2)
|
||||
if len(kv) != 2 {
|
||||
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
|
||||
}
|
||||
out[kv[0]] = kv[1]
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetStringToString return the map[string]string value of a flag with the given name
|
||||
func (f *FlagSet) GetStringToString(name string) (map[string]string, error) {
|
||||
val, err := f.getFlagType(name, "stringToString", stringToStringConv)
|
||||
if err != nil {
|
||||
return map[string]string{}, err
|
||||
}
|
||||
return val.(map[string]string), nil
|
||||
}
|
||||
|
||||
// StringToStringVar defines a string flag with specified name, default value, and usage string.
|
||||
// The argument p points to a map[string]string variable in which to store the values of the multiple flags.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
|
||||
f.VarP(newStringToStringValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
|
||||
f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// StringToStringVar defines a string flag with specified name, default value, and usage string.
|
||||
// The argument p points to a map[string]string variable in which to store the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
|
||||
CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
|
||||
}
|
||||
|
||||
// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
|
||||
func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
|
||||
CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
|
||||
}
|
||||
|
||||
// StringToString defines a string flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a map[string]string variable that stores the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string {
|
||||
p := map[string]string{}
|
||||
f.StringToStringVarP(&p, name, "", value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
|
||||
func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
|
||||
p := map[string]string{}
|
||||
f.StringToStringVarP(&p, name, shorthand, value, usage)
|
||||
return &p
|
||||
}
|
||||
|
||||
// StringToString defines a string flag with specified name, default value, and usage string.
|
||||
// The return value is the address of a map[string]string variable that stores the value of the flag.
|
||||
// The value of each argument will not try to be separated by comma
|
||||
func StringToString(name string, value map[string]string, usage string) *map[string]string {
|
||||
return CommandLine.StringToStringP(name, "", value, usage)
|
||||
}
|
||||
|
||||
// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
|
||||
func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
|
||||
return CommandLine.StringToStringP(name, shorthand, value, usage)
|
||||
}
|
42
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
42
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
@ -50,6 +50,48 @@ func (s *uintSliceValue) String() string {
|
||||
return "[" + strings.Join(out, ",") + "]"
|
||||
}
|
||||
|
||||
func (s *uintSliceValue) fromString(val string) (uint, error) {
|
||||
t, err := strconv.ParseUint(val, 10, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint(t), nil
|
||||
}
|
||||
|
||||
func (s *uintSliceValue) toString(val uint) string {
|
||||
return fmt.Sprintf("%d", val)
|
||||
}
|
||||
|
||||
func (s *uintSliceValue) Append(val string) error {
|
||||
i, err := s.fromString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*s.value = append(*s.value, i)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *uintSliceValue) Replace(val []string) error {
|
||||
out := make([]uint, len(val))
|
||||
for i, d := range val {
|
||||
var err error
|
||||
out[i], err = s.fromString(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s.value = out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *uintSliceValue) GetSlice() []string {
|
||||
out := make([]string, len(*s.value))
|
||||
for i, d := range *s.value {
|
||||
out[i] = s.toString(d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func uintSliceConv(val string) (interface{}, error) {
|
||||
val = strings.Trim(val, "[]")
|
||||
// Empty string would cause a slice with one (empty) entry
|
||||
|
989
vendor/golang.org/x/crypto/ssh/terminal/terminal.go
generated
vendored
989
vendor/golang.org/x/crypto/ssh/terminal/terminal.go
generated
vendored
File diff suppressed because it is too large
Load Diff
12
vendor/golang.org/x/net/http2/server.go
generated
vendored
12
vendor/golang.org/x/net/http2/server.go
generated
vendored
@ -1694,6 +1694,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
||||
if len(data) > 0 {
|
||||
wrote, err := st.body.Write(data)
|
||||
if err != nil {
|
||||
sc.sendWindowUpdate(nil, int(f.Length)-wrote)
|
||||
return streamError(id, ErrCodeStreamClosed)
|
||||
}
|
||||
if wrote != len(data) {
|
||||
@ -2020,7 +2021,11 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||
}
|
||||
if bodyOpen {
|
||||
if vv, ok := rp.header["Content-Length"]; ok {
|
||||
req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
|
||||
if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil {
|
||||
req.ContentLength = int64(cl)
|
||||
} else {
|
||||
req.ContentLength = 0
|
||||
}
|
||||
} else {
|
||||
req.ContentLength = -1
|
||||
}
|
||||
@ -2403,9 +2408,8 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||
var ctype, clen string
|
||||
if clen = rws.snapHeader.Get("Content-Length"); clen != "" {
|
||||
rws.snapHeader.Del("Content-Length")
|
||||
clen64, err := strconv.ParseInt(clen, 10, 64)
|
||||
if err == nil && clen64 >= 0 {
|
||||
rws.sentContentLen = clen64
|
||||
if cl, err := strconv.ParseUint(clen, 10, 63); err == nil {
|
||||
rws.sentContentLen = int64(cl)
|
||||
} else {
|
||||
clen = ""
|
||||
}
|
||||
|
40
vendor/golang.org/x/net/http2/transport.go
generated
vendored
40
vendor/golang.org/x/net/http2/transport.go
generated
vendored
@ -154,12 +154,21 @@ func (t *Transport) pingTimeout() time.Duration {
|
||||
|
||||
// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
|
||||
// It returns an error if t1 has already been HTTP/2-enabled.
|
||||
//
|
||||
// Use ConfigureTransports instead to configure the HTTP/2 Transport.
|
||||
func ConfigureTransport(t1 *http.Transport) error {
|
||||
_, err := configureTransport(t1)
|
||||
_, err := ConfigureTransports(t1)
|
||||
return err
|
||||
}
|
||||
|
||||
func configureTransport(t1 *http.Transport) (*Transport, error) {
|
||||
// ConfigureTransports configures a net/http HTTP/1 Transport to use HTTP/2.
|
||||
// It returns a new HTTP/2 Transport for further configuration.
|
||||
// It returns an error if t1 has already been HTTP/2-enabled.
|
||||
func ConfigureTransports(t1 *http.Transport) (*Transport, error) {
|
||||
return configureTransports(t1)
|
||||
}
|
||||
|
||||
func configureTransports(t1 *http.Transport) (*Transport, error) {
|
||||
connPool := new(clientConnPool)
|
||||
t2 := &Transport{
|
||||
ConnPool: noDialClientConnPool{connPool},
|
||||
@ -689,6 +698,7 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
|
||||
cc.inflow.add(transportDefaultConnFlow + initialWindowSize)
|
||||
cc.bw.Flush()
|
||||
if cc.werr != nil {
|
||||
cc.Close()
|
||||
return nil, cc.werr
|
||||
}
|
||||
|
||||
@ -1080,6 +1090,15 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
||||
bodyWriter := cc.t.getBodyWriterState(cs, body)
|
||||
cs.on100 = bodyWriter.on100
|
||||
|
||||
defer func() {
|
||||
cc.wmu.Lock()
|
||||
werr := cc.werr
|
||||
cc.wmu.Unlock()
|
||||
if werr != nil {
|
||||
cc.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
cc.wmu.Lock()
|
||||
endStream := !hasBody && !hasTrailers
|
||||
werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
|
||||
@ -1129,6 +1148,9 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
||||
// we can keep it.
|
||||
bodyWriter.cancel()
|
||||
cs.abortRequestBodyWrite(errStopReqBodyWrite)
|
||||
if hasBody && !bodyWritten {
|
||||
<-bodyWriter.resc
|
||||
}
|
||||
}
|
||||
if re.err != nil {
|
||||
cc.forgetStreamID(cs.ID)
|
||||
@ -1149,6 +1171,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
||||
} else {
|
||||
bodyWriter.cancel()
|
||||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||
<-bodyWriter.resc
|
||||
}
|
||||
cc.forgetStreamID(cs.ID)
|
||||
return nil, cs.getStartedWrite(), errTimeout
|
||||
@ -1158,6 +1181,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
||||
} else {
|
||||
bodyWriter.cancel()
|
||||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||
<-bodyWriter.resc
|
||||
}
|
||||
cc.forgetStreamID(cs.ID)
|
||||
return nil, cs.getStartedWrite(), ctx.Err()
|
||||
@ -1167,6 +1191,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
||||
} else {
|
||||
bodyWriter.cancel()
|
||||
cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
|
||||
<-bodyWriter.resc
|
||||
}
|
||||
cc.forgetStreamID(cs.ID)
|
||||
return nil, cs.getStartedWrite(), errRequestCanceled
|
||||
@ -1176,6 +1201,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
||||
// forgetStreamID.
|
||||
return nil, cs.getStartedWrite(), cs.resetErr
|
||||
case err := <-bodyWriter.resc:
|
||||
bodyWritten = true
|
||||
// Prefer the read loop's response, if available. Issue 16102.
|
||||
select {
|
||||
case re := <-readLoopResCh:
|
||||
@ -1186,7 +1212,6 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
||||
cc.forgetStreamID(cs.ID)
|
||||
return nil, cs.getStartedWrite(), err
|
||||
}
|
||||
bodyWritten = true
|
||||
if d := cc.responseHeaderTimeout(); d != 0 {
|
||||
timer := time.NewTimer(d)
|
||||
defer timer.Stop()
|
||||
@ -2006,8 +2031,8 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
|
||||
if !streamEnded || isHead {
|
||||
res.ContentLength = -1
|
||||
if clens := res.Header["Content-Length"]; len(clens) == 1 {
|
||||
if clen64, err := strconv.ParseInt(clens[0], 10, 64); err == nil {
|
||||
res.ContentLength = clen64
|
||||
if cl, err := strconv.ParseUint(clens[0], 10, 63); err == nil {
|
||||
res.ContentLength = int64(cl)
|
||||
} else {
|
||||
// TODO: care? unlike http/1, it won't mess up our framing, so it's
|
||||
// more safe smuggling-wise to ignore.
|
||||
@ -2525,6 +2550,7 @@ func strSliceContains(ss []string, s string) bool {
|
||||
|
||||
type erringRoundTripper struct{ err error }
|
||||
|
||||
func (rt erringRoundTripper) RoundTripErr() error { return rt.err }
|
||||
func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err }
|
||||
|
||||
// gzipReader wraps a response body so it can lazily
|
||||
@ -2606,7 +2632,9 @@ func (t *Transport) getBodyWriterState(cs *clientStream, body io.Reader) (s body
|
||||
|
||||
func (s bodyWriterState) cancel() {
|
||||
if s.timer != nil {
|
||||
s.timer.Stop()
|
||||
if s.timer.Stop() {
|
||||
s.resc <- nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
59
vendor/golang.org/x/net/icmp/dstunreach.go
generated
vendored
Normal file
59
vendor/golang.org/x/net/icmp/dstunreach.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// A DstUnreach represents an ICMP destination unreachable message
|
||||
// body.
|
||||
type DstUnreach struct {
|
||||
Data []byte // data, known as original datagram field
|
||||
Extensions []Extension // extensions
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *DstUnreach) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
|
||||
return l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *DstUnreach) Marshal(proto int) ([]byte, error) {
|
||||
var typ Type
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
typ = ipv4.ICMPTypeDestinationUnreachable
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
typ = ipv6.ICMPTypeDestinationUnreachable
|
||||
default:
|
||||
return nil, errInvalidProtocol
|
||||
}
|
||||
if !validExtensions(typ, p.Extensions) {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
return marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
|
||||
}
|
||||
|
||||
// parseDstUnreach parses b as an ICMP destination unreachable message
|
||||
// body.
|
||||
func parseDstUnreach(proto int, typ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &DstUnreach{}
|
||||
var err error
|
||||
p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
173
vendor/golang.org/x/net/icmp/echo.go
generated
vendored
Normal file
173
vendor/golang.org/x/net/icmp/echo.go
generated
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// An Echo represents an ICMP echo request or reply message body.
|
||||
type Echo struct {
|
||||
ID int // identifier
|
||||
Seq int // sequence number
|
||||
Data []byte // data
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *Echo) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return 4 + len(p.Data)
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *Echo) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, 4+len(p.Data))
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
|
||||
binary.BigEndian.PutUint16(b[2:4], uint16(p.Seq))
|
||||
copy(b[4:], p.Data)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseEcho parses b as an ICMP echo request or reply message body.
|
||||
func parseEcho(proto int, _ Type, b []byte) (MessageBody, error) {
|
||||
bodyLen := len(b)
|
||||
if bodyLen < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &Echo{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(binary.BigEndian.Uint16(b[2:4]))}
|
||||
if bodyLen > 4 {
|
||||
p.Data = make([]byte, bodyLen-4)
|
||||
copy(p.Data, b[4:])
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// An ExtendedEchoRequest represents an ICMP extended echo request
|
||||
// message body.
|
||||
type ExtendedEchoRequest struct {
|
||||
ID int // identifier
|
||||
Seq int // sequence number
|
||||
Local bool // must be true when identifying by name or index
|
||||
Extensions []Extension // extensions
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *ExtendedEchoRequest) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
l, _ := multipartMessageBodyDataLen(proto, false, nil, p.Extensions)
|
||||
return l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *ExtendedEchoRequest) Marshal(proto int) ([]byte, error) {
|
||||
var typ Type
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
typ = ipv4.ICMPTypeExtendedEchoRequest
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
typ = ipv6.ICMPTypeExtendedEchoRequest
|
||||
default:
|
||||
return nil, errInvalidProtocol
|
||||
}
|
||||
if !validExtensions(typ, p.Extensions) {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
b, err := marshalMultipartMessageBody(proto, false, nil, p.Extensions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
|
||||
b[2] = byte(p.Seq)
|
||||
if p.Local {
|
||||
b[3] |= 0x01
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseExtendedEchoRequest parses b as an ICMP extended echo request
|
||||
// message body.
|
||||
func parseExtendedEchoRequest(proto int, typ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &ExtendedEchoRequest{ID: int(binary.BigEndian.Uint16(b[:2])), Seq: int(b[2])}
|
||||
if b[3]&0x01 != 0 {
|
||||
p.Local = true
|
||||
}
|
||||
var err error
|
||||
_, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// An ExtendedEchoReply represents an ICMP extended echo reply message
|
||||
// body.
|
||||
type ExtendedEchoReply struct {
|
||||
ID int // identifier
|
||||
Seq int // sequence number
|
||||
State int // 3-bit state working together with Message.Code
|
||||
Active bool // probed interface is active
|
||||
IPv4 bool // probed interface runs IPv4
|
||||
IPv6 bool // probed interface runs IPv6
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *ExtendedEchoReply) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return 4
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *ExtendedEchoReply) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, 4)
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(p.ID))
|
||||
b[2] = byte(p.Seq)
|
||||
b[3] = byte(p.State<<5) & 0xe0
|
||||
if p.Active {
|
||||
b[3] |= 0x04
|
||||
}
|
||||
if p.IPv4 {
|
||||
b[3] |= 0x02
|
||||
}
|
||||
if p.IPv6 {
|
||||
b[3] |= 0x01
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseExtendedEchoReply parses b as an ICMP extended echo reply
|
||||
// message body.
|
||||
func parseExtendedEchoReply(proto int, _ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &ExtendedEchoReply{
|
||||
ID: int(binary.BigEndian.Uint16(b[:2])),
|
||||
Seq: int(b[2]),
|
||||
State: int(b[3]) >> 5,
|
||||
}
|
||||
if b[3]&0x04 != 0 {
|
||||
p.Active = true
|
||||
}
|
||||
if b[3]&0x02 != 0 {
|
||||
p.IPv4 = true
|
||||
}
|
||||
if b[3]&0x01 != 0 {
|
||||
p.IPv6 = true
|
||||
}
|
||||
return p, nil
|
||||
}
|
113
vendor/golang.org/x/net/icmp/endpoint.go
generated
vendored
Normal file
113
vendor/golang.org/x/net/icmp/endpoint.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
var _ net.PacketConn = &PacketConn{}
|
||||
|
||||
// A PacketConn represents a packet network endpoint that uses either
|
||||
// ICMPv4 or ICMPv6.
|
||||
type PacketConn struct {
|
||||
c net.PacketConn
|
||||
p4 *ipv4.PacketConn
|
||||
p6 *ipv6.PacketConn
|
||||
}
|
||||
|
||||
func (c *PacketConn) ok() bool { return c != nil && c.c != nil }
|
||||
|
||||
// IPv4PacketConn returns the ipv4.PacketConn of c.
|
||||
// It returns nil when c is not created as the endpoint for ICMPv4.
|
||||
func (c *PacketConn) IPv4PacketConn() *ipv4.PacketConn {
|
||||
if !c.ok() {
|
||||
return nil
|
||||
}
|
||||
return c.p4
|
||||
}
|
||||
|
||||
// IPv6PacketConn returns the ipv6.PacketConn of c.
|
||||
// It returns nil when c is not created as the endpoint for ICMPv6.
|
||||
func (c *PacketConn) IPv6PacketConn() *ipv6.PacketConn {
|
||||
if !c.ok() {
|
||||
return nil
|
||||
}
|
||||
return c.p6
|
||||
}
|
||||
|
||||
// ReadFrom reads an ICMP message from the connection.
|
||||
func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
if !c.ok() {
|
||||
return 0, nil, errInvalidConn
|
||||
}
|
||||
// Please be informed that ipv4.NewPacketConn enables
|
||||
// IP_STRIPHDR option by default on Darwin.
|
||||
// See golang.org/issue/9395 for further information.
|
||||
if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && c.p4 != nil {
|
||||
n, _, peer, err := c.p4.ReadFrom(b)
|
||||
return n, peer, err
|
||||
}
|
||||
return c.c.ReadFrom(b)
|
||||
}
|
||||
|
||||
// WriteTo writes the ICMP message b to dst.
|
||||
// The provided dst must be net.UDPAddr when c is a non-privileged
|
||||
// datagram-oriented ICMP endpoint.
|
||||
// Otherwise it must be net.IPAddr.
|
||||
func (c *PacketConn) WriteTo(b []byte, dst net.Addr) (int, error) {
|
||||
if !c.ok() {
|
||||
return 0, errInvalidConn
|
||||
}
|
||||
return c.c.WriteTo(b, dst)
|
||||
}
|
||||
|
||||
// Close closes the endpoint.
|
||||
func (c *PacketConn) Close() error {
|
||||
if !c.ok() {
|
||||
return errInvalidConn
|
||||
}
|
||||
return c.c.Close()
|
||||
}
|
||||
|
||||
// LocalAddr returns the local network address.
|
||||
func (c *PacketConn) LocalAddr() net.Addr {
|
||||
if !c.ok() {
|
||||
return nil
|
||||
}
|
||||
return c.c.LocalAddr()
|
||||
}
|
||||
|
||||
// SetDeadline sets the read and write deadlines associated with the
|
||||
// endpoint.
|
||||
func (c *PacketConn) SetDeadline(t time.Time) error {
|
||||
if !c.ok() {
|
||||
return errInvalidConn
|
||||
}
|
||||
return c.c.SetDeadline(t)
|
||||
}
|
||||
|
||||
// SetReadDeadline sets the read deadline associated with the
|
||||
// endpoint.
|
||||
func (c *PacketConn) SetReadDeadline(t time.Time) error {
|
||||
if !c.ok() {
|
||||
return errInvalidConn
|
||||
}
|
||||
return c.c.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
// SetWriteDeadline sets the write deadline associated with the
|
||||
// endpoint.
|
||||
func (c *PacketConn) SetWriteDeadline(t time.Time) error {
|
||||
if !c.ok() {
|
||||
return errInvalidConn
|
||||
}
|
||||
return c.c.SetWriteDeadline(t)
|
||||
}
|
170
vendor/golang.org/x/net/icmp/extension.go
generated
vendored
Normal file
170
vendor/golang.org/x/net/icmp/extension.go
generated
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// An Extension represents an ICMP extension.
|
||||
type Extension interface {
|
||||
// Len returns the length of ICMP extension.
|
||||
// The provided proto must be either the ICMPv4 or ICMPv6
|
||||
// protocol number.
|
||||
Len(proto int) int
|
||||
|
||||
// Marshal returns the binary encoding of ICMP extension.
|
||||
// The provided proto must be either the ICMPv4 or ICMPv6
|
||||
// protocol number.
|
||||
Marshal(proto int) ([]byte, error)
|
||||
}
|
||||
|
||||
const extensionVersion = 2
|
||||
|
||||
func validExtensionHeader(b []byte) bool {
|
||||
v := int(b[0]&0xf0) >> 4
|
||||
s := binary.BigEndian.Uint16(b[2:4])
|
||||
if s != 0 {
|
||||
s = checksum(b)
|
||||
}
|
||||
if v != extensionVersion || s != 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// parseExtensions parses b as a list of ICMP extensions.
|
||||
// The length attribute l must be the length attribute field in
|
||||
// received icmp messages.
|
||||
//
|
||||
// It will return a list of ICMP extensions and an adjusted length
|
||||
// attribute that represents the length of the padded original
|
||||
// datagram field. Otherwise, it returns an error.
|
||||
func parseExtensions(typ Type, b []byte, l int) ([]Extension, int, error) {
|
||||
// Still a lot of non-RFC 4884 compliant implementations are
|
||||
// out there. Set the length attribute l to 128 when it looks
|
||||
// inappropriate for backwards compatibility.
|
||||
//
|
||||
// A minimal extension at least requires 8 octets; 4 octets
|
||||
// for an extension header, and 4 octets for a single object
|
||||
// header.
|
||||
//
|
||||
// See RFC 4884 for further information.
|
||||
switch typ {
|
||||
case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
|
||||
if len(b) < 8 || !validExtensionHeader(b) {
|
||||
return nil, -1, errNoExtension
|
||||
}
|
||||
l = 0
|
||||
default:
|
||||
if 128 > l || l+8 > len(b) {
|
||||
l = 128
|
||||
}
|
||||
if l+8 > len(b) {
|
||||
return nil, -1, errNoExtension
|
||||
}
|
||||
if !validExtensionHeader(b[l:]) {
|
||||
if l == 128 {
|
||||
return nil, -1, errNoExtension
|
||||
}
|
||||
l = 128
|
||||
if !validExtensionHeader(b[l:]) {
|
||||
return nil, -1, errNoExtension
|
||||
}
|
||||
}
|
||||
}
|
||||
var exts []Extension
|
||||
for b = b[l+4:]; len(b) >= 4; {
|
||||
ol := int(binary.BigEndian.Uint16(b[:2]))
|
||||
if 4 > ol || ol > len(b) {
|
||||
break
|
||||
}
|
||||
switch b[2] {
|
||||
case classMPLSLabelStack:
|
||||
ext, err := parseMPLSLabelStack(b[:ol])
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
exts = append(exts, ext)
|
||||
case classInterfaceInfo:
|
||||
ext, err := parseInterfaceInfo(b[:ol])
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
exts = append(exts, ext)
|
||||
case classInterfaceIdent:
|
||||
ext, err := parseInterfaceIdent(b[:ol])
|
||||
if err != nil {
|
||||
return nil, -1, err
|
||||
}
|
||||
exts = append(exts, ext)
|
||||
default:
|
||||
ext := &RawExtension{Data: make([]byte, ol)}
|
||||
copy(ext.Data, b[:ol])
|
||||
exts = append(exts, ext)
|
||||
}
|
||||
b = b[ol:]
|
||||
}
|
||||
return exts, l, nil
|
||||
}
|
||||
|
||||
func validExtensions(typ Type, exts []Extension) bool {
|
||||
switch typ {
|
||||
case ipv4.ICMPTypeDestinationUnreachable, ipv4.ICMPTypeTimeExceeded, ipv4.ICMPTypeParameterProblem,
|
||||
ipv6.ICMPTypeDestinationUnreachable, ipv6.ICMPTypeTimeExceeded:
|
||||
for i := range exts {
|
||||
switch exts[i].(type) {
|
||||
case *MPLSLabelStack, *InterfaceInfo, *RawExtension:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
case ipv4.ICMPTypeExtendedEchoRequest, ipv6.ICMPTypeExtendedEchoRequest:
|
||||
var n int
|
||||
for i := range exts {
|
||||
switch exts[i].(type) {
|
||||
case *InterfaceIdent:
|
||||
n++
|
||||
case *RawExtension:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Not a single InterfaceIdent object or a combo of
|
||||
// RawExtension and InterfaceIdent objects is not
|
||||
// allowed.
|
||||
if n == 1 && len(exts) > 1 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// A RawExtension represents a raw extension.
|
||||
//
|
||||
// A raw extension is excluded from message processing and can be used
|
||||
// to construct applications such as protocol conformance testing.
|
||||
type RawExtension struct {
|
||||
Data []byte // data
|
||||
}
|
||||
|
||||
// Len implements the Len method of Extension interface.
|
||||
func (p *RawExtension) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return len(p.Data)
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of Extension interface.
|
||||
func (p *RawExtension) Marshal(proto int) ([]byte, error) {
|
||||
return p.Data, nil
|
||||
}
|
75
vendor/golang.org/x/net/icmp/helper_posix.go
generated
vendored
Normal file
75
vendor/golang.org/x/net/icmp/helper_posix.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func sockaddr(family int, address string) (syscall.Sockaddr, error) {
|
||||
switch family {
|
||||
case syscall.AF_INET:
|
||||
a, err := net.ResolveIPAddr("ip4", address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(a.IP) == 0 {
|
||||
a.IP = net.IPv4zero
|
||||
}
|
||||
if a.IP = a.IP.To4(); a.IP == nil {
|
||||
return nil, net.InvalidAddrError("non-ipv4 address")
|
||||
}
|
||||
sa := &syscall.SockaddrInet4{}
|
||||
copy(sa.Addr[:], a.IP)
|
||||
return sa, nil
|
||||
case syscall.AF_INET6:
|
||||
a, err := net.ResolveIPAddr("ip6", address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(a.IP) == 0 {
|
||||
a.IP = net.IPv6unspecified
|
||||
}
|
||||
if a.IP.Equal(net.IPv4zero) {
|
||||
a.IP = net.IPv6unspecified
|
||||
}
|
||||
if a.IP = a.IP.To16(); a.IP == nil || a.IP.To4() != nil {
|
||||
return nil, net.InvalidAddrError("non-ipv6 address")
|
||||
}
|
||||
sa := &syscall.SockaddrInet6{ZoneId: zoneToUint32(a.Zone)}
|
||||
copy(sa.Addr[:], a.IP)
|
||||
return sa, nil
|
||||
default:
|
||||
return nil, net.InvalidAddrError("unexpected family")
|
||||
}
|
||||
}
|
||||
|
||||
func zoneToUint32(zone string) uint32 {
|
||||
if zone == "" {
|
||||
return 0
|
||||
}
|
||||
if ifi, err := net.InterfaceByName(zone); err == nil {
|
||||
return uint32(ifi.Index)
|
||||
}
|
||||
n, err := strconv.Atoi(zone)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return uint32(n)
|
||||
}
|
||||
|
||||
func last(s string, b byte) int {
|
||||
i := len(s)
|
||||
for i--; i >= 0; i-- {
|
||||
if s[i] == b {
|
||||
break
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
322
vendor/golang.org/x/net/icmp/interface.go
generated
vendored
Normal file
322
vendor/golang.org/x/net/icmp/interface.go
generated
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
)
|
||||
|
||||
const (
|
||||
classInterfaceInfo = 2
|
||||
)
|
||||
|
||||
const (
|
||||
attrMTU = 1 << iota
|
||||
attrName
|
||||
attrIPAddr
|
||||
attrIfIndex
|
||||
)
|
||||
|
||||
// An InterfaceInfo represents interface and next-hop identification.
|
||||
type InterfaceInfo struct {
|
||||
Class int // extension object class number
|
||||
Type int // extension object sub-type
|
||||
Interface *net.Interface
|
||||
Addr *net.IPAddr
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) nameLen() int {
|
||||
if len(ifi.Interface.Name) > 63 {
|
||||
return 64
|
||||
}
|
||||
l := 1 + len(ifi.Interface.Name)
|
||||
return (l + 3) &^ 3
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) attrsAndLen(proto int) (attrs, l int) {
|
||||
l = 4
|
||||
if ifi.Interface != nil && ifi.Interface.Index > 0 {
|
||||
attrs |= attrIfIndex
|
||||
l += 4
|
||||
if len(ifi.Interface.Name) > 0 {
|
||||
attrs |= attrName
|
||||
l += ifi.nameLen()
|
||||
}
|
||||
if ifi.Interface.MTU > 0 {
|
||||
attrs |= attrMTU
|
||||
l += 4
|
||||
}
|
||||
}
|
||||
if ifi.Addr != nil {
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
if ifi.Addr.IP.To4() != nil {
|
||||
attrs |= attrIPAddr
|
||||
l += 4 + net.IPv4len
|
||||
}
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
if ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
|
||||
attrs |= attrIPAddr
|
||||
l += 4 + net.IPv6len
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Len implements the Len method of Extension interface.
|
||||
func (ifi *InterfaceInfo) Len(proto int) int {
|
||||
_, l := ifi.attrsAndLen(proto)
|
||||
return l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of Extension interface.
|
||||
func (ifi *InterfaceInfo) Marshal(proto int) ([]byte, error) {
|
||||
attrs, l := ifi.attrsAndLen(proto)
|
||||
b := make([]byte, l)
|
||||
if err := ifi.marshal(proto, b, attrs, l); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshal(proto int, b []byte, attrs, l int) error {
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(l))
|
||||
b[2], b[3] = classInterfaceInfo, byte(ifi.Type)
|
||||
for b = b[4:]; len(b) > 0 && attrs != 0; {
|
||||
switch {
|
||||
case attrs&attrIfIndex != 0:
|
||||
b = ifi.marshalIfIndex(proto, b)
|
||||
attrs &^= attrIfIndex
|
||||
case attrs&attrIPAddr != 0:
|
||||
b = ifi.marshalIPAddr(proto, b)
|
||||
attrs &^= attrIPAddr
|
||||
case attrs&attrName != 0:
|
||||
b = ifi.marshalName(proto, b)
|
||||
attrs &^= attrName
|
||||
case attrs&attrMTU != 0:
|
||||
b = ifi.marshalMTU(proto, b)
|
||||
attrs &^= attrMTU
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshalIfIndex(proto int, b []byte) []byte {
|
||||
binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.Index))
|
||||
return b[4:]
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) parseIfIndex(b []byte) ([]byte, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
ifi.Interface.Index = int(binary.BigEndian.Uint32(b[:4]))
|
||||
return b[4:], nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshalIPAddr(proto int, b []byte) []byte {
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv4))
|
||||
copy(b[4:4+net.IPv4len], ifi.Addr.IP.To4())
|
||||
b = b[4+net.IPv4len:]
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(iana.AddrFamilyIPv6))
|
||||
copy(b[4:4+net.IPv6len], ifi.Addr.IP.To16())
|
||||
b = b[4+net.IPv6len:]
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) parseIPAddr(b []byte) ([]byte, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
afi := int(binary.BigEndian.Uint16(b[:2]))
|
||||
b = b[4:]
|
||||
switch afi {
|
||||
case iana.AddrFamilyIPv4:
|
||||
if len(b) < net.IPv4len {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
ifi.Addr.IP = make(net.IP, net.IPv4len)
|
||||
copy(ifi.Addr.IP, b[:net.IPv4len])
|
||||
b = b[net.IPv4len:]
|
||||
case iana.AddrFamilyIPv6:
|
||||
if len(b) < net.IPv6len {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
ifi.Addr.IP = make(net.IP, net.IPv6len)
|
||||
copy(ifi.Addr.IP, b[:net.IPv6len])
|
||||
b = b[net.IPv6len:]
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshalName(proto int, b []byte) []byte {
|
||||
l := byte(ifi.nameLen())
|
||||
b[0] = l
|
||||
copy(b[1:], []byte(ifi.Interface.Name))
|
||||
return b[l:]
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) parseName(b []byte) ([]byte, error) {
|
||||
if 4 > len(b) || len(b) < int(b[0]) {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
l := int(b[0])
|
||||
if l%4 != 0 || 4 > l || l > 64 {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
var name [63]byte
|
||||
copy(name[:], b[1:l])
|
||||
ifi.Interface.Name = strings.Trim(string(name[:]), "\000")
|
||||
return b[l:], nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) marshalMTU(proto int, b []byte) []byte {
|
||||
binary.BigEndian.PutUint32(b[:4], uint32(ifi.Interface.MTU))
|
||||
return b[4:]
|
||||
}
|
||||
|
||||
func (ifi *InterfaceInfo) parseMTU(b []byte) ([]byte, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
ifi.Interface.MTU = int(binary.BigEndian.Uint32(b[:4]))
|
||||
return b[4:], nil
|
||||
}
|
||||
|
||||
func parseInterfaceInfo(b []byte) (Extension, error) {
|
||||
ifi := &InterfaceInfo{
|
||||
Class: int(b[2]),
|
||||
Type: int(b[3]),
|
||||
}
|
||||
if ifi.Type&(attrIfIndex|attrName|attrMTU) != 0 {
|
||||
ifi.Interface = &net.Interface{}
|
||||
}
|
||||
if ifi.Type&attrIPAddr != 0 {
|
||||
ifi.Addr = &net.IPAddr{}
|
||||
}
|
||||
attrs := ifi.Type & (attrIfIndex | attrIPAddr | attrName | attrMTU)
|
||||
for b = b[4:]; len(b) > 0 && attrs != 0; {
|
||||
var err error
|
||||
switch {
|
||||
case attrs&attrIfIndex != 0:
|
||||
b, err = ifi.parseIfIndex(b)
|
||||
attrs &^= attrIfIndex
|
||||
case attrs&attrIPAddr != 0:
|
||||
b, err = ifi.parseIPAddr(b)
|
||||
attrs &^= attrIPAddr
|
||||
case attrs&attrName != 0:
|
||||
b, err = ifi.parseName(b)
|
||||
attrs &^= attrName
|
||||
case attrs&attrMTU != 0:
|
||||
b, err = ifi.parseMTU(b)
|
||||
attrs &^= attrMTU
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if ifi.Interface != nil && ifi.Interface.Name != "" && ifi.Addr != nil && ifi.Addr.IP.To16() != nil && ifi.Addr.IP.To4() == nil {
|
||||
ifi.Addr.Zone = ifi.Interface.Name
|
||||
}
|
||||
return ifi, nil
|
||||
}
|
||||
|
||||
const (
|
||||
classInterfaceIdent = 3
|
||||
typeInterfaceByName = 1
|
||||
typeInterfaceByIndex = 2
|
||||
typeInterfaceByAddress = 3
|
||||
)
|
||||
|
||||
// An InterfaceIdent represents interface identification.
|
||||
type InterfaceIdent struct {
|
||||
Class int // extension object class number
|
||||
Type int // extension object sub-type
|
||||
Name string // interface name
|
||||
Index int // interface index
|
||||
AFI int // address family identifier; see address family numbers in IANA registry
|
||||
Addr []byte // address
|
||||
}
|
||||
|
||||
// Len implements the Len method of Extension interface.
|
||||
func (ifi *InterfaceIdent) Len(_ int) int {
|
||||
switch ifi.Type {
|
||||
case typeInterfaceByName:
|
||||
l := len(ifi.Name)
|
||||
if l > 255 {
|
||||
l = 255
|
||||
}
|
||||
return 4 + (l+3)&^3
|
||||
case typeInterfaceByIndex:
|
||||
return 4 + 4
|
||||
case typeInterfaceByAddress:
|
||||
return 4 + 4 + (len(ifi.Addr)+3)&^3
|
||||
default:
|
||||
return 4
|
||||
}
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of Extension interface.
|
||||
func (ifi *InterfaceIdent) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, ifi.Len(proto))
|
||||
if err := ifi.marshal(proto, b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (ifi *InterfaceIdent) marshal(proto int, b []byte) error {
|
||||
l := ifi.Len(proto)
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(l))
|
||||
b[2], b[3] = classInterfaceIdent, byte(ifi.Type)
|
||||
switch ifi.Type {
|
||||
case typeInterfaceByName:
|
||||
copy(b[4:], ifi.Name)
|
||||
case typeInterfaceByIndex:
|
||||
binary.BigEndian.PutUint32(b[4:4+4], uint32(ifi.Index))
|
||||
case typeInterfaceByAddress:
|
||||
binary.BigEndian.PutUint16(b[4:4+2], uint16(ifi.AFI))
|
||||
b[4+2] = byte(len(ifi.Addr))
|
||||
copy(b[4+4:], ifi.Addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseInterfaceIdent(b []byte) (Extension, error) {
|
||||
ifi := &InterfaceIdent{
|
||||
Class: int(b[2]),
|
||||
Type: int(b[3]),
|
||||
}
|
||||
switch ifi.Type {
|
||||
case typeInterfaceByName:
|
||||
ifi.Name = strings.Trim(string(b[4:]), "\x00")
|
||||
case typeInterfaceByIndex:
|
||||
if len(b[4:]) < 4 {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
ifi.Index = int(binary.BigEndian.Uint32(b[4 : 4+4]))
|
||||
case typeInterfaceByAddress:
|
||||
if len(b[4:]) < 4 {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
ifi.AFI = int(binary.BigEndian.Uint16(b[4 : 4+2]))
|
||||
l := int(b[4+2])
|
||||
if len(b[4+4:]) < l {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
ifi.Addr = make([]byte, l)
|
||||
copy(ifi.Addr, b[4+4:])
|
||||
}
|
||||
return ifi, nil
|
||||
}
|
69
vendor/golang.org/x/net/icmp/ipv4.go
generated
vendored
Normal file
69
vendor/golang.org/x/net/icmp/ipv4.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/net/internal/socket"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
// freebsdVersion is set in sys_freebsd.go.
|
||||
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
|
||||
var freebsdVersion uint32
|
||||
|
||||
// ParseIPv4Header returns the IPv4 header of the IPv4 packet that
|
||||
// triggered an ICMP error message.
|
||||
// This is found in the Data field of the ICMP error message body.
|
||||
//
|
||||
// The provided b must be in the format used by a raw ICMP socket on
|
||||
// the local system.
|
||||
// This may differ from the wire format, and the format used by a raw
|
||||
// IP socket, depending on the system.
|
||||
//
|
||||
// To parse an IPv6 header, use ipv6.ParseHeader.
|
||||
func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
|
||||
if len(b) < ipv4.HeaderLen {
|
||||
return nil, errHeaderTooShort
|
||||
}
|
||||
hdrlen := int(b[0]&0x0f) << 2
|
||||
if hdrlen > len(b) {
|
||||
return nil, errBufferTooShort
|
||||
}
|
||||
h := &ipv4.Header{
|
||||
Version: int(b[0] >> 4),
|
||||
Len: hdrlen,
|
||||
TOS: int(b[1]),
|
||||
ID: int(binary.BigEndian.Uint16(b[4:6])),
|
||||
FragOff: int(binary.BigEndian.Uint16(b[6:8])),
|
||||
TTL: int(b[8]),
|
||||
Protocol: int(b[9]),
|
||||
Checksum: int(binary.BigEndian.Uint16(b[10:12])),
|
||||
Src: net.IPv4(b[12], b[13], b[14], b[15]),
|
||||
Dst: net.IPv4(b[16], b[17], b[18], b[19]),
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "ios":
|
||||
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
|
||||
case "freebsd":
|
||||
if freebsdVersion >= 1000000 {
|
||||
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
|
||||
} else {
|
||||
h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
|
||||
}
|
||||
default:
|
||||
h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
|
||||
}
|
||||
h.Flags = ipv4.HeaderFlags(h.FragOff&0xe000) >> 13
|
||||
h.FragOff = h.FragOff & 0x1fff
|
||||
if hdrlen-ipv4.HeaderLen > 0 {
|
||||
h.Options = make([]byte, hdrlen-ipv4.HeaderLen)
|
||||
copy(h.Options, b[ipv4.HeaderLen:])
|
||||
}
|
||||
return h, nil
|
||||
}
|
23
vendor/golang.org/x/net/icmp/ipv6.go
generated
vendored
Normal file
23
vendor/golang.org/x/net/icmp/ipv6.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
)
|
||||
|
||||
const ipv6PseudoHeaderLen = 2*net.IPv6len + 8
|
||||
|
||||
// IPv6PseudoHeader returns an IPv6 pseudo header for checksum
|
||||
// calculation.
|
||||
func IPv6PseudoHeader(src, dst net.IP) []byte {
|
||||
b := make([]byte, ipv6PseudoHeaderLen)
|
||||
copy(b, src.To16())
|
||||
copy(b[net.IPv6len:], dst.To16())
|
||||
b[len(b)-1] = byte(iana.ProtocolIPv6ICMP)
|
||||
return b
|
||||
}
|
103
vendor/golang.org/x/net/icmp/listen_posix.go
generated
vendored
Normal file
103
vendor/golang.org/x/net/icmp/listen_posix.go
generated
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
const sysIP_STRIPHDR = 0x17 // for now only darwin supports this option
|
||||
|
||||
// ListenPacket listens for incoming ICMP packets addressed to
|
||||
// address. See net.Dial for the syntax of address.
|
||||
//
|
||||
// For non-privileged datagram-oriented ICMP endpoints, network must
|
||||
// be "udp4" or "udp6". The endpoint allows to read, write a few
|
||||
// limited ICMP messages such as echo request and echo reply.
|
||||
// Currently only Darwin and Linux support this.
|
||||
//
|
||||
// Examples:
|
||||
// ListenPacket("udp4", "192.168.0.1")
|
||||
// ListenPacket("udp4", "0.0.0.0")
|
||||
// ListenPacket("udp6", "fe80::1%en0")
|
||||
// ListenPacket("udp6", "::")
|
||||
//
|
||||
// For privileged raw ICMP endpoints, network must be "ip4" or "ip6"
|
||||
// followed by a colon and an ICMP protocol number or name.
|
||||
//
|
||||
// Examples:
|
||||
// ListenPacket("ip4:icmp", "192.168.0.1")
|
||||
// ListenPacket("ip4:1", "0.0.0.0")
|
||||
// ListenPacket("ip6:ipv6-icmp", "fe80::1%en0")
|
||||
// ListenPacket("ip6:58", "::")
|
||||
func ListenPacket(network, address string) (*PacketConn, error) {
|
||||
var family, proto int
|
||||
switch network {
|
||||
case "udp4":
|
||||
family, proto = syscall.AF_INET, iana.ProtocolICMP
|
||||
case "udp6":
|
||||
family, proto = syscall.AF_INET6, iana.ProtocolIPv6ICMP
|
||||
default:
|
||||
i := last(network, ':')
|
||||
if i < 0 {
|
||||
i = len(network)
|
||||
}
|
||||
switch network[:i] {
|
||||
case "ip4":
|
||||
proto = iana.ProtocolICMP
|
||||
case "ip6":
|
||||
proto = iana.ProtocolIPv6ICMP
|
||||
}
|
||||
}
|
||||
var cerr error
|
||||
var c net.PacketConn
|
||||
switch family {
|
||||
case syscall.AF_INET, syscall.AF_INET6:
|
||||
s, err := syscall.Socket(family, syscall.SOCK_DGRAM, proto)
|
||||
if err != nil {
|
||||
return nil, os.NewSyscallError("socket", err)
|
||||
}
|
||||
if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && family == syscall.AF_INET {
|
||||
if err := syscall.SetsockoptInt(s, iana.ProtocolIP, sysIP_STRIPHDR, 1); err != nil {
|
||||
syscall.Close(s)
|
||||
return nil, os.NewSyscallError("setsockopt", err)
|
||||
}
|
||||
}
|
||||
sa, err := sockaddr(family, address)
|
||||
if err != nil {
|
||||
syscall.Close(s)
|
||||
return nil, err
|
||||
}
|
||||
if err := syscall.Bind(s, sa); err != nil {
|
||||
syscall.Close(s)
|
||||
return nil, os.NewSyscallError("bind", err)
|
||||
}
|
||||
f := os.NewFile(uintptr(s), "datagram-oriented icmp")
|
||||
c, cerr = net.FilePacketConn(f)
|
||||
f.Close()
|
||||
default:
|
||||
c, cerr = net.ListenPacket(network, address)
|
||||
}
|
||||
if cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
return &PacketConn{c: c, p4: ipv4.NewPacketConn(c)}, nil
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
return &PacketConn{c: c, p6: ipv6.NewPacketConn(c)}, nil
|
||||
default:
|
||||
return &PacketConn{c: c}, nil
|
||||
}
|
||||
}
|
33
vendor/golang.org/x/net/icmp/listen_stub.go
generated
vendored
Normal file
33
vendor/golang.org/x/net/icmp/listen_stub.go
generated
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
|
||||
|
||||
package icmp
|
||||
|
||||
// ListenPacket listens for incoming ICMP packets addressed to
|
||||
// address. See net.Dial for the syntax of address.
|
||||
//
|
||||
// For non-privileged datagram-oriented ICMP endpoints, network must
|
||||
// be "udp4" or "udp6". The endpoint allows to read, write a few
|
||||
// limited ICMP messages such as echo request and echo reply.
|
||||
// Currently only Darwin and Linux support this.
|
||||
//
|
||||
// Examples:
|
||||
// ListenPacket("udp4", "192.168.0.1")
|
||||
// ListenPacket("udp4", "0.0.0.0")
|
||||
// ListenPacket("udp6", "fe80::1%en0")
|
||||
// ListenPacket("udp6", "::")
|
||||
//
|
||||
// For privileged raw ICMP endpoints, network must be "ip4" or "ip6"
|
||||
// followed by a colon and an ICMP protocol number or name.
|
||||
//
|
||||
// Examples:
|
||||
// ListenPacket("ip4:icmp", "192.168.0.1")
|
||||
// ListenPacket("ip4:1", "0.0.0.0")
|
||||
// ListenPacket("ip6:ipv6-icmp", "fe80::1%en0")
|
||||
// ListenPacket("ip6:58", "::")
|
||||
func ListenPacket(network, address string) (*PacketConn, error) {
|
||||
return nil, errNotImplemented
|
||||
}
|
162
vendor/golang.org/x/net/icmp/message.go
generated
vendored
Normal file
162
vendor/golang.org/x/net/icmp/message.go
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package icmp provides basic functions for the manipulation of
|
||||
// messages used in the Internet Control Message Protocols,
|
||||
// ICMPv4 and ICMPv6.
|
||||
//
|
||||
// ICMPv4 and ICMPv6 are defined in RFC 792 and RFC 4443.
|
||||
// Multi-part message support for ICMP is defined in RFC 4884.
|
||||
// ICMP extensions for MPLS are defined in RFC 4950.
|
||||
// ICMP extensions for interface and next-hop identification are
|
||||
// defined in RFC 5837.
|
||||
// PROBE: A utility for probing interfaces is defined in RFC 8335.
|
||||
package icmp // import "golang.org/x/net/icmp"
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// BUG(mikio): This package is not implemented on JS, NaCl and Plan 9.
|
||||
|
||||
var (
|
||||
errInvalidConn = errors.New("invalid connection")
|
||||
errInvalidProtocol = errors.New("invalid protocol")
|
||||
errMessageTooShort = errors.New("message too short")
|
||||
errHeaderTooShort = errors.New("header too short")
|
||||
errBufferTooShort = errors.New("buffer too short")
|
||||
errInvalidBody = errors.New("invalid body")
|
||||
errNoExtension = errors.New("no extension")
|
||||
errInvalidExtension = errors.New("invalid extension")
|
||||
errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
|
||||
)
|
||||
|
||||
func checksum(b []byte) uint16 {
|
||||
csumcv := len(b) - 1 // checksum coverage
|
||||
s := uint32(0)
|
||||
for i := 0; i < csumcv; i += 2 {
|
||||
s += uint32(b[i+1])<<8 | uint32(b[i])
|
||||
}
|
||||
if csumcv&1 == 0 {
|
||||
s += uint32(b[csumcv])
|
||||
}
|
||||
s = s>>16 + s&0xffff
|
||||
s = s + s>>16
|
||||
return ^uint16(s)
|
||||
}
|
||||
|
||||
// A Type represents an ICMP message type.
|
||||
type Type interface {
|
||||
Protocol() int
|
||||
}
|
||||
|
||||
// A Message represents an ICMP message.
|
||||
type Message struct {
|
||||
Type Type // type, either ipv4.ICMPType or ipv6.ICMPType
|
||||
Code int // code
|
||||
Checksum int // checksum
|
||||
Body MessageBody // body
|
||||
}
|
||||
|
||||
// Marshal returns the binary encoding of the ICMP message m.
|
||||
//
|
||||
// For an ICMPv4 message, the returned message always contains the
|
||||
// calculated checksum field.
|
||||
//
|
||||
// For an ICMPv6 message, the returned message contains the calculated
|
||||
// checksum field when psh is not nil, otherwise the kernel will
|
||||
// compute the checksum field during the message transmission.
|
||||
// When psh is not nil, it must be the pseudo header for IPv6.
|
||||
func (m *Message) Marshal(psh []byte) ([]byte, error) {
|
||||
var mtype byte
|
||||
switch typ := m.Type.(type) {
|
||||
case ipv4.ICMPType:
|
||||
mtype = byte(typ)
|
||||
case ipv6.ICMPType:
|
||||
mtype = byte(typ)
|
||||
default:
|
||||
return nil, errInvalidProtocol
|
||||
}
|
||||
b := []byte{mtype, byte(m.Code), 0, 0}
|
||||
proto := m.Type.Protocol()
|
||||
if proto == iana.ProtocolIPv6ICMP && psh != nil {
|
||||
b = append(psh, b...)
|
||||
}
|
||||
if m.Body != nil && m.Body.Len(proto) != 0 {
|
||||
mb, err := m.Body.Marshal(proto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = append(b, mb...)
|
||||
}
|
||||
if proto == iana.ProtocolIPv6ICMP {
|
||||
if psh == nil { // cannot calculate checksum here
|
||||
return b, nil
|
||||
}
|
||||
off, l := 2*net.IPv6len, len(b)-len(psh)
|
||||
binary.BigEndian.PutUint32(b[off:off+4], uint32(l))
|
||||
}
|
||||
s := checksum(b)
|
||||
// Place checksum back in header; using ^= avoids the
|
||||
// assumption the checksum bytes are zero.
|
||||
b[len(psh)+2] ^= byte(s)
|
||||
b[len(psh)+3] ^= byte(s >> 8)
|
||||
return b[len(psh):], nil
|
||||
}
|
||||
|
||||
var parseFns = map[Type]func(int, Type, []byte) (MessageBody, error){
|
||||
ipv4.ICMPTypeDestinationUnreachable: parseDstUnreach,
|
||||
ipv4.ICMPTypeTimeExceeded: parseTimeExceeded,
|
||||
ipv4.ICMPTypeParameterProblem: parseParamProb,
|
||||
|
||||
ipv4.ICMPTypeEcho: parseEcho,
|
||||
ipv4.ICMPTypeEchoReply: parseEcho,
|
||||
ipv4.ICMPTypeExtendedEchoRequest: parseExtendedEchoRequest,
|
||||
ipv4.ICMPTypeExtendedEchoReply: parseExtendedEchoReply,
|
||||
|
||||
ipv6.ICMPTypeDestinationUnreachable: parseDstUnreach,
|
||||
ipv6.ICMPTypePacketTooBig: parsePacketTooBig,
|
||||
ipv6.ICMPTypeTimeExceeded: parseTimeExceeded,
|
||||
ipv6.ICMPTypeParameterProblem: parseParamProb,
|
||||
|
||||
ipv6.ICMPTypeEchoRequest: parseEcho,
|
||||
ipv6.ICMPTypeEchoReply: parseEcho,
|
||||
ipv6.ICMPTypeExtendedEchoRequest: parseExtendedEchoRequest,
|
||||
ipv6.ICMPTypeExtendedEchoReply: parseExtendedEchoReply,
|
||||
}
|
||||
|
||||
// ParseMessage parses b as an ICMP message.
|
||||
// The provided proto must be either the ICMPv4 or ICMPv6 protocol
|
||||
// number.
|
||||
func ParseMessage(proto int, b []byte) (*Message, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
var err error
|
||||
m := &Message{Code: int(b[1]), Checksum: int(binary.BigEndian.Uint16(b[2:4]))}
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
m.Type = ipv4.ICMPType(b[0])
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
m.Type = ipv6.ICMPType(b[0])
|
||||
default:
|
||||
return nil, errInvalidProtocol
|
||||
}
|
||||
if fn, ok := parseFns[m.Type]; !ok {
|
||||
m.Body, err = parseRawBody(proto, b[4:])
|
||||
} else {
|
||||
m.Body, err = fn(proto, m.Type, b[4:])
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
52
vendor/golang.org/x/net/icmp/messagebody.go
generated
vendored
Normal file
52
vendor/golang.org/x/net/icmp/messagebody.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
// A MessageBody represents an ICMP message body.
|
||||
type MessageBody interface {
|
||||
// Len returns the length of ICMP message body.
|
||||
// The provided proto must be either the ICMPv4 or ICMPv6
|
||||
// protocol number.
|
||||
Len(proto int) int
|
||||
|
||||
// Marshal returns the binary encoding of ICMP message body.
|
||||
// The provided proto must be either the ICMPv4 or ICMPv6
|
||||
// protocol number.
|
||||
Marshal(proto int) ([]byte, error)
|
||||
}
|
||||
|
||||
// A RawBody represents a raw message body.
|
||||
//
|
||||
// A raw message body is excluded from message processing and can be
|
||||
// used to construct applications such as protocol conformance
|
||||
// testing.
|
||||
type RawBody struct {
|
||||
Data []byte // data
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *RawBody) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return len(p.Data)
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *RawBody) Marshal(proto int) ([]byte, error) {
|
||||
return p.Data, nil
|
||||
}
|
||||
|
||||
// parseRawBody parses b as an ICMP message body.
|
||||
func parseRawBody(proto int, b []byte) (MessageBody, error) {
|
||||
p := &RawBody{Data: make([]byte, len(b))}
|
||||
copy(p.Data, b)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// A DefaultMessageBody represents the default message body.
|
||||
//
|
||||
// Deprecated: Use RawBody instead.
|
||||
type DefaultMessageBody = RawBody
|
77
vendor/golang.org/x/net/icmp/mpls.go
generated
vendored
Normal file
77
vendor/golang.org/x/net/icmp/mpls.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// MPLSLabel represents an MPLS label stack entry.
|
||||
type MPLSLabel struct {
|
||||
Label int // label value
|
||||
TC int // traffic class; formerly experimental use
|
||||
S bool // bottom of stack
|
||||
TTL int // time to live
|
||||
}
|
||||
|
||||
const (
|
||||
classMPLSLabelStack = 1
|
||||
typeIncomingMPLSLabelStack = 1
|
||||
)
|
||||
|
||||
// MPLSLabelStack represents an MPLS label stack.
|
||||
type MPLSLabelStack struct {
|
||||
Class int // extension object class number
|
||||
Type int // extension object sub-type
|
||||
Labels []MPLSLabel
|
||||
}
|
||||
|
||||
// Len implements the Len method of Extension interface.
|
||||
func (ls *MPLSLabelStack) Len(proto int) int {
|
||||
return 4 + (4 * len(ls.Labels))
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of Extension interface.
|
||||
func (ls *MPLSLabelStack) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, ls.Len(proto))
|
||||
if err := ls.marshal(proto, b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (ls *MPLSLabelStack) marshal(proto int, b []byte) error {
|
||||
l := ls.Len(proto)
|
||||
binary.BigEndian.PutUint16(b[:2], uint16(l))
|
||||
b[2], b[3] = classMPLSLabelStack, typeIncomingMPLSLabelStack
|
||||
off := 4
|
||||
for _, ll := range ls.Labels {
|
||||
b[off], b[off+1], b[off+2] = byte(ll.Label>>12), byte(ll.Label>>4&0xff), byte(ll.Label<<4&0xf0)
|
||||
b[off+2] |= byte(ll.TC << 1 & 0x0e)
|
||||
if ll.S {
|
||||
b[off+2] |= 0x1
|
||||
}
|
||||
b[off+3] = byte(ll.TTL)
|
||||
off += 4
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseMPLSLabelStack(b []byte) (Extension, error) {
|
||||
ls := &MPLSLabelStack{
|
||||
Class: int(b[2]),
|
||||
Type: int(b[3]),
|
||||
}
|
||||
for b = b[4:]; len(b) >= 4; b = b[4:] {
|
||||
ll := MPLSLabel{
|
||||
Label: int(b[0])<<12 | int(b[1])<<4 | int(b[2])>>4,
|
||||
TC: int(b[2]&0x0e) >> 1,
|
||||
TTL: int(b[3]),
|
||||
}
|
||||
if b[2]&0x1 != 0 {
|
||||
ll.S = true
|
||||
}
|
||||
ls.Labels = append(ls.Labels, ll)
|
||||
}
|
||||
return ls, nil
|
||||
}
|
129
vendor/golang.org/x/net/icmp/multipart.go
generated
vendored
Normal file
129
vendor/golang.org/x/net/icmp/multipart.go
generated
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import "golang.org/x/net/internal/iana"
|
||||
|
||||
// multipartMessageBodyDataLen takes b as an original datagram and
|
||||
// exts as extensions, and returns a required length for message body
|
||||
// and a required length for a padded original datagram in wire
|
||||
// format.
|
||||
func multipartMessageBodyDataLen(proto int, withOrigDgram bool, b []byte, exts []Extension) (bodyLen, dataLen int) {
|
||||
bodyLen = 4 // length of leading octets
|
||||
var extLen int
|
||||
var rawExt bool // raw extension may contain an empty object
|
||||
for _, ext := range exts {
|
||||
extLen += ext.Len(proto)
|
||||
if _, ok := ext.(*RawExtension); ok {
|
||||
rawExt = true
|
||||
}
|
||||
}
|
||||
if extLen > 0 && withOrigDgram {
|
||||
dataLen = multipartMessageOrigDatagramLen(proto, b)
|
||||
} else {
|
||||
dataLen = len(b)
|
||||
}
|
||||
if extLen > 0 || rawExt {
|
||||
bodyLen += 4 // length of extension header
|
||||
}
|
||||
bodyLen += dataLen + extLen
|
||||
return bodyLen, dataLen
|
||||
}
|
||||
|
||||
// multipartMessageOrigDatagramLen takes b as an original datagram,
|
||||
// and returns a required length for a padded orignal datagram in wire
|
||||
// format.
|
||||
func multipartMessageOrigDatagramLen(proto int, b []byte) int {
|
||||
roundup := func(b []byte, align int) int {
|
||||
// According to RFC 4884, the padded original datagram
|
||||
// field must contain at least 128 octets.
|
||||
if len(b) < 128 {
|
||||
return 128
|
||||
}
|
||||
r := len(b)
|
||||
return (r + align - 1) &^ (align - 1)
|
||||
}
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
return roundup(b, 4)
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
return roundup(b, 8)
|
||||
default:
|
||||
return len(b)
|
||||
}
|
||||
}
|
||||
|
||||
// marshalMultipartMessageBody takes data as an original datagram and
|
||||
// exts as extesnsions, and returns a binary encoding of message body.
|
||||
// It can be used for non-multipart message bodies when exts is nil.
|
||||
func marshalMultipartMessageBody(proto int, withOrigDgram bool, data []byte, exts []Extension) ([]byte, error) {
|
||||
bodyLen, dataLen := multipartMessageBodyDataLen(proto, withOrigDgram, data, exts)
|
||||
b := make([]byte, bodyLen)
|
||||
copy(b[4:], data)
|
||||
if len(exts) > 0 {
|
||||
b[4+dataLen] = byte(extensionVersion << 4)
|
||||
off := 4 + dataLen + 4 // leading octets, data, extension header
|
||||
for _, ext := range exts {
|
||||
switch ext := ext.(type) {
|
||||
case *MPLSLabelStack:
|
||||
if err := ext.marshal(proto, b[off:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
off += ext.Len(proto)
|
||||
case *InterfaceInfo:
|
||||
attrs, l := ext.attrsAndLen(proto)
|
||||
if err := ext.marshal(proto, b[off:], attrs, l); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
off += ext.Len(proto)
|
||||
case *InterfaceIdent:
|
||||
if err := ext.marshal(proto, b[off:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
off += ext.Len(proto)
|
||||
case *RawExtension:
|
||||
copy(b[off:], ext.Data)
|
||||
off += ext.Len(proto)
|
||||
}
|
||||
}
|
||||
s := checksum(b[4+dataLen:])
|
||||
b[4+dataLen+2] ^= byte(s)
|
||||
b[4+dataLen+3] ^= byte(s >> 8)
|
||||
if withOrigDgram {
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
b[1] = byte(dataLen / 4)
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
b[0] = byte(dataLen / 8)
|
||||
}
|
||||
}
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parseMultipartMessageBody parses b as either a non-multipart
|
||||
// message body or a multipart message body.
|
||||
func parseMultipartMessageBody(proto int, typ Type, b []byte) ([]byte, []Extension, error) {
|
||||
var l int
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
l = 4 * int(b[1])
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
l = 8 * int(b[0])
|
||||
}
|
||||
if len(b) == 4 {
|
||||
return nil, nil, nil
|
||||
}
|
||||
exts, l, err := parseExtensions(typ, b[4:], l)
|
||||
if err != nil {
|
||||
l = len(b) - 4
|
||||
}
|
||||
var data []byte
|
||||
if l > 0 {
|
||||
data = make([]byte, l)
|
||||
copy(data, b[4:])
|
||||
}
|
||||
return data, exts, nil
|
||||
}
|
43
vendor/golang.org/x/net/icmp/packettoobig.go
generated
vendored
Normal file
43
vendor/golang.org/x/net/icmp/packettoobig.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// A PacketTooBig represents an ICMP packet too big message body.
|
||||
type PacketTooBig struct {
|
||||
MTU int // maximum transmission unit of the nexthop link
|
||||
Data []byte // data, known as original datagram field
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *PacketTooBig) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
return 4 + len(p.Data)
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *PacketTooBig) Marshal(proto int) ([]byte, error) {
|
||||
b := make([]byte, 4+len(p.Data))
|
||||
binary.BigEndian.PutUint32(b[:4], uint32(p.MTU))
|
||||
copy(b[4:], p.Data)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// parsePacketTooBig parses b as an ICMP packet too big message body.
|
||||
func parsePacketTooBig(proto int, _ Type, b []byte) (MessageBody, error) {
|
||||
bodyLen := len(b)
|
||||
if bodyLen < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &PacketTooBig{MTU: int(binary.BigEndian.Uint32(b[:4]))}
|
||||
if bodyLen > 4 {
|
||||
p.Data = make([]byte, bodyLen-4)
|
||||
copy(p.Data, b[4:])
|
||||
}
|
||||
return p, nil
|
||||
}
|
72
vendor/golang.org/x/net/icmp/paramprob.go
generated
vendored
Normal file
72
vendor/golang.org/x/net/icmp/paramprob.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
)
|
||||
|
||||
// A ParamProb represents an ICMP parameter problem message body.
|
||||
type ParamProb struct {
|
||||
Pointer uintptr // offset within the data where the error was detected
|
||||
Data []byte // data, known as original datagram field
|
||||
Extensions []Extension // extensions
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *ParamProb) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
|
||||
return l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *ParamProb) Marshal(proto int) ([]byte, error) {
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
if !validExtensions(ipv4.ICMPTypeParameterProblem, p.Extensions) {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
b, err := marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b[0] = byte(p.Pointer)
|
||||
return b, nil
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
b := make([]byte, p.Len(proto))
|
||||
binary.BigEndian.PutUint32(b[:4], uint32(p.Pointer))
|
||||
copy(b[4:], p.Data)
|
||||
return b, nil
|
||||
default:
|
||||
return nil, errInvalidProtocol
|
||||
}
|
||||
}
|
||||
|
||||
// parseParamProb parses b as an ICMP parameter problem message body.
|
||||
func parseParamProb(proto int, typ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &ParamProb{}
|
||||
if proto == iana.ProtocolIPv6ICMP {
|
||||
p.Pointer = uintptr(binary.BigEndian.Uint32(b[:4]))
|
||||
p.Data = make([]byte, len(b)-4)
|
||||
copy(p.Data, b[4:])
|
||||
return p, nil
|
||||
}
|
||||
p.Pointer = uintptr(b[0])
|
||||
var err error
|
||||
p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
11
vendor/golang.org/x/net/icmp/sys_freebsd.go
generated
vendored
Normal file
11
vendor/golang.org/x/net/icmp/sys_freebsd.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import "syscall"
|
||||
|
||||
func init() {
|
||||
freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
|
||||
}
|
57
vendor/golang.org/x/net/icmp/timeexceeded.go
generated
vendored
Normal file
57
vendor/golang.org/x/net/icmp/timeexceeded.go
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package icmp
|
||||
|
||||
import (
|
||||
"golang.org/x/net/internal/iana"
|
||||
"golang.org/x/net/ipv4"
|
||||
"golang.org/x/net/ipv6"
|
||||
)
|
||||
|
||||
// A TimeExceeded represents an ICMP time exceeded message body.
|
||||
type TimeExceeded struct {
|
||||
Data []byte // data, known as original datagram field
|
||||
Extensions []Extension // extensions
|
||||
}
|
||||
|
||||
// Len implements the Len method of MessageBody interface.
|
||||
func (p *TimeExceeded) Len(proto int) int {
|
||||
if p == nil {
|
||||
return 0
|
||||
}
|
||||
l, _ := multipartMessageBodyDataLen(proto, true, p.Data, p.Extensions)
|
||||
return l
|
||||
}
|
||||
|
||||
// Marshal implements the Marshal method of MessageBody interface.
|
||||
func (p *TimeExceeded) Marshal(proto int) ([]byte, error) {
|
||||
var typ Type
|
||||
switch proto {
|
||||
case iana.ProtocolICMP:
|
||||
typ = ipv4.ICMPTypeTimeExceeded
|
||||
case iana.ProtocolIPv6ICMP:
|
||||
typ = ipv6.ICMPTypeTimeExceeded
|
||||
default:
|
||||
return nil, errInvalidProtocol
|
||||
}
|
||||
if !validExtensions(typ, p.Extensions) {
|
||||
return nil, errInvalidExtension
|
||||
}
|
||||
return marshalMultipartMessageBody(proto, true, p.Data, p.Extensions)
|
||||
}
|
||||
|
||||
// parseTimeExceeded parses b as an ICMP time exceeded message body.
|
||||
func parseTimeExceeded(proto int, typ Type, b []byte) (MessageBody, error) {
|
||||
if len(b) < 4 {
|
||||
return nil, errMessageTooShort
|
||||
}
|
||||
p := &TimeExceeded{}
|
||||
var err error
|
||||
p.Data, p.Extensions, err = parseMultipartMessageBody(proto, typ, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p, nil
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// +build go1.14
|
||||
// +build go1.14,!go1.16
|
||||
|
||||
package idna
|
||||
|
4839
vendor/golang.org/x/net/idna/tables13.0.0.go
generated
vendored
Normal file
4839
vendor/golang.org/x/net/idna/tables13.0.0.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
2
vendor/golang.org/x/net/internal/socket/cmsghdr.go
generated
vendored
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos
|
||||
|
||||
package socket
|
||||
|
||||
|
16
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
16
vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
generated
vendored
@ -2,13 +2,23 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
|
||||
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos
|
||||
|
||||
package socket
|
||||
|
||||
type cmsghdr struct{}
|
||||
func controlHeaderLen() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
const sizeofCmsghdr = 0
|
||||
func controlMessageLen(dataLen int) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func controlMessageSpace(dataLen int) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
type cmsghdr struct{}
|
||||
|
||||
func (h *cmsghdr) len() int { return 0 }
|
||||
func (h *cmsghdr) lvl() int { return 0 }
|
||||
|
21
vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
generated
vendored
Normal file
21
vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package socket
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
func controlHeaderLen() int {
|
||||
return unix.CmsgLen(0)
|
||||
}
|
||||
|
||||
func controlMessageLen(dataLen int) int {
|
||||
return unix.CmsgLen(dataLen)
|
||||
}
|
||||
|
||||
func controlMessageSpace(dataLen int) int {
|
||||
return unix.CmsgSpace(dataLen)
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user