mirror of
https://github.com/AdguardTeam/AdGuardDNS.git
synced 2025-02-20 11:23:36 +08:00
Sync with upstream
This commit is contained in:
parent
151fc83b68
commit
c2344850da
@ -1,5 +0,0 @@
|
|||||||
# alternate
|
|
||||||
|
|
||||||
Fork of https://github.com/coredns/alternate
|
|
||||||
|
|
||||||
The purpose is to keep it working with the new CoreDNS version and use our fork of "forward".
|
|
@ -1,70 +0,0 @@
|
|||||||
// Package alternate implements a alternate plugin for CoreDNS
|
|
||||||
package alternate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/nonwriter"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Alternate plugin allows an alternate set of upstreams be specified which will be used
|
|
||||||
// if the plugin chain returns specific error messages.
|
|
||||||
type Alternate struct {
|
|
||||||
Next plugin.Handler
|
|
||||||
rules map[int]rule
|
|
||||||
original bool // At least one rule has "original" flag
|
|
||||||
}
|
|
||||||
|
|
||||||
type rule struct {
|
|
||||||
original bool
|
|
||||||
handler HandlerWithCallbacks
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandlerWithCallbacks interface is made for handling the requests
|
|
||||||
type HandlerWithCallbacks interface {
|
|
||||||
plugin.Handler
|
|
||||||
OnStartup() error
|
|
||||||
OnShutdown() error
|
|
||||||
}
|
|
||||||
|
|
||||||
// New initializes Alternate plugin
|
|
||||||
func New() (f *Alternate) {
|
|
||||||
return &Alternate{rules: make(map[int]rule)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServeDNS implements the plugin.Handler interface.
|
|
||||||
func (f Alternate) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
||||||
// If alternate has original option set for any code then copy original request to use it instead of changed
|
|
||||||
var originalRequest *dns.Msg
|
|
||||||
if f.original {
|
|
||||||
originalRequest = r.Copy()
|
|
||||||
}
|
|
||||||
nw := nonwriter.New(w)
|
|
||||||
rcode, err := plugin.NextOrFailure(f.Name(), f.Next, ctx, nw, r)
|
|
||||||
|
|
||||||
//By default the rulesIndex is equal rcode, so in such way we handle the case
|
|
||||||
//when rcode is SERVFAIL and nw.Msg is nil, otherwise we use nw.Msg.Rcode
|
|
||||||
//because, for example, for the following cases like NXDOMAIN, REFUSED the rcode is 0 (returned by forward)
|
|
||||||
//A forward doesn't return 0 only in case SERVFAIL
|
|
||||||
rulesIndex := rcode
|
|
||||||
if nw.Msg != nil {
|
|
||||||
rulesIndex = nw.Msg.Rcode
|
|
||||||
}
|
|
||||||
|
|
||||||
if u, ok := f.rules[rulesIndex]; ok {
|
|
||||||
if u.original && originalRequest != nil {
|
|
||||||
return u.handler.ServeDNS(ctx, w, originalRequest)
|
|
||||||
}
|
|
||||||
return u.handler.ServeDNS(ctx, w, r)
|
|
||||||
}
|
|
||||||
if nw.Msg != nil {
|
|
||||||
w.WriteMsg(nw.Msg)
|
|
||||||
}
|
|
||||||
return rcode, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name implements the Handler interface.
|
|
||||||
func (f Alternate) Name() string { return "alternate" }
|
|
@ -1,221 +0,0 @@
|
|||||||
package alternate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
|
||||||
"github.com/coredns/coredns/plugin/test"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// testHandler implements HandlerWithCallbacks to mock handler
|
|
||||||
type testHandler struct {
|
|
||||||
rcode int
|
|
||||||
called int
|
|
||||||
lastIsEdns0 bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// newTestHandler sets up handler (forward plugin) mock. It returns rcode defined in parameter.
|
|
||||||
func newTestHandler(rcode int) *testHandler {
|
|
||||||
return &testHandler{rcode: rcode}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *testHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
||||||
h.lastIsEdns0 = r.IsEdns0() != nil
|
|
||||||
h.called++
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
ret.Answer = append(ret.Answer, test.A("example.org. IN A 127.0.0.1"))
|
|
||||||
ret.Rcode = h.rcode
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
return 0, nil
|
|
||||||
}
|
|
||||||
func (h *testHandler) Name() string { return "testHandler" }
|
|
||||||
func (h *testHandler) OnStartup() error { return nil }
|
|
||||||
func (h *testHandler) OnShutdown() error { return nil }
|
|
||||||
|
|
||||||
// stubNextHandler is used to simulate a rewrite and forward plugin.
|
|
||||||
// It returns a stub Handler that returns the rcode and err specified when invoked.
|
|
||||||
// Also it adds edns0 option to given request.
|
|
||||||
func stubNextHandler(rcode int, err error) test.Handler {
|
|
||||||
return test.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
||||||
returnCode := rcode
|
|
||||||
if r == nil {
|
|
||||||
r = &dns.Msg{}
|
|
||||||
}
|
|
||||||
r.SetEdns0(4096, false)
|
|
||||||
if rcode != dns.RcodeServerFailure {
|
|
||||||
r.MsgHdr.Rcode = rcode
|
|
||||||
returnCode = dns.RcodeSuccess
|
|
||||||
w.WriteMsg(r)
|
|
||||||
} else {
|
|
||||||
w.WriteMsg(nil)
|
|
||||||
}
|
|
||||||
return returnCode, err
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// makeTestCall makes test call to handler
|
|
||||||
func makeTestCall(handler *Alternate) (*dnstest.Recorder, int, error) {
|
|
||||||
// Prepare query and make a call
|
|
||||||
ctx := context.TODO()
|
|
||||||
req := &dns.Msg{
|
|
||||||
Question: []dns.Question{{
|
|
||||||
Name: "abc.com.",
|
|
||||||
Qclass: dns.ClassINET,
|
|
||||||
Qtype: dns.TypeA,
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
|
|
||||||
rec := dnstest.NewRecorder(&test.ResponseWriter{})
|
|
||||||
rcode, err := handler.ServeDNS(ctx, rec, req)
|
|
||||||
return rec, rcode, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test case for alternate
|
|
||||||
type alternateTestCase struct {
|
|
||||||
nextRcode int // rcode to be returned by the stub Handler
|
|
||||||
expectedRcode int // this is expected rcode by test handler (forward plugin)
|
|
||||||
called int // this is expected number of calls reached test alternate server
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAlternate(t *testing.T) {
|
|
||||||
testCases := []alternateTestCase{
|
|
||||||
{
|
|
||||||
nextRcode: dns.RcodeNXRrset,
|
|
||||||
expectedRcode: dns.RcodeRefused,
|
|
||||||
called: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nextRcode: dns.RcodeServerFailure,
|
|
||||||
expectedRcode: dns.RcodeRefused,
|
|
||||||
called: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
//No such code in table.
|
|
||||||
nextRcode: dns.RcodeBadName,
|
|
||||||
expectedRcode: dns.RcodeBadName, //Remains from nextRcode
|
|
||||||
called: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
//No such code in table.
|
|
||||||
nextRcode: dns.RcodeRefused,
|
|
||||||
expectedRcode: dns.RcodeRefused, //Remains from nextRcode
|
|
||||||
called: 0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for testNum, tc := range testCases {
|
|
||||||
// mocked Forward for servicing a specific rcode
|
|
||||||
h := newTestHandler(dns.RcodeRefused)
|
|
||||||
|
|
||||||
handler := New()
|
|
||||||
// create stub handler to return the test rcode
|
|
||||||
handler.Next = stubNextHandler(tc.nextRcode, nil)
|
|
||||||
// add rules
|
|
||||||
handler.rules = map[int]rule{
|
|
||||||
dns.RcodeNXRrset: {handler: h},
|
|
||||||
dns.RcodeServerFailure: {handler: h},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare query and make a call
|
|
||||||
rec, rcode, err := makeTestCall(handler)
|
|
||||||
|
|
||||||
// Ensure that no errors returned
|
|
||||||
if rcode != dns.RcodeSuccess || err != nil {
|
|
||||||
t.Errorf("Test '%d': Alternate returned code '%d' error '%v'. Expected RcodeSuccess (0) and no error",
|
|
||||||
testNum, rcode, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that overall returned code is correct
|
|
||||||
if rec.Rcode != tc.expectedRcode {
|
|
||||||
t.Errorf("Test '%d': Alternate returned code '%v (%d)', but expected '%v (%d)'",
|
|
||||||
testNum, dns.RcodeToString[rec.Rcode], rec.Rcode, dns.RcodeToString[tc.expectedRcode], tc.expectedRcode)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that server was called required number of times
|
|
||||||
if h.called != tc.called {
|
|
||||||
t.Errorf("Test '%d': Server expected to be called %d time(s) but called %d times(s)",
|
|
||||||
testNum, tc.called, h.called)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAlternateMultipleCalls(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
nextRcode int
|
|
||||||
called int
|
|
||||||
}{
|
|
||||||
{nextRcode: dns.RcodeNXRrset, called: 10},
|
|
||||||
// No RcodeBadName in table. So, no calls to test server made.
|
|
||||||
{nextRcode: dns.RcodeBadName, called: 0},
|
|
||||||
}
|
|
||||||
|
|
||||||
for testNum, tc := range testCases {
|
|
||||||
// mocked Forward for servicing a specific rcode
|
|
||||||
h := newTestHandler(dns.RcodeRefused)
|
|
||||||
|
|
||||||
handler := New()
|
|
||||||
// create stub handler to return the test rcode
|
|
||||||
handler.Next = stubNextHandler(tc.nextRcode, nil)
|
|
||||||
// add rules
|
|
||||||
handler.rules = map[int]rule{
|
|
||||||
dns.RcodeNXRrset: {handler: h},
|
|
||||||
dns.RcodeServerFailure: {handler: h},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare query and make 10 calls
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
makeTestCall(handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that server was called required number of times
|
|
||||||
if h.called != tc.called {
|
|
||||||
t.Errorf("Test '%d': Server expected to be called %d time(s) but called %d times(s)",
|
|
||||||
testNum, tc.called, h.called)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAlternateOriginal(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
nextRcode int
|
|
||||||
isEdns0 bool
|
|
||||||
}{
|
|
||||||
// isEdns0 is rewrited by original
|
|
||||||
{nextRcode: dns.RcodeNXRrset, isEdns0: false},
|
|
||||||
// RcodeServerFailure hasn't original flag set. isEdns0 remains the same
|
|
||||||
{nextRcode: dns.RcodeServerFailure, isEdns0: true},
|
|
||||||
}
|
|
||||||
|
|
||||||
for testNum, tc := range testCases {
|
|
||||||
// mocked Forward for servicing a specific rcode
|
|
||||||
h := newTestHandler(dns.RcodeRefused)
|
|
||||||
|
|
||||||
handler := New()
|
|
||||||
// One of rules has "original" flag set
|
|
||||||
handler.original = true
|
|
||||||
// create stub handler to return the test rcode
|
|
||||||
handler.Next = stubNextHandler(tc.nextRcode, nil)
|
|
||||||
// add rules
|
|
||||||
handler.rules = map[int]rule{
|
|
||||||
dns.RcodeNXRrset: {original: true, handler: h},
|
|
||||||
dns.RcodeServerFailure: {handler: h},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare query and make a call
|
|
||||||
makeTestCall(handler)
|
|
||||||
|
|
||||||
// Ensure edns0 option has expected state
|
|
||||||
if h.lastIsEdns0 != tc.isEdns0 {
|
|
||||||
if tc.isEdns0 {
|
|
||||||
t.Errorf("Test '%d': Server expected to recieve Edns0, but didn't", testNum)
|
|
||||||
} else {
|
|
||||||
t.Errorf("Test '%d': Server not expected to recieve Edns0, but received it", testNum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package alternate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardDNS/forward"
|
|
||||||
"github.com/coredns/coredns/core/dnsserver"
|
|
||||||
"github.com/coredns/coredns/plugin"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy"
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
caddy.RegisterPlugin("alternate", caddy.Plugin{
|
|
||||||
ServerType: "dns",
|
|
||||||
Action: setup,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func setup(c *caddy.Controller) error {
|
|
||||||
a := New()
|
|
||||||
|
|
||||||
for c.Next() {
|
|
||||||
var (
|
|
||||||
original bool
|
|
||||||
rcode string
|
|
||||||
)
|
|
||||||
if !c.Dispenser.Args(&rcode) {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
if rcode == "original" {
|
|
||||||
original = true
|
|
||||||
// Reread parameter is not rcode. Get it again.
|
|
||||||
if !c.Dispenser.Args(&rcode) {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rc, ok := dns.StringToRcode[strings.ToUpper(rcode)]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%s is not a valid rcode", rcode)
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := forward.ParseForwardStanza(c)
|
|
||||||
if err != nil {
|
|
||||||
return plugin.Error("alternate", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := a.rules[rc]; ok {
|
|
||||||
return fmt.Errorf("rcode '%s' is specified more than once", rcode)
|
|
||||||
}
|
|
||||||
a.rules[rc] = rule{original: original, handler: u}
|
|
||||||
if original {
|
|
||||||
a.original = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
|
|
||||||
a.Next = next
|
|
||||||
return a
|
|
||||||
})
|
|
||||||
|
|
||||||
c.OnStartup(func() error {
|
|
||||||
for _, r := range a.rules {
|
|
||||||
if err := r.handler.OnStartup(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
c.OnShutdown(func() error {
|
|
||||||
for _, r := range a.rules {
|
|
||||||
if err := r.handler.OnShutdown(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
package alternate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy"
|
|
||||||
)
|
|
||||||
|
|
||||||
type setupTestCase struct {
|
|
||||||
config string
|
|
||||||
expectedError string
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetupAlternate(t *testing.T) {
|
|
||||||
testCases := []setupTestCase{
|
|
||||||
{
|
|
||||||
config: `alternate REFUSED . 192.168.1.1:53`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate SERVFAIL . 192.168.1.1:53`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate NXDOMAIN . 192.168.1.1:53`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate original NXDOMAIN . 192.168.1.1:53`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate REFUSE . 192.168.1.1:53`,
|
|
||||||
expectedError: `is not a valid rcode`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate SRVFAIL . 192.168.1.1:53`,
|
|
||||||
expectedError: `is not a valid rcode`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate NODOMAIN . 192.168.1.1:53`,
|
|
||||||
expectedError: `is not a valid rcode`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate original NODOMAIN . 192.168.1.1:53`,
|
|
||||||
expectedError: `is not a valid rcode`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate REFUSED . 192.168.1.1:53 {
|
|
||||||
max_fails 5
|
|
||||||
force_tcp
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate REFUSED . abc`,
|
|
||||||
expectedError: `not an IP address or file`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate REFUSED . 192.168.1.1:53
|
|
||||||
alternate REFUSED . 192.168.1.2:53`,
|
|
||||||
expectedError: `specified more than once`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
config: `alternate REFUSED . 192.168.1.1:53
|
|
||||||
alternate original REFUSED . 192.168.1.2:53`,
|
|
||||||
expectedError: `specified more than once`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(fmt.Sprintf("%s", tc.config), func(t *testing.T) {
|
|
||||||
c := caddy.NewTestController("dns", tc.config)
|
|
||||||
err := setup(c)
|
|
||||||
if err == nil {
|
|
||||||
if tc.expectedError != "" {
|
|
||||||
t.Errorf("Expected error '%s', but got no error", tc.expectedError)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if tc.expectedError == "" {
|
|
||||||
t.Errorf("Expected no error, but got '%s'", err)
|
|
||||||
} else if !strings.Contains(err.Error(), tc.expectedError) {
|
|
||||||
t.Errorf("Expected error '%s', but got '%s'", tc.expectedError, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
# forward
|
|
||||||
|
|
||||||
Fork of https://github.com/coredns/coredns/tree/master/plugin/forward.
|
|
||||||
|
|
||||||
The purpose is to expose "parseStanza" method to our fork of "alternate" module.
|
|
@ -1,137 +0,0 @@
|
|||||||
// Package forward implements a forwarding proxy. It caches an upstream net.Conn for some time, so if the same
|
|
||||||
// client returns the upstream's Conn will be precached. Depending on how you benchmark this looks to be
|
|
||||||
// 50% faster than just opening a new connection for every client. It works with UDP and TCP and uses
|
|
||||||
// inband healthchecking.
|
|
||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/request"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// limitTimeout is a utility function to auto-tune timeout values
|
|
||||||
// average observed time is moved towards the last observed delay moderated by a weight
|
|
||||||
// next timeout to use will be the double of the computed average, limited by min and max frame.
|
|
||||||
func limitTimeout(currentAvg *int64, minValue time.Duration, maxValue time.Duration) time.Duration {
|
|
||||||
rt := time.Duration(atomic.LoadInt64(currentAvg))
|
|
||||||
if rt < minValue {
|
|
||||||
return minValue
|
|
||||||
}
|
|
||||||
if rt < maxValue/2 {
|
|
||||||
return 2 * rt
|
|
||||||
}
|
|
||||||
return maxValue
|
|
||||||
}
|
|
||||||
|
|
||||||
func averageTimeout(currentAvg *int64, observedDuration time.Duration, weight int64) {
|
|
||||||
dt := time.Duration(atomic.LoadInt64(currentAvg))
|
|
||||||
atomic.AddInt64(currentAvg, int64(observedDuration-dt)/weight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Transport) dialTimeout() time.Duration {
|
|
||||||
return limitTimeout(&t.avgDialTime, minDialTimeout, maxDialTimeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Transport) updateDialTimeout(newDialTime time.Duration) {
|
|
||||||
averageTimeout(&t.avgDialTime, newDialTime, cumulativeAvgWeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dial dials the address configured in transport, potentially reusing a connection or creating a new one.
|
|
||||||
func (t *Transport) Dial(proto string) (*persistConn, bool, error) {
|
|
||||||
// If tls has been configured; use it.
|
|
||||||
if t.tlsConfig != nil {
|
|
||||||
proto = "tcp-tls"
|
|
||||||
}
|
|
||||||
|
|
||||||
t.dial <- proto
|
|
||||||
pc := <-t.ret
|
|
||||||
|
|
||||||
if pc != nil {
|
|
||||||
return pc, true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
reqTime := time.Now()
|
|
||||||
timeout := t.dialTimeout()
|
|
||||||
if proto == "tcp-tls" {
|
|
||||||
conn, err := dns.DialTimeoutWithTLS("tcp", t.addr, t.tlsConfig, timeout)
|
|
||||||
t.updateDialTimeout(time.Since(reqTime))
|
|
||||||
return &persistConn{c: conn}, false, err
|
|
||||||
}
|
|
||||||
conn, err := dns.DialTimeout(proto, t.addr, timeout)
|
|
||||||
t.updateDialTimeout(time.Since(reqTime))
|
|
||||||
return &persistConn{c: conn}, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect selects an upstream, sends the request and waits for a response.
|
|
||||||
func (p *Proxy) Connect(ctx context.Context, state request.Request, opts options) (*dns.Msg, error) {
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
proto := ""
|
|
||||||
switch {
|
|
||||||
case opts.forceTCP: // TCP flag has precedence over UDP flag
|
|
||||||
proto = "tcp"
|
|
||||||
case opts.preferUDP:
|
|
||||||
proto = "udp"
|
|
||||||
default:
|
|
||||||
proto = state.Proto()
|
|
||||||
}
|
|
||||||
|
|
||||||
pc, cached, err := p.transport.Dial(proto)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set buffer size correctly for this client.
|
|
||||||
pc.c.UDPSize = uint16(state.Size())
|
|
||||||
if pc.c.UDPSize < 512 {
|
|
||||||
pc.c.UDPSize = 512
|
|
||||||
}
|
|
||||||
|
|
||||||
pc.c.SetWriteDeadline(time.Now().Add(maxTimeout))
|
|
||||||
if err := pc.c.WriteMsg(state.Req); err != nil {
|
|
||||||
pc.c.Close() // not giving it back
|
|
||||||
if err == io.EOF && cached {
|
|
||||||
return nil, ErrCachedClosed
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var ret *dns.Msg
|
|
||||||
pc.c.SetReadDeadline(time.Now().Add(readTimeout))
|
|
||||||
for {
|
|
||||||
ret, err = pc.c.ReadMsg()
|
|
||||||
if err != nil {
|
|
||||||
pc.c.Close() // not giving it back
|
|
||||||
if err == io.EOF && cached {
|
|
||||||
return nil, ErrCachedClosed
|
|
||||||
}
|
|
||||||
return ret, err
|
|
||||||
}
|
|
||||||
// drop out-of-order responses
|
|
||||||
if state.Req.Id == ret.Id {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.transport.Yield(pc)
|
|
||||||
|
|
||||||
rc, ok := dns.RcodeToString[ret.Rcode]
|
|
||||||
if !ok {
|
|
||||||
rc = strconv.Itoa(ret.Rcode)
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestCount.WithLabelValues(p.addr).Add(1)
|
|
||||||
RcodeCount.WithLabelValues(rc, p.addr).Add(1)
|
|
||||||
RequestDuration.WithLabelValues(p.addr).Observe(time.Since(start).Seconds())
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const cumulativeAvgWeight = 4
|
|
@ -1,61 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap"
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap/msg"
|
|
||||||
"github.com/coredns/coredns/request"
|
|
||||||
|
|
||||||
tap "github.com/dnstap/golang-dnstap"
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func toDnstap(ctx context.Context, host string, f *Forward, state request.Request, reply *dns.Msg, start time.Time) error {
|
|
||||||
tapper := dnstap.TapperFromContext(ctx)
|
|
||||||
if tapper == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Query
|
|
||||||
b := msg.New().Time(start).HostPort(host)
|
|
||||||
opts := f.opts
|
|
||||||
t := ""
|
|
||||||
switch {
|
|
||||||
case opts.forceTCP: // TCP flag has precedence over UDP flag
|
|
||||||
t = "tcp"
|
|
||||||
case opts.preferUDP:
|
|
||||||
t = "udp"
|
|
||||||
default:
|
|
||||||
t = state.Proto()
|
|
||||||
}
|
|
||||||
|
|
||||||
if t == "tcp" {
|
|
||||||
b.SocketProto = tap.SocketProtocol_TCP
|
|
||||||
} else {
|
|
||||||
b.SocketProto = tap.SocketProtocol_UDP
|
|
||||||
}
|
|
||||||
|
|
||||||
if tapper.Pack() {
|
|
||||||
b.Msg(state.Req)
|
|
||||||
}
|
|
||||||
m, err := b.ToOutsideQuery(tap.Message_FORWARDER_QUERY)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tapper.TapMessage(m)
|
|
||||||
|
|
||||||
// Response
|
|
||||||
if reply != nil {
|
|
||||||
if tapper.Pack() {
|
|
||||||
b.Msg(reply)
|
|
||||||
}
|
|
||||||
m, err := b.Time(time.Now()).ToOutsideResponse(tap.Message_FORWARDER_RESPONSE)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tapper.TapMessage(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap"
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap/msg"
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap/test"
|
|
||||||
mwtest "github.com/coredns/coredns/plugin/test"
|
|
||||||
"github.com/coredns/coredns/request"
|
|
||||||
|
|
||||||
tap "github.com/dnstap/golang-dnstap"
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func testCase(t *testing.T, f *Forward, q, r *dns.Msg, datq, datr *msg.Builder) {
|
|
||||||
tapq, _ := datq.ToOutsideQuery(tap.Message_FORWARDER_QUERY)
|
|
||||||
tapr, _ := datr.ToOutsideResponse(tap.Message_FORWARDER_RESPONSE)
|
|
||||||
tapper := test.TrapTapper{}
|
|
||||||
ctx := dnstap.ContextWithTapper(context.TODO(), &tapper)
|
|
||||||
err := toDnstap(ctx, "10.240.0.1:40212", f,
|
|
||||||
request.Request{W: &mwtest.ResponseWriter{}, Req: q}, r, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if len(tapper.Trap) != 2 {
|
|
||||||
t.Fatalf("Messages: %d", len(tapper.Trap))
|
|
||||||
}
|
|
||||||
if !test.MsgEqual(tapper.Trap[0], tapq) {
|
|
||||||
t.Errorf("Want: %v\nhave: %v", tapq, tapper.Trap[0])
|
|
||||||
}
|
|
||||||
if !test.MsgEqual(tapper.Trap[1], tapr) {
|
|
||||||
t.Errorf("Want: %v\nhave: %v", tapr, tapper.Trap[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDnstap(t *testing.T) {
|
|
||||||
q := mwtest.Case{Qname: "example.org", Qtype: dns.TypeA}.Msg()
|
|
||||||
r := mwtest.Case{
|
|
||||||
Qname: "example.org.", Qtype: dns.TypeA,
|
|
||||||
Answer: []dns.RR{
|
|
||||||
mwtest.A("example.org. 3600 IN A 10.0.0.1"),
|
|
||||||
},
|
|
||||||
}.Msg()
|
|
||||||
tapq, tapr := test.TestingData(), test.TestingData()
|
|
||||||
fu := New()
|
|
||||||
fu.opts.preferUDP = true
|
|
||||||
testCase(t, fu, q, r, tapq, tapr)
|
|
||||||
tapq.SocketProto = tap.SocketProtocol_TCP
|
|
||||||
tapr.SocketProto = tap.SocketProtocol_TCP
|
|
||||||
ft := New()
|
|
||||||
ft.opts.forceTCP = true
|
|
||||||
testCase(t, ft, q, r, tapq, tapr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNoDnstap(t *testing.T) {
|
|
||||||
err := toDnstap(context.TODO(), "", nil, request.Request{}, nil, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,232 +0,0 @@
|
|||||||
// Package forward implements a forwarding proxy. It caches an upstream net.Conn for some time, so if the same
|
|
||||||
// client returns the upstream's Conn will be precached. Depending on how you benchmark this looks to be
|
|
||||||
// 50% faster than just opening a new connection for every client. It works with UDP and TCP and uses
|
|
||||||
// inband healthchecking.
|
|
||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"errors"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin"
|
|
||||||
"github.com/coredns/coredns/plugin/debug"
|
|
||||||
clog "github.com/coredns/coredns/plugin/pkg/log"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/policy"
|
|
||||||
"github.com/coredns/coredns/request"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
ot "github.com/opentracing/opentracing-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
var log = clog.NewWithPlugin("forward")
|
|
||||||
|
|
||||||
// Forward represents a plugin instance that can proxy requests to another (DNS) server. It has a list
|
|
||||||
// of proxies each representing one upstream proxy.
|
|
||||||
type Forward struct {
|
|
||||||
concurrent int64 // atomic counters need to be first in struct for proper alignment
|
|
||||||
|
|
||||||
proxies []*Proxy
|
|
||||||
p policy.Policy
|
|
||||||
hcInterval time.Duration
|
|
||||||
|
|
||||||
from string
|
|
||||||
ignored []string
|
|
||||||
|
|
||||||
tlsConfig *tls.Config
|
|
||||||
tlsServerName string
|
|
||||||
maxfails uint32
|
|
||||||
expire time.Duration
|
|
||||||
maxConcurrent int64
|
|
||||||
|
|
||||||
opts options // also here for testing
|
|
||||||
|
|
||||||
// ErrLimitExceeded indicates that a query was rejected because the number of concurrent queries has exceeded
|
|
||||||
// the maximum allowed (maxConcurrent)
|
|
||||||
ErrLimitExceeded error
|
|
||||||
|
|
||||||
Next plugin.Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new Forward.
|
|
||||||
func New() *Forward {
|
|
||||||
f := &Forward{maxfails: 2, tlsConfig: new(tls.Config), expire: defaultExpire, p: new(policy.Random), from: ".", hcInterval: hcInterval, opts: options{forceTCP: false, preferUDP: false, hcRecursionDesired: true}}
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetProxy appends p to the proxy list and starts healthchecking.
|
|
||||||
func (f *Forward) SetProxy(p *Proxy) {
|
|
||||||
f.proxies = append(f.proxies, p)
|
|
||||||
p.start(f.hcInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the number of configured proxies.
|
|
||||||
func (f *Forward) Len() int { return len(f.proxies) }
|
|
||||||
|
|
||||||
// Name implements plugin.Handler.
|
|
||||||
func (f *Forward) Name() string { return "forward" }
|
|
||||||
|
|
||||||
// ServeDNS implements plugin.Handler.
|
|
||||||
func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
||||||
|
|
||||||
state := request.Request{W: w, Req: r}
|
|
||||||
if !f.match(state) {
|
|
||||||
return plugin.NextOrFailure(f.Name(), f.Next, ctx, w, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.maxConcurrent > 0 {
|
|
||||||
count := atomic.AddInt64(&(f.concurrent), 1)
|
|
||||||
defer atomic.AddInt64(&(f.concurrent), -1)
|
|
||||||
if count > f.maxConcurrent {
|
|
||||||
MaxConcurrentRejectCount.Add(1)
|
|
||||||
return dns.RcodeServerFailure, f.ErrLimitExceeded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fails := 0
|
|
||||||
var span, child ot.Span
|
|
||||||
var upstreamErr error
|
|
||||||
span = ot.SpanFromContext(ctx)
|
|
||||||
i := 0
|
|
||||||
list := f.List()
|
|
||||||
deadline := time.Now().Add(defaultTimeout)
|
|
||||||
start := time.Now()
|
|
||||||
for time.Now().Before(deadline) {
|
|
||||||
if i >= len(list) {
|
|
||||||
// reached the end of list, reset to begin
|
|
||||||
i = 0
|
|
||||||
fails = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy := list[i]
|
|
||||||
i++
|
|
||||||
if proxy.Down(f.maxfails) {
|
|
||||||
fails++
|
|
||||||
if fails < len(f.proxies) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// All upstream proxies are dead, assume healthcheck is completely broken and randomly
|
|
||||||
// select an upstream to connect to.
|
|
||||||
r := new(policy.Random)
|
|
||||||
proxy = r.List(f.proxies)[0].([]*Proxy)[0]
|
|
||||||
|
|
||||||
HealthcheckBrokenCount.Add(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if span != nil {
|
|
||||||
child = span.Tracer().StartSpan("connect", ot.ChildOf(span.Context()))
|
|
||||||
ctx = ot.ContextWithSpan(ctx, child)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ret *dns.Msg
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
opts := f.opts
|
|
||||||
for {
|
|
||||||
ret, err = proxy.Connect(ctx, state, opts)
|
|
||||||
if err == ErrCachedClosed { // Remote side closed conn, can only happen with TCP.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Retry with TCP if truncated and prefer_udp configured.
|
|
||||||
if ret != nil && ret.Truncated && !opts.forceTCP && opts.preferUDP {
|
|
||||||
opts.forceTCP = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if child != nil {
|
|
||||||
child.Finish()
|
|
||||||
}
|
|
||||||
taperr := toDnstap(ctx, proxy.addr, f, state, ret, start)
|
|
||||||
|
|
||||||
upstreamErr = err
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
// Kick off health check to see if *our* upstream is broken.
|
|
||||||
if f.maxfails != 0 {
|
|
||||||
proxy.Healthcheck()
|
|
||||||
}
|
|
||||||
|
|
||||||
if fails < len(f.proxies) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the reply is correct; if not return FormErr.
|
|
||||||
if !state.Match(ret) {
|
|
||||||
debug.Hexdumpf(ret, "Wrong reply for id: %d, %s %d", ret.Id, state.QName(), state.QType())
|
|
||||||
|
|
||||||
formerr := new(dns.Msg)
|
|
||||||
formerr.SetRcode(state.Req, dns.RcodeFormatError)
|
|
||||||
w.WriteMsg(formerr)
|
|
||||||
return 0, taperr
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
return 0, taperr
|
|
||||||
}
|
|
||||||
|
|
||||||
if upstreamErr != nil {
|
|
||||||
return dns.RcodeServerFailure, upstreamErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return dns.RcodeServerFailure, ErrNoHealthy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Forward) match(state request.Request) bool {
|
|
||||||
if !plugin.Name(f.from).Matches(state.Name()) || !f.isAllowedDomain(state.Name()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Forward) isAllowedDomain(name string) bool {
|
|
||||||
if dns.Name(name) == dns.Name(f.from) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ignore := range f.ignored {
|
|
||||||
if plugin.Name(ignore).Matches(name) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForceTCP returns if TCP is forced to be used even when the request comes in over UDP.
|
|
||||||
func (f *Forward) ForceTCP() bool { return f.opts.forceTCP }
|
|
||||||
|
|
||||||
// PreferUDP returns if UDP is preferred to be used even when the request comes in over TCP.
|
|
||||||
func (f *Forward) PreferUDP() bool { return f.opts.preferUDP }
|
|
||||||
|
|
||||||
// List returns a set of proxies to be used for this client depending on the policy in f.
|
|
||||||
func (f *Forward) List() []*Proxy {
|
|
||||||
if len(f.p.List(f.proxies)) == 1 {
|
|
||||||
return f.p.List(f.proxies)[0].([]*Proxy)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrNoHealthy means no healthy proxies left.
|
|
||||||
ErrNoHealthy = errors.New("no healthy proxies")
|
|
||||||
// ErrNoForward means no forwarder defined.
|
|
||||||
ErrNoForward = errors.New("no forwarder defined")
|
|
||||||
// ErrCachedClosed means cached connection was closed by peer.
|
|
||||||
ErrCachedClosed = errors.New("cached connection was closed by peer")
|
|
||||||
)
|
|
||||||
|
|
||||||
// options holds various options that can be set.
|
|
||||||
type options struct {
|
|
||||||
forceTCP bool
|
|
||||||
preferUDP bool
|
|
||||||
hcRecursionDesired bool
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultTimeout = 5 * time.Second
|
|
@ -1,34 +0,0 @@
|
|||||||
// +build gofuzz
|
|
||||||
|
|
||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/fuzz"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
var f *Forward
|
|
||||||
|
|
||||||
// abuse init to setup an environment to test against. This start another server to that will
|
|
||||||
// reflect responses.
|
|
||||||
func init() {
|
|
||||||
f = New()
|
|
||||||
s := dnstest.NewServer(r{}.reflectHandler)
|
|
||||||
f.proxies = append(f.proxies, NewProxy(s.Addr, "tcp"))
|
|
||||||
f.proxies = append(f.proxies, NewProxy(s.Addr, "udp"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fuzz fuzzes forward.
|
|
||||||
func Fuzz(data []byte) int {
|
|
||||||
return fuzz.Do(f, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
type r struct{}
|
|
||||||
|
|
||||||
func (r r) reflectHandler(w dns.ResponseWriter, req *dns.Msg) {
|
|
||||||
m := new(dns.Msg)
|
|
||||||
m.SetReply(req)
|
|
||||||
w.WriteMsg(m)
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/transport"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HealthChecker checks the upstream health.
|
|
||||||
type HealthChecker interface {
|
|
||||||
Check(*Proxy) error
|
|
||||||
SetTLSConfig(*tls.Config)
|
|
||||||
SetRecursionDesired(bool)
|
|
||||||
GetRecursionDesired() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// dnsHc is a health checker for a DNS endpoint (DNS, and DoT).
|
|
||||||
type dnsHc struct {
|
|
||||||
c *dns.Client
|
|
||||||
recursionDesired bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHealthChecker returns a new HealthChecker based on transport.
|
|
||||||
func NewHealthChecker(trans string, recursionDesired bool) HealthChecker {
|
|
||||||
switch trans {
|
|
||||||
case transport.DNS, transport.TLS:
|
|
||||||
c := new(dns.Client)
|
|
||||||
c.Net = "udp"
|
|
||||||
c.ReadTimeout = 1 * time.Second
|
|
||||||
c.WriteTimeout = 1 * time.Second
|
|
||||||
|
|
||||||
return &dnsHc{c: c, recursionDesired: recursionDesired}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Warningf("No healthchecker for transport %q", trans)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *dnsHc) SetTLSConfig(cfg *tls.Config) {
|
|
||||||
h.c.Net = "tcp-tls"
|
|
||||||
h.c.TLSConfig = cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *dnsHc) SetRecursionDesired(recursionDesired bool) {
|
|
||||||
h.recursionDesired = recursionDesired
|
|
||||||
}
|
|
||||||
func (h *dnsHc) GetRecursionDesired() bool {
|
|
||||||
return h.recursionDesired
|
|
||||||
}
|
|
||||||
|
|
||||||
// For HC we send to . IN NS +[no]rec message to the upstream. Dial timeouts and empty
|
|
||||||
// replies are considered fails, basically anything else constitutes a healthy upstream.
|
|
||||||
|
|
||||||
// Check is used as the up.Func in the up.Probe.
|
|
||||||
func (h *dnsHc) Check(p *Proxy) error {
|
|
||||||
err := h.send(p.addr)
|
|
||||||
if err != nil {
|
|
||||||
HealthcheckFailureCount.WithLabelValues(p.addr).Add(1)
|
|
||||||
atomic.AddUint32(&p.fails, 1)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.StoreUint32(&p.fails, 0)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *dnsHc) send(addr string) error {
|
|
||||||
ping := new(dns.Msg)
|
|
||||||
ping.SetQuestion(".", dns.TypeNS)
|
|
||||||
ping.MsgHdr.RecursionDesired = h.recursionDesired
|
|
||||||
|
|
||||||
m, _, err := h.c.Exchange(ping, addr)
|
|
||||||
// If we got a header, we're alright, basically only care about I/O errors 'n stuff.
|
|
||||||
if err != nil && m != nil {
|
|
||||||
// Silly check, something sane came back.
|
|
||||||
if m.Response || m.Opcode == dns.OpcodeQuery {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
@ -1,225 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync/atomic"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/transport"
|
|
||||||
"github.com/coredns/coredns/plugin/test"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHealth(t *testing.T) {
|
|
||||||
const expected = 1
|
|
||||||
i := uint32(0)
|
|
||||||
q := uint32(0)
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
if atomic.LoadUint32(&q) == 0 { //drop the first query to trigger health-checking
|
|
||||||
atomic.AddUint32(&q, 1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Question[0].Name == "." && r.RecursionDesired == true {
|
|
||||||
atomic.AddUint32(&i, 1)
|
|
||||||
}
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
p := NewProxy(s.Addr, transport.DNS)
|
|
||||||
f := New()
|
|
||||||
f.SetProxy(p)
|
|
||||||
defer f.OnShutdown()
|
|
||||||
|
|
||||||
req := new(dns.Msg)
|
|
||||||
req.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
|
|
||||||
f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req)
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
i1 := atomic.LoadUint32(&i)
|
|
||||||
if i1 != expected {
|
|
||||||
t.Errorf("Expected number of health checks with RecursionDesired==true to be %d, got %d", expected, i1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHealthNoRecursion(t *testing.T) {
|
|
||||||
const expected = 1
|
|
||||||
i := uint32(0)
|
|
||||||
q := uint32(0)
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
if atomic.LoadUint32(&q) == 0 { //drop the first query to trigger health-checking
|
|
||||||
atomic.AddUint32(&q, 1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Question[0].Name == "." && r.RecursionDesired == false {
|
|
||||||
atomic.AddUint32(&i, 1)
|
|
||||||
}
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
p := NewProxy(s.Addr, transport.DNS)
|
|
||||||
p.health.SetRecursionDesired(false)
|
|
||||||
f := New()
|
|
||||||
f.SetProxy(p)
|
|
||||||
defer f.OnShutdown()
|
|
||||||
|
|
||||||
req := new(dns.Msg)
|
|
||||||
req.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
|
|
||||||
f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req)
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
i1 := atomic.LoadUint32(&i)
|
|
||||||
if i1 != expected {
|
|
||||||
t.Errorf("Expected number of health checks with RecursionDesired==false to be %d, got %d", expected, i1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHealthTimeout(t *testing.T) {
|
|
||||||
const expected = 1
|
|
||||||
i := uint32(0)
|
|
||||||
q := uint32(0)
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
if r.Question[0].Name == "." {
|
|
||||||
// health check, answer
|
|
||||||
atomic.AddUint32(&i, 1)
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if atomic.LoadUint32(&q) == 0 { //drop only first query
|
|
||||||
atomic.AddUint32(&q, 1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
p := NewProxy(s.Addr, transport.DNS)
|
|
||||||
f := New()
|
|
||||||
f.SetProxy(p)
|
|
||||||
defer f.OnShutdown()
|
|
||||||
|
|
||||||
req := new(dns.Msg)
|
|
||||||
req.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
|
|
||||||
f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req)
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
i1 := atomic.LoadUint32(&i)
|
|
||||||
if i1 != expected {
|
|
||||||
t.Errorf("Expected number of health checks to be %d, got %d", expected, i1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHealthFailTwice(t *testing.T) {
|
|
||||||
const expected = 2
|
|
||||||
i := uint32(0)
|
|
||||||
q := uint32(0)
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
if r.Question[0].Name == "." {
|
|
||||||
atomic.AddUint32(&i, 1)
|
|
||||||
i1 := atomic.LoadUint32(&i)
|
|
||||||
// Timeout health until we get the second one
|
|
||||||
if i1 < 2 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if atomic.LoadUint32(&q) == 0 { //drop only first query
|
|
||||||
atomic.AddUint32(&q, 1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
p := NewProxy(s.Addr, transport.DNS)
|
|
||||||
f := New()
|
|
||||||
f.SetProxy(p)
|
|
||||||
defer f.OnShutdown()
|
|
||||||
|
|
||||||
req := new(dns.Msg)
|
|
||||||
req.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
|
|
||||||
f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req)
|
|
||||||
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
i1 := atomic.LoadUint32(&i)
|
|
||||||
if i1 != expected {
|
|
||||||
t.Errorf("Expected number of health checks to be %d, got %d", expected, i1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHealthMaxFails(t *testing.T) {
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
// timeout
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
p := NewProxy(s.Addr, transport.DNS)
|
|
||||||
f := New()
|
|
||||||
f.maxfails = 2
|
|
||||||
f.SetProxy(p)
|
|
||||||
defer f.OnShutdown()
|
|
||||||
|
|
||||||
req := new(dns.Msg)
|
|
||||||
req.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
|
|
||||||
f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req)
|
|
||||||
|
|
||||||
time.Sleep(readTimeout + 1*time.Second)
|
|
||||||
fails := atomic.LoadUint32(&p.fails)
|
|
||||||
if !p.Down(f.maxfails) {
|
|
||||||
t.Errorf("Expected Proxy fails to be greater than %d, got %d", f.maxfails, fails)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHealthNoMaxFails(t *testing.T) {
|
|
||||||
const expected = 0
|
|
||||||
i := uint32(0)
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
if r.Question[0].Name == "." {
|
|
||||||
// health check, answer
|
|
||||||
atomic.AddUint32(&i, 1)
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
p := NewProxy(s.Addr, transport.DNS)
|
|
||||||
f := New()
|
|
||||||
f.maxfails = 0
|
|
||||||
f.SetProxy(p)
|
|
||||||
defer f.OnShutdown()
|
|
||||||
|
|
||||||
req := new(dns.Msg)
|
|
||||||
req.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
|
|
||||||
f.ServeDNS(context.TODO(), &test.ResponseWriter{}, req)
|
|
||||||
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
i1 := atomic.LoadUint32(&i)
|
|
||||||
if i1 != expected {
|
|
||||||
t.Errorf("Expected number of health checks to be %d, got %d", expected, i1)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import clog "github.com/coredns/coredns/plugin/pkg/log"
|
|
||||||
|
|
||||||
func init() { clog.Discard() }
|
|
@ -1,54 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/coredns/coredns/plugin"
|
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Variables declared for monitoring.
|
|
||||||
var (
|
|
||||||
RequestCount = prometheus.NewCounterVec(prometheus.CounterOpts{
|
|
||||||
Namespace: plugin.Namespace,
|
|
||||||
Subsystem: "forward",
|
|
||||||
Name: "request_count_total",
|
|
||||||
Help: "Counter of requests made per upstream.",
|
|
||||||
}, []string{"to"})
|
|
||||||
RcodeCount = prometheus.NewCounterVec(prometheus.CounterOpts{
|
|
||||||
Namespace: plugin.Namespace,
|
|
||||||
Subsystem: "forward",
|
|
||||||
Name: "response_rcode_count_total",
|
|
||||||
Help: "Counter of requests made per upstream.",
|
|
||||||
}, []string{"rcode", "to"})
|
|
||||||
RequestDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
|
||||||
Namespace: plugin.Namespace,
|
|
||||||
Subsystem: "forward",
|
|
||||||
Name: "request_duration_seconds",
|
|
||||||
Buckets: plugin.TimeBuckets,
|
|
||||||
Help: "Histogram of the time each request took.",
|
|
||||||
}, []string{"to"})
|
|
||||||
HealthcheckFailureCount = prometheus.NewCounterVec(prometheus.CounterOpts{
|
|
||||||
Namespace: plugin.Namespace,
|
|
||||||
Subsystem: "forward",
|
|
||||||
Name: "healthcheck_failure_count_total",
|
|
||||||
Help: "Counter of the number of failed healthchecks.",
|
|
||||||
}, []string{"to"})
|
|
||||||
HealthcheckBrokenCount = prometheus.NewCounter(prometheus.CounterOpts{
|
|
||||||
Namespace: plugin.Namespace,
|
|
||||||
Subsystem: "forward",
|
|
||||||
Name: "healthcheck_broken_count_total",
|
|
||||||
Help: "Counter of the number of complete failures of the healthchecks.",
|
|
||||||
})
|
|
||||||
SocketGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
|
||||||
Namespace: plugin.Namespace,
|
|
||||||
Subsystem: "forward",
|
|
||||||
Name: "sockets_open",
|
|
||||||
Help: "Gauge of open sockets per upstream.",
|
|
||||||
}, []string{"to"})
|
|
||||||
MaxConcurrentRejectCount = prometheus.NewCounter(prometheus.CounterOpts{
|
|
||||||
Namespace: plugin.Namespace,
|
|
||||||
Subsystem: "forward",
|
|
||||||
Name: "max_concurrent_reject_count_total",
|
|
||||||
Help: "Counter of the number of queries rejected because the concurrent queries were at maximum.",
|
|
||||||
})
|
|
||||||
)
|
|
@ -1,158 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"sort"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// a persistConn hold the dns.Conn and the last used time.
|
|
||||||
type persistConn struct {
|
|
||||||
c *dns.Conn
|
|
||||||
used time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transport hold the persistent cache.
|
|
||||||
type Transport struct {
|
|
||||||
avgDialTime int64 // kind of average time of dial time
|
|
||||||
conns [typeTotalCount][]*persistConn // Buckets for udp, tcp and tcp-tls.
|
|
||||||
expire time.Duration // After this duration a connection is expired.
|
|
||||||
addr string
|
|
||||||
tlsConfig *tls.Config
|
|
||||||
|
|
||||||
dial chan string
|
|
||||||
yield chan *persistConn
|
|
||||||
ret chan *persistConn
|
|
||||||
stop chan bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTransport(addr string) *Transport {
|
|
||||||
t := &Transport{
|
|
||||||
avgDialTime: int64(maxDialTimeout / 2),
|
|
||||||
conns: [typeTotalCount][]*persistConn{},
|
|
||||||
expire: defaultExpire,
|
|
||||||
addr: addr,
|
|
||||||
dial: make(chan string),
|
|
||||||
yield: make(chan *persistConn),
|
|
||||||
ret: make(chan *persistConn),
|
|
||||||
stop: make(chan bool),
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// connManagers manages the persistent connection cache for UDP and TCP.
|
|
||||||
func (t *Transport) connManager() {
|
|
||||||
ticker := time.NewTicker(t.expire)
|
|
||||||
Wait:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case proto := <-t.dial:
|
|
||||||
transtype := stringToTransportType(proto)
|
|
||||||
// take the last used conn - complexity O(1)
|
|
||||||
if stack := t.conns[transtype]; len(stack) > 0 {
|
|
||||||
pc := stack[len(stack)-1]
|
|
||||||
if time.Since(pc.used) < t.expire {
|
|
||||||
// Found one, remove from pool and return this conn.
|
|
||||||
t.conns[transtype] = stack[:len(stack)-1]
|
|
||||||
t.ret <- pc
|
|
||||||
continue Wait
|
|
||||||
}
|
|
||||||
// clear entire cache if the last conn is expired
|
|
||||||
t.conns[transtype] = nil
|
|
||||||
// now, the connections being passed to closeConns() are not reachable from
|
|
||||||
// transport methods anymore. So, it's safe to close them in a separate goroutine
|
|
||||||
go closeConns(stack)
|
|
||||||
}
|
|
||||||
t.ret <- nil
|
|
||||||
|
|
||||||
case pc := <-t.yield:
|
|
||||||
transtype := t.transportTypeFromConn(pc)
|
|
||||||
t.conns[transtype] = append(t.conns[transtype], pc)
|
|
||||||
|
|
||||||
case <-ticker.C:
|
|
||||||
t.cleanup(false)
|
|
||||||
|
|
||||||
case <-t.stop:
|
|
||||||
t.cleanup(true)
|
|
||||||
close(t.ret)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// closeConns closes connections.
|
|
||||||
func closeConns(conns []*persistConn) {
|
|
||||||
for _, pc := range conns {
|
|
||||||
pc.c.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup removes connections from cache.
|
|
||||||
func (t *Transport) cleanup(all bool) {
|
|
||||||
staleTime := time.Now().Add(-t.expire)
|
|
||||||
for transtype, stack := range t.conns {
|
|
||||||
if len(stack) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if all {
|
|
||||||
t.conns[transtype] = nil
|
|
||||||
// now, the connections being passed to closeConns() are not reachable from
|
|
||||||
// transport methods anymore. So, it's safe to close them in a separate goroutine
|
|
||||||
go closeConns(stack)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if stack[0].used.After(staleTime) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// connections in stack are sorted by "used"
|
|
||||||
good := sort.Search(len(stack), func(i int) bool {
|
|
||||||
return stack[i].used.After(staleTime)
|
|
||||||
})
|
|
||||||
t.conns[transtype] = stack[good:]
|
|
||||||
// now, the connections being passed to closeConns() are not reachable from
|
|
||||||
// transport methods anymore. So, it's safe to close them in a separate goroutine
|
|
||||||
go closeConns(stack[:good])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// It is hard to pin a value to this, the import thing is to no block forever, losing at cached connection is not terrible.
|
|
||||||
const yieldTimeout = 25 * time.Millisecond
|
|
||||||
|
|
||||||
// Yield return the connection to transport for reuse.
|
|
||||||
func (t *Transport) Yield(pc *persistConn) {
|
|
||||||
pc.used = time.Now() // update used time
|
|
||||||
|
|
||||||
// Make this non-blocking, because in the case of a very busy forwarder we will *block* on this yield. This
|
|
||||||
// blocks the outer go-routine and stuff will just pile up. We timeout when the send fails to as returning
|
|
||||||
// these connection is an optimization anyway.
|
|
||||||
select {
|
|
||||||
case t.yield <- pc:
|
|
||||||
return
|
|
||||||
case <-time.After(yieldTimeout):
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start starts the transport's connection manager.
|
|
||||||
func (t *Transport) Start() { go t.connManager() }
|
|
||||||
|
|
||||||
// Stop stops the transport's connection manager.
|
|
||||||
func (t *Transport) Stop() { close(t.stop) }
|
|
||||||
|
|
||||||
// SetExpire sets the connection expire time in transport.
|
|
||||||
func (t *Transport) SetExpire(expire time.Duration) { t.expire = expire }
|
|
||||||
|
|
||||||
// SetTLSConfig sets the TLS config in transport.
|
|
||||||
func (t *Transport) SetTLSConfig(cfg *tls.Config) { t.tlsConfig = cfg }
|
|
||||||
|
|
||||||
const (
|
|
||||||
defaultExpire = 10 * time.Second
|
|
||||||
minDialTimeout = 1 * time.Second
|
|
||||||
maxDialTimeout = 30 * time.Second
|
|
||||||
|
|
||||||
// Some resolves might take quite a while, usually (cached) responses are fast. Set to 2s to give us some time to retry a different upstream.
|
|
||||||
readTimeout = 2 * time.Second
|
|
||||||
)
|
|
@ -1,109 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCached(t *testing.T) {
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
tr := newTransport(s.Addr)
|
|
||||||
tr.Start()
|
|
||||||
defer tr.Stop()
|
|
||||||
|
|
||||||
c1, cache1, _ := tr.Dial("udp")
|
|
||||||
c2, cache2, _ := tr.Dial("udp")
|
|
||||||
|
|
||||||
if cache1 || cache2 {
|
|
||||||
t.Errorf("Expected non-cached connection")
|
|
||||||
}
|
|
||||||
|
|
||||||
tr.Yield(c1)
|
|
||||||
tr.Yield(c2)
|
|
||||||
c3, cached3, _ := tr.Dial("udp")
|
|
||||||
if !cached3 {
|
|
||||||
t.Error("Expected cached connection (c3)")
|
|
||||||
}
|
|
||||||
if c2 != c3 {
|
|
||||||
t.Error("Expected c2 == c3")
|
|
||||||
}
|
|
||||||
|
|
||||||
tr.Yield(c3)
|
|
||||||
|
|
||||||
// dial another protocol
|
|
||||||
c4, cached4, _ := tr.Dial("tcp")
|
|
||||||
if cached4 {
|
|
||||||
t.Errorf("Expected non-cached connection (c4)")
|
|
||||||
}
|
|
||||||
tr.Yield(c4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCleanupByTimer(t *testing.T) {
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
tr := newTransport(s.Addr)
|
|
||||||
tr.SetExpire(100 * time.Millisecond)
|
|
||||||
tr.Start()
|
|
||||||
defer tr.Stop()
|
|
||||||
|
|
||||||
c1, _, _ := tr.Dial("udp")
|
|
||||||
c2, _, _ := tr.Dial("udp")
|
|
||||||
tr.Yield(c1)
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
tr.Yield(c2)
|
|
||||||
|
|
||||||
time.Sleep(120 * time.Millisecond)
|
|
||||||
c3, cached, _ := tr.Dial("udp")
|
|
||||||
if cached {
|
|
||||||
t.Error("Expected non-cached connection (c3)")
|
|
||||||
}
|
|
||||||
tr.Yield(c3)
|
|
||||||
|
|
||||||
time.Sleep(120 * time.Millisecond)
|
|
||||||
c4, cached, _ := tr.Dial("udp")
|
|
||||||
if cached {
|
|
||||||
t.Error("Expected non-cached connection (c4)")
|
|
||||||
}
|
|
||||||
tr.Yield(c4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCleanupAll(t *testing.T) {
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
tr := newTransport(s.Addr)
|
|
||||||
|
|
||||||
c1, _ := dns.DialTimeout("udp", tr.addr, maxDialTimeout)
|
|
||||||
c2, _ := dns.DialTimeout("udp", tr.addr, maxDialTimeout)
|
|
||||||
c3, _ := dns.DialTimeout("udp", tr.addr, maxDialTimeout)
|
|
||||||
|
|
||||||
tr.conns[typeUdp] = []*persistConn{{c1, time.Now()}, {c2, time.Now()}, {c3, time.Now()}}
|
|
||||||
|
|
||||||
if len(tr.conns[typeUdp]) != 3 {
|
|
||||||
t.Error("Expected 3 connections")
|
|
||||||
}
|
|
||||||
tr.cleanup(true)
|
|
||||||
|
|
||||||
if len(tr.conns[typeUdp]) > 0 {
|
|
||||||
t.Error("Expected no cached connections")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"runtime"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/up"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Proxy defines an upstream host.
|
|
||||||
type Proxy struct {
|
|
||||||
fails uint32
|
|
||||||
addr string
|
|
||||||
|
|
||||||
transport *Transport
|
|
||||||
|
|
||||||
// health checking
|
|
||||||
probe *up.Probe
|
|
||||||
health HealthChecker
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewProxy returns a new proxy.
|
|
||||||
func NewProxy(addr, trans string) *Proxy {
|
|
||||||
p := &Proxy{
|
|
||||||
addr: addr,
|
|
||||||
fails: 0,
|
|
||||||
probe: up.New(),
|
|
||||||
transport: newTransport(addr),
|
|
||||||
}
|
|
||||||
p.health = NewHealthChecker(trans, true)
|
|
||||||
runtime.SetFinalizer(p, (*Proxy).finalizer)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTLSConfig sets the TLS config in the lower p.transport and in the healthchecking client.
|
|
||||||
func (p *Proxy) SetTLSConfig(cfg *tls.Config) {
|
|
||||||
p.transport.SetTLSConfig(cfg)
|
|
||||||
p.health.SetTLSConfig(cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetExpire sets the expire duration in the lower p.transport.
|
|
||||||
func (p *Proxy) SetExpire(expire time.Duration) { p.transport.SetExpire(expire) }
|
|
||||||
|
|
||||||
// Healthcheck kicks of a round of health checks for this proxy.
|
|
||||||
func (p *Proxy) Healthcheck() {
|
|
||||||
if p.health == nil {
|
|
||||||
log.Warning("No healthchecker")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p.probe.Do(func() error {
|
|
||||||
return p.health.Check(p)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Down returns true if this proxy is down, i.e. has *more* fails than maxfails.
|
|
||||||
func (p *Proxy) Down(maxfails uint32) bool {
|
|
||||||
if maxfails == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fails := atomic.LoadUint32(&p.fails)
|
|
||||||
return fails > maxfails
|
|
||||||
}
|
|
||||||
|
|
||||||
// close stops the health checking goroutine.
|
|
||||||
func (p *Proxy) stop() { p.probe.Stop() }
|
|
||||||
func (p *Proxy) finalizer() { p.transport.Stop() }
|
|
||||||
|
|
||||||
// start starts the proxy's healthchecking.
|
|
||||||
func (p *Proxy) start(duration time.Duration) {
|
|
||||||
p.probe.Start(duration)
|
|
||||||
p.transport.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
maxTimeout = 2 * time.Second
|
|
||||||
hcInterval = 500 * time.Millisecond
|
|
||||||
)
|
|
@ -1,123 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/transport"
|
|
||||||
"github.com/coredns/coredns/plugin/test"
|
|
||||||
"github.com/coredns/coredns/request"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy"
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestProxyClose(t *testing.T) {
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
req := new(dns.Msg)
|
|
||||||
req.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
state := request.Request{W: &test.ResponseWriter{}, Req: req}
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
p := NewProxy(s.Addr, transport.DNS)
|
|
||||||
p.start(hcInterval)
|
|
||||||
|
|
||||||
go func() { p.Connect(ctx, state, options{}) }()
|
|
||||||
go func() { p.Connect(ctx, state, options{forceTCP: true}) }()
|
|
||||||
go func() { p.Connect(ctx, state, options{}) }()
|
|
||||||
go func() { p.Connect(ctx, state, options{forceTCP: true}) }()
|
|
||||||
|
|
||||||
p.stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProxy(t *testing.T) {
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
ret.Answer = append(ret.Answer, test.A("example.org. IN A 127.0.0.1"))
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
c := caddy.NewTestController("dns", "forward . "+s.Addr)
|
|
||||||
f, err := parseForward(c)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to create forwarder: %s", err)
|
|
||||||
}
|
|
||||||
f.OnStartup()
|
|
||||||
defer f.OnShutdown()
|
|
||||||
|
|
||||||
m := new(dns.Msg)
|
|
||||||
m.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
rec := dnstest.NewRecorder(&test.ResponseWriter{})
|
|
||||||
|
|
||||||
if _, err := f.ServeDNS(context.TODO(), rec, m); err != nil {
|
|
||||||
t.Fatal("Expected to receive reply, but didn't")
|
|
||||||
}
|
|
||||||
if x := rec.Msg.Answer[0].Header().Name; x != "example.org." {
|
|
||||||
t.Errorf("Expected %s, got %s", "example.org.", x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProxyTLSFail(t *testing.T) {
|
|
||||||
// This is an udp/tcp test server, so we shouldn't reach it with TLS.
|
|
||||||
s := dnstest.NewServer(func(w dns.ResponseWriter, r *dns.Msg) {
|
|
||||||
ret := new(dns.Msg)
|
|
||||||
ret.SetReply(r)
|
|
||||||
ret.Answer = append(ret.Answer, test.A("example.org. IN A 127.0.0.1"))
|
|
||||||
w.WriteMsg(ret)
|
|
||||||
})
|
|
||||||
defer s.Close()
|
|
||||||
|
|
||||||
c := caddy.NewTestController("dns", "forward . tls://"+s.Addr)
|
|
||||||
f, err := parseForward(c)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Failed to create forwarder: %s", err)
|
|
||||||
}
|
|
||||||
f.OnStartup()
|
|
||||||
defer f.OnShutdown()
|
|
||||||
|
|
||||||
m := new(dns.Msg)
|
|
||||||
m.SetQuestion("example.org.", dns.TypeA)
|
|
||||||
rec := dnstest.NewRecorder(&test.ResponseWriter{})
|
|
||||||
|
|
||||||
if _, err := f.ServeDNS(context.TODO(), rec, m); err == nil {
|
|
||||||
t.Fatal("Expected *not* to receive reply, but got one")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProtocolSelection(t *testing.T) {
|
|
||||||
p := NewProxy("bad_address", transport.DNS)
|
|
||||||
|
|
||||||
stateUDP := request.Request{W: &test.ResponseWriter{}, Req: new(dns.Msg)}
|
|
||||||
stateTCP := request.Request{W: &test.ResponseWriter{TCP: true}, Req: new(dns.Msg)}
|
|
||||||
ctx := context.TODO()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
p.Connect(ctx, stateUDP, options{})
|
|
||||||
p.Connect(ctx, stateUDP, options{forceTCP: true})
|
|
||||||
p.Connect(ctx, stateUDP, options{preferUDP: true})
|
|
||||||
p.Connect(ctx, stateUDP, options{preferUDP: true, forceTCP: true})
|
|
||||||
p.Connect(ctx, stateTCP, options{})
|
|
||||||
p.Connect(ctx, stateTCP, options{forceTCP: true})
|
|
||||||
p.Connect(ctx, stateTCP, options{preferUDP: true})
|
|
||||||
p.Connect(ctx, stateTCP, options{preferUDP: true, forceTCP: true})
|
|
||||||
}()
|
|
||||||
|
|
||||||
for i, exp := range []string{"udp", "tcp", "udp", "tcp", "tcp", "tcp", "udp", "tcp"} {
|
|
||||||
proto := <-p.transport.dial
|
|
||||||
p.transport.ret <- nil
|
|
||||||
if proto != exp {
|
|
||||||
t.Errorf("Unexpected protocol in case %d, expected %q, actual %q", i, exp, proto)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
253
forward/setup.go
253
forward/setup.go
@ -1,253 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/core/dnsserver"
|
|
||||||
"github.com/coredns/coredns/plugin"
|
|
||||||
"github.com/coredns/coredns/plugin/metrics"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/parse"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/policy"
|
|
||||||
pkgtls "github.com/coredns/coredns/plugin/pkg/tls"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/transport"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() { plugin.Register("forward", setup) }
|
|
||||||
|
|
||||||
func setup(c *caddy.Controller) error {
|
|
||||||
f, err := parseForward(c)
|
|
||||||
if err != nil {
|
|
||||||
return plugin.Error("forward", err)
|
|
||||||
}
|
|
||||||
if f.Len() > max {
|
|
||||||
return plugin.Error("forward", fmt.Errorf("more than %d TOs configured: %d", max, f.Len()))
|
|
||||||
}
|
|
||||||
|
|
||||||
dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
|
|
||||||
f.Next = next
|
|
||||||
return f
|
|
||||||
})
|
|
||||||
|
|
||||||
c.OnStartup(func() error {
|
|
||||||
metrics.MustRegister(c, RequestCount, RcodeCount, RequestDuration, HealthcheckFailureCount, SocketGauge, MaxConcurrentRejectCount)
|
|
||||||
return f.OnStartup()
|
|
||||||
})
|
|
||||||
|
|
||||||
c.OnShutdown(func() error {
|
|
||||||
return f.OnShutdown()
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnStartup starts a goroutines for all proxies.
|
|
||||||
func (f *Forward) OnStartup() (err error) {
|
|
||||||
for _, p := range f.proxies {
|
|
||||||
p.start(f.hcInterval)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnShutdown stops all configured proxies.
|
|
||||||
func (f *Forward) OnShutdown() error {
|
|
||||||
for _, p := range f.proxies {
|
|
||||||
p.stop()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseForward(c *caddy.Controller) (*Forward, error) {
|
|
||||||
var (
|
|
||||||
f *Forward
|
|
||||||
err error
|
|
||||||
i int
|
|
||||||
)
|
|
||||||
for c.Next() {
|
|
||||||
if i > 0 {
|
|
||||||
return nil, plugin.ErrOnce
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
f, err = parseStanza(c)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exposed to our "alternate" plugin
|
|
||||||
func ParseForwardStanza(c *caddy.Controller) (*Forward, error) {
|
|
||||||
return parseStanza(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseStanza(c *caddy.Controller) (*Forward, error) {
|
|
||||||
f := New()
|
|
||||||
|
|
||||||
if !c.Args(&f.from) {
|
|
||||||
return f, c.ArgErr()
|
|
||||||
}
|
|
||||||
f.from = plugin.Host(f.from).Normalize()
|
|
||||||
|
|
||||||
to := c.RemainingArgs()
|
|
||||||
if len(to) == 0 {
|
|
||||||
return f, c.ArgErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
toHosts, err := parse.HostPortOrFile(to...)
|
|
||||||
if err != nil {
|
|
||||||
return f, err
|
|
||||||
}
|
|
||||||
|
|
||||||
transports := make([]string, len(toHosts))
|
|
||||||
for i, host := range toHosts {
|
|
||||||
trans, h := parse.Transport(host)
|
|
||||||
p := NewProxy(h, trans)
|
|
||||||
f.proxies = append(f.proxies, p)
|
|
||||||
transports[i] = trans
|
|
||||||
}
|
|
||||||
|
|
||||||
for c.NextBlock() {
|
|
||||||
if err := parseBlock(c, f); err != nil {
|
|
||||||
return f, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if f.tlsServerName != "" {
|
|
||||||
f.tlsConfig.ServerName = f.tlsServerName
|
|
||||||
}
|
|
||||||
for i := range f.proxies {
|
|
||||||
// Only set this for proxies that need it.
|
|
||||||
if transports[i] == transport.TLS {
|
|
||||||
f.proxies[i].SetTLSConfig(f.tlsConfig)
|
|
||||||
}
|
|
||||||
f.proxies[i].SetExpire(f.expire)
|
|
||||||
f.proxies[i].health.SetRecursionDesired(f.opts.hcRecursionDesired)
|
|
||||||
}
|
|
||||||
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseBlock(c *caddy.Controller, f *Forward) error {
|
|
||||||
switch c.Val() {
|
|
||||||
case "except":
|
|
||||||
ignore := c.RemainingArgs()
|
|
||||||
if len(ignore) == 0 {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
for i := 0; i < len(ignore); i++ {
|
|
||||||
ignore[i] = plugin.Host(ignore[i]).Normalize()
|
|
||||||
}
|
|
||||||
f.ignored = ignore
|
|
||||||
case "max_fails":
|
|
||||||
if !c.NextArg() {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
n, err := strconv.Atoi(c.Val())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if n < 0 {
|
|
||||||
return fmt.Errorf("max_fails can't be negative: %d", n)
|
|
||||||
}
|
|
||||||
f.maxfails = uint32(n)
|
|
||||||
case "health_check":
|
|
||||||
if !c.NextArg() {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
dur, err := time.ParseDuration(c.Val())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if dur < 0 {
|
|
||||||
return fmt.Errorf("health_check can't be negative: %d", dur)
|
|
||||||
}
|
|
||||||
f.hcInterval = dur
|
|
||||||
|
|
||||||
for c.NextArg() {
|
|
||||||
switch hcOpts := c.Val(); hcOpts {
|
|
||||||
case "no_rec":
|
|
||||||
f.opts.hcRecursionDesired = false
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("health_check: unknown option %s", hcOpts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case "force_tcp":
|
|
||||||
if c.NextArg() {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
f.opts.forceTCP = true
|
|
||||||
case "prefer_udp":
|
|
||||||
if c.NextArg() {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
f.opts.preferUDP = true
|
|
||||||
case "tls":
|
|
||||||
args := c.RemainingArgs()
|
|
||||||
if len(args) > 3 {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConfig, err := pkgtls.NewTLSConfigFromArgs(args...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.tlsConfig = tlsConfig
|
|
||||||
case "tls_servername":
|
|
||||||
if !c.NextArg() {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
f.tlsServerName = c.Val()
|
|
||||||
case "expire":
|
|
||||||
if !c.NextArg() {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
dur, err := time.ParseDuration(c.Val())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if dur < 0 {
|
|
||||||
return fmt.Errorf("expire can't be negative: %s", dur)
|
|
||||||
}
|
|
||||||
f.expire = dur
|
|
||||||
case "policy":
|
|
||||||
if !c.NextArg() {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
switch x := c.Val(); x {
|
|
||||||
case "random":
|
|
||||||
f.p = &policy.Random{}
|
|
||||||
case "round_robin":
|
|
||||||
f.p = &policy.RoundRobin{}
|
|
||||||
case "sequential":
|
|
||||||
f.p = &policy.Sequential{}
|
|
||||||
default:
|
|
||||||
return c.Errf("unknown policy '%s'", x)
|
|
||||||
}
|
|
||||||
case "max_concurrent":
|
|
||||||
if !c.NextArg() {
|
|
||||||
return c.ArgErr()
|
|
||||||
}
|
|
||||||
n, err := strconv.Atoi(c.Val())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if n < 0 {
|
|
||||||
return fmt.Errorf("max_concurrent can't be negative: %d", n)
|
|
||||||
}
|
|
||||||
f.ErrLimitExceeded = errors.New("concurrent queries exceeded maximum " + c.Val())
|
|
||||||
f.maxConcurrent = int64(n)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return c.Errf("unknown property '%s'", c.Val())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const max = 15 // Maximum number of upstreams.
|
|
@ -1,47 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSetupPolicy(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
shouldErr bool
|
|
||||||
expectedPolicy string
|
|
||||||
expectedErr string
|
|
||||||
}{
|
|
||||||
// positive
|
|
||||||
{"forward . 127.0.0.1 {\npolicy random\n}\n", false, "random", ""},
|
|
||||||
{"forward . 127.0.0.1 {\npolicy round_robin\n}\n", false, "round_robin", ""},
|
|
||||||
{"forward . 127.0.0.1 {\npolicy sequential\n}\n", false, "sequential", ""},
|
|
||||||
// negative
|
|
||||||
{"forward . 127.0.0.1 {\npolicy random2\n}\n", true, "random", "unknown policy"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
c := caddy.NewTestController("dns", test.input)
|
|
||||||
f, err := parseForward(c)
|
|
||||||
|
|
||||||
if test.shouldErr && err == nil {
|
|
||||||
t.Errorf("Test %d: expected error but found %s for input %s", i, err, test.input)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if !test.shouldErr {
|
|
||||||
t.Errorf("Test %d: expected no error but found one for input %s, got: %v", i, test.input, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), test.expectedErr) {
|
|
||||||
t.Errorf("Test %d: expected error to contain: %v, found error: %v, input: %s", i, test.expectedErr, err, test.input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !test.shouldErr && f.p.String() != test.expectedPolicy {
|
|
||||||
t.Errorf("Test %d: expected: %s, got: %s", i, test.expectedPolicy, f.p.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,257 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSetup(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
shouldErr bool
|
|
||||||
expectedFrom string
|
|
||||||
expectedIgnored []string
|
|
||||||
expectedFails uint32
|
|
||||||
expectedOpts options
|
|
||||||
expectedErr string
|
|
||||||
}{
|
|
||||||
// positive
|
|
||||||
{"forward . 127.0.0.1", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . 127.0.0.1 {\nexcept miek.nl\n}\n", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . 127.0.0.1 {\nmax_fails 3\n}\n", false, ".", nil, 3, options{hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . 127.0.0.1 {\nforce_tcp\n}\n", false, ".", nil, 2, options{forceTCP: true, hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . 127.0.0.1 {\nprefer_udp\n}\n", false, ".", nil, 2, options{preferUDP: true, hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . 127.0.0.1 {\nforce_tcp\nprefer_udp\n}\n", false, ".", nil, 2, options{preferUDP: true, forceTCP: true, hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . 127.0.0.1:53", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . 127.0.0.1:8080", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . [::1]:53", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . [2003::1]:53", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
|
|
||||||
{"forward . 127.0.0.1 \n", false, ".", nil, 2, options{hcRecursionDesired: true}, ""},
|
|
||||||
// negative
|
|
||||||
{"forward . a27.0.0.1", true, "", nil, 0, options{hcRecursionDesired: true}, "not an IP"},
|
|
||||||
{"forward . 127.0.0.1 {\nblaatl\n}\n", true, "", nil, 0, options{hcRecursionDesired: true}, "unknown property"},
|
|
||||||
{`forward . ::1
|
|
||||||
forward com ::2`, true, "", nil, 0, options{hcRecursionDesired: true}, "plugin"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
c := caddy.NewTestController("dns", test.input)
|
|
||||||
f, err := parseForward(c)
|
|
||||||
|
|
||||||
if test.shouldErr && err == nil {
|
|
||||||
t.Errorf("Test %d: expected error but found %s for input %s", i, err, test.input)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if !test.shouldErr {
|
|
||||||
t.Errorf("Test %d: expected no error but found one for input %s, got: %v", i, test.input, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), test.expectedErr) {
|
|
||||||
t.Errorf("Test %d: expected error to contain: %v, found error: %v, input: %s", i, test.expectedErr, err, test.input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !test.shouldErr && f.from != test.expectedFrom {
|
|
||||||
t.Errorf("Test %d: expected: %s, got: %s", i, test.expectedFrom, f.from)
|
|
||||||
}
|
|
||||||
if !test.shouldErr && test.expectedIgnored != nil {
|
|
||||||
if !reflect.DeepEqual(f.ignored, test.expectedIgnored) {
|
|
||||||
t.Errorf("Test %d: expected: %q, actual: %q", i, test.expectedIgnored, f.ignored)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !test.shouldErr && f.maxfails != test.expectedFails {
|
|
||||||
t.Errorf("Test %d: expected: %d, got: %d", i, test.expectedFails, f.maxfails)
|
|
||||||
}
|
|
||||||
if !test.shouldErr && f.opts != test.expectedOpts {
|
|
||||||
t.Errorf("Test %d: expected: %v, got: %v", i, test.expectedOpts, f.opts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetupTLS(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
shouldErr bool
|
|
||||||
expectedServerName string
|
|
||||||
expectedErr string
|
|
||||||
}{
|
|
||||||
// positive
|
|
||||||
{`forward . tls://127.0.0.1 {
|
|
||||||
tls_servername dns
|
|
||||||
}`, false, "dns", ""},
|
|
||||||
{`forward . 127.0.0.1 {
|
|
||||||
tls_servername dns
|
|
||||||
}`, false, "", ""},
|
|
||||||
{`forward . 127.0.0.1 {
|
|
||||||
tls
|
|
||||||
}`, false, "", ""},
|
|
||||||
{`forward . tls://127.0.0.1`, false, "", ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
c := caddy.NewTestController("dns", test.input)
|
|
||||||
f, err := parseForward(c)
|
|
||||||
|
|
||||||
if test.shouldErr && err == nil {
|
|
||||||
t.Errorf("Test %d: expected error but found %s for input %s", i, err, test.input)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if !test.shouldErr {
|
|
||||||
t.Errorf("Test %d: expected no error but found one for input %s, got: %v", i, test.input, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), test.expectedErr) {
|
|
||||||
t.Errorf("Test %d: expected error to contain: %v, found error: %v, input: %s", i, test.expectedErr, err, test.input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !test.shouldErr && test.expectedServerName != "" && test.expectedServerName != f.tlsConfig.ServerName {
|
|
||||||
t.Errorf("Test %d: expected: %q, actual: %q", i, test.expectedServerName, f.tlsConfig.ServerName)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !test.shouldErr && test.expectedServerName != "" && test.expectedServerName != f.proxies[0].health.(*dnsHc).c.TLSConfig.ServerName {
|
|
||||||
t.Errorf("Test %d: expected: %q, actual: %q", i, test.expectedServerName, f.proxies[0].health.(*dnsHc).c.TLSConfig.ServerName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetupResolvconf(t *testing.T) {
|
|
||||||
const resolv = "resolv.conf"
|
|
||||||
if err := ioutil.WriteFile(resolv,
|
|
||||||
[]byte(`nameserver 10.10.255.252
|
|
||||||
nameserver 10.10.255.253`), 0666); err != nil {
|
|
||||||
t.Fatalf("Failed to write resolv.conf file: %s", err)
|
|
||||||
}
|
|
||||||
defer os.Remove(resolv)
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
shouldErr bool
|
|
||||||
expectedErr string
|
|
||||||
expectedNames []string
|
|
||||||
}{
|
|
||||||
// pass
|
|
||||||
{`forward . ` + resolv, false, "", []string{"10.10.255.252:53", "10.10.255.253:53"}},
|
|
||||||
// fail
|
|
||||||
{`forward . /dev/null`, true, "no nameservers", nil},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
c := caddy.NewTestController("dns", test.input)
|
|
||||||
f, err := parseForward(c)
|
|
||||||
|
|
||||||
if test.shouldErr && err == nil {
|
|
||||||
t.Errorf("Test %d: expected error but found %s for input %s", i, err, test.input)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if !test.shouldErr {
|
|
||||||
t.Errorf("Test %d: expected no error but found one for input %s, got: %v", i, test.input, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), test.expectedErr) {
|
|
||||||
t.Errorf("Test %d: expected error to contain: %v, found error: %v, input: %s", i, test.expectedErr, err, test.input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !test.shouldErr {
|
|
||||||
for j, n := range test.expectedNames {
|
|
||||||
addr := f.proxies[j].addr
|
|
||||||
if n != addr {
|
|
||||||
t.Errorf("Test %d, expected %q, got %q", j, n, addr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if test.shouldErr {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, p := range f.proxies {
|
|
||||||
p.health.Check(p) // this should almost always err, we don't care it shouldn't crash
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetupMaxConcurrent(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
shouldErr bool
|
|
||||||
expectedVal int64
|
|
||||||
expectedErr string
|
|
||||||
}{
|
|
||||||
// positive
|
|
||||||
{"forward . 127.0.0.1 {\nmax_concurrent 1000\n}\n", false, 1000, ""},
|
|
||||||
// negative
|
|
||||||
{"forward . 127.0.0.1 {\nmax_concurrent many\n}\n", true, 0, "invalid"},
|
|
||||||
{"forward . 127.0.0.1 {\nmax_concurrent -4\n}\n", true, 0, "negative"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
c := caddy.NewTestController("dns", test.input)
|
|
||||||
f, err := parseForward(c)
|
|
||||||
|
|
||||||
if test.shouldErr && err == nil {
|
|
||||||
t.Errorf("Test %d: expected error but found %s for input %s", i, err, test.input)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if !test.shouldErr {
|
|
||||||
t.Errorf("Test %d: expected no error but found one for input %s, got: %v", i, test.input, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), test.expectedErr) {
|
|
||||||
t.Errorf("Test %d: expected error to contain: %v, found error: %v, input: %s", i, test.expectedErr, err, test.input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !test.shouldErr && f.maxConcurrent != test.expectedVal {
|
|
||||||
t.Errorf("Test %d: expected: %d, got: %d", i, test.expectedVal, f.maxConcurrent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSetupHealthCheck(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
input string
|
|
||||||
shouldErr bool
|
|
||||||
expectedVal bool
|
|
||||||
expectedErr string
|
|
||||||
}{
|
|
||||||
// positive
|
|
||||||
{"forward . 127.0.0.1\n", false, true, ""},
|
|
||||||
{"forward . 127.0.0.1 {\nhealth_check 0.5s\n}\n", false, true, ""},
|
|
||||||
{"forward . 127.0.0.1 {\nhealth_check 0.5s no_rec\n}\n", false, false, ""},
|
|
||||||
// negative
|
|
||||||
{"forward . 127.0.0.1 {\nhealth_check no_rec\n}\n", true, true, "time: invalid duration"},
|
|
||||||
{"forward . 127.0.0.1 {\nhealth_check 0.5s rec\n}\n", true, true, "health_check: unknown option rec"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, test := range tests {
|
|
||||||
c := caddy.NewTestController("dns", test.input)
|
|
||||||
f, err := parseForward(c)
|
|
||||||
|
|
||||||
if test.shouldErr && err == nil {
|
|
||||||
t.Errorf("Test %d: expected error but found %s for input %s", i, err, test.input)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if !test.shouldErr {
|
|
||||||
t.Errorf("Test %d: expected no error but found one for input %s, got: %v", i, test.input, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), test.expectedErr) {
|
|
||||||
t.Errorf("Test %d: expected error to contain: %v, found error: %v, input: %s", i, test.expectedErr, err, test.input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !test.shouldErr && (f.opts.hcRecursionDesired != test.expectedVal || f.proxies[0].health.GetRecursionDesired() != test.expectedVal) {
|
|
||||||
t.Errorf("Test %d: expected: %t, got: %d", i, test.expectedVal, f.maxConcurrent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package forward
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
type transportType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
typeUdp transportType = iota
|
|
||||||
typeTcp
|
|
||||||
typeTls
|
|
||||||
typeTotalCount // keep this last
|
|
||||||
)
|
|
||||||
|
|
||||||
func stringToTransportType(s string) transportType {
|
|
||||||
switch s {
|
|
||||||
case "udp":
|
|
||||||
return typeUdp
|
|
||||||
case "tcp":
|
|
||||||
return typeTcp
|
|
||||||
case "tcp-tls":
|
|
||||||
return typeTls
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeUdp
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Transport) transportTypeFromConn(pc *persistConn) transportType {
|
|
||||||
if _, ok := pc.c.Conn.(*net.UDPConn); ok {
|
|
||||||
return typeUdp
|
|
||||||
}
|
|
||||||
|
|
||||||
if t.tlsConfig == nil {
|
|
||||||
return typeTcp
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeTls
|
|
||||||
}
|
|
22
vendor/github.com/cenkalti/backoff/v4/.gitignore
generated
vendored
22
vendor/github.com/cenkalti/backoff/v4/.gitignore
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
|
||||||
*.o
|
|
||||||
*.a
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Folders
|
|
||||||
_obj
|
|
||||||
_test
|
|
||||||
|
|
||||||
# Architecture specific extensions/prefixes
|
|
||||||
*.[568vq]
|
|
||||||
[568vq].out
|
|
||||||
|
|
||||||
*.cgo1.go
|
|
||||||
*.cgo2.c
|
|
||||||
_cgo_defun.c
|
|
||||||
_cgo_gotypes.go
|
|
||||||
_cgo_export.*
|
|
||||||
|
|
||||||
_testmain.go
|
|
||||||
|
|
||||||
*.exe
|
|
10
vendor/github.com/cenkalti/backoff/v4/.travis.yml
generated
vendored
10
vendor/github.com/cenkalti/backoff/v4/.travis.yml
generated
vendored
@ -1,10 +0,0 @@
|
|||||||
language: go
|
|
||||||
go:
|
|
||||||
- 1.12
|
|
||||||
- 1.x
|
|
||||||
- tip
|
|
||||||
before_install:
|
|
||||||
- go get github.com/mattn/goveralls
|
|
||||||
- go get golang.org/x/tools/cmd/cover
|
|
||||||
script:
|
|
||||||
- $HOME/gopath/bin/goveralls -service=travis-ci
|
|
20
vendor/github.com/cenkalti/backoff/v4/LICENSE
generated
vendored
20
vendor/github.com/cenkalti/backoff/v4/LICENSE
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Cenk Altı
|
|
||||||
|
|
||||||
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.
|
|
33
vendor/github.com/cenkalti/backoff/v4/README.md
generated
vendored
33
vendor/github.com/cenkalti/backoff/v4/README.md
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
|
|
||||||
|
|
||||||
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
|
|
||||||
|
|
||||||
[Exponential backoff][exponential backoff wiki]
|
|
||||||
is an algorithm that uses feedback to multiplicatively decrease the rate of some process,
|
|
||||||
in order to gradually find an acceptable rate.
|
|
||||||
The retries exponentially increase and stop increasing when a certain threshold is met.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end.
|
|
||||||
|
|
||||||
godoc.org does not support modules yet,
|
|
||||||
so you can use https://godoc.org/gopkg.in/cenkalti/backoff.v4 to view the documentation.
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
* I would like to keep this library as small as possible.
|
|
||||||
* Please don't send a PR without opening an issue and discussing it first.
|
|
||||||
* If proposed change is not a common use case, I will probably not accept it.
|
|
||||||
|
|
||||||
[godoc]: https://godoc.org/github.com/cenkalti/backoff
|
|
||||||
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
|
|
||||||
[travis]: https://travis-ci.org/cenkalti/backoff
|
|
||||||
[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master
|
|
||||||
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
|
|
||||||
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
|
|
||||||
|
|
||||||
[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java
|
|
||||||
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
|
|
||||||
|
|
||||||
[advanced example]: https://godoc.org/github.com/cenkalti/backoff#example_
|
|
66
vendor/github.com/cenkalti/backoff/v4/backoff.go
generated
vendored
66
vendor/github.com/cenkalti/backoff/v4/backoff.go
generated
vendored
@ -1,66 +0,0 @@
|
|||||||
// Package backoff implements backoff algorithms for retrying operations.
|
|
||||||
//
|
|
||||||
// Use Retry function for retrying operations that may fail.
|
|
||||||
// If Retry does not meet your needs,
|
|
||||||
// copy/paste the function into your project and modify as you wish.
|
|
||||||
//
|
|
||||||
// There is also Ticker type similar to time.Ticker.
|
|
||||||
// You can use it if you need to work with channels.
|
|
||||||
//
|
|
||||||
// See Examples section below for usage examples.
|
|
||||||
package backoff
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// BackOff is a backoff policy for retrying an operation.
|
|
||||||
type BackOff interface {
|
|
||||||
// NextBackOff returns the duration to wait before retrying the operation,
|
|
||||||
// or backoff. Stop to indicate that no more retries should be made.
|
|
||||||
//
|
|
||||||
// Example usage:
|
|
||||||
//
|
|
||||||
// duration := backoff.NextBackOff();
|
|
||||||
// if (duration == backoff.Stop) {
|
|
||||||
// // Do not retry operation.
|
|
||||||
// } else {
|
|
||||||
// // Sleep for duration and retry operation.
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
NextBackOff() time.Duration
|
|
||||||
|
|
||||||
// Reset to initial state.
|
|
||||||
Reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop indicates that no more retries should be made for use in NextBackOff().
|
|
||||||
const Stop time.Duration = -1
|
|
||||||
|
|
||||||
// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
|
|
||||||
// meaning that the operation is retried immediately without waiting, indefinitely.
|
|
||||||
type ZeroBackOff struct{}
|
|
||||||
|
|
||||||
func (b *ZeroBackOff) Reset() {}
|
|
||||||
|
|
||||||
func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
|
|
||||||
|
|
||||||
// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
|
|
||||||
// NextBackOff(), meaning that the operation should never be retried.
|
|
||||||
type StopBackOff struct{}
|
|
||||||
|
|
||||||
func (b *StopBackOff) Reset() {}
|
|
||||||
|
|
||||||
func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
|
|
||||||
|
|
||||||
// ConstantBackOff is a backoff policy that always returns the same backoff delay.
|
|
||||||
// This is in contrast to an exponential backoff policy,
|
|
||||||
// which returns a delay that grows longer as you call NextBackOff() over and over again.
|
|
||||||
type ConstantBackOff struct {
|
|
||||||
Interval time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *ConstantBackOff) Reset() {}
|
|
||||||
func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval }
|
|
||||||
|
|
||||||
func NewConstantBackOff(d time.Duration) *ConstantBackOff {
|
|
||||||
return &ConstantBackOff{Interval: d}
|
|
||||||
}
|
|
66
vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
66
vendor/github.com/cenkalti/backoff/v4/context.go
generated
vendored
@ -1,66 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BackOffContext is a backoff policy that stops retrying after the context
|
|
||||||
// is canceled.
|
|
||||||
type BackOffContext interface { // nolint: golint
|
|
||||||
BackOff
|
|
||||||
Context() context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
type backOffContext struct {
|
|
||||||
BackOff
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithContext returns a BackOffContext with context ctx
|
|
||||||
//
|
|
||||||
// ctx must not be nil
|
|
||||||
func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint
|
|
||||||
if ctx == nil {
|
|
||||||
panic("nil context")
|
|
||||||
}
|
|
||||||
|
|
||||||
if b, ok := b.(*backOffContext); ok {
|
|
||||||
return &backOffContext{
|
|
||||||
BackOff: b.BackOff,
|
|
||||||
ctx: ctx,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &backOffContext{
|
|
||||||
BackOff: b,
|
|
||||||
ctx: ctx,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getContext(b BackOff) context.Context {
|
|
||||||
if cb, ok := b.(BackOffContext); ok {
|
|
||||||
return cb.Context()
|
|
||||||
}
|
|
||||||
if tb, ok := b.(*backOffTries); ok {
|
|
||||||
return getContext(tb.delegate)
|
|
||||||
}
|
|
||||||
return context.Background()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backOffContext) Context() context.Context {
|
|
||||||
return b.ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backOffContext) NextBackOff() time.Duration {
|
|
||||||
select {
|
|
||||||
case <-b.ctx.Done():
|
|
||||||
return Stop
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
next := b.BackOff.NextBackOff()
|
|
||||||
if deadline, ok := b.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next { // nolint: gosimple
|
|
||||||
return Stop
|
|
||||||
}
|
|
||||||
return next
|
|
||||||
}
|
|
156
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
156
vendor/github.com/cenkalti/backoff/v4/exponential.go
generated
vendored
@ -1,156 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
ExponentialBackOff is a backoff implementation that increases the backoff
|
|
||||||
period for each retry attempt using a randomization function that grows exponentially.
|
|
||||||
|
|
||||||
NextBackOff() is calculated using the following formula:
|
|
||||||
|
|
||||||
randomized interval =
|
|
||||||
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
|
|
||||||
|
|
||||||
In other words NextBackOff() will range between the randomization factor
|
|
||||||
percentage below and above the retry interval.
|
|
||||||
|
|
||||||
For example, given the following parameters:
|
|
||||||
|
|
||||||
RetryInterval = 2
|
|
||||||
RandomizationFactor = 0.5
|
|
||||||
Multiplier = 2
|
|
||||||
|
|
||||||
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
|
|
||||||
multiplied by the exponential, that is, between 2 and 6 seconds.
|
|
||||||
|
|
||||||
Note: MaxInterval caps the RetryInterval and not the randomized interval.
|
|
||||||
|
|
||||||
If the time elapsed since an ExponentialBackOff instance is created goes past the
|
|
||||||
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
|
|
||||||
|
|
||||||
The elapsed time can be reset by calling Reset().
|
|
||||||
|
|
||||||
Example: Given the following default arguments, for 10 tries the sequence will be,
|
|
||||||
and assuming we go over the MaxElapsedTime on the 10th try:
|
|
||||||
|
|
||||||
Request # RetryInterval (seconds) Randomized Interval (seconds)
|
|
||||||
|
|
||||||
1 0.5 [0.25, 0.75]
|
|
||||||
2 0.75 [0.375, 1.125]
|
|
||||||
3 1.125 [0.562, 1.687]
|
|
||||||
4 1.687 [0.8435, 2.53]
|
|
||||||
5 2.53 [1.265, 3.795]
|
|
||||||
6 3.795 [1.897, 5.692]
|
|
||||||
7 5.692 [2.846, 8.538]
|
|
||||||
8 8.538 [4.269, 12.807]
|
|
||||||
9 12.807 [6.403, 19.210]
|
|
||||||
10 19.210 backoff.Stop
|
|
||||||
|
|
||||||
Note: Implementation is not thread-safe.
|
|
||||||
*/
|
|
||||||
type ExponentialBackOff struct {
|
|
||||||
InitialInterval time.Duration
|
|
||||||
RandomizationFactor float64
|
|
||||||
Multiplier float64
|
|
||||||
MaxInterval time.Duration
|
|
||||||
// After MaxElapsedTime the ExponentialBackOff returns Stop.
|
|
||||||
// It never stops if MaxElapsedTime == 0.
|
|
||||||
MaxElapsedTime time.Duration
|
|
||||||
Stop time.Duration
|
|
||||||
Clock Clock
|
|
||||||
|
|
||||||
currentInterval time.Duration
|
|
||||||
startTime time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clock is an interface that returns current time for BackOff.
|
|
||||||
type Clock interface {
|
|
||||||
Now() time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default values for ExponentialBackOff.
|
|
||||||
const (
|
|
||||||
DefaultInitialInterval = 500 * time.Millisecond
|
|
||||||
DefaultRandomizationFactor = 0.5
|
|
||||||
DefaultMultiplier = 1.5
|
|
||||||
DefaultMaxInterval = 60 * time.Second
|
|
||||||
DefaultMaxElapsedTime = 15 * time.Minute
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
|
|
||||||
func NewExponentialBackOff() *ExponentialBackOff {
|
|
||||||
b := &ExponentialBackOff{
|
|
||||||
InitialInterval: DefaultInitialInterval,
|
|
||||||
RandomizationFactor: DefaultRandomizationFactor,
|
|
||||||
Multiplier: DefaultMultiplier,
|
|
||||||
MaxInterval: DefaultMaxInterval,
|
|
||||||
MaxElapsedTime: DefaultMaxElapsedTime,
|
|
||||||
Stop: Stop,
|
|
||||||
Clock: SystemClock,
|
|
||||||
}
|
|
||||||
b.Reset()
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
type systemClock struct{}
|
|
||||||
|
|
||||||
func (t systemClock) Now() time.Time {
|
|
||||||
return time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SystemClock implements Clock interface that uses time.Now().
|
|
||||||
var SystemClock = systemClock{}
|
|
||||||
|
|
||||||
// Reset the interval back to the initial retry interval and restarts the timer.
|
|
||||||
// Reset must be called before using b.
|
|
||||||
func (b *ExponentialBackOff) Reset() {
|
|
||||||
b.currentInterval = b.InitialInterval
|
|
||||||
b.startTime = b.Clock.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NextBackOff calculates the next backoff interval using the formula:
|
|
||||||
// Randomized interval = RetryInterval * (1 ± RandomizationFactor)
|
|
||||||
func (b *ExponentialBackOff) NextBackOff() time.Duration {
|
|
||||||
// Make sure we have not gone over the maximum elapsed time.
|
|
||||||
if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
|
|
||||||
return b.Stop
|
|
||||||
}
|
|
||||||
defer b.incrementCurrentInterval()
|
|
||||||
return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
|
|
||||||
// is created and is reset when Reset() is called.
|
|
||||||
//
|
|
||||||
// The elapsed time is computed using time.Now().UnixNano(). It is
|
|
||||||
// safe to call even while the backoff policy is used by a running
|
|
||||||
// ticker.
|
|
||||||
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
|
|
||||||
return b.Clock.Now().Sub(b.startTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increments the current interval by multiplying it with the multiplier.
|
|
||||||
func (b *ExponentialBackOff) incrementCurrentInterval() {
|
|
||||||
// Check for overflow, if overflow is detected set the current interval to the max interval.
|
|
||||||
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
|
|
||||||
b.currentInterval = b.MaxInterval
|
|
||||||
} else {
|
|
||||||
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a random value from the following interval:
|
|
||||||
// [randomizationFactor * currentInterval, randomizationFactor * currentInterval].
|
|
||||||
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
|
|
||||||
var delta = randomizationFactor * float64(currentInterval)
|
|
||||||
var minInterval = float64(currentInterval) - delta
|
|
||||||
var maxInterval = float64(currentInterval) + delta
|
|
||||||
|
|
||||||
// Get a random value from the range [minInterval, maxInterval].
|
|
||||||
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
|
|
||||||
// we want a 33% chance for selecting either 1, 2 or 3.
|
|
||||||
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
|
|
||||||
}
|
|
3
vendor/github.com/cenkalti/backoff/v4/go.mod
generated
vendored
3
vendor/github.com/cenkalti/backoff/v4/go.mod
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
module github.com/cenkalti/backoff/v4
|
|
||||||
|
|
||||||
go 1.12
|
|
96
vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
96
vendor/github.com/cenkalti/backoff/v4/retry.go
generated
vendored
@ -1,96 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// An Operation is executing by Retry() or RetryNotify().
|
|
||||||
// The operation will be retried using a backoff policy if it returns an error.
|
|
||||||
type Operation func() error
|
|
||||||
|
|
||||||
// Notify is a notify-on-error function. It receives an operation error and
|
|
||||||
// backoff delay if the operation failed (with an error).
|
|
||||||
//
|
|
||||||
// NOTE that if the backoff policy stated to stop retrying,
|
|
||||||
// the notify function isn't called.
|
|
||||||
type Notify func(error, time.Duration)
|
|
||||||
|
|
||||||
// Retry the operation o until it does not return error or BackOff stops.
|
|
||||||
// o is guaranteed to be run at least once.
|
|
||||||
//
|
|
||||||
// If o returns a *PermanentError, the operation is not retried, and the
|
|
||||||
// wrapped error is returned.
|
|
||||||
//
|
|
||||||
// Retry sleeps the goroutine for the duration returned by BackOff after a
|
|
||||||
// failed operation returns.
|
|
||||||
func Retry(o Operation, b BackOff) error {
|
|
||||||
return RetryNotify(o, b, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetryNotify calls notify function with the error and wait duration
|
|
||||||
// for each failed attempt before sleep.
|
|
||||||
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
|
|
||||||
return RetryNotifyWithTimer(operation, b, notify, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer
|
|
||||||
// for each failed attempt before sleep.
|
|
||||||
// A default timer that uses system timer is used when nil is passed.
|
|
||||||
func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error {
|
|
||||||
var err error
|
|
||||||
var next time.Duration
|
|
||||||
if t == nil {
|
|
||||||
t = &defaultTimer{}
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
t.Stop()
|
|
||||||
}()
|
|
||||||
|
|
||||||
ctx := getContext(b)
|
|
||||||
|
|
||||||
b.Reset()
|
|
||||||
for {
|
|
||||||
if err = operation(); err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if permanent, ok := err.(*PermanentError); ok {
|
|
||||||
return permanent.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
if next = b.NextBackOff(); next == Stop {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if notify != nil {
|
|
||||||
notify(err, next)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Start(next)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
|
||||||
case <-t.C():
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PermanentError signals that the operation should not be retried.
|
|
||||||
type PermanentError struct {
|
|
||||||
Err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *PermanentError) Error() string {
|
|
||||||
return e.Err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *PermanentError) Unwrap() error {
|
|
||||||
return e.Err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Permanent wraps the given err in a *PermanentError.
|
|
||||||
func Permanent(err error) *PermanentError {
|
|
||||||
return &PermanentError{
|
|
||||||
Err: err,
|
|
||||||
}
|
|
||||||
}
|
|
94
vendor/github.com/cenkalti/backoff/v4/ticker.go
generated
vendored
94
vendor/github.com/cenkalti/backoff/v4/ticker.go
generated
vendored
@ -1,94 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
|
|
||||||
//
|
|
||||||
// Ticks will continue to arrive when the previous operation is still running,
|
|
||||||
// so operations that take a while to fail could run in quick succession.
|
|
||||||
type Ticker struct {
|
|
||||||
C <-chan time.Time
|
|
||||||
c chan time.Time
|
|
||||||
b BackOff
|
|
||||||
ctx context.Context
|
|
||||||
timer Timer
|
|
||||||
stop chan struct{}
|
|
||||||
stopOnce sync.Once
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTicker returns a new Ticker containing a channel that will send
|
|
||||||
// the time at times specified by the BackOff argument. Ticker is
|
|
||||||
// guaranteed to tick at least once. The channel is closed when Stop
|
|
||||||
// method is called or BackOff stops. It is not safe to manipulate the
|
|
||||||
// provided backoff policy (notably calling NextBackOff or Reset)
|
|
||||||
// while the ticker is running.
|
|
||||||
func NewTicker(b BackOff) *Ticker {
|
|
||||||
return NewTickerWithTimer(b, &defaultTimer{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTickerWithTimer returns a new Ticker with a custom timer.
|
|
||||||
// A default timer that uses system timer is used when nil is passed.
|
|
||||||
func NewTickerWithTimer(b BackOff, timer Timer) *Ticker {
|
|
||||||
c := make(chan time.Time)
|
|
||||||
t := &Ticker{
|
|
||||||
C: c,
|
|
||||||
c: c,
|
|
||||||
b: b,
|
|
||||||
ctx: getContext(b),
|
|
||||||
timer: timer,
|
|
||||||
stop: make(chan struct{}),
|
|
||||||
}
|
|
||||||
t.b.Reset()
|
|
||||||
go t.run()
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop turns off a ticker. After Stop, no more ticks will be sent.
|
|
||||||
func (t *Ticker) Stop() {
|
|
||||||
t.stopOnce.Do(func() { close(t.stop) })
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Ticker) run() {
|
|
||||||
c := t.c
|
|
||||||
defer close(c)
|
|
||||||
|
|
||||||
// Ticker is guaranteed to tick at least once.
|
|
||||||
afterC := t.send(time.Now())
|
|
||||||
|
|
||||||
for {
|
|
||||||
if afterC == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case tick := <-afterC:
|
|
||||||
afterC = t.send(tick)
|
|
||||||
case <-t.stop:
|
|
||||||
t.c = nil // Prevent future ticks from being sent to the channel.
|
|
||||||
return
|
|
||||||
case <-t.ctx.Done():
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Ticker) send(tick time.Time) <-chan time.Time {
|
|
||||||
select {
|
|
||||||
case t.c <- tick:
|
|
||||||
case <-t.stop:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
next := t.b.NextBackOff()
|
|
||||||
if next == Stop {
|
|
||||||
t.Stop()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
t.timer.Start(next)
|
|
||||||
return t.timer.C()
|
|
||||||
}
|
|
35
vendor/github.com/cenkalti/backoff/v4/timer.go
generated
vendored
35
vendor/github.com/cenkalti/backoff/v4/timer.go
generated
vendored
@ -1,35 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
type Timer interface {
|
|
||||||
Start(duration time.Duration)
|
|
||||||
Stop()
|
|
||||||
C() <-chan time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultTimer implements Timer interface using time.Timer
|
|
||||||
type defaultTimer struct {
|
|
||||||
timer *time.Timer
|
|
||||||
}
|
|
||||||
|
|
||||||
// C returns the timers channel which receives the current time when the timer fires.
|
|
||||||
func (t *defaultTimer) C() <-chan time.Time {
|
|
||||||
return t.timer.C
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start starts the timer to fire after the given duration
|
|
||||||
func (t *defaultTimer) Start(duration time.Duration) {
|
|
||||||
if t.timer == nil {
|
|
||||||
t.timer = time.NewTimer(duration)
|
|
||||||
} else {
|
|
||||||
t.timer.Reset(duration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop is called when the timer is not used anymore and resources may be freed.
|
|
||||||
func (t *defaultTimer) Stop() {
|
|
||||||
if t.timer != nil {
|
|
||||||
t.timer.Stop()
|
|
||||||
}
|
|
||||||
}
|
|
38
vendor/github.com/cenkalti/backoff/v4/tries.go
generated
vendored
38
vendor/github.com/cenkalti/backoff/v4/tries.go
generated
vendored
@ -1,38 +0,0 @@
|
|||||||
package backoff
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
/*
|
|
||||||
WithMaxRetries creates a wrapper around another BackOff, which will
|
|
||||||
return Stop if NextBackOff() has been called too many times since
|
|
||||||
the last time Reset() was called
|
|
||||||
|
|
||||||
Note: Implementation is not thread-safe.
|
|
||||||
*/
|
|
||||||
func WithMaxRetries(b BackOff, max uint64) BackOff {
|
|
||||||
return &backOffTries{delegate: b, maxTries: max}
|
|
||||||
}
|
|
||||||
|
|
||||||
type backOffTries struct {
|
|
||||||
delegate BackOff
|
|
||||||
maxTries uint64
|
|
||||||
numTries uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backOffTries) NextBackOff() time.Duration {
|
|
||||||
if b.maxTries == 0 {
|
|
||||||
return Stop
|
|
||||||
}
|
|
||||||
if b.maxTries > 0 {
|
|
||||||
if b.maxTries <= b.numTries {
|
|
||||||
return Stop
|
|
||||||
}
|
|
||||||
b.numTries++
|
|
||||||
}
|
|
||||||
return b.delegate.NextBackOff()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *backOffTries) Reset() {
|
|
||||||
b.numTries = 0
|
|
||||||
b.delegate.Reset()
|
|
||||||
}
|
|
93
vendor/github.com/coredns/coredns/plugin/dnstap/README.md
generated
vendored
93
vendor/github.com/coredns/coredns/plugin/dnstap/README.md
generated
vendored
@ -1,93 +0,0 @@
|
|||||||
# dnstap
|
|
||||||
|
|
||||||
## Name
|
|
||||||
|
|
||||||
*dnstap* - enables logging to dnstap.
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
dnstap is a flexible, structured binary log format for DNS software; see https://dnstap.info. With this
|
|
||||||
plugin you make CoreDNS output dnstap logging.
|
|
||||||
|
|
||||||
Note that there is an internal buffer, so expect at least 13 requests before the server sends its
|
|
||||||
dnstap messages to the socket.
|
|
||||||
|
|
||||||
## Syntax
|
|
||||||
|
|
||||||
~~~ txt
|
|
||||||
dnstap SOCKET [full]
|
|
||||||
~~~
|
|
||||||
|
|
||||||
* **SOCKET** is the socket path supplied to the dnstap command line tool.
|
|
||||||
* `full` to include the wire-format DNS message.
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
Log information about client requests and responses to */tmp/dnstap.sock*.
|
|
||||||
|
|
||||||
~~~ txt
|
|
||||||
dnstap /tmp/dnstap.sock
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Log information including the wire-format DNS message about client requests and responses to */tmp/dnstap.sock*.
|
|
||||||
|
|
||||||
~~~ txt
|
|
||||||
dnstap unix:///tmp/dnstap.sock full
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Log to a remote endpoint.
|
|
||||||
|
|
||||||
~~~ txt
|
|
||||||
dnstap tcp://127.0.0.1:6000 full
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Command Line Tool
|
|
||||||
|
|
||||||
Dnstap has a command line tool that can be used to inspect the logging. The tool can be found
|
|
||||||
at Github: <https://github.com/dnstap/golang-dnstap>. It's written in Go.
|
|
||||||
|
|
||||||
The following command listens on the given socket and decodes messages to stdout.
|
|
||||||
|
|
||||||
~~~ sh
|
|
||||||
$ dnstap -u /tmp/dnstap.sock
|
|
||||||
~~~
|
|
||||||
|
|
||||||
The following command listens on the given socket and saves message payloads to a binary dnstap-format log file.
|
|
||||||
|
|
||||||
~~~ sh
|
|
||||||
$ dnstap -u /tmp/dnstap.sock -w /tmp/test.dnstap
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Listen for dnstap messages on port 6000.
|
|
||||||
|
|
||||||
~~~ sh
|
|
||||||
$ dnstap -l 127.0.0.1:6000
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Using Dnstap in your plugin
|
|
||||||
|
|
||||||
~~~ Go
|
|
||||||
import (
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap"
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap/msg"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (h Dnstap) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
||||||
// log client query to Dnstap
|
|
||||||
if t := dnstap.TapperFromContext(ctx); t != nil {
|
|
||||||
b := msg.New().Time(time.Now()).Addr(w.RemoteAddr())
|
|
||||||
if t.Pack() {
|
|
||||||
b.Msg(r)
|
|
||||||
}
|
|
||||||
if m, err := b.ToClientQuery(); err == nil {
|
|
||||||
t.TapMessage(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## See Also
|
|
||||||
|
|
||||||
[dnstap.info](https://dnstap.info).
|
|
91
vendor/github.com/coredns/coredns/plugin/dnstap/dnstapio/dnstap_encoder.go
generated
vendored
91
vendor/github.com/coredns/coredns/plugin/dnstap/dnstapio/dnstap_encoder.go
generated
vendored
@ -1,91 +0,0 @@
|
|||||||
package dnstapio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
tap "github.com/dnstap/golang-dnstap"
|
|
||||||
fs "github.com/farsightsec/golang-framestream"
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
protobufSize = 1024 * 1024
|
|
||||||
)
|
|
||||||
|
|
||||||
type dnstapEncoder struct {
|
|
||||||
fse *fs.Encoder
|
|
||||||
opts *fs.EncoderOptions
|
|
||||||
writer io.Writer
|
|
||||||
buffer *proto.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func newDnstapEncoder(o *fs.EncoderOptions) *dnstapEncoder {
|
|
||||||
return &dnstapEncoder{
|
|
||||||
opts: o,
|
|
||||||
buffer: proto.NewBuffer(make([]byte, 0, protobufSize)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *dnstapEncoder) resetWriter(w io.Writer) error {
|
|
||||||
fse, err := fs.NewEncoder(w, enc.opts)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = fse.Flush(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
enc.fse = fse
|
|
||||||
enc.writer = w
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *dnstapEncoder) writeMsg(msg *tap.Dnstap) error {
|
|
||||||
if len(enc.buffer.Bytes()) >= protobufSize {
|
|
||||||
if err := enc.flushBuffer(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bufLen := len(enc.buffer.Bytes())
|
|
||||||
// add placeholder for frame length
|
|
||||||
if err := enc.buffer.EncodeFixed32(0); err != nil {
|
|
||||||
enc.buffer.SetBuf(enc.buffer.Bytes()[:bufLen])
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := enc.buffer.Marshal(msg); err != nil {
|
|
||||||
enc.buffer.SetBuf(enc.buffer.Bytes()[:bufLen])
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
enc.encodeFrameLen(enc.buffer.Bytes()[bufLen:])
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *dnstapEncoder) flushBuffer() error {
|
|
||||||
if enc.fse == nil || enc.writer == nil {
|
|
||||||
return fmt.Errorf("no writer")
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := enc.buffer.Bytes()
|
|
||||||
written := 0
|
|
||||||
for written < len(buf) {
|
|
||||||
n, err := enc.writer.Write(buf[written:])
|
|
||||||
written += n
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enc.buffer.Reset()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *dnstapEncoder) encodeFrameLen(buf []byte) {
|
|
||||||
binary.BigEndian.PutUint32(buf, uint32(len(buf)-4))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *dnstapEncoder) close() error {
|
|
||||||
if enc.fse != nil {
|
|
||||||
return enc.fse.Close()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
146
vendor/github.com/coredns/coredns/plugin/dnstap/dnstapio/io.go
generated
vendored
146
vendor/github.com/coredns/coredns/plugin/dnstap/dnstapio/io.go
generated
vendored
@ -1,146 +0,0 @@
|
|||||||
package dnstapio
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
clog "github.com/coredns/coredns/plugin/pkg/log"
|
|
||||||
|
|
||||||
tap "github.com/dnstap/golang-dnstap"
|
|
||||||
fs "github.com/farsightsec/golang-framestream"
|
|
||||||
)
|
|
||||||
|
|
||||||
var log = clog.NewWithPlugin("dnstap")
|
|
||||||
|
|
||||||
const (
|
|
||||||
tcpWriteBufSize = 1024 * 1024
|
|
||||||
tcpTimeout = 4 * time.Second
|
|
||||||
flushTimeout = 1 * time.Second
|
|
||||||
queueSize = 10000
|
|
||||||
)
|
|
||||||
|
|
||||||
type dnstapIO struct {
|
|
||||||
endpoint string
|
|
||||||
socket bool
|
|
||||||
conn net.Conn
|
|
||||||
enc *dnstapEncoder
|
|
||||||
queue chan tap.Dnstap
|
|
||||||
dropped uint32
|
|
||||||
quit chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new and initialized DnstapIO.
|
|
||||||
func New(endpoint string, socket bool) DnstapIO {
|
|
||||||
return &dnstapIO{
|
|
||||||
endpoint: endpoint,
|
|
||||||
socket: socket,
|
|
||||||
enc: newDnstapEncoder(&fs.EncoderOptions{
|
|
||||||
ContentType: []byte("protobuf:dnstap.Dnstap"),
|
|
||||||
Bidirectional: true,
|
|
||||||
}),
|
|
||||||
queue: make(chan tap.Dnstap, queueSize),
|
|
||||||
quit: make(chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DnstapIO interface
|
|
||||||
type DnstapIO interface {
|
|
||||||
Connect()
|
|
||||||
Dnstap(payload tap.Dnstap)
|
|
||||||
Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dio *dnstapIO) newConnect() error {
|
|
||||||
var err error
|
|
||||||
if dio.socket {
|
|
||||||
if dio.conn, err = net.Dial("unix", dio.endpoint); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if dio.conn, err = net.DialTimeout("tcp", dio.endpoint, tcpTimeout); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if tcpConn, ok := dio.conn.(*net.TCPConn); ok {
|
|
||||||
tcpConn.SetWriteBuffer(tcpWriteBufSize)
|
|
||||||
tcpConn.SetNoDelay(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dio.enc.resetWriter(dio.conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect connects to the dnstap endpoint.
|
|
||||||
func (dio *dnstapIO) Connect() {
|
|
||||||
if err := dio.newConnect(); err != nil {
|
|
||||||
log.Error("No connection to dnstap endpoint")
|
|
||||||
}
|
|
||||||
go dio.serve()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dnstap enqueues the payload for log.
|
|
||||||
func (dio *dnstapIO) Dnstap(payload tap.Dnstap) {
|
|
||||||
select {
|
|
||||||
case dio.queue <- payload:
|
|
||||||
default:
|
|
||||||
atomic.AddUint32(&dio.dropped, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dio *dnstapIO) closeConnection() {
|
|
||||||
dio.enc.close()
|
|
||||||
if dio.conn != nil {
|
|
||||||
dio.conn.Close()
|
|
||||||
dio.conn = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close waits until the I/O routine is finished to return.
|
|
||||||
func (dio *dnstapIO) Close() {
|
|
||||||
close(dio.quit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dio *dnstapIO) flushBuffer() {
|
|
||||||
if dio.conn == nil {
|
|
||||||
if err := dio.newConnect(); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Info("Reconnected to dnstap")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := dio.enc.flushBuffer(); err != nil {
|
|
||||||
log.Warningf("Connection lost: %s", err)
|
|
||||||
dio.closeConnection()
|
|
||||||
if err := dio.newConnect(); err != nil {
|
|
||||||
log.Errorf("Cannot connect to dnstap: %s", err)
|
|
||||||
} else {
|
|
||||||
log.Info("Reconnected to dnstap")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dio *dnstapIO) write(payload *tap.Dnstap) {
|
|
||||||
if err := dio.enc.writeMsg(payload); err != nil {
|
|
||||||
atomic.AddUint32(&dio.dropped, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dio *dnstapIO) serve() {
|
|
||||||
timeout := time.After(flushTimeout)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-dio.quit:
|
|
||||||
dio.flushBuffer()
|
|
||||||
dio.closeConnection()
|
|
||||||
return
|
|
||||||
case payload := <-dio.queue:
|
|
||||||
dio.write(&payload)
|
|
||||||
case <-timeout:
|
|
||||||
if dropped := atomic.SwapUint32(&dio.dropped, 0); dropped > 0 {
|
|
||||||
log.Warningf("Dropped dnstap messages: %d", dropped)
|
|
||||||
}
|
|
||||||
dio.flushBuffer()
|
|
||||||
timeout = time.After(flushTimeout)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
23
vendor/github.com/coredns/coredns/plugin/dnstap/gocontext.go
generated
vendored
23
vendor/github.com/coredns/coredns/plugin/dnstap/gocontext.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
package dnstap
|
|
||||||
|
|
||||||
import "context"
|
|
||||||
|
|
||||||
type contextKey struct{}
|
|
||||||
|
|
||||||
var dnstapKey = contextKey{}
|
|
||||||
|
|
||||||
// ContextWithTapper returns a new `context.Context` that holds a reference to
|
|
||||||
// `t`'s Tapper.
|
|
||||||
func ContextWithTapper(ctx context.Context, t Tapper) context.Context {
|
|
||||||
return context.WithValue(ctx, dnstapKey, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TapperFromContext returns the `Tapper` previously associated with `ctx`, or
|
|
||||||
// `nil` if no such `Tapper` could be found.
|
|
||||||
func TapperFromContext(ctx context.Context) Tapper {
|
|
||||||
val := ctx.Value(dnstapKey)
|
|
||||||
if sp, ok := val.(Tapper); ok {
|
|
||||||
return sp
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
88
vendor/github.com/coredns/coredns/plugin/dnstap/handler.go
generated
vendored
88
vendor/github.com/coredns/coredns/plugin/dnstap/handler.go
generated
vendored
@ -1,88 +0,0 @@
|
|||||||
package dnstap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin"
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap/taprw"
|
|
||||||
|
|
||||||
tap "github.com/dnstap/golang-dnstap"
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Dnstap is the dnstap handler.
|
|
||||||
type Dnstap struct {
|
|
||||||
Next plugin.Handler
|
|
||||||
IO IORoutine
|
|
||||||
|
|
||||||
// Set to true to include the relevant raw DNS message into the dnstap messages.
|
|
||||||
JoinRawMessage bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type (
|
|
||||||
// IORoutine is the dnstap I/O thread as defined by: <http://dnstap.info/Architecture>.
|
|
||||||
IORoutine interface {
|
|
||||||
Dnstap(tap.Dnstap)
|
|
||||||
}
|
|
||||||
// Tapper is implemented by the Context passed by the dnstap handler.
|
|
||||||
Tapper interface {
|
|
||||||
TapMessage(message *tap.Message)
|
|
||||||
Pack() bool
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// ContextKey defines the type of key that is used to save data into the context.
|
|
||||||
type ContextKey string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// DnstapSendOption specifies the Dnstap message to be send. Default is sent all.
|
|
||||||
DnstapSendOption ContextKey = "dnstap-send-option"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TapMessage implements Tapper.
|
|
||||||
func (h Dnstap) TapMessage(m *tap.Message) {
|
|
||||||
t := tap.Dnstap_MESSAGE
|
|
||||||
h.IO.Dnstap(tap.Dnstap{
|
|
||||||
Type: &t,
|
|
||||||
Message: m,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pack returns true if the raw DNS message should be included into the dnstap messages.
|
|
||||||
func (h Dnstap) Pack() bool {
|
|
||||||
return h.JoinRawMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServeDNS logs the client query and response to dnstap and passes the dnstap Context.
|
|
||||||
func (h Dnstap) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
|
||||||
|
|
||||||
// Add send option into context so other plugin can decide on which DNSTap
|
|
||||||
// message to be sent out
|
|
||||||
sendOption := taprw.SendOption{Cq: true, Cr: true}
|
|
||||||
newCtx := context.WithValue(ctx, DnstapSendOption, &sendOption)
|
|
||||||
newCtx = ContextWithTapper(newCtx, h)
|
|
||||||
|
|
||||||
rw := &taprw.ResponseWriter{
|
|
||||||
ResponseWriter: w,
|
|
||||||
Tapper: &h,
|
|
||||||
Query: r,
|
|
||||||
Send: &sendOption,
|
|
||||||
QueryEpoch: time.Now(),
|
|
||||||
}
|
|
||||||
|
|
||||||
code, err := plugin.NextOrFailure(h.Name(), h.Next, newCtx, rw, r)
|
|
||||||
if err != nil {
|
|
||||||
// ignore dnstap errors
|
|
||||||
return code, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = rw.DnstapError(); err != nil {
|
|
||||||
return code, plugin.Error("dnstap", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return code, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns dnstap.
|
|
||||||
func (h Dnstap) Name() string { return "dnstap" }
|
|
159
vendor/github.com/coredns/coredns/plugin/dnstap/msg/msg.go
generated
vendored
159
vendor/github.com/coredns/coredns/plugin/dnstap/msg/msg.go
generated
vendored
@ -1,159 +0,0 @@
|
|||||||
package msg
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
tap "github.com/dnstap/golang-dnstap"
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Builder helps to build a Dnstap message.
|
|
||||||
type Builder struct {
|
|
||||||
Packed []byte
|
|
||||||
SocketProto tap.SocketProtocol
|
|
||||||
SocketFam tap.SocketFamily
|
|
||||||
Address net.IP
|
|
||||||
Port uint32
|
|
||||||
TimeSec uint64
|
|
||||||
TimeNsec uint32
|
|
||||||
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a new Builder
|
|
||||||
func New() *Builder {
|
|
||||||
return &Builder{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Addr adds the remote address to the message.
|
|
||||||
func (b *Builder) Addr(remote net.Addr) *Builder {
|
|
||||||
if b.err != nil {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
switch addr := remote.(type) {
|
|
||||||
case *net.TCPAddr:
|
|
||||||
b.Address = addr.IP
|
|
||||||
b.Port = uint32(addr.Port)
|
|
||||||
b.SocketProto = tap.SocketProtocol_TCP
|
|
||||||
case *net.UDPAddr:
|
|
||||||
b.Address = addr.IP
|
|
||||||
b.Port = uint32(addr.Port)
|
|
||||||
b.SocketProto = tap.SocketProtocol_UDP
|
|
||||||
default:
|
|
||||||
b.err = errors.New("unknown remote address type")
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
if b.Address.To4() != nil {
|
|
||||||
b.SocketFam = tap.SocketFamily_INET
|
|
||||||
} else {
|
|
||||||
b.SocketFam = tap.SocketFamily_INET6
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Msg adds the raw DNS message to the dnstap message.
|
|
||||||
func (b *Builder) Msg(m *dns.Msg) *Builder {
|
|
||||||
if b.err != nil {
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
b.Packed, b.err = m.Pack()
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// HostPort adds the remote address as encoded by dnsutil.ParseHostPortOrFile to the message.
|
|
||||||
func (b *Builder) HostPort(addr string) *Builder {
|
|
||||||
ip, port, err := net.SplitHostPort(addr)
|
|
||||||
if err != nil {
|
|
||||||
b.err = err
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
p, err := strconv.ParseUint(port, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
b.err = err
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
b.Port = uint32(p)
|
|
||||||
|
|
||||||
if ip := net.ParseIP(ip); ip != nil {
|
|
||||||
b.Address = []byte(ip)
|
|
||||||
if ip := ip.To4(); ip != nil {
|
|
||||||
b.SocketFam = tap.SocketFamily_INET
|
|
||||||
} else {
|
|
||||||
b.SocketFam = tap.SocketFamily_INET6
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
b.err = errors.New("not an ip address")
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time adds the timestamp to the message.
|
|
||||||
func (b *Builder) Time(ts time.Time) *Builder {
|
|
||||||
b.TimeSec = uint64(ts.Unix())
|
|
||||||
b.TimeNsec = uint32(ts.Nanosecond())
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToClientResponse transforms Data into a client response message.
|
|
||||||
func (b *Builder) ToClientResponse() (*tap.Message, error) {
|
|
||||||
t := tap.Message_CLIENT_RESPONSE
|
|
||||||
return &tap.Message{
|
|
||||||
Type: &t,
|
|
||||||
SocketFamily: &b.SocketFam,
|
|
||||||
SocketProtocol: &b.SocketProto,
|
|
||||||
ResponseTimeSec: &b.TimeSec,
|
|
||||||
ResponseTimeNsec: &b.TimeNsec,
|
|
||||||
ResponseMessage: b.Packed,
|
|
||||||
QueryAddress: b.Address,
|
|
||||||
QueryPort: &b.Port,
|
|
||||||
}, b.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToClientQuery transforms Data into a client query message.
|
|
||||||
func (b *Builder) ToClientQuery() (*tap.Message, error) {
|
|
||||||
t := tap.Message_CLIENT_QUERY
|
|
||||||
return &tap.Message{
|
|
||||||
Type: &t,
|
|
||||||
SocketFamily: &b.SocketFam,
|
|
||||||
SocketProtocol: &b.SocketProto,
|
|
||||||
QueryTimeSec: &b.TimeSec,
|
|
||||||
QueryTimeNsec: &b.TimeNsec,
|
|
||||||
QueryMessage: b.Packed,
|
|
||||||
QueryAddress: b.Address,
|
|
||||||
QueryPort: &b.Port,
|
|
||||||
}, b.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToOutsideQuery transforms the data into a forwarder or resolver query message.
|
|
||||||
func (b *Builder) ToOutsideQuery(t tap.Message_Type) (*tap.Message, error) {
|
|
||||||
return &tap.Message{
|
|
||||||
Type: &t,
|
|
||||||
SocketFamily: &b.SocketFam,
|
|
||||||
SocketProtocol: &b.SocketProto,
|
|
||||||
QueryTimeSec: &b.TimeSec,
|
|
||||||
QueryTimeNsec: &b.TimeNsec,
|
|
||||||
QueryMessage: b.Packed,
|
|
||||||
ResponseAddress: b.Address,
|
|
||||||
ResponsePort: &b.Port,
|
|
||||||
}, b.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToOutsideResponse transforms the data into a forwarder or resolver response message.
|
|
||||||
func (b *Builder) ToOutsideResponse(t tap.Message_Type) (*tap.Message, error) {
|
|
||||||
return &tap.Message{
|
|
||||||
Type: &t,
|
|
||||||
SocketFamily: &b.SocketFam,
|
|
||||||
SocketProtocol: &b.SocketProto,
|
|
||||||
ResponseTimeSec: &b.TimeSec,
|
|
||||||
ResponseTimeNsec: &b.TimeNsec,
|
|
||||||
ResponseMessage: b.Packed,
|
|
||||||
ResponseAddress: b.Address,
|
|
||||||
ResponsePort: &b.Port,
|
|
||||||
}, b.err
|
|
||||||
}
|
|
85
vendor/github.com/coredns/coredns/plugin/dnstap/setup.go
generated
vendored
85
vendor/github.com/coredns/coredns/plugin/dnstap/setup.go
generated
vendored
@ -1,85 +0,0 @@
|
|||||||
package dnstap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/core/dnsserver"
|
|
||||||
"github.com/coredns/coredns/plugin"
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap/dnstapio"
|
|
||||||
"github.com/coredns/coredns/plugin/pkg/parse"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() { plugin.Register("dnstap", wrapSetup) }
|
|
||||||
|
|
||||||
func wrapSetup(c *caddy.Controller) error {
|
|
||||||
if err := setup(c); err != nil {
|
|
||||||
return plugin.Error("dnstap", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type config struct {
|
|
||||||
target string
|
|
||||||
socket bool
|
|
||||||
full bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseConfig(d *caddy.Controller) (c config, err error) {
|
|
||||||
d.Next() // directive name
|
|
||||||
|
|
||||||
if !d.Args(&c.target) {
|
|
||||||
return c, d.ArgErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(c.target, "tcp://") {
|
|
||||||
// remote IP endpoint
|
|
||||||
servers, err := parse.HostPortOrFile(c.target[6:])
|
|
||||||
if err != nil {
|
|
||||||
return c, d.ArgErr()
|
|
||||||
}
|
|
||||||
c.target = servers[0]
|
|
||||||
} else {
|
|
||||||
// default to UNIX socket
|
|
||||||
c.target = strings.TrimPrefix(c.target, "unix://")
|
|
||||||
c.socket = true
|
|
||||||
}
|
|
||||||
|
|
||||||
c.full = d.NextArg() && d.Val() == "full"
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func setup(c *caddy.Controller) error {
|
|
||||||
conf, err := parseConfig(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
dio := dnstapio.New(conf.target, conf.socket)
|
|
||||||
dnstap := Dnstap{IO: dio, JoinRawMessage: conf.full}
|
|
||||||
|
|
||||||
c.OnStartup(func() error {
|
|
||||||
dio.Connect()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
c.OnRestart(func() error {
|
|
||||||
dio.Close()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
c.OnFinalShutdown(func() error {
|
|
||||||
dio.Close()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
dnsserver.GetConfig(c).AddPlugin(
|
|
||||||
func(next plugin.Handler) plugin.Handler {
|
|
||||||
dnstap.Next = next
|
|
||||||
return dnstap
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
79
vendor/github.com/coredns/coredns/plugin/dnstap/taprw/writer.go
generated
vendored
79
vendor/github.com/coredns/coredns/plugin/dnstap/taprw/writer.go
generated
vendored
@ -1,79 +0,0 @@
|
|||||||
// Package taprw takes a query and intercepts the response.
|
|
||||||
// It will log both after the response is written.
|
|
||||||
package taprw
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap/msg"
|
|
||||||
|
|
||||||
tap "github.com/dnstap/golang-dnstap"
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SendOption stores the flag to indicate whether a certain DNSTap message to
|
|
||||||
// be sent out or not.
|
|
||||||
type SendOption struct {
|
|
||||||
Cq bool
|
|
||||||
Cr bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tapper is what ResponseWriter needs to log to dnstap.
|
|
||||||
type Tapper interface {
|
|
||||||
TapMessage(*tap.Message)
|
|
||||||
Pack() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResponseWriter captures the client response and logs the query to dnstap.
|
|
||||||
// Single request use.
|
|
||||||
// SendOption configures Dnstap to selectively send Dnstap messages. Default is send all.
|
|
||||||
type ResponseWriter struct {
|
|
||||||
QueryEpoch time.Time
|
|
||||||
Query *dns.Msg
|
|
||||||
dns.ResponseWriter
|
|
||||||
Tapper
|
|
||||||
Send *SendOption
|
|
||||||
|
|
||||||
dnstapErr error
|
|
||||||
}
|
|
||||||
|
|
||||||
// DnstapError check if a dnstap error occurred during Write and returns it.
|
|
||||||
func (w *ResponseWriter) DnstapError() error {
|
|
||||||
return w.dnstapErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteMsg writes back the response to the client and THEN works on logging the request
|
|
||||||
// and response to dnstap.
|
|
||||||
func (w *ResponseWriter) WriteMsg(resp *dns.Msg) (writeErr error) {
|
|
||||||
writeErr = w.ResponseWriter.WriteMsg(resp)
|
|
||||||
writeEpoch := time.Now()
|
|
||||||
|
|
||||||
b := msg.New().Time(w.QueryEpoch).Addr(w.RemoteAddr())
|
|
||||||
|
|
||||||
if w.Send == nil || w.Send.Cq {
|
|
||||||
if w.Pack() {
|
|
||||||
b.Msg(w.Query)
|
|
||||||
}
|
|
||||||
if m, err := b.ToClientQuery(); err != nil {
|
|
||||||
w.dnstapErr = fmt.Errorf("client query: %s", err)
|
|
||||||
} else {
|
|
||||||
w.TapMessage(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if w.Send == nil || w.Send.Cr {
|
|
||||||
if writeErr == nil {
|
|
||||||
if w.Pack() {
|
|
||||||
b.Msg(resp)
|
|
||||||
}
|
|
||||||
if m, err := b.Time(writeEpoch).ToClientResponse(); err != nil {
|
|
||||||
w.dnstapErr = fmt.Errorf("client response: %s", err)
|
|
||||||
} else {
|
|
||||||
w.TapMessage(m)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return writeErr
|
|
||||||
}
|
|
72
vendor/github.com/coredns/coredns/plugin/dnstap/test/helpers.go
generated
vendored
72
vendor/github.com/coredns/coredns/plugin/dnstap/test/helpers.go
generated
vendored
@ -1,72 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/coredns/coredns/plugin/dnstap/msg"
|
|
||||||
|
|
||||||
tap "github.com/dnstap/golang-dnstap"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestingData returns the Data matching coredns/test.ResponseWriter.
|
|
||||||
func TestingData() (d *msg.Builder) {
|
|
||||||
d = &msg.Builder{
|
|
||||||
SocketFam: tap.SocketFamily_INET,
|
|
||||||
SocketProto: tap.SocketProtocol_UDP,
|
|
||||||
Address: net.ParseIP("10.240.0.1"),
|
|
||||||
Port: 40212,
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type comp struct {
|
|
||||||
Type *tap.Message_Type
|
|
||||||
SF *tap.SocketFamily
|
|
||||||
SP *tap.SocketProtocol
|
|
||||||
QA []byte
|
|
||||||
RA []byte
|
|
||||||
QP *uint32
|
|
||||||
RP *uint32
|
|
||||||
QTSec bool
|
|
||||||
RTSec bool
|
|
||||||
RM []byte
|
|
||||||
QM []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func toComp(m *tap.Message) comp {
|
|
||||||
return comp{
|
|
||||||
Type: m.Type,
|
|
||||||
SF: m.SocketFamily,
|
|
||||||
SP: m.SocketProtocol,
|
|
||||||
QA: m.QueryAddress,
|
|
||||||
RA: m.ResponseAddress,
|
|
||||||
QP: m.QueryPort,
|
|
||||||
RP: m.ResponsePort,
|
|
||||||
QTSec: m.QueryTimeSec != nil,
|
|
||||||
RTSec: m.ResponseTimeSec != nil,
|
|
||||||
RM: m.ResponseMessage,
|
|
||||||
QM: m.QueryMessage,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MsgEqual compares two dnstap messages ignoring timestamps.
|
|
||||||
func MsgEqual(a, b *tap.Message) bool {
|
|
||||||
return reflect.DeepEqual(toComp(a), toComp(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrapTapper traps messages.
|
|
||||||
type TrapTapper struct {
|
|
||||||
Trap []*tap.Message
|
|
||||||
Full bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pack returns field Full.
|
|
||||||
func (t *TrapTapper) Pack() bool {
|
|
||||||
return t.Full
|
|
||||||
}
|
|
||||||
|
|
||||||
// TapMessage adds the message to the trap.
|
|
||||||
func (t *TrapTapper) TapMessage(m *tap.Message) {
|
|
||||||
t.Trap = append(t.Trap, m)
|
|
||||||
}
|
|
23
vendor/github.com/coredns/coredns/plugin/metrics/register.go
generated
vendored
23
vendor/github.com/coredns/coredns/plugin/metrics/register.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
package metrics
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/coredns/coredns/core/dnsserver"
|
|
||||||
|
|
||||||
"github.com/caddyserver/caddy"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MustRegister registers the prometheus Collectors when the metrics plugin is used.
|
|
||||||
func MustRegister(c *caddy.Controller, cs ...prometheus.Collector) {
|
|
||||||
m := dnsserver.GetConfig(c).Handler("prometheus")
|
|
||||||
if m == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
x, ok := m.(*Metrics)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, c := range cs {
|
|
||||||
x.MustRegister(c)
|
|
||||||
}
|
|
||||||
}
|
|
76
vendor/github.com/coredns/coredns/plugin/pkg/policy/policy.go
generated
vendored
76
vendor/github.com/coredns/coredns/plugin/pkg/policy/policy.go
generated
vendored
@ -1,76 +0,0 @@
|
|||||||
package policy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Policy defines a policy we use for selecting upstreams.
|
|
||||||
type Policy interface {
|
|
||||||
List(policy ...interface{}) []interface{}
|
|
||||||
String() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Random is a policy that implements random upstream selection.
|
|
||||||
type Random struct{}
|
|
||||||
|
|
||||||
var _ Policy = &Random{}
|
|
||||||
|
|
||||||
// String returns the name of policy Random
|
|
||||||
func (r *Random) String() string { return "random" }
|
|
||||||
|
|
||||||
// List returns a set of proxies to be used for this client depending on Random policy.
|
|
||||||
func (r *Random) List(p ...interface{}) []interface{} {
|
|
||||||
switch len(p) {
|
|
||||||
case 1:
|
|
||||||
return p
|
|
||||||
case 2:
|
|
||||||
if rand.Int()%2 == 0 {
|
|
||||||
return []interface{}{p[1], p[0]} // swap
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
perms := rand.Perm(len(p))
|
|
||||||
rnd := make([]interface{}, len(p))
|
|
||||||
|
|
||||||
for i, p1 := range perms {
|
|
||||||
rnd[i] = p[p1]
|
|
||||||
}
|
|
||||||
return rnd
|
|
||||||
}
|
|
||||||
|
|
||||||
// RoundRobin is a policy that selects hosts based on round robin ordering.
|
|
||||||
type RoundRobin struct {
|
|
||||||
robin uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Policy = &RoundRobin{}
|
|
||||||
|
|
||||||
// String returns the name of policy RoundRobin
|
|
||||||
func (r *RoundRobin) String() string { return "round_robin" }
|
|
||||||
|
|
||||||
// List returns a set of proxies to be used for this client depending on RoundRobin policy.
|
|
||||||
func (r *RoundRobin) List(p ...interface{}) []interface{} {
|
|
||||||
poolLen := uint32(len(p))
|
|
||||||
i := atomic.AddUint32(&r.robin, 1) % poolLen
|
|
||||||
|
|
||||||
robin := []interface{}{p[i]}
|
|
||||||
robin = append(robin, p[:i]...)
|
|
||||||
robin = append(robin, p[i+1:]...)
|
|
||||||
|
|
||||||
return robin
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sequential is a policy that selects hosts based on sequential ordering.
|
|
||||||
type Sequential struct{}
|
|
||||||
|
|
||||||
var _ Policy = &Sequential{}
|
|
||||||
|
|
||||||
// String returns the name of policy Sequential
|
|
||||||
func (r *Sequential) String() string { return "sequential" }
|
|
||||||
|
|
||||||
// List returns a set of proxies without filter.
|
|
||||||
func (r *Sequential) List(p ...interface{}) []interface{} {
|
|
||||||
return p
|
|
||||||
}
|
|
96
vendor/github.com/coredns/coredns/plugin/pkg/up/up.go
generated
vendored
96
vendor/github.com/coredns/coredns/plugin/pkg/up/up.go
generated
vendored
@ -1,96 +0,0 @@
|
|||||||
// Package up is used to run a function for some duration. If a new function is added while a previous run is
|
|
||||||
// still ongoing, nothing new will be executed.
|
|
||||||
package up
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Probe is used to run a single Func until it returns true (indicating a target is healthy). If an Func
|
|
||||||
// is already in progress no new one will be added, i.e. there is always a maximum of 1 checks in flight.
|
|
||||||
// When failures start to happen we will back off every second failure up to maximum of 4 intervals.
|
|
||||||
type Probe struct {
|
|
||||||
sync.Mutex
|
|
||||||
inprogress int
|
|
||||||
expBackoff backoff.ExponentialBackOff
|
|
||||||
}
|
|
||||||
|
|
||||||
// Func is used to determine if a target is alive. If so this function must return nil.
|
|
||||||
type Func func() error
|
|
||||||
|
|
||||||
// New returns a pointer to an initialized Probe.
|
|
||||||
func New() *Probe { return &Probe{} }
|
|
||||||
|
|
||||||
// Do will probe target, if a probe is already in progress this is a noop.
|
|
||||||
func (p *Probe) Do(f Func) {
|
|
||||||
p.Lock()
|
|
||||||
if p.inprogress != idle {
|
|
||||||
p.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.inprogress = active
|
|
||||||
interval := p.expBackoff.NextBackOff()
|
|
||||||
// If exponential backoff has reached the maximum elapsed time (15 minutes),
|
|
||||||
// reset it and try again
|
|
||||||
if interval == -1 {
|
|
||||||
p.expBackoff.Reset()
|
|
||||||
interval = p.expBackoff.NextBackOff()
|
|
||||||
}
|
|
||||||
p.Unlock()
|
|
||||||
// Passed the lock. Now run f for as long it returns false. If a true is returned
|
|
||||||
// we return from the goroutine and we can accept another Func to run.
|
|
||||||
go func() {
|
|
||||||
i := 1
|
|
||||||
for {
|
|
||||||
if err := f(); err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(interval)
|
|
||||||
p.Lock()
|
|
||||||
if p.inprogress == stop {
|
|
||||||
p.Unlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.Unlock()
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Lock()
|
|
||||||
p.inprogress = idle
|
|
||||||
p.Unlock()
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop stops the probing.
|
|
||||||
func (p *Probe) Stop() {
|
|
||||||
p.Lock()
|
|
||||||
p.inprogress = stop
|
|
||||||
p.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start will initialize the probe manager, after which probes can be initiated with Do.
|
|
||||||
// Initializes exponential backoff using the given interval duration
|
|
||||||
func (p *Probe) Start(interval time.Duration) {
|
|
||||||
p.Lock()
|
|
||||||
eB := &backoff.ExponentialBackOff{
|
|
||||||
InitialInterval: interval,
|
|
||||||
RandomizationFactor: backoff.DefaultRandomizationFactor,
|
|
||||||
Multiplier: backoff.DefaultMultiplier,
|
|
||||||
MaxInterval: 15 * time.Second,
|
|
||||||
MaxElapsedTime: 2 * time.Minute,
|
|
||||||
Stop: backoff.Stop,
|
|
||||||
Clock: backoff.SystemClock,
|
|
||||||
}
|
|
||||||
p.expBackoff = *eB
|
|
||||||
p.expBackoff.Reset()
|
|
||||||
p.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
idle = iota
|
|
||||||
active
|
|
||||||
stop
|
|
||||||
)
|
|
1
vendor/github.com/dnstap/golang-dnstap/.gitignore
generated
vendored
1
vendor/github.com/dnstap/golang-dnstap/.gitignore
generated
vendored
@ -1 +0,0 @@
|
|||||||
*.swp
|
|
14
vendor/github.com/dnstap/golang-dnstap/COPYRIGHT
generated
vendored
14
vendor/github.com/dnstap/golang-dnstap/COPYRIGHT
generated
vendored
@ -1,14 +0,0 @@
|
|||||||
Copyright (c) 2013-2014 by Farsight Security, Inc.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
73
vendor/github.com/dnstap/golang-dnstap/FrameStreamInput.go
generated
vendored
73
vendor/github.com/dnstap/golang-dnstap/FrameStreamInput.go
generated
vendored
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013-2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dnstap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/farsightsec/golang-framestream"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FrameStreamInput struct {
|
|
||||||
wait chan bool
|
|
||||||
decoder *framestream.Decoder
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFrameStreamInput(r io.ReadWriter, bi bool) (input *FrameStreamInput, err error) {
|
|
||||||
input = new(FrameStreamInput)
|
|
||||||
decoderOptions := framestream.DecoderOptions{
|
|
||||||
ContentType: FSContentType,
|
|
||||||
Bidirectional: bi,
|
|
||||||
}
|
|
||||||
input.decoder, err = framestream.NewDecoder(r, &decoderOptions)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
input.wait = make(chan bool)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFrameStreamInputFromFilename(fname string) (input *FrameStreamInput, err error) {
|
|
||||||
file, err := os.Open(fname)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
input, err = NewFrameStreamInput(file, false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (input *FrameStreamInput) ReadInto(output chan []byte) {
|
|
||||||
for {
|
|
||||||
buf, err := input.decoder.Decode()
|
|
||||||
if err != nil {
|
|
||||||
if err != io.EOF {
|
|
||||||
log.Printf("framestream.Decoder.Decode() failed: %s\n", err)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
newbuf := make([]byte, len(buf))
|
|
||||||
copy(newbuf, buf)
|
|
||||||
output <- newbuf
|
|
||||||
}
|
|
||||||
close(input.wait)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (input *FrameStreamInput) Wait() {
|
|
||||||
<-input.wait
|
|
||||||
}
|
|
74
vendor/github.com/dnstap/golang-dnstap/FrameStreamOutput.go
generated
vendored
74
vendor/github.com/dnstap/golang-dnstap/FrameStreamOutput.go
generated
vendored
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dnstap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/farsightsec/golang-framestream"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FrameStreamOutput struct {
|
|
||||||
outputChannel chan []byte
|
|
||||||
wait chan bool
|
|
||||||
enc *framestream.Encoder
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFrameStreamOutput(w io.Writer) (o *FrameStreamOutput, err error) {
|
|
||||||
o = new(FrameStreamOutput)
|
|
||||||
o.outputChannel = make(chan []byte, outputChannelSize)
|
|
||||||
o.enc, err = framestream.NewEncoder(w, &framestream.EncoderOptions{ContentType: FSContentType})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
o.wait = make(chan bool)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFrameStreamOutputFromFilename(fname string) (o *FrameStreamOutput, err error) {
|
|
||||||
if fname == "" || fname == "-" {
|
|
||||||
return NewFrameStreamOutput(os.Stdout)
|
|
||||||
}
|
|
||||||
w, err := os.Create(fname)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return NewFrameStreamOutput(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *FrameStreamOutput) GetOutputChannel() chan []byte {
|
|
||||||
return o.outputChannel
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *FrameStreamOutput) RunOutputLoop() {
|
|
||||||
for frame := range o.outputChannel {
|
|
||||||
if _, err := o.enc.Write(frame); err != nil {
|
|
||||||
log.Fatalf("framestream.Encoder.Write() failed: %s\n", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(o.wait)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *FrameStreamOutput) Close() {
|
|
||||||
close(o.outputChannel)
|
|
||||||
<-o.wait
|
|
||||||
o.enc.Flush()
|
|
||||||
o.enc.Close()
|
|
||||||
}
|
|
64
vendor/github.com/dnstap/golang-dnstap/FrameStreamSockInput.go
generated
vendored
64
vendor/github.com/dnstap/golang-dnstap/FrameStreamSockInput.go
generated
vendored
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013-2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dnstap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FrameStreamSockInput struct {
|
|
||||||
wait chan bool
|
|
||||||
listener net.Listener
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFrameStreamSockInput(listener net.Listener) (input *FrameStreamSockInput) {
|
|
||||||
input = new(FrameStreamSockInput)
|
|
||||||
input.listener = listener
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFrameStreamSockInputFromPath(socketPath string) (input *FrameStreamSockInput, err error) {
|
|
||||||
os.Remove(socketPath)
|
|
||||||
listener, err := net.Listen("unix", socketPath)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return NewFrameStreamSockInput(listener), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (input *FrameStreamSockInput) ReadInto(output chan []byte) {
|
|
||||||
for {
|
|
||||||
conn, err := input.listener.Accept()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("net.Listener.Accept() failed: %s\n", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
i, err := NewFrameStreamInput(conn, true)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("dnstap.NewFrameStreamInput() failed: %s\n", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Printf("dnstap.FrameStreamSockInput: accepted a socket connection\n")
|
|
||||||
go i.ReadInto(output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (input *FrameStreamSockInput) Wait() {
|
|
||||||
select {}
|
|
||||||
}
|
|
202
vendor/github.com/dnstap/golang-dnstap/LICENSE
generated
vendored
202
vendor/github.com/dnstap/golang-dnstap/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
|
|
||||||
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.
|
|
172
vendor/github.com/dnstap/golang-dnstap/QuietTextFormat.go
generated
vendored
172
vendor/github.com/dnstap/golang-dnstap/QuietTextFormat.go
generated
vendored
@ -1,172 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013-2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dnstap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
const quietTimeFormat = "15:04:05"
|
|
||||||
|
|
||||||
func textConvertTime(s *bytes.Buffer, secs *uint64, nsecs *uint32) {
|
|
||||||
if secs != nil {
|
|
||||||
s.WriteString(time.Unix(int64(*secs), 0).Format(quietTimeFormat))
|
|
||||||
} else {
|
|
||||||
s.WriteString("??:??:??")
|
|
||||||
}
|
|
||||||
if nsecs != nil {
|
|
||||||
s.WriteString(fmt.Sprintf(".%06d", *nsecs/1000))
|
|
||||||
} else {
|
|
||||||
s.WriteString(".??????")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func textConvertIP(s *bytes.Buffer, ip []byte) {
|
|
||||||
if ip != nil {
|
|
||||||
s.WriteString(net.IP(ip).String())
|
|
||||||
} else {
|
|
||||||
s.WriteString("MISSING_ADDRESS")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func textConvertMessage(m *Message, s *bytes.Buffer) {
|
|
||||||
isQuery := false
|
|
||||||
printQueryAddress := false
|
|
||||||
|
|
||||||
switch *m.Type {
|
|
||||||
case Message_CLIENT_QUERY,
|
|
||||||
Message_RESOLVER_QUERY,
|
|
||||||
Message_AUTH_QUERY,
|
|
||||||
Message_FORWARDER_QUERY,
|
|
||||||
Message_TOOL_QUERY:
|
|
||||||
isQuery = true
|
|
||||||
case Message_CLIENT_RESPONSE,
|
|
||||||
Message_RESOLVER_RESPONSE,
|
|
||||||
Message_AUTH_RESPONSE,
|
|
||||||
Message_FORWARDER_RESPONSE,
|
|
||||||
Message_TOOL_RESPONSE:
|
|
||||||
isQuery = false
|
|
||||||
default:
|
|
||||||
s.WriteString("[unhandled Message.Type]\n")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if isQuery {
|
|
||||||
textConvertTime(s, m.QueryTimeSec, m.QueryTimeNsec)
|
|
||||||
} else {
|
|
||||||
textConvertTime(s, m.ResponseTimeSec, m.ResponseTimeNsec)
|
|
||||||
}
|
|
||||||
s.WriteString(" ")
|
|
||||||
|
|
||||||
switch *m.Type {
|
|
||||||
case Message_CLIENT_QUERY,
|
|
||||||
Message_CLIENT_RESPONSE:
|
|
||||||
{
|
|
||||||
s.WriteString("C")
|
|
||||||
}
|
|
||||||
case Message_RESOLVER_QUERY,
|
|
||||||
Message_RESOLVER_RESPONSE:
|
|
||||||
{
|
|
||||||
s.WriteString("R")
|
|
||||||
}
|
|
||||||
case Message_AUTH_QUERY,
|
|
||||||
Message_AUTH_RESPONSE:
|
|
||||||
{
|
|
||||||
s.WriteString("A")
|
|
||||||
}
|
|
||||||
case Message_FORWARDER_QUERY,
|
|
||||||
Message_FORWARDER_RESPONSE:
|
|
||||||
{
|
|
||||||
s.WriteString("F")
|
|
||||||
}
|
|
||||||
case Message_STUB_QUERY,
|
|
||||||
Message_STUB_RESPONSE:
|
|
||||||
{
|
|
||||||
s.WriteString("S")
|
|
||||||
}
|
|
||||||
case Message_TOOL_QUERY,
|
|
||||||
Message_TOOL_RESPONSE:
|
|
||||||
{
|
|
||||||
s.WriteString("T")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isQuery {
|
|
||||||
s.WriteString("Q ")
|
|
||||||
} else {
|
|
||||||
s.WriteString("R ")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch *m.Type {
|
|
||||||
case Message_CLIENT_QUERY,
|
|
||||||
Message_CLIENT_RESPONSE,
|
|
||||||
Message_AUTH_QUERY,
|
|
||||||
Message_AUTH_RESPONSE:
|
|
||||||
printQueryAddress = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if printQueryAddress {
|
|
||||||
textConvertIP(s, m.QueryAddress)
|
|
||||||
} else {
|
|
||||||
textConvertIP(s, m.ResponseAddress)
|
|
||||||
}
|
|
||||||
s.WriteString(" ")
|
|
||||||
|
|
||||||
if m.SocketProtocol != nil {
|
|
||||||
s.WriteString(m.SocketProtocol.String())
|
|
||||||
}
|
|
||||||
s.WriteString(" ")
|
|
||||||
|
|
||||||
var err error
|
|
||||||
msg := new(dns.Msg)
|
|
||||||
if isQuery {
|
|
||||||
s.WriteString(strconv.Itoa(len(m.QueryMessage)))
|
|
||||||
s.WriteString("b ")
|
|
||||||
err = msg.Unpack(m.QueryMessage)
|
|
||||||
} else {
|
|
||||||
s.WriteString(strconv.Itoa(len(m.ResponseMessage)))
|
|
||||||
s.WriteString("b ")
|
|
||||||
err = msg.Unpack(m.ResponseMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
s.WriteString("X ")
|
|
||||||
} else {
|
|
||||||
s.WriteString("\"" + msg.Question[0].Name + "\" ")
|
|
||||||
s.WriteString(dns.Class(msg.Question[0].Qclass).String() + " ")
|
|
||||||
s.WriteString(dns.Type(msg.Question[0].Qtype).String())
|
|
||||||
}
|
|
||||||
|
|
||||||
s.WriteString("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TextFormat(dt *Dnstap) (out []byte, ok bool) {
|
|
||||||
var s bytes.Buffer
|
|
||||||
|
|
||||||
if *dt.Type == Dnstap_MESSAGE {
|
|
||||||
textConvertMessage(dt.Message, &s)
|
|
||||||
return s.Bytes(), true
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
15
vendor/github.com/dnstap/golang-dnstap/README
generated
vendored
15
vendor/github.com/dnstap/golang-dnstap/README
generated
vendored
@ -1,15 +0,0 @@
|
|||||||
dnstap: flexible, structured event replication format for DNS servers
|
|
||||||
---------------------------------------------------------------------
|
|
||||||
|
|
||||||
dnstap implements an encoding format for DNS server events. It uses a
|
|
||||||
lightweight framing on top of event payloads encoded using Protocol Buffers and
|
|
||||||
is transport neutral.
|
|
||||||
|
|
||||||
dnstap can represent internal state inside a DNS server that is difficult to
|
|
||||||
obtain using techniques based on traditional packet capture or unstructured
|
|
||||||
textual format logging.
|
|
||||||
|
|
||||||
This repository contains a command-line tool named "dnstap" developed in the
|
|
||||||
Go programming language. It can be installed with the following command:
|
|
||||||
|
|
||||||
go get -u github.com/dnstap/golang-dnstap/dnstap
|
|
86
vendor/github.com/dnstap/golang-dnstap/TextOutput.go
generated
vendored
86
vendor/github.com/dnstap/golang-dnstap/TextOutput.go
generated
vendored
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dnstap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TextFormatFunc func(*Dnstap) ([]byte, bool)
|
|
||||||
|
|
||||||
type TextOutput struct {
|
|
||||||
format TextFormatFunc
|
|
||||||
outputChannel chan []byte
|
|
||||||
wait chan bool
|
|
||||||
writer *bufio.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTextOutput(writer io.Writer, format TextFormatFunc) (o *TextOutput) {
|
|
||||||
o = new(TextOutput)
|
|
||||||
o.format = format
|
|
||||||
o.outputChannel = make(chan []byte, outputChannelSize)
|
|
||||||
o.writer = bufio.NewWriter(writer)
|
|
||||||
o.wait = make(chan bool)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTextOutputFromFilename(fname string, format TextFormatFunc) (o *TextOutput, err error) {
|
|
||||||
if fname == "" || fname == "-" {
|
|
||||||
return NewTextOutput(os.Stdout, format), nil
|
|
||||||
}
|
|
||||||
writer, err := os.Create(fname)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return NewTextOutput(writer, format), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *TextOutput) GetOutputChannel() chan []byte {
|
|
||||||
return o.outputChannel
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *TextOutput) RunOutputLoop() {
|
|
||||||
dt := &Dnstap{}
|
|
||||||
for frame := range o.outputChannel {
|
|
||||||
if err := proto.Unmarshal(frame, dt); err != nil {
|
|
||||||
log.Fatalf("dnstap.TextOutput: proto.Unmarshal() failed: %s\n", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buf, ok := o.format(dt)
|
|
||||||
if !ok {
|
|
||||||
log.Fatalf("dnstap.TextOutput: text format function failed\n")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if _, err := o.writer.Write(buf); err != nil {
|
|
||||||
log.Fatalf("dnstap.TextOutput: write failed: %s\n", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
o.writer.Flush()
|
|
||||||
}
|
|
||||||
close(o.wait)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *TextOutput) Close() {
|
|
||||||
close(o.outputChannel)
|
|
||||||
<-o.wait
|
|
||||||
o.writer.Flush()
|
|
||||||
}
|
|
116
vendor/github.com/dnstap/golang-dnstap/YamlFormat.go
generated
vendored
116
vendor/github.com/dnstap/golang-dnstap/YamlFormat.go
generated
vendored
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013-2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dnstap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
const yamlTimeFormat = "2006-01-02 15:04:05.999999999"
|
|
||||||
|
|
||||||
func yamlConvertMessage(m *Message, s *bytes.Buffer) {
|
|
||||||
s.WriteString(fmt.Sprint(" type: ", m.Type, "\n"))
|
|
||||||
|
|
||||||
if m.QueryTimeSec != nil && m.QueryTimeNsec != nil {
|
|
||||||
t := time.Unix(int64(*m.QueryTimeSec), int64(*m.QueryTimeNsec)).UTC()
|
|
||||||
s.WriteString(fmt.Sprint(" query_time: !!timestamp ", t.Format(yamlTimeFormat), "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.ResponseTimeSec != nil && m.ResponseTimeNsec != nil {
|
|
||||||
t := time.Unix(int64(*m.ResponseTimeSec), int64(*m.ResponseTimeNsec)).UTC()
|
|
||||||
s.WriteString(fmt.Sprint(" response_time: !!timestamp ", t.Format(yamlTimeFormat), "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.SocketFamily != nil {
|
|
||||||
s.WriteString(fmt.Sprint(" socket_family: ", m.SocketFamily, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.SocketProtocol != nil {
|
|
||||||
s.WriteString(fmt.Sprint(" socket_protocol: ", m.SocketProtocol, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.QueryAddress != nil {
|
|
||||||
s.WriteString(fmt.Sprint(" query_address: ", net.IP(m.QueryAddress), "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.ResponseAddress != nil {
|
|
||||||
s.WriteString(fmt.Sprint(" response_address: ", net.IP(m.ResponseAddress), "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.QueryPort != nil {
|
|
||||||
s.WriteString(fmt.Sprint(" query_port: ", *m.QueryPort, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.ResponsePort != nil {
|
|
||||||
s.WriteString(fmt.Sprint(" response_port: ", *m.ResponsePort, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.QueryZone != nil {
|
|
||||||
name, _, err := dns.UnpackDomainName(m.QueryZone, 0)
|
|
||||||
if err != nil {
|
|
||||||
s.WriteString(" # query_zone: parse failed\n")
|
|
||||||
} else {
|
|
||||||
s.WriteString(fmt.Sprint(" query_zone: ", strconv.Quote(name), "\n"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.QueryMessage != nil {
|
|
||||||
msg := new(dns.Msg)
|
|
||||||
err := msg.Unpack(m.QueryMessage)
|
|
||||||
if err != nil {
|
|
||||||
s.WriteString(" # query_message: parse failed\n")
|
|
||||||
} else {
|
|
||||||
s.WriteString(" query_message: |\n")
|
|
||||||
s.WriteString(" " + strings.Replace(strings.TrimSpace(msg.String()), "\n", "\n ", -1) + "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if m.ResponseMessage != nil {
|
|
||||||
msg := new(dns.Msg)
|
|
||||||
err := msg.Unpack(m.ResponseMessage)
|
|
||||||
if err != nil {
|
|
||||||
s.WriteString(fmt.Sprint(" # response_message: parse failed: ", err, "\n"))
|
|
||||||
} else {
|
|
||||||
s.WriteString(" response_message: |\n")
|
|
||||||
s.WriteString(" " + strings.Replace(strings.TrimSpace(msg.String()), "\n", "\n ", -1) + "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.WriteString("---\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
func YamlFormat(dt *Dnstap) (out []byte, ok bool) {
|
|
||||||
var s bytes.Buffer
|
|
||||||
|
|
||||||
s.WriteString(fmt.Sprint("type: ", dt.Type, "\n"))
|
|
||||||
if dt.Identity != nil {
|
|
||||||
s.WriteString(fmt.Sprint("identity: ", strconv.Quote(string(dt.Identity)), "\n"))
|
|
||||||
}
|
|
||||||
if dt.Version != nil {
|
|
||||||
s.WriteString(fmt.Sprint("version: ", strconv.Quote(string(dt.Version)), "\n"))
|
|
||||||
}
|
|
||||||
if *dt.Type == Dnstap_MESSAGE {
|
|
||||||
s.WriteString("message:\n")
|
|
||||||
yamlConvertMessage(dt.Message, &s)
|
|
||||||
}
|
|
||||||
return s.Bytes(), true
|
|
||||||
}
|
|
32
vendor/github.com/dnstap/golang-dnstap/dnstap.go
generated
vendored
32
vendor/github.com/dnstap/golang-dnstap/dnstap.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dnstap
|
|
||||||
|
|
||||||
const outputChannelSize = 32
|
|
||||||
|
|
||||||
var FSContentType = []byte("protobuf:dnstap.Dnstap")
|
|
||||||
|
|
||||||
type Input interface {
|
|
||||||
ReadInto(chan []byte)
|
|
||||||
Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Output interface {
|
|
||||||
GetOutputChannel() chan []byte
|
|
||||||
RunOutputLoop()
|
|
||||||
Close()
|
|
||||||
}
|
|
448
vendor/github.com/dnstap/golang-dnstap/dnstap.pb.go
generated
vendored
448
vendor/github.com/dnstap/golang-dnstap/dnstap.pb.go
generated
vendored
@ -1,448 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go.
|
|
||||||
// source: dnstap.proto
|
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
/*
|
|
||||||
Package dnstap is a generated protocol buffer package.
|
|
||||||
|
|
||||||
It is generated from these files:
|
|
||||||
dnstap.proto
|
|
||||||
|
|
||||||
It has these top-level messages:
|
|
||||||
Dnstap
|
|
||||||
Message
|
|
||||||
*/
|
|
||||||
package dnstap
|
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
|
||||||
import json "encoding/json"
|
|
||||||
import math "math"
|
|
||||||
|
|
||||||
// Reference proto, json, and math imports to suppress error if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = &json.SyntaxError{}
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
// SocketFamily: the network protocol family of a socket. This specifies how
|
|
||||||
// to interpret "network address" fields.
|
|
||||||
type SocketFamily int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
SocketFamily_INET SocketFamily = 1
|
|
||||||
SocketFamily_INET6 SocketFamily = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
var SocketFamily_name = map[int32]string{
|
|
||||||
1: "INET",
|
|
||||||
2: "INET6",
|
|
||||||
}
|
|
||||||
var SocketFamily_value = map[string]int32{
|
|
||||||
"INET": 1,
|
|
||||||
"INET6": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x SocketFamily) Enum() *SocketFamily {
|
|
||||||
p := new(SocketFamily)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x SocketFamily) String() string {
|
|
||||||
return proto.EnumName(SocketFamily_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *SocketFamily) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(SocketFamily_value, data, "SocketFamily")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = SocketFamily(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SocketProtocol: the transport protocol of a socket. This specifies how to
|
|
||||||
// interpret "transport port" fields.
|
|
||||||
type SocketProtocol int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
SocketProtocol_UDP SocketProtocol = 1
|
|
||||||
SocketProtocol_TCP SocketProtocol = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
var SocketProtocol_name = map[int32]string{
|
|
||||||
1: "UDP",
|
|
||||||
2: "TCP",
|
|
||||||
}
|
|
||||||
var SocketProtocol_value = map[string]int32{
|
|
||||||
"UDP": 1,
|
|
||||||
"TCP": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x SocketProtocol) Enum() *SocketProtocol {
|
|
||||||
p := new(SocketProtocol)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x SocketProtocol) String() string {
|
|
||||||
return proto.EnumName(SocketProtocol_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *SocketProtocol) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(SocketProtocol_value, data, "SocketProtocol")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = SocketProtocol(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Identifies which field below is filled in.
|
|
||||||
type Dnstap_Type int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
Dnstap_MESSAGE Dnstap_Type = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
var Dnstap_Type_name = map[int32]string{
|
|
||||||
1: "MESSAGE",
|
|
||||||
}
|
|
||||||
var Dnstap_Type_value = map[string]int32{
|
|
||||||
"MESSAGE": 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Dnstap_Type) Enum() *Dnstap_Type {
|
|
||||||
p := new(Dnstap_Type)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x Dnstap_Type) String() string {
|
|
||||||
return proto.EnumName(Dnstap_Type_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *Dnstap_Type) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(Dnstap_Type_value, data, "Dnstap_Type")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = Dnstap_Type(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Message_Type int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
// AUTH_QUERY is a DNS query message received from a resolver by an
|
|
||||||
// authoritative name server, from the perspective of the authorative
|
|
||||||
// name server.
|
|
||||||
Message_AUTH_QUERY Message_Type = 1
|
|
||||||
// AUTH_RESPONSE is a DNS response message sent from an authoritative
|
|
||||||
// name server to a resolver, from the perspective of the authoritative
|
|
||||||
// name server.
|
|
||||||
Message_AUTH_RESPONSE Message_Type = 2
|
|
||||||
// RESOLVER_QUERY is a DNS query message sent from a resolver to an
|
|
||||||
// authoritative name server, from the perspective of the resolver.
|
|
||||||
// Resolvers typically clear the RD (recursion desired) bit when
|
|
||||||
// sending queries.
|
|
||||||
Message_RESOLVER_QUERY Message_Type = 3
|
|
||||||
// RESOLVER_RESPONSE is a DNS response message received from an
|
|
||||||
// authoritative name server by a resolver, from the perspective of
|
|
||||||
// the resolver.
|
|
||||||
Message_RESOLVER_RESPONSE Message_Type = 4
|
|
||||||
// CLIENT_QUERY is a DNS query message sent from a client to a DNS
|
|
||||||
// server which is expected to perform further recursion, from the
|
|
||||||
// perspective of the DNS server. The client may be a stub resolver or
|
|
||||||
// forwarder or some other type of software which typically sets the RD
|
|
||||||
// (recursion desired) bit when querying the DNS server. The DNS server
|
|
||||||
// may be a simple forwarding proxy or it may be a full recursive
|
|
||||||
// resolver.
|
|
||||||
Message_CLIENT_QUERY Message_Type = 5
|
|
||||||
// CLIENT_RESPONSE is a DNS response message sent from a DNS server to
|
|
||||||
// a client, from the perspective of the DNS server. The DNS server
|
|
||||||
// typically sets the RA (recursion available) bit when responding.
|
|
||||||
Message_CLIENT_RESPONSE Message_Type = 6
|
|
||||||
// FORWARDER_QUERY is a DNS query message sent from a downstream DNS
|
|
||||||
// server to an upstream DNS server which is expected to perform
|
|
||||||
// further recursion, from the perspective of the downstream DNS
|
|
||||||
// server.
|
|
||||||
Message_FORWARDER_QUERY Message_Type = 7
|
|
||||||
// FORWARDER_RESPONSE is a DNS response message sent from an upstream
|
|
||||||
// DNS server performing recursion to a downstream DNS server, from the
|
|
||||||
// perspective of the downstream DNS server.
|
|
||||||
Message_FORWARDER_RESPONSE Message_Type = 8
|
|
||||||
// STUB_QUERY is a DNS query message sent from a stub resolver to a DNS
|
|
||||||
// server, from the perspective of the stub resolver.
|
|
||||||
Message_STUB_QUERY Message_Type = 9
|
|
||||||
// STUB_RESPONSE is a DNS response message sent from a DNS server to a
|
|
||||||
// stub resolver, from the perspective of the stub resolver.
|
|
||||||
Message_STUB_RESPONSE Message_Type = 10
|
|
||||||
// TOOL_QUERY is a DNS query message sent from a DNS software tool to a
|
|
||||||
// DNS server, from the perspective of the tool.
|
|
||||||
Message_TOOL_QUERY Message_Type = 11
|
|
||||||
// TOOL_RESPONSE is a DNS response message received by a DNS software
|
|
||||||
// tool from a DNS server, from the perspective of the tool.
|
|
||||||
Message_TOOL_RESPONSE Message_Type = 12
|
|
||||||
)
|
|
||||||
|
|
||||||
var Message_Type_name = map[int32]string{
|
|
||||||
1: "AUTH_QUERY",
|
|
||||||
2: "AUTH_RESPONSE",
|
|
||||||
3: "RESOLVER_QUERY",
|
|
||||||
4: "RESOLVER_RESPONSE",
|
|
||||||
5: "CLIENT_QUERY",
|
|
||||||
6: "CLIENT_RESPONSE",
|
|
||||||
7: "FORWARDER_QUERY",
|
|
||||||
8: "FORWARDER_RESPONSE",
|
|
||||||
9: "STUB_QUERY",
|
|
||||||
10: "STUB_RESPONSE",
|
|
||||||
11: "TOOL_QUERY",
|
|
||||||
12: "TOOL_RESPONSE",
|
|
||||||
}
|
|
||||||
var Message_Type_value = map[string]int32{
|
|
||||||
"AUTH_QUERY": 1,
|
|
||||||
"AUTH_RESPONSE": 2,
|
|
||||||
"RESOLVER_QUERY": 3,
|
|
||||||
"RESOLVER_RESPONSE": 4,
|
|
||||||
"CLIENT_QUERY": 5,
|
|
||||||
"CLIENT_RESPONSE": 6,
|
|
||||||
"FORWARDER_QUERY": 7,
|
|
||||||
"FORWARDER_RESPONSE": 8,
|
|
||||||
"STUB_QUERY": 9,
|
|
||||||
"STUB_RESPONSE": 10,
|
|
||||||
"TOOL_QUERY": 11,
|
|
||||||
"TOOL_RESPONSE": 12,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Message_Type) Enum() *Message_Type {
|
|
||||||
p := new(Message_Type)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x Message_Type) String() string {
|
|
||||||
return proto.EnumName(Message_Type_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *Message_Type) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(Message_Type_value, data, "Message_Type")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = Message_Type(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Dnstap": this is the top-level dnstap type, which is a "union" type that
|
|
||||||
// contains other kinds of dnstap payloads, although currently only one type
|
|
||||||
// of dnstap payload is defined.
|
|
||||||
// See: https://developers.google.com/protocol-buffers/docs/techniques#union
|
|
||||||
type Dnstap struct {
|
|
||||||
// DNS server identity.
|
|
||||||
// If enabled, this is the identity string of the DNS server which generated
|
|
||||||
// this message. Typically this would be the same string as returned by an
|
|
||||||
// "NSID" (RFC 5001) query.
|
|
||||||
Identity []byte `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"`
|
|
||||||
// DNS server version.
|
|
||||||
// If enabled, this is the version string of the DNS server which generated
|
|
||||||
// this message. Typically this would be the same string as returned by a
|
|
||||||
// "version.bind" query.
|
|
||||||
Version []byte `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
|
|
||||||
// Extra data for this payload.
|
|
||||||
// This field can be used for adding an arbitrary byte-string annotation to
|
|
||||||
// the payload. No encoding or interpretation is applied or enforced.
|
|
||||||
Extra []byte `protobuf:"bytes,3,opt,name=extra" json:"extra,omitempty"`
|
|
||||||
Type *Dnstap_Type `protobuf:"varint,15,req,name=type,enum=dnstap.Dnstap_Type" json:"type,omitempty"`
|
|
||||||
// One of the following will be filled in.
|
|
||||||
Message *Message `protobuf:"bytes,14,opt,name=message" json:"message,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Dnstap) Reset() { *m = Dnstap{} }
|
|
||||||
func (m *Dnstap) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*Dnstap) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (m *Dnstap) GetIdentity() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Identity
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Dnstap) GetVersion() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Version
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Dnstap) GetExtra() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.Extra
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Dnstap) GetType() Dnstap_Type {
|
|
||||||
if m != nil && m.Type != nil {
|
|
||||||
return *m.Type
|
|
||||||
}
|
|
||||||
return Dnstap_MESSAGE
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Dnstap) GetMessage() *Message {
|
|
||||||
if m != nil {
|
|
||||||
return m.Message
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message: a wire-format (RFC 1035 section 4) DNS message and associated
|
|
||||||
// metadata. Applications generating "Message" payloads should follow
|
|
||||||
// certain requirements based on the MessageType, see below.
|
|
||||||
type Message struct {
|
|
||||||
// One of the Type values described above.
|
|
||||||
Type *Message_Type `protobuf:"varint,1,req,name=type,enum=dnstap.Message_Type" json:"type,omitempty"`
|
|
||||||
// One of the SocketFamily values described above.
|
|
||||||
SocketFamily *SocketFamily `protobuf:"varint,2,opt,name=socket_family,enum=dnstap.SocketFamily" json:"socket_family,omitempty"`
|
|
||||||
// One of the SocketProtocol values described above.
|
|
||||||
SocketProtocol *SocketProtocol `protobuf:"varint,3,opt,name=socket_protocol,enum=dnstap.SocketProtocol" json:"socket_protocol,omitempty"`
|
|
||||||
// The network address of the message initiator.
|
|
||||||
// For SocketFamily INET, this field is 4 octets (IPv4 address).
|
|
||||||
// For SocketFamily INET6, this field is 16 octets (IPv6 address).
|
|
||||||
QueryAddress []byte `protobuf:"bytes,4,opt,name=query_address" json:"query_address,omitempty"`
|
|
||||||
// The network address of the message responder.
|
|
||||||
// For SocketFamily INET, this field is 4 octets (IPv4 address).
|
|
||||||
// For SocketFamily INET6, this field is 16 octets (IPv6 address).
|
|
||||||
ResponseAddress []byte `protobuf:"bytes,5,opt,name=response_address" json:"response_address,omitempty"`
|
|
||||||
// The transport port of the message initiator.
|
|
||||||
// This is a 16-bit UDP or TCP port number, depending on SocketProtocol.
|
|
||||||
QueryPort *uint32 `protobuf:"varint,6,opt,name=query_port" json:"query_port,omitempty"`
|
|
||||||
// The transport port of the message responder.
|
|
||||||
// This is a 16-bit UDP or TCP port number, depending on SocketProtocol.
|
|
||||||
ResponsePort *uint32 `protobuf:"varint,7,opt,name=response_port" json:"response_port,omitempty"`
|
|
||||||
// The time at which the DNS query message was sent or received, depending
|
|
||||||
// on whether this is an AUTH_QUERY, RESOLVER_QUERY, or CLIENT_QUERY.
|
|
||||||
// This is the number of seconds since the UNIX epoch.
|
|
||||||
QueryTimeSec *uint64 `protobuf:"varint,8,opt,name=query_time_sec" json:"query_time_sec,omitempty"`
|
|
||||||
// The time at which the DNS query message was sent or received.
|
|
||||||
// This is the seconds fraction, expressed as a count of nanoseconds.
|
|
||||||
QueryTimeNsec *uint32 `protobuf:"fixed32,9,opt,name=query_time_nsec" json:"query_time_nsec,omitempty"`
|
|
||||||
// The initiator's original wire-format DNS query message, verbatim.
|
|
||||||
QueryMessage []byte `protobuf:"bytes,10,opt,name=query_message" json:"query_message,omitempty"`
|
|
||||||
// The "zone" or "bailiwick" pertaining to the DNS query message.
|
|
||||||
// This is a wire-format DNS domain name.
|
|
||||||
QueryZone []byte `protobuf:"bytes,11,opt,name=query_zone" json:"query_zone,omitempty"`
|
|
||||||
// The time at which the DNS response message was sent or received,
|
|
||||||
// depending on whether this is an AUTH_RESPONSE, RESOLVER_RESPONSE, or
|
|
||||||
// CLIENT_RESPONSE.
|
|
||||||
// This is the number of seconds since the UNIX epoch.
|
|
||||||
ResponseTimeSec *uint64 `protobuf:"varint,12,opt,name=response_time_sec" json:"response_time_sec,omitempty"`
|
|
||||||
// The time at which the DNS response message was sent or received.
|
|
||||||
// This is the seconds fraction, expressed as a count of nanoseconds.
|
|
||||||
ResponseTimeNsec *uint32 `protobuf:"fixed32,13,opt,name=response_time_nsec" json:"response_time_nsec,omitempty"`
|
|
||||||
// The responder's original wire-format DNS response message, verbatim.
|
|
||||||
ResponseMessage []byte `protobuf:"bytes,14,opt,name=response_message" json:"response_message,omitempty"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) Reset() { *m = Message{} }
|
|
||||||
func (m *Message) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*Message) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (m *Message) GetType() Message_Type {
|
|
||||||
if m != nil && m.Type != nil {
|
|
||||||
return *m.Type
|
|
||||||
}
|
|
||||||
return Message_AUTH_QUERY
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetSocketFamily() SocketFamily {
|
|
||||||
if m != nil && m.SocketFamily != nil {
|
|
||||||
return *m.SocketFamily
|
|
||||||
}
|
|
||||||
return SocketFamily_INET
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetSocketProtocol() SocketProtocol {
|
|
||||||
if m != nil && m.SocketProtocol != nil {
|
|
||||||
return *m.SocketProtocol
|
|
||||||
}
|
|
||||||
return SocketProtocol_UDP
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetQueryAddress() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.QueryAddress
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetResponseAddress() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.ResponseAddress
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetQueryPort() uint32 {
|
|
||||||
if m != nil && m.QueryPort != nil {
|
|
||||||
return *m.QueryPort
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetResponsePort() uint32 {
|
|
||||||
if m != nil && m.ResponsePort != nil {
|
|
||||||
return *m.ResponsePort
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetQueryTimeSec() uint64 {
|
|
||||||
if m != nil && m.QueryTimeSec != nil {
|
|
||||||
return *m.QueryTimeSec
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetQueryTimeNsec() uint32 {
|
|
||||||
if m != nil && m.QueryTimeNsec != nil {
|
|
||||||
return *m.QueryTimeNsec
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetQueryMessage() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.QueryMessage
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetQueryZone() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.QueryZone
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetResponseTimeSec() uint64 {
|
|
||||||
if m != nil && m.ResponseTimeSec != nil {
|
|
||||||
return *m.ResponseTimeSec
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetResponseTimeNsec() uint32 {
|
|
||||||
if m != nil && m.ResponseTimeNsec != nil {
|
|
||||||
return *m.ResponseTimeNsec
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Message) GetResponseMessage() []byte {
|
|
||||||
if m != nil {
|
|
||||||
return m.ResponseMessage
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterEnum("dnstap.SocketFamily", SocketFamily_name, SocketFamily_value)
|
|
||||||
proto.RegisterEnum("dnstap.SocketProtocol", SocketProtocol_name, SocketProtocol_value)
|
|
||||||
proto.RegisterEnum("dnstap.Dnstap_Type", Dnstap_Type_name, Dnstap_Type_value)
|
|
||||||
proto.RegisterEnum("dnstap.Message_Type", Message_Type_name, Message_Type_value)
|
|
||||||
}
|
|
1
vendor/github.com/farsightsec/golang-framestream/.gitignore
generated
vendored
1
vendor/github.com/farsightsec/golang-framestream/.gitignore
generated
vendored
@ -1 +0,0 @@
|
|||||||
.*swp
|
|
13
vendor/github.com/farsightsec/golang-framestream/COPYRIGHT
generated
vendored
13
vendor/github.com/farsightsec/golang-framestream/COPYRIGHT
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
Copyright (c) 2014 by Farsight Security, Inc.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
156
vendor/github.com/farsightsec/golang-framestream/Control.go
generated
vendored
156
vendor/github.com/farsightsec/golang-framestream/Control.go
generated
vendored
@ -1,156 +0,0 @@
|
|||||||
package framestream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
const CONTROL_ACCEPT = 0x01
|
|
||||||
const CONTROL_START = 0x02
|
|
||||||
const CONTROL_STOP = 0x03
|
|
||||||
const CONTROL_READY = 0x04
|
|
||||||
const CONTROL_FINISH = 0x05
|
|
||||||
|
|
||||||
const CONTROL_FIELD_CONTENT_TYPE = 0x01
|
|
||||||
|
|
||||||
type ControlFrame struct {
|
|
||||||
ControlType uint32
|
|
||||||
ContentTypes [][]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
var ControlStart = ControlFrame{ControlType: CONTROL_START}
|
|
||||||
var ControlStop = ControlFrame{ControlType: CONTROL_STOP}
|
|
||||||
var ControlReady = ControlFrame{ControlType: CONTROL_READY}
|
|
||||||
var ControlAccept = ControlFrame{ControlType: CONTROL_ACCEPT}
|
|
||||||
var ControlFinish = ControlFrame{ControlType: CONTROL_FINISH}
|
|
||||||
|
|
||||||
func (c *ControlFrame) Encode(w io.Writer) (err error) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
err = binary.Write(&buf, binary.BigEndian, c.ControlType)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, ctype := range c.ContentTypes {
|
|
||||||
err = binary.Write(&buf, binary.BigEndian, uint32(CONTROL_FIELD_CONTENT_TYPE))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = binary.Write(&buf, binary.BigEndian, uint32(len(ctype)))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = buf.Write(ctype)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = binary.Write(w, binary.BigEndian, uint32(0))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = binary.Write(w, binary.BigEndian, uint32(buf.Len()))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = buf.WriteTo(w)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlFrame) EncodeFlush(w *bufio.Writer) error {
|
|
||||||
if err := c.Encode(w); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return w.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlFrame) Decode(r io.Reader) (err error) {
|
|
||||||
var cflen uint32
|
|
||||||
err = binary.Read(r, binary.BigEndian, &cflen)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = binary.Read(r, binary.BigEndian, &c.ControlType)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
cflen -= 4
|
|
||||||
if cflen > 0 {
|
|
||||||
cfields := make([]byte, int(cflen))
|
|
||||||
_, err = io.ReadFull(r, cfields)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for len(cfields) > 8 {
|
|
||||||
cftype := binary.BigEndian.Uint32(cfields[:4])
|
|
||||||
cfields = cfields[4:]
|
|
||||||
if cftype != CONTROL_FIELD_CONTENT_TYPE {
|
|
||||||
return ErrDecode
|
|
||||||
}
|
|
||||||
|
|
||||||
cflen := int(binary.BigEndian.Uint32(cfields[:4]))
|
|
||||||
cfields = cfields[4:]
|
|
||||||
if cflen > len(cfields) {
|
|
||||||
return ErrDecode
|
|
||||||
}
|
|
||||||
|
|
||||||
c.ContentTypes = append(c.ContentTypes, cfields[:cflen])
|
|
||||||
cfields = cfields[cflen:]
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(cfields) > 0 {
|
|
||||||
return ErrDecode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlFrame) DecodeEscape(r io.Reader) error {
|
|
||||||
var zero uint32
|
|
||||||
err := binary.Read(r, binary.BigEndian, &zero)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if zero != 0 {
|
|
||||||
return ErrDecode
|
|
||||||
}
|
|
||||||
return c.Decode(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlFrame) DecodeTypeEscape(r io.Reader, ctype uint32) error {
|
|
||||||
err := c.DecodeEscape(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctype != c.ControlType {
|
|
||||||
return ErrDecode
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlFrame) MatchContentType(ctype []byte) bool {
|
|
||||||
if ctype == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
for _, cfctype := range c.ContentTypes {
|
|
||||||
if bytes.Compare(ctype, cfctype) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ControlFrame) SetContentType(ctype []byte) {
|
|
||||||
if ctype != nil {
|
|
||||||
c.ContentTypes = [][]byte{ctype}
|
|
||||||
}
|
|
||||||
}
|
|
154
vendor/github.com/farsightsec/golang-framestream/Decoder.go
generated
vendored
154
vendor/github.com/farsightsec/golang-framestream/Decoder.go
generated
vendored
@ -1,154 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package framestream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DecoderOptions struct {
|
|
||||||
MaxPayloadSize uint32
|
|
||||||
ContentType []byte
|
|
||||||
Bidirectional bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Decoder struct {
|
|
||||||
buf []byte
|
|
||||||
opt DecoderOptions
|
|
||||||
reader *bufio.Reader
|
|
||||||
writer *bufio.Writer
|
|
||||||
stopped bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDecoder(r io.Reader, opt *DecoderOptions) (dec *Decoder, err error) {
|
|
||||||
if opt == nil {
|
|
||||||
opt = &DecoderOptions{}
|
|
||||||
}
|
|
||||||
if opt.MaxPayloadSize == 0 {
|
|
||||||
opt.MaxPayloadSize = DEFAULT_MAX_PAYLOAD_SIZE
|
|
||||||
}
|
|
||||||
dec = &Decoder{
|
|
||||||
buf: make([]byte, opt.MaxPayloadSize),
|
|
||||||
opt: *opt,
|
|
||||||
reader: bufio.NewReader(r),
|
|
||||||
writer: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
var cf ControlFrame
|
|
||||||
if opt.Bidirectional {
|
|
||||||
w, ok := r.(io.Writer)
|
|
||||||
if !ok {
|
|
||||||
return dec, ErrType
|
|
||||||
}
|
|
||||||
dec.writer = bufio.NewWriter(w)
|
|
||||||
|
|
||||||
// Read the ready control frame.
|
|
||||||
err = cf.DecodeTypeEscape(dec.reader, CONTROL_READY)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check content type.
|
|
||||||
if !cf.MatchContentType(dec.opt.ContentType) {
|
|
||||||
return dec, ErrContentTypeMismatch
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the accept control frame.
|
|
||||||
accept := ControlAccept
|
|
||||||
accept.SetContentType(dec.opt.ContentType)
|
|
||||||
err = accept.EncodeFlush(dec.writer)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the start control frame.
|
|
||||||
err = cf.DecodeTypeEscape(dec.reader, CONTROL_START)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check content type.
|
|
||||||
if !cf.MatchContentType(dec.opt.ContentType) {
|
|
||||||
return dec, ErrContentTypeMismatch
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dec *Decoder) readFrame(frameLen uint32) (err error) {
|
|
||||||
// Enforce limits on frame size.
|
|
||||||
if frameLen > dec.opt.MaxPayloadSize {
|
|
||||||
err = ErrDataFrameTooLarge
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the frame.
|
|
||||||
n, err := io.ReadFull(dec.reader, dec.buf[0:frameLen])
|
|
||||||
if err != nil || uint32(n) != frameLen {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dec *Decoder) Decode() (frameData []byte, err error) {
|
|
||||||
if dec.stopped {
|
|
||||||
err = EOF
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the frame length.
|
|
||||||
var frameLen uint32
|
|
||||||
err = binary.Read(dec.reader, binary.BigEndian, &frameLen)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if frameLen == 0 {
|
|
||||||
// This is a control frame.
|
|
||||||
var cf ControlFrame
|
|
||||||
err = cf.Decode(dec.reader)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if cf.ControlType == CONTROL_STOP {
|
|
||||||
dec.stopped = true
|
|
||||||
if dec.opt.Bidirectional {
|
|
||||||
ff := &ControlFrame{ControlType: CONTROL_FINISH}
|
|
||||||
err = ff.EncodeFlush(dec.writer)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, EOF
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// This is a data frame.
|
|
||||||
err = dec.readFrame(frameLen)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
frameData = dec.buf[0:frameLen]
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
99
vendor/github.com/farsightsec/golang-framestream/Encoder.go
generated
vendored
99
vendor/github.com/farsightsec/golang-framestream/Encoder.go
generated
vendored
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package framestream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
type EncoderOptions struct {
|
|
||||||
ContentType []byte
|
|
||||||
Bidirectional bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Encoder struct {
|
|
||||||
writer *bufio.Writer
|
|
||||||
reader *bufio.Reader
|
|
||||||
opt EncoderOptions
|
|
||||||
buf []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEncoder(w io.Writer, opt *EncoderOptions) (enc *Encoder, err error) {
|
|
||||||
if opt == nil {
|
|
||||||
opt = &EncoderOptions{}
|
|
||||||
}
|
|
||||||
enc = &Encoder{
|
|
||||||
writer: bufio.NewWriter(w),
|
|
||||||
opt: *opt,
|
|
||||||
}
|
|
||||||
|
|
||||||
if opt.Bidirectional {
|
|
||||||
r, ok := w.(io.Reader)
|
|
||||||
if !ok {
|
|
||||||
return nil, ErrType
|
|
||||||
}
|
|
||||||
enc.reader = bufio.NewReader(r)
|
|
||||||
ready := ControlReady
|
|
||||||
ready.SetContentType(opt.ContentType)
|
|
||||||
if err = ready.EncodeFlush(enc.writer); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var accept ControlFrame
|
|
||||||
if err = accept.DecodeTypeEscape(enc.reader, CONTROL_ACCEPT); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !accept.MatchContentType(opt.ContentType) {
|
|
||||||
return nil, ErrContentTypeMismatch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the start control frame.
|
|
||||||
start := ControlStart
|
|
||||||
start.SetContentType(opt.ContentType)
|
|
||||||
err = start.EncodeFlush(enc.writer)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) Close() (err error) {
|
|
||||||
err = ControlStop.EncodeFlush(enc.writer)
|
|
||||||
if err != nil || !enc.opt.Bidirectional {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var finish ControlFrame
|
|
||||||
return finish.DecodeTypeEscape(enc.reader, CONTROL_FINISH)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) Write(frame []byte) (n int, err error) {
|
|
||||||
err = binary.Write(enc.writer, binary.BigEndian, uint32(len(frame)))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return enc.writer.Write(frame)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (enc *Encoder) Flush() error {
|
|
||||||
return enc.writer.Flush()
|
|
||||||
}
|
|
202
vendor/github.com/farsightsec/golang-framestream/LICENSE
generated
vendored
202
vendor/github.com/farsightsec/golang-framestream/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
|
|
||||||
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.
|
|
13
vendor/github.com/farsightsec/golang-framestream/README.md
generated
vendored
13
vendor/github.com/farsightsec/golang-framestream/README.md
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
# Frame Streams implementation in Go
|
|
||||||
|
|
||||||
https://github.com/farsightsec/golang-framestream
|
|
||||||
|
|
||||||
Frame Streams is a lightweight, binary-clean protocol that allows
|
|
||||||
for the transport of arbitrarily encoded data payload sequences with
|
|
||||||
minimal framing overhead.
|
|
||||||
|
|
||||||
This package provides a pure Golang implementation. The Frame Streams
|
|
||||||
implementation in C is at https://github.com/farsightsec/fstrm/.
|
|
||||||
|
|
||||||
The example framestream_dump program reads a Frame Streams formatted
|
|
||||||
input file and prints the data frames and frame byte counts.
|
|
32
vendor/github.com/farsightsec/golang-framestream/framestream.go
generated
vendored
32
vendor/github.com/farsightsec/golang-framestream/framestream.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 by Farsight Security, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package framestream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
const DEFAULT_MAX_PAYLOAD_SIZE = 1048576
|
|
||||||
const MAX_CONTROL_FRAME_SIZE = 512
|
|
||||||
|
|
||||||
var EOF = io.EOF
|
|
||||||
var ErrContentTypeMismatch = errors.New("content type mismatch")
|
|
||||||
var ErrDataFrameTooLarge = errors.New("data frame too large")
|
|
||||||
var ErrShortRead = errors.New("short read")
|
|
||||||
var ErrDecode = errors.New("decoding error")
|
|
||||||
var ErrType = errors.New("invalid type")
|
|
253
vendor/github.com/golang/protobuf/proto/clone.go
generated
vendored
253
vendor/github.com/golang/protobuf/proto/clone.go
generated
vendored
@ -1,253 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Protocol buffer deep copy and merge.
|
|
||||||
// TODO: RawMessage.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Clone returns a deep copy of a protocol buffer.
|
|
||||||
func Clone(src Message) Message {
|
|
||||||
in := reflect.ValueOf(src)
|
|
||||||
if in.IsNil() {
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
out := reflect.New(in.Type().Elem())
|
|
||||||
dst := out.Interface().(Message)
|
|
||||||
Merge(dst, src)
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merger is the interface representing objects that can merge messages of the same type.
|
|
||||||
type Merger interface {
|
|
||||||
// Merge merges src into this message.
|
|
||||||
// Required and optional fields that are set in src will be set to that value in dst.
|
|
||||||
// Elements of repeated fields will be appended.
|
|
||||||
//
|
|
||||||
// Merge may panic if called with a different argument type than the receiver.
|
|
||||||
Merge(src Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// generatedMerger is the custom merge method that generated protos will have.
|
|
||||||
// We must add this method since a generate Merge method will conflict with
|
|
||||||
// many existing protos that have a Merge data field already defined.
|
|
||||||
type generatedMerger interface {
|
|
||||||
XXX_Merge(src Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge merges src into dst.
|
|
||||||
// Required and optional fields that are set in src will be set to that value in dst.
|
|
||||||
// Elements of repeated fields will be appended.
|
|
||||||
// Merge panics if src and dst are not the same type, or if dst is nil.
|
|
||||||
func Merge(dst, src Message) {
|
|
||||||
if m, ok := dst.(Merger); ok {
|
|
||||||
m.Merge(src)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
in := reflect.ValueOf(src)
|
|
||||||
out := reflect.ValueOf(dst)
|
|
||||||
if out.IsNil() {
|
|
||||||
panic("proto: nil destination")
|
|
||||||
}
|
|
||||||
if in.Type() != out.Type() {
|
|
||||||
panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
|
|
||||||
}
|
|
||||||
if in.IsNil() {
|
|
||||||
return // Merge from nil src is a noop
|
|
||||||
}
|
|
||||||
if m, ok := dst.(generatedMerger); ok {
|
|
||||||
m.XXX_Merge(src)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mergeStruct(out.Elem(), in.Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
func mergeStruct(out, in reflect.Value) {
|
|
||||||
sprop := GetProperties(in.Type())
|
|
||||||
for i := 0; i < in.NumField(); i++ {
|
|
||||||
f := in.Type().Field(i)
|
|
||||||
if strings.HasPrefix(f.Name, "XXX_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
if emIn, err := extendable(in.Addr().Interface()); err == nil {
|
|
||||||
emOut, _ := extendable(out.Addr().Interface())
|
|
||||||
mIn, muIn := emIn.extensionsRead()
|
|
||||||
if mIn != nil {
|
|
||||||
mOut := emOut.extensionsWrite()
|
|
||||||
muIn.Lock()
|
|
||||||
mergeExtension(mOut, mIn)
|
|
||||||
muIn.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uf := in.FieldByName("XXX_unrecognized")
|
|
||||||
if !uf.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uin := uf.Bytes()
|
|
||||||
if len(uin) > 0 {
|
|
||||||
out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mergeAny performs a merge between two values of the same type.
|
|
||||||
// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
|
|
||||||
// prop is set if this is a struct field (it may be nil).
|
|
||||||
func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
|
|
||||||
if in.Type() == protoMessageType {
|
|
||||||
if !in.IsNil() {
|
|
||||||
if out.IsNil() {
|
|
||||||
out.Set(reflect.ValueOf(Clone(in.Interface().(Message))))
|
|
||||||
} else {
|
|
||||||
Merge(out.Interface().(Message), in.Interface().(Message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch in.Kind() {
|
|
||||||
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
|
|
||||||
reflect.String, reflect.Uint32, reflect.Uint64:
|
|
||||||
if !viaPtr && isProto3Zero(in) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
out.Set(in)
|
|
||||||
case reflect.Interface:
|
|
||||||
// Probably a oneof field; copy non-nil values.
|
|
||||||
if in.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Allocate destination if it is not set, or set to a different type.
|
|
||||||
// Otherwise we will merge as normal.
|
|
||||||
if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
|
|
||||||
out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
|
|
||||||
}
|
|
||||||
mergeAny(out.Elem(), in.Elem(), false, nil)
|
|
||||||
case reflect.Map:
|
|
||||||
if in.Len() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if out.IsNil() {
|
|
||||||
out.Set(reflect.MakeMap(in.Type()))
|
|
||||||
}
|
|
||||||
// For maps with value types of *T or []byte we need to deep copy each value.
|
|
||||||
elemKind := in.Type().Elem().Kind()
|
|
||||||
for _, key := range in.MapKeys() {
|
|
||||||
var val reflect.Value
|
|
||||||
switch elemKind {
|
|
||||||
case reflect.Ptr:
|
|
||||||
val = reflect.New(in.Type().Elem().Elem())
|
|
||||||
mergeAny(val, in.MapIndex(key), false, nil)
|
|
||||||
case reflect.Slice:
|
|
||||||
val = in.MapIndex(key)
|
|
||||||
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
|
|
||||||
default:
|
|
||||||
val = in.MapIndex(key)
|
|
||||||
}
|
|
||||||
out.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
case reflect.Ptr:
|
|
||||||
if in.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if out.IsNil() {
|
|
||||||
out.Set(reflect.New(in.Elem().Type()))
|
|
||||||
}
|
|
||||||
mergeAny(out.Elem(), in.Elem(), true, nil)
|
|
||||||
case reflect.Slice:
|
|
||||||
if in.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if in.Type().Elem().Kind() == reflect.Uint8 {
|
|
||||||
// []byte is a scalar bytes field, not a repeated field.
|
|
||||||
|
|
||||||
// Edge case: if this is in a proto3 message, a zero length
|
|
||||||
// bytes field is considered the zero value, and should not
|
|
||||||
// be merged.
|
|
||||||
if prop != nil && prop.proto3 && in.Len() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a deep copy.
|
|
||||||
// Append to []byte{} instead of []byte(nil) so that we never end up
|
|
||||||
// with a nil result.
|
|
||||||
out.SetBytes(append([]byte{}, in.Bytes()...))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n := in.Len()
|
|
||||||
if out.IsNil() {
|
|
||||||
out.Set(reflect.MakeSlice(in.Type(), 0, n))
|
|
||||||
}
|
|
||||||
switch in.Type().Elem().Kind() {
|
|
||||||
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
|
|
||||||
reflect.String, reflect.Uint32, reflect.Uint64:
|
|
||||||
out.Set(reflect.AppendSlice(out, in))
|
|
||||||
default:
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
x := reflect.Indirect(reflect.New(in.Type().Elem()))
|
|
||||||
mergeAny(x, in.Index(i), false, nil)
|
|
||||||
out.Set(reflect.Append(out, x))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
mergeStruct(out, in)
|
|
||||||
default:
|
|
||||||
// unknown type, so not a protocol buffer
|
|
||||||
log.Printf("proto: don't know how to copy %v", in)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mergeExtension(out, in map[int32]Extension) {
|
|
||||||
for extNum, eIn := range in {
|
|
||||||
eOut := Extension{desc: eIn.desc}
|
|
||||||
if eIn.value != nil {
|
|
||||||
v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
|
|
||||||
mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
|
|
||||||
eOut.value = v.Interface()
|
|
||||||
}
|
|
||||||
if eIn.enc != nil {
|
|
||||||
eOut.enc = make([]byte, len(eIn.enc))
|
|
||||||
copy(eOut.enc, eIn.enc)
|
|
||||||
}
|
|
||||||
|
|
||||||
out[extNum] = eOut
|
|
||||||
}
|
|
||||||
}
|
|
427
vendor/github.com/golang/protobuf/proto/decode.go
generated
vendored
427
vendor/github.com/golang/protobuf/proto/decode.go
generated
vendored
@ -1,427 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Routines for decoding protocol buffer data to construct in-memory representations.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// errOverflow is returned when an integer is too large to be represented.
|
|
||||||
var errOverflow = errors.New("proto: integer overflow")
|
|
||||||
|
|
||||||
// ErrInternalBadWireType is returned by generated code when an incorrect
|
|
||||||
// wire type is encountered. It does not get returned to user code.
|
|
||||||
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
|
|
||||||
|
|
||||||
// DecodeVarint reads a varint-encoded integer from the slice.
|
|
||||||
// It returns the integer and the number of bytes consumed, or
|
|
||||||
// zero if there is not enough.
|
|
||||||
// This is the format for the
|
|
||||||
// int32, int64, uint32, uint64, bool, and enum
|
|
||||||
// protocol buffer types.
|
|
||||||
func DecodeVarint(buf []byte) (x uint64, n int) {
|
|
||||||
for shift := uint(0); shift < 64; shift += 7 {
|
|
||||||
if n >= len(buf) {
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
b := uint64(buf[n])
|
|
||||||
n++
|
|
||||||
x |= (b & 0x7F) << shift
|
|
||||||
if (b & 0x80) == 0 {
|
|
||||||
return x, n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The number is too large to represent in a 64-bit value.
|
|
||||||
return 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Buffer) decodeVarintSlow() (x uint64, err error) {
|
|
||||||
i := p.index
|
|
||||||
l := len(p.buf)
|
|
||||||
|
|
||||||
for shift := uint(0); shift < 64; shift += 7 {
|
|
||||||
if i >= l {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b := p.buf[i]
|
|
||||||
i++
|
|
||||||
x |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
p.index = i
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The number is too large to represent in a 64-bit value.
|
|
||||||
err = errOverflow
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeVarint reads a varint-encoded integer from the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// int32, int64, uint32, uint64, bool, and enum
|
|
||||||
// protocol buffer types.
|
|
||||||
func (p *Buffer) DecodeVarint() (x uint64, err error) {
|
|
||||||
i := p.index
|
|
||||||
buf := p.buf
|
|
||||||
|
|
||||||
if i >= len(buf) {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
} else if buf[i] < 0x80 {
|
|
||||||
p.index++
|
|
||||||
return uint64(buf[i]), nil
|
|
||||||
} else if len(buf)-i < 10 {
|
|
||||||
return p.decodeVarintSlow()
|
|
||||||
}
|
|
||||||
|
|
||||||
var b uint64
|
|
||||||
// we already checked the first byte
|
|
||||||
x = uint64(buf[i]) - 0x80
|
|
||||||
i++
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 7
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 7
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 14
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 14
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 21
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 21
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 28
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 28
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 35
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 35
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 42
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 42
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 49
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 49
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 56
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
x -= 0x80 << 56
|
|
||||||
|
|
||||||
b = uint64(buf[i])
|
|
||||||
i++
|
|
||||||
x += b << 63
|
|
||||||
if b&0x80 == 0 {
|
|
||||||
goto done
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0, errOverflow
|
|
||||||
|
|
||||||
done:
|
|
||||||
p.index = i
|
|
||||||
return x, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeFixed64 reads a 64-bit integer from the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// fixed64, sfixed64, and double protocol buffer types.
|
|
||||||
func (p *Buffer) DecodeFixed64() (x uint64, err error) {
|
|
||||||
// x, err already 0
|
|
||||||
i := p.index + 8
|
|
||||||
if i < 0 || i > len(p.buf) {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.index = i
|
|
||||||
|
|
||||||
x = uint64(p.buf[i-8])
|
|
||||||
x |= uint64(p.buf[i-7]) << 8
|
|
||||||
x |= uint64(p.buf[i-6]) << 16
|
|
||||||
x |= uint64(p.buf[i-5]) << 24
|
|
||||||
x |= uint64(p.buf[i-4]) << 32
|
|
||||||
x |= uint64(p.buf[i-3]) << 40
|
|
||||||
x |= uint64(p.buf[i-2]) << 48
|
|
||||||
x |= uint64(p.buf[i-1]) << 56
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeFixed32 reads a 32-bit integer from the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// fixed32, sfixed32, and float protocol buffer types.
|
|
||||||
func (p *Buffer) DecodeFixed32() (x uint64, err error) {
|
|
||||||
// x, err already 0
|
|
||||||
i := p.index + 4
|
|
||||||
if i < 0 || i > len(p.buf) {
|
|
||||||
err = io.ErrUnexpectedEOF
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.index = i
|
|
||||||
|
|
||||||
x = uint64(p.buf[i-4])
|
|
||||||
x |= uint64(p.buf[i-3]) << 8
|
|
||||||
x |= uint64(p.buf[i-2]) << 16
|
|
||||||
x |= uint64(p.buf[i-1]) << 24
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
|
|
||||||
// from the Buffer.
|
|
||||||
// This is the format used for the sint64 protocol buffer type.
|
|
||||||
func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
|
|
||||||
x, err = p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
|
|
||||||
// from the Buffer.
|
|
||||||
// This is the format used for the sint32 protocol buffer type.
|
|
||||||
func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
|
|
||||||
x, err = p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
|
|
||||||
// This is the format used for the bytes protocol buffer
|
|
||||||
// type and for embedded messages.
|
|
||||||
func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
|
|
||||||
n, err := p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
nb := int(n)
|
|
||||||
if nb < 0 {
|
|
||||||
return nil, fmt.Errorf("proto: bad byte length %d", nb)
|
|
||||||
}
|
|
||||||
end := p.index + nb
|
|
||||||
if end < p.index || end > len(p.buf) {
|
|
||||||
return nil, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
|
|
||||||
if !alloc {
|
|
||||||
// todo: check if can get more uses of alloc=false
|
|
||||||
buf = p.buf[p.index:end]
|
|
||||||
p.index += nb
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = make([]byte, nb)
|
|
||||||
copy(buf, p.buf[p.index:])
|
|
||||||
p.index += nb
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeStringBytes reads an encoded string from the Buffer.
|
|
||||||
// This is the format used for the proto2 string type.
|
|
||||||
func (p *Buffer) DecodeStringBytes() (s string, err error) {
|
|
||||||
buf, err := p.DecodeRawBytes(false)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return string(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshaler is the interface representing objects that can
|
|
||||||
// unmarshal themselves. The argument points to data that may be
|
|
||||||
// overwritten, so implementations should not keep references to the
|
|
||||||
// buffer.
|
|
||||||
// Unmarshal implementations should not clear the receiver.
|
|
||||||
// Any unmarshaled data should be merged into the receiver.
|
|
||||||
// Callers of Unmarshal that do not want to retain existing data
|
|
||||||
// should Reset the receiver before calling Unmarshal.
|
|
||||||
type Unmarshaler interface {
|
|
||||||
Unmarshal([]byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// newUnmarshaler is the interface representing objects that can
|
|
||||||
// unmarshal themselves. The semantics are identical to Unmarshaler.
|
|
||||||
//
|
|
||||||
// This exists to support protoc-gen-go generated messages.
|
|
||||||
// The proto package will stop type-asserting to this interface in the future.
|
|
||||||
//
|
|
||||||
// DO NOT DEPEND ON THIS.
|
|
||||||
type newUnmarshaler interface {
|
|
||||||
XXX_Unmarshal([]byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal parses the protocol buffer representation in buf and places the
|
|
||||||
// decoded result in pb. If the struct underlying pb does not match
|
|
||||||
// the data in buf, the results can be unpredictable.
|
|
||||||
//
|
|
||||||
// Unmarshal resets pb before starting to unmarshal, so any
|
|
||||||
// existing data in pb is always removed. Use UnmarshalMerge
|
|
||||||
// to preserve and append to existing data.
|
|
||||||
func Unmarshal(buf []byte, pb Message) error {
|
|
||||||
pb.Reset()
|
|
||||||
if u, ok := pb.(newUnmarshaler); ok {
|
|
||||||
return u.XXX_Unmarshal(buf)
|
|
||||||
}
|
|
||||||
if u, ok := pb.(Unmarshaler); ok {
|
|
||||||
return u.Unmarshal(buf)
|
|
||||||
}
|
|
||||||
return NewBuffer(buf).Unmarshal(pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalMerge parses the protocol buffer representation in buf and
|
|
||||||
// writes the decoded result to pb. If the struct underlying pb does not match
|
|
||||||
// the data in buf, the results can be unpredictable.
|
|
||||||
//
|
|
||||||
// UnmarshalMerge merges into existing data in pb.
|
|
||||||
// Most code should use Unmarshal instead.
|
|
||||||
func UnmarshalMerge(buf []byte, pb Message) error {
|
|
||||||
if u, ok := pb.(newUnmarshaler); ok {
|
|
||||||
return u.XXX_Unmarshal(buf)
|
|
||||||
}
|
|
||||||
if u, ok := pb.(Unmarshaler); ok {
|
|
||||||
// NOTE: The history of proto have unfortunately been inconsistent
|
|
||||||
// whether Unmarshaler should or should not implicitly clear itself.
|
|
||||||
// Some implementations do, most do not.
|
|
||||||
// Thus, calling this here may or may not do what people want.
|
|
||||||
//
|
|
||||||
// See https://github.com/golang/protobuf/issues/424
|
|
||||||
return u.Unmarshal(buf)
|
|
||||||
}
|
|
||||||
return NewBuffer(buf).Unmarshal(pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeMessage reads a count-delimited message from the Buffer.
|
|
||||||
func (p *Buffer) DecodeMessage(pb Message) error {
|
|
||||||
enc, err := p.DecodeRawBytes(false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return NewBuffer(enc).Unmarshal(pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeGroup reads a tag-delimited group from the Buffer.
|
|
||||||
// StartGroup tag is already consumed. This function consumes
|
|
||||||
// EndGroup tag.
|
|
||||||
func (p *Buffer) DecodeGroup(pb Message) error {
|
|
||||||
b := p.buf[p.index:]
|
|
||||||
x, y := findEndGroup(b)
|
|
||||||
if x < 0 {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
err := Unmarshal(b[:x], pb)
|
|
||||||
p.index += y
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal parses the protocol buffer representation in the
|
|
||||||
// Buffer and places the decoded result in pb. If the struct
|
|
||||||
// underlying pb does not match the data in the buffer, the results can be
|
|
||||||
// unpredictable.
|
|
||||||
//
|
|
||||||
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
|
|
||||||
func (p *Buffer) Unmarshal(pb Message) error {
|
|
||||||
// If the object can unmarshal itself, let it.
|
|
||||||
if u, ok := pb.(newUnmarshaler); ok {
|
|
||||||
err := u.XXX_Unmarshal(p.buf[p.index:])
|
|
||||||
p.index = len(p.buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if u, ok := pb.(Unmarshaler); ok {
|
|
||||||
// NOTE: The history of proto have unfortunately been inconsistent
|
|
||||||
// whether Unmarshaler should or should not implicitly clear itself.
|
|
||||||
// Some implementations do, most do not.
|
|
||||||
// Thus, calling this here may or may not do what people want.
|
|
||||||
//
|
|
||||||
// See https://github.com/golang/protobuf/issues/424
|
|
||||||
err := u.Unmarshal(p.buf[p.index:])
|
|
||||||
p.index = len(p.buf)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slow workaround for messages that aren't Unmarshalers.
|
|
||||||
// This includes some hand-coded .pb.go files and
|
|
||||||
// bootstrap protos.
|
|
||||||
// TODO: fix all of those and then add Unmarshal to
|
|
||||||
// the Message interface. Then:
|
|
||||||
// The cast above and code below can be deleted.
|
|
||||||
// The old unmarshaler can be deleted.
|
|
||||||
// Clients can call Unmarshal directly (can already do that, actually).
|
|
||||||
var info InternalMessageInfo
|
|
||||||
err := info.Unmarshal(pb, p.buf[p.index:])
|
|
||||||
p.index = len(p.buf)
|
|
||||||
return err
|
|
||||||
}
|
|
203
vendor/github.com/golang/protobuf/proto/encode.go
generated
vendored
203
vendor/github.com/golang/protobuf/proto/encode.go
generated
vendored
@ -1,203 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Routines for encoding data into the wire format for protocol buffers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// errRepeatedHasNil is the error returned if Marshal is called with
|
|
||||||
// a struct with a repeated field containing a nil element.
|
|
||||||
errRepeatedHasNil = errors.New("proto: repeated field has nil element")
|
|
||||||
|
|
||||||
// errOneofHasNil is the error returned if Marshal is called with
|
|
||||||
// a struct with a oneof field containing a nil element.
|
|
||||||
errOneofHasNil = errors.New("proto: oneof field has nil value")
|
|
||||||
|
|
||||||
// ErrNil is the error returned if Marshal is called with nil.
|
|
||||||
ErrNil = errors.New("proto: Marshal called with nil")
|
|
||||||
|
|
||||||
// ErrTooLarge is the error returned if Marshal is called with a
|
|
||||||
// message that encodes to >2GB.
|
|
||||||
ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
|
|
||||||
)
|
|
||||||
|
|
||||||
// The fundamental encoders that put bytes on the wire.
|
|
||||||
// Those that take integer types all accept uint64 and are
|
|
||||||
// therefore of type valueEncoder.
|
|
||||||
|
|
||||||
const maxVarintBytes = 10 // maximum length of a varint
|
|
||||||
|
|
||||||
// EncodeVarint returns the varint encoding of x.
|
|
||||||
// This is the format for the
|
|
||||||
// int32, int64, uint32, uint64, bool, and enum
|
|
||||||
// protocol buffer types.
|
|
||||||
// Not used by the package itself, but helpful to clients
|
|
||||||
// wishing to use the same encoding.
|
|
||||||
func EncodeVarint(x uint64) []byte {
|
|
||||||
var buf [maxVarintBytes]byte
|
|
||||||
var n int
|
|
||||||
for n = 0; x > 127; n++ {
|
|
||||||
buf[n] = 0x80 | uint8(x&0x7F)
|
|
||||||
x >>= 7
|
|
||||||
}
|
|
||||||
buf[n] = uint8(x)
|
|
||||||
n++
|
|
||||||
return buf[0:n]
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeVarint writes a varint-encoded integer to the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// int32, int64, uint32, uint64, bool, and enum
|
|
||||||
// protocol buffer types.
|
|
||||||
func (p *Buffer) EncodeVarint(x uint64) error {
|
|
||||||
for x >= 1<<7 {
|
|
||||||
p.buf = append(p.buf, uint8(x&0x7f|0x80))
|
|
||||||
x >>= 7
|
|
||||||
}
|
|
||||||
p.buf = append(p.buf, uint8(x))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SizeVarint returns the varint encoding size of an integer.
|
|
||||||
func SizeVarint(x uint64) int {
|
|
||||||
switch {
|
|
||||||
case x < 1<<7:
|
|
||||||
return 1
|
|
||||||
case x < 1<<14:
|
|
||||||
return 2
|
|
||||||
case x < 1<<21:
|
|
||||||
return 3
|
|
||||||
case x < 1<<28:
|
|
||||||
return 4
|
|
||||||
case x < 1<<35:
|
|
||||||
return 5
|
|
||||||
case x < 1<<42:
|
|
||||||
return 6
|
|
||||||
case x < 1<<49:
|
|
||||||
return 7
|
|
||||||
case x < 1<<56:
|
|
||||||
return 8
|
|
||||||
case x < 1<<63:
|
|
||||||
return 9
|
|
||||||
}
|
|
||||||
return 10
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeFixed64 writes a 64-bit integer to the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// fixed64, sfixed64, and double protocol buffer types.
|
|
||||||
func (p *Buffer) EncodeFixed64(x uint64) error {
|
|
||||||
p.buf = append(p.buf,
|
|
||||||
uint8(x),
|
|
||||||
uint8(x>>8),
|
|
||||||
uint8(x>>16),
|
|
||||||
uint8(x>>24),
|
|
||||||
uint8(x>>32),
|
|
||||||
uint8(x>>40),
|
|
||||||
uint8(x>>48),
|
|
||||||
uint8(x>>56))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeFixed32 writes a 32-bit integer to the Buffer.
|
|
||||||
// This is the format for the
|
|
||||||
// fixed32, sfixed32, and float protocol buffer types.
|
|
||||||
func (p *Buffer) EncodeFixed32(x uint64) error {
|
|
||||||
p.buf = append(p.buf,
|
|
||||||
uint8(x),
|
|
||||||
uint8(x>>8),
|
|
||||||
uint8(x>>16),
|
|
||||||
uint8(x>>24))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
|
|
||||||
// to the Buffer.
|
|
||||||
// This is the format used for the sint64 protocol buffer type.
|
|
||||||
func (p *Buffer) EncodeZigzag64(x uint64) error {
|
|
||||||
// use signed number to get arithmetic right shift.
|
|
||||||
return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
|
|
||||||
// to the Buffer.
|
|
||||||
// This is the format used for the sint32 protocol buffer type.
|
|
||||||
func (p *Buffer) EncodeZigzag32(x uint64) error {
|
|
||||||
// use signed number to get arithmetic right shift.
|
|
||||||
return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
|
|
||||||
// This is the format used for the bytes protocol buffer
|
|
||||||
// type and for embedded messages.
|
|
||||||
func (p *Buffer) EncodeRawBytes(b []byte) error {
|
|
||||||
p.EncodeVarint(uint64(len(b)))
|
|
||||||
p.buf = append(p.buf, b...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeStringBytes writes an encoded string to the Buffer.
|
|
||||||
// This is the format used for the proto2 string type.
|
|
||||||
func (p *Buffer) EncodeStringBytes(s string) error {
|
|
||||||
p.EncodeVarint(uint64(len(s)))
|
|
||||||
p.buf = append(p.buf, s...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshaler is the interface representing objects that can marshal themselves.
|
|
||||||
type Marshaler interface {
|
|
||||||
Marshal() ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeMessage writes the protocol buffer to the Buffer,
|
|
||||||
// prefixed by a varint-encoded length.
|
|
||||||
func (p *Buffer) EncodeMessage(pb Message) error {
|
|
||||||
siz := Size(pb)
|
|
||||||
p.EncodeVarint(uint64(siz))
|
|
||||||
return p.Marshal(pb)
|
|
||||||
}
|
|
||||||
|
|
||||||
// All protocol buffer fields are nillable, but be careful.
|
|
||||||
func isNil(v reflect.Value) bool {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
|
||||||
return v.IsNil()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
301
vendor/github.com/golang/protobuf/proto/equal.go
generated
vendored
301
vendor/github.com/golang/protobuf/proto/equal.go
generated
vendored
@ -1,301 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// Protocol buffer comparison.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"log"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
Equal returns true iff protocol buffers a and b are equal.
|
|
||||||
The arguments must both be pointers to protocol buffer structs.
|
|
||||||
|
|
||||||
Equality is defined in this way:
|
|
||||||
- Two messages are equal iff they are the same type,
|
|
||||||
corresponding fields are equal, unknown field sets
|
|
||||||
are equal, and extensions sets are equal.
|
|
||||||
- Two set scalar fields are equal iff their values are equal.
|
|
||||||
If the fields are of a floating-point type, remember that
|
|
||||||
NaN != x for all x, including NaN. If the message is defined
|
|
||||||
in a proto3 .proto file, fields are not "set"; specifically,
|
|
||||||
zero length proto3 "bytes" fields are equal (nil == {}).
|
|
||||||
- Two repeated fields are equal iff their lengths are the same,
|
|
||||||
and their corresponding elements are equal. Note a "bytes" field,
|
|
||||||
although represented by []byte, is not a repeated field and the
|
|
||||||
rule for the scalar fields described above applies.
|
|
||||||
- Two unset fields are equal.
|
|
||||||
- Two unknown field sets are equal if their current
|
|
||||||
encoded state is equal.
|
|
||||||
- Two extension sets are equal iff they have corresponding
|
|
||||||
elements that are pairwise equal.
|
|
||||||
- Two map fields are equal iff their lengths are the same,
|
|
||||||
and they contain the same set of elements. Zero-length map
|
|
||||||
fields are equal.
|
|
||||||
- Every other combination of things are not equal.
|
|
||||||
|
|
||||||
The return value is undefined if a and b are not protocol buffers.
|
|
||||||
*/
|
|
||||||
func Equal(a, b Message) bool {
|
|
||||||
if a == nil || b == nil {
|
|
||||||
return a == b
|
|
||||||
}
|
|
||||||
v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
|
|
||||||
if v1.Type() != v2.Type() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if v1.Kind() == reflect.Ptr {
|
|
||||||
if v1.IsNil() {
|
|
||||||
return v2.IsNil()
|
|
||||||
}
|
|
||||||
if v2.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
v1, v2 = v1.Elem(), v2.Elem()
|
|
||||||
}
|
|
||||||
if v1.Kind() != reflect.Struct {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return equalStruct(v1, v2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// v1 and v2 are known to have the same type.
|
|
||||||
func equalStruct(v1, v2 reflect.Value) bool {
|
|
||||||
sprop := GetProperties(v1.Type())
|
|
||||||
for i := 0; i < v1.NumField(); i++ {
|
|
||||||
f := v1.Type().Field(i)
|
|
||||||
if strings.HasPrefix(f.Name, "XXX_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
f1, f2 := v1.Field(i), v2.Field(i)
|
|
||||||
if f.Type.Kind() == reflect.Ptr {
|
|
||||||
if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
|
|
||||||
// both unset
|
|
||||||
continue
|
|
||||||
} else if n1 != n2 {
|
|
||||||
// set/unset mismatch
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
f1, f2 = f1.Elem(), f2.Elem()
|
|
||||||
}
|
|
||||||
if !equalAny(f1, f2, sprop.Prop[i]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
|
|
||||||
em2 := v2.FieldByName("XXX_InternalExtensions")
|
|
||||||
if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
|
|
||||||
em2 := v2.FieldByName("XXX_extensions")
|
|
||||||
if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uf := v1.FieldByName("XXX_unrecognized")
|
|
||||||
if !uf.IsValid() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
u1 := uf.Bytes()
|
|
||||||
u2 := v2.FieldByName("XXX_unrecognized").Bytes()
|
|
||||||
return bytes.Equal(u1, u2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// v1 and v2 are known to have the same type.
|
|
||||||
// prop may be nil.
|
|
||||||
func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
|
|
||||||
if v1.Type() == protoMessageType {
|
|
||||||
m1, _ := v1.Interface().(Message)
|
|
||||||
m2, _ := v2.Interface().(Message)
|
|
||||||
return Equal(m1, m2)
|
|
||||||
}
|
|
||||||
switch v1.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return v1.Bool() == v2.Bool()
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return v1.Float() == v2.Float()
|
|
||||||
case reflect.Int32, reflect.Int64:
|
|
||||||
return v1.Int() == v2.Int()
|
|
||||||
case reflect.Interface:
|
|
||||||
// Probably a oneof field; compare the inner values.
|
|
||||||
n1, n2 := v1.IsNil(), v2.IsNil()
|
|
||||||
if n1 || n2 {
|
|
||||||
return n1 == n2
|
|
||||||
}
|
|
||||||
e1, e2 := v1.Elem(), v2.Elem()
|
|
||||||
if e1.Type() != e2.Type() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return equalAny(e1, e2, nil)
|
|
||||||
case reflect.Map:
|
|
||||||
if v1.Len() != v2.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, key := range v1.MapKeys() {
|
|
||||||
val2 := v2.MapIndex(key)
|
|
||||||
if !val2.IsValid() {
|
|
||||||
// This key was not found in the second map.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !equalAny(v1.MapIndex(key), val2, nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case reflect.Ptr:
|
|
||||||
// Maps may have nil values in them, so check for nil.
|
|
||||||
if v1.IsNil() && v2.IsNil() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if v1.IsNil() != v2.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return equalAny(v1.Elem(), v2.Elem(), prop)
|
|
||||||
case reflect.Slice:
|
|
||||||
if v1.Type().Elem().Kind() == reflect.Uint8 {
|
|
||||||
// short circuit: []byte
|
|
||||||
|
|
||||||
// Edge case: if this is in a proto3 message, a zero length
|
|
||||||
// bytes field is considered the zero value.
|
|
||||||
if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if v1.IsNil() != v2.IsNil() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
|
|
||||||
}
|
|
||||||
|
|
||||||
if v1.Len() != v2.Len() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := 0; i < v1.Len(); i++ {
|
|
||||||
if !equalAny(v1.Index(i), v2.Index(i), prop) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
case reflect.String:
|
|
||||||
return v1.Interface().(string) == v2.Interface().(string)
|
|
||||||
case reflect.Struct:
|
|
||||||
return equalStruct(v1, v2)
|
|
||||||
case reflect.Uint32, reflect.Uint64:
|
|
||||||
return v1.Uint() == v2.Uint()
|
|
||||||
}
|
|
||||||
|
|
||||||
// unknown type, so not a protocol buffer
|
|
||||||
log.Printf("proto: don't know how to compare %v", v1)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// base is the struct type that the extensions are based on.
|
|
||||||
// x1 and x2 are InternalExtensions.
|
|
||||||
func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
|
|
||||||
em1, _ := x1.extensionsRead()
|
|
||||||
em2, _ := x2.extensionsRead()
|
|
||||||
return equalExtMap(base, em1, em2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
|
|
||||||
if len(em1) != len(em2) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for extNum, e1 := range em1 {
|
|
||||||
e2, ok := em2[extNum]
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
m1 := extensionAsLegacyType(e1.value)
|
|
||||||
m2 := extensionAsLegacyType(e2.value)
|
|
||||||
|
|
||||||
if m1 == nil && m2 == nil {
|
|
||||||
// Both have only encoded form.
|
|
||||||
if bytes.Equal(e1.enc, e2.enc) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// The bytes are different, but the extensions might still be
|
|
||||||
// equal. We need to decode them to compare.
|
|
||||||
}
|
|
||||||
|
|
||||||
if m1 != nil && m2 != nil {
|
|
||||||
// Both are unencoded.
|
|
||||||
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// At least one is encoded. To do a semantically correct comparison
|
|
||||||
// we need to unmarshal them first.
|
|
||||||
var desc *ExtensionDesc
|
|
||||||
if m := extensionMaps[base]; m != nil {
|
|
||||||
desc = m[extNum]
|
|
||||||
}
|
|
||||||
if desc == nil {
|
|
||||||
// If both have only encoded form and the bytes are the same,
|
|
||||||
// it is handled above. We get here when the bytes are different.
|
|
||||||
// We don't know how to decode it, so just compare them as byte
|
|
||||||
// slices.
|
|
||||||
log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
if m1 == nil {
|
|
||||||
m1, err = decodeExtension(e1.enc, desc)
|
|
||||||
}
|
|
||||||
if m2 == nil && err == nil {
|
|
||||||
m2, err = decodeExtension(e2.enc, desc)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
// The encoded form is invalid.
|
|
||||||
log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
965
vendor/github.com/golang/protobuf/proto/lib.go
generated
vendored
965
vendor/github.com/golang/protobuf/proto/lib.go
generated
vendored
@ -1,965 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
/*
|
|
||||||
Package proto converts data structures to and from the wire format of
|
|
||||||
protocol buffers. It works in concert with the Go source code generated
|
|
||||||
for .proto files by the protocol compiler.
|
|
||||||
|
|
||||||
A summary of the properties of the protocol buffer interface
|
|
||||||
for a protocol buffer variable v:
|
|
||||||
|
|
||||||
- Names are turned from camel_case to CamelCase for export.
|
|
||||||
- There are no methods on v to set fields; just treat
|
|
||||||
them as structure fields.
|
|
||||||
- There are getters that return a field's value if set,
|
|
||||||
and return the field's default value if unset.
|
|
||||||
The getters work even if the receiver is a nil message.
|
|
||||||
- The zero value for a struct is its correct initialization state.
|
|
||||||
All desired fields must be set before marshaling.
|
|
||||||
- A Reset() method will restore a protobuf struct to its zero state.
|
|
||||||
- Non-repeated fields are pointers to the values; nil means unset.
|
|
||||||
That is, optional or required field int32 f becomes F *int32.
|
|
||||||
- Repeated fields are slices.
|
|
||||||
- Helper functions are available to aid the setting of fields.
|
|
||||||
msg.Foo = proto.String("hello") // set field
|
|
||||||
- Constants are defined to hold the default values of all fields that
|
|
||||||
have them. They have the form Default_StructName_FieldName.
|
|
||||||
Because the getter methods handle defaulted values,
|
|
||||||
direct use of these constants should be rare.
|
|
||||||
- Enums are given type names and maps from names to values.
|
|
||||||
Enum values are prefixed by the enclosing message's name, or by the
|
|
||||||
enum's type name if it is a top-level enum. Enum types have a String
|
|
||||||
method, and a Enum method to assist in message construction.
|
|
||||||
- Nested messages, groups and enums have type names prefixed with the name of
|
|
||||||
the surrounding message type.
|
|
||||||
- Extensions are given descriptor names that start with E_,
|
|
||||||
followed by an underscore-delimited list of the nested messages
|
|
||||||
that contain it (if any) followed by the CamelCased name of the
|
|
||||||
extension field itself. HasExtension, ClearExtension, GetExtension
|
|
||||||
and SetExtension are functions for manipulating extensions.
|
|
||||||
- Oneof field sets are given a single field in their message,
|
|
||||||
with distinguished wrapper types for each possible field value.
|
|
||||||
- Marshal and Unmarshal are functions to encode and decode the wire format.
|
|
||||||
|
|
||||||
When the .proto file specifies `syntax="proto3"`, there are some differences:
|
|
||||||
|
|
||||||
- Non-repeated fields of non-message type are values instead of pointers.
|
|
||||||
- Enum types do not get an Enum method.
|
|
||||||
|
|
||||||
The simplest way to describe this is to see an example.
|
|
||||||
Given file test.proto, containing
|
|
||||||
|
|
||||||
package example;
|
|
||||||
|
|
||||||
enum FOO { X = 17; }
|
|
||||||
|
|
||||||
message Test {
|
|
||||||
required string label = 1;
|
|
||||||
optional int32 type = 2 [default=77];
|
|
||||||
repeated int64 reps = 3;
|
|
||||||
optional group OptionalGroup = 4 {
|
|
||||||
required string RequiredField = 5;
|
|
||||||
}
|
|
||||||
oneof union {
|
|
||||||
int32 number = 6;
|
|
||||||
string name = 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
The resulting file, test.pb.go, is:
|
|
||||||
|
|
||||||
package example
|
|
||||||
|
|
||||||
import proto "github.com/golang/protobuf/proto"
|
|
||||||
import math "math"
|
|
||||||
|
|
||||||
type FOO int32
|
|
||||||
const (
|
|
||||||
FOO_X FOO = 17
|
|
||||||
)
|
|
||||||
var FOO_name = map[int32]string{
|
|
||||||
17: "X",
|
|
||||||
}
|
|
||||||
var FOO_value = map[string]int32{
|
|
||||||
"X": 17,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x FOO) Enum() *FOO {
|
|
||||||
p := new(FOO)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
func (x FOO) String() string {
|
|
||||||
return proto.EnumName(FOO_name, int32(x))
|
|
||||||
}
|
|
||||||
func (x *FOO) UnmarshalJSON(data []byte) error {
|
|
||||||
value, err := proto.UnmarshalJSONEnum(FOO_value, data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*x = FOO(value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Test struct {
|
|
||||||
Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
|
|
||||||
Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
|
|
||||||
Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
|
|
||||||
Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
|
|
||||||
// Types that are valid to be assigned to Union:
|
|
||||||
// *Test_Number
|
|
||||||
// *Test_Name
|
|
||||||
Union isTest_Union `protobuf_oneof:"union"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
}
|
|
||||||
func (m *Test) Reset() { *m = Test{} }
|
|
||||||
func (m *Test) String() string { return proto.CompactTextString(m) }
|
|
||||||
func (*Test) ProtoMessage() {}
|
|
||||||
|
|
||||||
type isTest_Union interface {
|
|
||||||
isTest_Union()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Test_Number struct {
|
|
||||||
Number int32 `protobuf:"varint,6,opt,name=number"`
|
|
||||||
}
|
|
||||||
type Test_Name struct {
|
|
||||||
Name string `protobuf:"bytes,7,opt,name=name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Test_Number) isTest_Union() {}
|
|
||||||
func (*Test_Name) isTest_Union() {}
|
|
||||||
|
|
||||||
func (m *Test) GetUnion() isTest_Union {
|
|
||||||
if m != nil {
|
|
||||||
return m.Union
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
const Default_Test_Type int32 = 77
|
|
||||||
|
|
||||||
func (m *Test) GetLabel() string {
|
|
||||||
if m != nil && m.Label != nil {
|
|
||||||
return *m.Label
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Test) GetType() int32 {
|
|
||||||
if m != nil && m.Type != nil {
|
|
||||||
return *m.Type
|
|
||||||
}
|
|
||||||
return Default_Test_Type
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
|
|
||||||
if m != nil {
|
|
||||||
return m.Optionalgroup
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Test_OptionalGroup struct {
|
|
||||||
RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
|
|
||||||
}
|
|
||||||
func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
|
|
||||||
func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
|
|
||||||
|
|
||||||
func (m *Test_OptionalGroup) GetRequiredField() string {
|
|
||||||
if m != nil && m.RequiredField != nil {
|
|
||||||
return *m.RequiredField
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Test) GetNumber() int32 {
|
|
||||||
if x, ok := m.GetUnion().(*Test_Number); ok {
|
|
||||||
return x.Number
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Test) GetName() string {
|
|
||||||
if x, ok := m.GetUnion().(*Test_Name); ok {
|
|
||||||
return x.Name
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
|
|
||||||
}
|
|
||||||
|
|
||||||
To create and play with a Test object:
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
pb "./example.pb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
test := &pb.Test{
|
|
||||||
Label: proto.String("hello"),
|
|
||||||
Type: proto.Int32(17),
|
|
||||||
Reps: []int64{1, 2, 3},
|
|
||||||
Optionalgroup: &pb.Test_OptionalGroup{
|
|
||||||
RequiredField: proto.String("good bye"),
|
|
||||||
},
|
|
||||||
Union: &pb.Test_Name{"fred"},
|
|
||||||
}
|
|
||||||
data, err := proto.Marshal(test)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("marshaling error: ", err)
|
|
||||||
}
|
|
||||||
newTest := &pb.Test{}
|
|
||||||
err = proto.Unmarshal(data, newTest)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("unmarshaling error: ", err)
|
|
||||||
}
|
|
||||||
// Now test and newTest contain the same data.
|
|
||||||
if test.GetLabel() != newTest.GetLabel() {
|
|
||||||
log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
|
|
||||||
}
|
|
||||||
// Use a type switch to determine which oneof was set.
|
|
||||||
switch u := test.Union.(type) {
|
|
||||||
case *pb.Test_Number: // u.Number contains the number.
|
|
||||||
case *pb.Test_Name: // u.Name contains the string.
|
|
||||||
}
|
|
||||||
// etc.
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
|
|
||||||
// Marshal reports this when a required field is not initialized.
|
|
||||||
// Unmarshal reports this when a required field is missing from the wire data.
|
|
||||||
type RequiredNotSetError struct{ field string }
|
|
||||||
|
|
||||||
func (e *RequiredNotSetError) Error() string {
|
|
||||||
if e.field == "" {
|
|
||||||
return fmt.Sprintf("proto: required field not set")
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("proto: required field %q not set", e.field)
|
|
||||||
}
|
|
||||||
func (e *RequiredNotSetError) RequiredNotSet() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
type invalidUTF8Error struct{ field string }
|
|
||||||
|
|
||||||
func (e *invalidUTF8Error) Error() string {
|
|
||||||
if e.field == "" {
|
|
||||||
return "proto: invalid UTF-8 detected"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
|
|
||||||
}
|
|
||||||
func (e *invalidUTF8Error) InvalidUTF8() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
|
|
||||||
// This error should not be exposed to the external API as such errors should
|
|
||||||
// be recreated with the field information.
|
|
||||||
var errInvalidUTF8 = &invalidUTF8Error{}
|
|
||||||
|
|
||||||
// isNonFatal reports whether the error is either a RequiredNotSet error
|
|
||||||
// or a InvalidUTF8 error.
|
|
||||||
func isNonFatal(err error) bool {
|
|
||||||
if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type nonFatal struct{ E error }
|
|
||||||
|
|
||||||
// Merge merges err into nf and reports whether it was successful.
|
|
||||||
// Otherwise it returns false for any fatal non-nil errors.
|
|
||||||
func (nf *nonFatal) Merge(err error) (ok bool) {
|
|
||||||
if err == nil {
|
|
||||||
return true // not an error
|
|
||||||
}
|
|
||||||
if !isNonFatal(err) {
|
|
||||||
return false // fatal error
|
|
||||||
}
|
|
||||||
if nf.E == nil {
|
|
||||||
nf.E = err // store first instance of non-fatal error
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Message is implemented by generated protocol buffer messages.
|
|
||||||
type Message interface {
|
|
||||||
Reset()
|
|
||||||
String() string
|
|
||||||
ProtoMessage()
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Buffer is a buffer manager for marshaling and unmarshaling
|
|
||||||
// protocol buffers. It may be reused between invocations to
|
|
||||||
// reduce memory usage. It is not necessary to use a Buffer;
|
|
||||||
// the global functions Marshal and Unmarshal create a
|
|
||||||
// temporary Buffer and are fine for most applications.
|
|
||||||
type Buffer struct {
|
|
||||||
buf []byte // encode/decode byte stream
|
|
||||||
index int // read point
|
|
||||||
|
|
||||||
deterministic bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBuffer allocates a new Buffer and initializes its internal data to
|
|
||||||
// the contents of the argument slice.
|
|
||||||
func NewBuffer(e []byte) *Buffer {
|
|
||||||
return &Buffer{buf: e}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset resets the Buffer, ready for marshaling a new protocol buffer.
|
|
||||||
func (p *Buffer) Reset() {
|
|
||||||
p.buf = p.buf[0:0] // for reading/writing
|
|
||||||
p.index = 0 // for reading
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetBuf replaces the internal buffer with the slice,
|
|
||||||
// ready for unmarshaling the contents of the slice.
|
|
||||||
func (p *Buffer) SetBuf(s []byte) {
|
|
||||||
p.buf = s
|
|
||||||
p.index = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytes returns the contents of the Buffer.
|
|
||||||
func (p *Buffer) Bytes() []byte { return p.buf }
|
|
||||||
|
|
||||||
// SetDeterministic sets whether to use deterministic serialization.
|
|
||||||
//
|
|
||||||
// Deterministic serialization guarantees that for a given binary, equal
|
|
||||||
// messages will always be serialized to the same bytes. This implies:
|
|
||||||
//
|
|
||||||
// - Repeated serialization of a message will return the same bytes.
|
|
||||||
// - Different processes of the same binary (which may be executing on
|
|
||||||
// different machines) will serialize equal messages to the same bytes.
|
|
||||||
//
|
|
||||||
// Note that the deterministic serialization is NOT canonical across
|
|
||||||
// languages. It is not guaranteed to remain stable over time. It is unstable
|
|
||||||
// across different builds with schema changes due to unknown fields.
|
|
||||||
// Users who need canonical serialization (e.g., persistent storage in a
|
|
||||||
// canonical form, fingerprinting, etc.) should define their own
|
|
||||||
// canonicalization specification and implement their own serializer rather
|
|
||||||
// than relying on this API.
|
|
||||||
//
|
|
||||||
// If deterministic serialization is requested, map entries will be sorted
|
|
||||||
// by keys in lexicographical order. This is an implementation detail and
|
|
||||||
// subject to change.
|
|
||||||
func (p *Buffer) SetDeterministic(deterministic bool) {
|
|
||||||
p.deterministic = deterministic
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper routines for simplifying the creation of optional fields of basic type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Bool is a helper routine that allocates a new bool value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Bool(v bool) *bool {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int32 is a helper routine that allocates a new int32 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Int32(v int32) *int32 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int is a helper routine that allocates a new int32 value
|
|
||||||
// to store v and returns a pointer to it, but unlike Int32
|
|
||||||
// its argument value is an int.
|
|
||||||
func Int(v int) *int32 {
|
|
||||||
p := new(int32)
|
|
||||||
*p = int32(v)
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64 is a helper routine that allocates a new int64 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Int64(v int64) *int64 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float32 is a helper routine that allocates a new float32 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Float32(v float32) *float32 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64 is a helper routine that allocates a new float64 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Float64(v float64) *float64 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint32 is a helper routine that allocates a new uint32 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Uint32(v uint32) *uint32 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64 is a helper routine that allocates a new uint64 value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func Uint64(v uint64) *uint64 {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// String is a helper routine that allocates a new string value
|
|
||||||
// to store v and returns a pointer to it.
|
|
||||||
func String(v string) *string {
|
|
||||||
return &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnumName is a helper function to simplify printing protocol buffer enums
|
|
||||||
// by name. Given an enum map and a value, it returns a useful string.
|
|
||||||
func EnumName(m map[int32]string, v int32) string {
|
|
||||||
s, ok := m[v]
|
|
||||||
if ok {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return strconv.Itoa(int(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSONEnum is a helper function to simplify recovering enum int values
|
|
||||||
// from their JSON-encoded representation. Given a map from the enum's symbolic
|
|
||||||
// names to its int values, and a byte buffer containing the JSON-encoded
|
|
||||||
// value, it returns an int32 that can be cast to the enum type by the caller.
|
|
||||||
//
|
|
||||||
// The function can deal with both JSON representations, numeric and symbolic.
|
|
||||||
func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
|
|
||||||
if data[0] == '"' {
|
|
||||||
// New style: enums are strings.
|
|
||||||
var repr string
|
|
||||||
if err := json.Unmarshal(data, &repr); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
val, ok := m[repr]
|
|
||||||
if !ok {
|
|
||||||
return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
|
|
||||||
}
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
// Old style: enums are ints.
|
|
||||||
var val int32
|
|
||||||
if err := json.Unmarshal(data, &val); err != nil {
|
|
||||||
return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
|
|
||||||
}
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DebugPrint dumps the encoded data in b in a debugging format with a header
|
|
||||||
// including the string s. Used in testing but made available for general debugging.
|
|
||||||
func (p *Buffer) DebugPrint(s string, b []byte) {
|
|
||||||
var u uint64
|
|
||||||
|
|
||||||
obuf := p.buf
|
|
||||||
index := p.index
|
|
||||||
p.buf = b
|
|
||||||
p.index = 0
|
|
||||||
depth := 0
|
|
||||||
|
|
||||||
fmt.Printf("\n--- %s ---\n", s)
|
|
||||||
|
|
||||||
out:
|
|
||||||
for {
|
|
||||||
for i := 0; i < depth; i++ {
|
|
||||||
fmt.Print(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
index := p.index
|
|
||||||
if index == len(p.buf) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
op, err := p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%3d: fetching op err %v\n", index, err)
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
tag := op >> 3
|
|
||||||
wire := op & 7
|
|
||||||
|
|
||||||
switch wire {
|
|
||||||
default:
|
|
||||||
fmt.Printf("%3d: t=%3d unknown wire=%d\n",
|
|
||||||
index, tag, wire)
|
|
||||||
break out
|
|
||||||
|
|
||||||
case WireBytes:
|
|
||||||
var r []byte
|
|
||||||
|
|
||||||
r, err = p.DecodeRawBytes(false)
|
|
||||||
if err != nil {
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
|
|
||||||
if len(r) <= 6 {
|
|
||||||
for i := 0; i < len(r); i++ {
|
|
||||||
fmt.Printf(" %.2x", r[i])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
fmt.Printf(" %.2x", r[i])
|
|
||||||
}
|
|
||||||
fmt.Printf(" ..")
|
|
||||||
for i := len(r) - 3; i < len(r); i++ {
|
|
||||||
fmt.Printf(" %.2x", r[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Printf("\n")
|
|
||||||
|
|
||||||
case WireFixed32:
|
|
||||||
u, err = p.DecodeFixed32()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
|
|
||||||
|
|
||||||
case WireFixed64:
|
|
||||||
u, err = p.DecodeFixed64()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
|
|
||||||
|
|
||||||
case WireVarint:
|
|
||||||
u, err = p.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
|
|
||||||
break out
|
|
||||||
}
|
|
||||||
fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
|
|
||||||
|
|
||||||
case WireStartGroup:
|
|
||||||
fmt.Printf("%3d: t=%3d start\n", index, tag)
|
|
||||||
depth++
|
|
||||||
|
|
||||||
case WireEndGroup:
|
|
||||||
depth--
|
|
||||||
fmt.Printf("%3d: t=%3d end\n", index, tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if depth != 0 {
|
|
||||||
fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
|
|
||||||
}
|
|
||||||
fmt.Printf("\n")
|
|
||||||
|
|
||||||
p.buf = obuf
|
|
||||||
p.index = index
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetDefaults sets unset protocol buffer fields to their default values.
|
|
||||||
// It only modifies fields that are both unset and have defined defaults.
|
|
||||||
// It recursively sets default values in any non-nil sub-messages.
|
|
||||||
func SetDefaults(pb Message) {
|
|
||||||
setDefaults(reflect.ValueOf(pb), true, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// v is a pointer to a struct.
|
|
||||||
func setDefaults(v reflect.Value, recur, zeros bool) {
|
|
||||||
v = v.Elem()
|
|
||||||
|
|
||||||
defaultMu.RLock()
|
|
||||||
dm, ok := defaults[v.Type()]
|
|
||||||
defaultMu.RUnlock()
|
|
||||||
if !ok {
|
|
||||||
dm = buildDefaultMessage(v.Type())
|
|
||||||
defaultMu.Lock()
|
|
||||||
defaults[v.Type()] = dm
|
|
||||||
defaultMu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sf := range dm.scalars {
|
|
||||||
f := v.Field(sf.index)
|
|
||||||
if !f.IsNil() {
|
|
||||||
// field already set
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
dv := sf.value
|
|
||||||
if dv == nil && !zeros {
|
|
||||||
// no explicit default, and don't want to set zeros
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fptr := f.Addr().Interface() // **T
|
|
||||||
// TODO: Consider batching the allocations we do here.
|
|
||||||
switch sf.kind {
|
|
||||||
case reflect.Bool:
|
|
||||||
b := new(bool)
|
|
||||||
if dv != nil {
|
|
||||||
*b = dv.(bool)
|
|
||||||
}
|
|
||||||
*(fptr.(**bool)) = b
|
|
||||||
case reflect.Float32:
|
|
||||||
f := new(float32)
|
|
||||||
if dv != nil {
|
|
||||||
*f = dv.(float32)
|
|
||||||
}
|
|
||||||
*(fptr.(**float32)) = f
|
|
||||||
case reflect.Float64:
|
|
||||||
f := new(float64)
|
|
||||||
if dv != nil {
|
|
||||||
*f = dv.(float64)
|
|
||||||
}
|
|
||||||
*(fptr.(**float64)) = f
|
|
||||||
case reflect.Int32:
|
|
||||||
// might be an enum
|
|
||||||
if ft := f.Type(); ft != int32PtrType {
|
|
||||||
// enum
|
|
||||||
f.Set(reflect.New(ft.Elem()))
|
|
||||||
if dv != nil {
|
|
||||||
f.Elem().SetInt(int64(dv.(int32)))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// int32 field
|
|
||||||
i := new(int32)
|
|
||||||
if dv != nil {
|
|
||||||
*i = dv.(int32)
|
|
||||||
}
|
|
||||||
*(fptr.(**int32)) = i
|
|
||||||
}
|
|
||||||
case reflect.Int64:
|
|
||||||
i := new(int64)
|
|
||||||
if dv != nil {
|
|
||||||
*i = dv.(int64)
|
|
||||||
}
|
|
||||||
*(fptr.(**int64)) = i
|
|
||||||
case reflect.String:
|
|
||||||
s := new(string)
|
|
||||||
if dv != nil {
|
|
||||||
*s = dv.(string)
|
|
||||||
}
|
|
||||||
*(fptr.(**string)) = s
|
|
||||||
case reflect.Uint8:
|
|
||||||
// exceptional case: []byte
|
|
||||||
var b []byte
|
|
||||||
if dv != nil {
|
|
||||||
db := dv.([]byte)
|
|
||||||
b = make([]byte, len(db))
|
|
||||||
copy(b, db)
|
|
||||||
} else {
|
|
||||||
b = []byte{}
|
|
||||||
}
|
|
||||||
*(fptr.(*[]byte)) = b
|
|
||||||
case reflect.Uint32:
|
|
||||||
u := new(uint32)
|
|
||||||
if dv != nil {
|
|
||||||
*u = dv.(uint32)
|
|
||||||
}
|
|
||||||
*(fptr.(**uint32)) = u
|
|
||||||
case reflect.Uint64:
|
|
||||||
u := new(uint64)
|
|
||||||
if dv != nil {
|
|
||||||
*u = dv.(uint64)
|
|
||||||
}
|
|
||||||
*(fptr.(**uint64)) = u
|
|
||||||
default:
|
|
||||||
log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ni := range dm.nested {
|
|
||||||
f := v.Field(ni)
|
|
||||||
// f is *T or []*T or map[T]*T
|
|
||||||
switch f.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if f.IsNil() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
setDefaults(f, recur, zeros)
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
for i := 0; i < f.Len(); i++ {
|
|
||||||
e := f.Index(i)
|
|
||||||
if e.IsNil() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
setDefaults(e, recur, zeros)
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
for _, k := range f.MapKeys() {
|
|
||||||
e := f.MapIndex(k)
|
|
||||||
if e.IsNil() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
setDefaults(e, recur, zeros)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
// defaults maps a protocol buffer struct type to a slice of the fields,
|
|
||||||
// with its scalar fields set to their proto-declared non-zero default values.
|
|
||||||
defaultMu sync.RWMutex
|
|
||||||
defaults = make(map[reflect.Type]defaultMessage)
|
|
||||||
|
|
||||||
int32PtrType = reflect.TypeOf((*int32)(nil))
|
|
||||||
)
|
|
||||||
|
|
||||||
// defaultMessage represents information about the default values of a message.
|
|
||||||
type defaultMessage struct {
|
|
||||||
scalars []scalarField
|
|
||||||
nested []int // struct field index of nested messages
|
|
||||||
}
|
|
||||||
|
|
||||||
type scalarField struct {
|
|
||||||
index int // struct field index
|
|
||||||
kind reflect.Kind // element type (the T in *T or []T)
|
|
||||||
value interface{} // the proto-declared default value, or nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// t is a struct type.
|
|
||||||
func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
|
|
||||||
sprop := GetProperties(t)
|
|
||||||
for _, prop := range sprop.Prop {
|
|
||||||
fi, ok := sprop.decoderTags.get(prop.Tag)
|
|
||||||
if !ok {
|
|
||||||
// XXX_unrecognized
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ft := t.Field(fi).Type
|
|
||||||
|
|
||||||
sf, nested, err := fieldDefault(ft, prop)
|
|
||||||
switch {
|
|
||||||
case err != nil:
|
|
||||||
log.Print(err)
|
|
||||||
case nested:
|
|
||||||
dm.nested = append(dm.nested, fi)
|
|
||||||
case sf != nil:
|
|
||||||
sf.index = fi
|
|
||||||
dm.scalars = append(dm.scalars, *sf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dm
|
|
||||||
}
|
|
||||||
|
|
||||||
// fieldDefault returns the scalarField for field type ft.
|
|
||||||
// sf will be nil if the field can not have a default.
|
|
||||||
// nestedMessage will be true if this is a nested message.
|
|
||||||
// Note that sf.index is not set on return.
|
|
||||||
func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
|
|
||||||
var canHaveDefault bool
|
|
||||||
switch ft.Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
if ft.Elem().Kind() == reflect.Struct {
|
|
||||||
nestedMessage = true
|
|
||||||
} else {
|
|
||||||
canHaveDefault = true // proto2 scalar field
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
switch ft.Elem().Kind() {
|
|
||||||
case reflect.Ptr:
|
|
||||||
nestedMessage = true // repeated message
|
|
||||||
case reflect.Uint8:
|
|
||||||
canHaveDefault = true // bytes field
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
if ft.Elem().Kind() == reflect.Ptr {
|
|
||||||
nestedMessage = true // map with message values
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !canHaveDefault {
|
|
||||||
if nestedMessage {
|
|
||||||
return nil, true, nil
|
|
||||||
}
|
|
||||||
return nil, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// We now know that ft is a pointer or slice.
|
|
||||||
sf = &scalarField{kind: ft.Elem().Kind()}
|
|
||||||
|
|
||||||
// scalar fields without defaults
|
|
||||||
if !prop.HasDefault {
|
|
||||||
return sf, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// a scalar field: either *T or []byte
|
|
||||||
switch ft.Elem().Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
x, err := strconv.ParseBool(prop.Default)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = x
|
|
||||||
case reflect.Float32:
|
|
||||||
x, err := strconv.ParseFloat(prop.Default, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = float32(x)
|
|
||||||
case reflect.Float64:
|
|
||||||
x, err := strconv.ParseFloat(prop.Default, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = x
|
|
||||||
case reflect.Int32:
|
|
||||||
x, err := strconv.ParseInt(prop.Default, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = int32(x)
|
|
||||||
case reflect.Int64:
|
|
||||||
x, err := strconv.ParseInt(prop.Default, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = x
|
|
||||||
case reflect.String:
|
|
||||||
sf.value = prop.Default
|
|
||||||
case reflect.Uint8:
|
|
||||||
// []byte (not *uint8)
|
|
||||||
sf.value = []byte(prop.Default)
|
|
||||||
case reflect.Uint32:
|
|
||||||
x, err := strconv.ParseUint(prop.Default, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = uint32(x)
|
|
||||||
case reflect.Uint64:
|
|
||||||
x, err := strconv.ParseUint(prop.Default, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
|
|
||||||
}
|
|
||||||
sf.value = x
|
|
||||||
default:
|
|
||||||
return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
|
|
||||||
}
|
|
||||||
|
|
||||||
return sf, false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// mapKeys returns a sort.Interface to be used for sorting the map keys.
|
|
||||||
// Map fields may have key types of non-float scalars, strings and enums.
|
|
||||||
func mapKeys(vs []reflect.Value) sort.Interface {
|
|
||||||
s := mapKeySorter{vs: vs}
|
|
||||||
|
|
||||||
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
|
|
||||||
if len(vs) == 0 {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
switch vs[0].Kind() {
|
|
||||||
case reflect.Int32, reflect.Int64:
|
|
||||||
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
|
|
||||||
case reflect.Uint32, reflect.Uint64:
|
|
||||||
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
|
|
||||||
case reflect.Bool:
|
|
||||||
s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
|
|
||||||
case reflect.String:
|
|
||||||
s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
type mapKeySorter struct {
|
|
||||||
vs []reflect.Value
|
|
||||||
less func(a, b reflect.Value) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s mapKeySorter) Len() int { return len(s.vs) }
|
|
||||||
func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
|
|
||||||
func (s mapKeySorter) Less(i, j int) bool {
|
|
||||||
return s.less(s.vs[i], s.vs[j])
|
|
||||||
}
|
|
||||||
|
|
||||||
// isProto3Zero reports whether v is a zero proto3 value.
|
|
||||||
func isProto3Zero(v reflect.Value) bool {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return !v.Bool()
|
|
||||||
case reflect.Int32, reflect.Int64:
|
|
||||||
return v.Int() == 0
|
|
||||||
case reflect.Uint32, reflect.Uint64:
|
|
||||||
return v.Uint() == 0
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return v.Float() == 0
|
|
||||||
case reflect.String:
|
|
||||||
return v.String() == ""
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
|
|
||||||
// to assert that that code is compatible with this version of the proto package.
|
|
||||||
ProtoPackageIsVersion3 = true
|
|
||||||
|
|
||||||
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
|
|
||||||
// to assert that that code is compatible with this version of the proto package.
|
|
||||||
ProtoPackageIsVersion2 = true
|
|
||||||
|
|
||||||
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
|
||||||
// to assert that that code is compatible with this version of the proto package.
|
|
||||||
ProtoPackageIsVersion1 = true
|
|
||||||
)
|
|
||||||
|
|
||||||
// InternalMessageInfo is a type used internally by generated .pb.go files.
|
|
||||||
// This type is not intended to be used by non-generated code.
|
|
||||||
// This type is not subject to any compatibility guarantee.
|
|
||||||
type InternalMessageInfo struct {
|
|
||||||
marshal *marshalInfo
|
|
||||||
unmarshal *unmarshalInfo
|
|
||||||
merge *mergeInfo
|
|
||||||
discard *discardInfo
|
|
||||||
}
|
|
181
vendor/github.com/golang/protobuf/proto/message_set.go
generated
vendored
181
vendor/github.com/golang/protobuf/proto/message_set.go
generated
vendored
@ -1,181 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Support for message sets.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
|
|
||||||
// A message type ID is required for storing a protocol buffer in a message set.
|
|
||||||
var errNoMessageTypeID = errors.New("proto does not have a message type ID")
|
|
||||||
|
|
||||||
// The first two types (_MessageSet_Item and messageSet)
|
|
||||||
// model what the protocol compiler produces for the following protocol message:
|
|
||||||
// message MessageSet {
|
|
||||||
// repeated group Item = 1 {
|
|
||||||
// required int32 type_id = 2;
|
|
||||||
// required string message = 3;
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// That is the MessageSet wire format. We can't use a proto to generate these
|
|
||||||
// because that would introduce a circular dependency between it and this package.
|
|
||||||
|
|
||||||
type _MessageSet_Item struct {
|
|
||||||
TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
|
|
||||||
Message []byte `protobuf:"bytes,3,req,name=message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type messageSet struct {
|
|
||||||
Item []*_MessageSet_Item `protobuf:"group,1,rep"`
|
|
||||||
XXX_unrecognized []byte
|
|
||||||
// TODO: caching?
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure messageSet is a Message.
|
|
||||||
var _ Message = (*messageSet)(nil)
|
|
||||||
|
|
||||||
// messageTypeIder is an interface satisfied by a protocol buffer type
|
|
||||||
// that may be stored in a MessageSet.
|
|
||||||
type messageTypeIder interface {
|
|
||||||
MessageTypeId() int32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) find(pb Message) *_MessageSet_Item {
|
|
||||||
mti, ok := pb.(messageTypeIder)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
id := mti.MessageTypeId()
|
|
||||||
for _, item := range ms.Item {
|
|
||||||
if *item.TypeId == id {
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) Has(pb Message) bool {
|
|
||||||
return ms.find(pb) != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) Unmarshal(pb Message) error {
|
|
||||||
if item := ms.find(pb); item != nil {
|
|
||||||
return Unmarshal(item.Message, pb)
|
|
||||||
}
|
|
||||||
if _, ok := pb.(messageTypeIder); !ok {
|
|
||||||
return errNoMessageTypeID
|
|
||||||
}
|
|
||||||
return nil // TODO: return error instead?
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) Marshal(pb Message) error {
|
|
||||||
msg, err := Marshal(pb)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if item := ms.find(pb); item != nil {
|
|
||||||
// reuse existing item
|
|
||||||
item.Message = msg
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mti, ok := pb.(messageTypeIder)
|
|
||||||
if !ok {
|
|
||||||
return errNoMessageTypeID
|
|
||||||
}
|
|
||||||
|
|
||||||
mtid := mti.MessageTypeId()
|
|
||||||
ms.Item = append(ms.Item, &_MessageSet_Item{
|
|
||||||
TypeId: &mtid,
|
|
||||||
Message: msg,
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ms *messageSet) Reset() { *ms = messageSet{} }
|
|
||||||
func (ms *messageSet) String() string { return CompactTextString(ms) }
|
|
||||||
func (*messageSet) ProtoMessage() {}
|
|
||||||
|
|
||||||
// Support for the message_set_wire_format message option.
|
|
||||||
|
|
||||||
func skipVarint(buf []byte) []byte {
|
|
||||||
i := 0
|
|
||||||
for ; buf[i]&0x80 != 0; i++ {
|
|
||||||
}
|
|
||||||
return buf[i+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
|
|
||||||
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
|
|
||||||
func unmarshalMessageSet(buf []byte, exts interface{}) error {
|
|
||||||
var m map[int32]Extension
|
|
||||||
switch exts := exts.(type) {
|
|
||||||
case *XXX_InternalExtensions:
|
|
||||||
m = exts.extensionsWrite()
|
|
||||||
case map[int32]Extension:
|
|
||||||
m = exts
|
|
||||||
default:
|
|
||||||
return errors.New("proto: not an extension map")
|
|
||||||
}
|
|
||||||
|
|
||||||
ms := new(messageSet)
|
|
||||||
if err := Unmarshal(buf, ms); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, item := range ms.Item {
|
|
||||||
id := *item.TypeId
|
|
||||||
msg := item.Message
|
|
||||||
|
|
||||||
// Restore wire type and field number varint, plus length varint.
|
|
||||||
// Be careful to preserve duplicate items.
|
|
||||||
b := EncodeVarint(uint64(id)<<3 | WireBytes)
|
|
||||||
if ext, ok := m[id]; ok {
|
|
||||||
// Existing data; rip off the tag and length varint
|
|
||||||
// so we join the new data correctly.
|
|
||||||
// We can assume that ext.enc is set because we are unmarshaling.
|
|
||||||
o := ext.enc[len(b):] // skip wire type and field number
|
|
||||||
_, n := DecodeVarint(o) // calculate length of length varint
|
|
||||||
o = o[n:] // skip length varint
|
|
||||||
msg = append(o, msg...) // join old data and new data
|
|
||||||
}
|
|
||||||
b = append(b, EncodeVarint(uint64(len(msg)))...)
|
|
||||||
b = append(b, msg...)
|
|
||||||
|
|
||||||
m[id] = Extension{enc: b}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
360
vendor/github.com/golang/protobuf/proto/pointer_reflect.go
generated
vendored
360
vendor/github.com/golang/protobuf/proto/pointer_reflect.go
generated
vendored
@ -1,360 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// +build purego appengine js
|
|
||||||
|
|
||||||
// This file contains an implementation of proto field accesses using package reflect.
|
|
||||||
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
|
|
||||||
// be used on App Engine.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const unsafeAllowed = false
|
|
||||||
|
|
||||||
// A field identifies a field in a struct, accessible from a pointer.
|
|
||||||
// In this implementation, a field is identified by the sequence of field indices
|
|
||||||
// passed to reflect's FieldByIndex.
|
|
||||||
type field []int
|
|
||||||
|
|
||||||
// toField returns a field equivalent to the given reflect field.
|
|
||||||
func toField(f *reflect.StructField) field {
|
|
||||||
return f.Index
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalidField is an invalid field identifier.
|
|
||||||
var invalidField = field(nil)
|
|
||||||
|
|
||||||
// zeroField is a noop when calling pointer.offset.
|
|
||||||
var zeroField = field([]int{})
|
|
||||||
|
|
||||||
// IsValid reports whether the field identifier is valid.
|
|
||||||
func (f field) IsValid() bool { return f != nil }
|
|
||||||
|
|
||||||
// The pointer type is for the table-driven decoder.
|
|
||||||
// The implementation here uses a reflect.Value of pointer type to
|
|
||||||
// create a generic pointer. In pointer_unsafe.go we use unsafe
|
|
||||||
// instead of reflect to implement the same (but faster) interface.
|
|
||||||
type pointer struct {
|
|
||||||
v reflect.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
// toPointer converts an interface of pointer type to a pointer
|
|
||||||
// that points to the same target.
|
|
||||||
func toPointer(i *Message) pointer {
|
|
||||||
return pointer{v: reflect.ValueOf(*i)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// toAddrPointer converts an interface to a pointer that points to
|
|
||||||
// the interface data.
|
|
||||||
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
|
|
||||||
v := reflect.ValueOf(*i)
|
|
||||||
u := reflect.New(v.Type())
|
|
||||||
u.Elem().Set(v)
|
|
||||||
if deref {
|
|
||||||
u = u.Elem()
|
|
||||||
}
|
|
||||||
return pointer{v: u}
|
|
||||||
}
|
|
||||||
|
|
||||||
// valToPointer converts v to a pointer. v must be of pointer type.
|
|
||||||
func valToPointer(v reflect.Value) pointer {
|
|
||||||
return pointer{v: v}
|
|
||||||
}
|
|
||||||
|
|
||||||
// offset converts from a pointer to a structure to a pointer to
|
|
||||||
// one of its fields.
|
|
||||||
func (p pointer) offset(f field) pointer {
|
|
||||||
return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) isNil() bool {
|
|
||||||
return p.v.IsNil()
|
|
||||||
}
|
|
||||||
|
|
||||||
// grow updates the slice s in place to make it one element longer.
|
|
||||||
// s must be addressable.
|
|
||||||
// Returns the (addressable) new element.
|
|
||||||
func grow(s reflect.Value) reflect.Value {
|
|
||||||
n, m := s.Len(), s.Cap()
|
|
||||||
if n < m {
|
|
||||||
s.SetLen(n + 1)
|
|
||||||
} else {
|
|
||||||
s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
|
|
||||||
}
|
|
||||||
return s.Index(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) toInt64() *int64 {
|
|
||||||
return p.v.Interface().(*int64)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt64Ptr() **int64 {
|
|
||||||
return p.v.Interface().(**int64)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt64Slice() *[]int64 {
|
|
||||||
return p.v.Interface().(*[]int64)
|
|
||||||
}
|
|
||||||
|
|
||||||
var int32ptr = reflect.TypeOf((*int32)(nil))
|
|
||||||
|
|
||||||
func (p pointer) toInt32() *int32 {
|
|
||||||
return p.v.Convert(int32ptr).Interface().(*int32)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The toInt32Ptr/Slice methods don't work because of enums.
|
|
||||||
// Instead, we must use set/get methods for the int32ptr/slice case.
|
|
||||||
/*
|
|
||||||
func (p pointer) toInt32Ptr() **int32 {
|
|
||||||
return p.v.Interface().(**int32)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt32Slice() *[]int32 {
|
|
||||||
return p.v.Interface().(*[]int32)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (p pointer) getInt32Ptr() *int32 {
|
|
||||||
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
|
||||||
// raw int32 type
|
|
||||||
return p.v.Elem().Interface().(*int32)
|
|
||||||
}
|
|
||||||
// an enum
|
|
||||||
return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
|
|
||||||
}
|
|
||||||
func (p pointer) setInt32Ptr(v int32) {
|
|
||||||
// Allocate value in a *int32. Possibly convert that to a *enum.
|
|
||||||
// Then assign it to a **int32 or **enum.
|
|
||||||
// Note: we can convert *int32 to *enum, but we can't convert
|
|
||||||
// **int32 to **enum!
|
|
||||||
p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInt32Slice copies []int32 from p as a new slice.
|
|
||||||
// This behavior differs from the implementation in pointer_unsafe.go.
|
|
||||||
func (p pointer) getInt32Slice() []int32 {
|
|
||||||
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
|
||||||
// raw int32 type
|
|
||||||
return p.v.Elem().Interface().([]int32)
|
|
||||||
}
|
|
||||||
// an enum
|
|
||||||
// Allocate a []int32, then assign []enum's values into it.
|
|
||||||
// Note: we can't convert []enum to []int32.
|
|
||||||
slice := p.v.Elem()
|
|
||||||
s := make([]int32, slice.Len())
|
|
||||||
for i := 0; i < slice.Len(); i++ {
|
|
||||||
s[i] = int32(slice.Index(i).Int())
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// setInt32Slice copies []int32 into p as a new slice.
|
|
||||||
// This behavior differs from the implementation in pointer_unsafe.go.
|
|
||||||
func (p pointer) setInt32Slice(v []int32) {
|
|
||||||
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
|
|
||||||
// raw int32 type
|
|
||||||
p.v.Elem().Set(reflect.ValueOf(v))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// an enum
|
|
||||||
// Allocate a []enum, then assign []int32's values into it.
|
|
||||||
// Note: we can't convert []enum to []int32.
|
|
||||||
slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
|
|
||||||
for i, x := range v {
|
|
||||||
slice.Index(i).SetInt(int64(x))
|
|
||||||
}
|
|
||||||
p.v.Elem().Set(slice)
|
|
||||||
}
|
|
||||||
func (p pointer) appendInt32Slice(v int32) {
|
|
||||||
grow(p.v.Elem()).SetInt(int64(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) toUint64() *uint64 {
|
|
||||||
return p.v.Interface().(*uint64)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint64Ptr() **uint64 {
|
|
||||||
return p.v.Interface().(**uint64)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint64Slice() *[]uint64 {
|
|
||||||
return p.v.Interface().(*[]uint64)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32() *uint32 {
|
|
||||||
return p.v.Interface().(*uint32)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32Ptr() **uint32 {
|
|
||||||
return p.v.Interface().(**uint32)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32Slice() *[]uint32 {
|
|
||||||
return p.v.Interface().(*[]uint32)
|
|
||||||
}
|
|
||||||
func (p pointer) toBool() *bool {
|
|
||||||
return p.v.Interface().(*bool)
|
|
||||||
}
|
|
||||||
func (p pointer) toBoolPtr() **bool {
|
|
||||||
return p.v.Interface().(**bool)
|
|
||||||
}
|
|
||||||
func (p pointer) toBoolSlice() *[]bool {
|
|
||||||
return p.v.Interface().(*[]bool)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64() *float64 {
|
|
||||||
return p.v.Interface().(*float64)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64Ptr() **float64 {
|
|
||||||
return p.v.Interface().(**float64)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64Slice() *[]float64 {
|
|
||||||
return p.v.Interface().(*[]float64)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32() *float32 {
|
|
||||||
return p.v.Interface().(*float32)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32Ptr() **float32 {
|
|
||||||
return p.v.Interface().(**float32)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32Slice() *[]float32 {
|
|
||||||
return p.v.Interface().(*[]float32)
|
|
||||||
}
|
|
||||||
func (p pointer) toString() *string {
|
|
||||||
return p.v.Interface().(*string)
|
|
||||||
}
|
|
||||||
func (p pointer) toStringPtr() **string {
|
|
||||||
return p.v.Interface().(**string)
|
|
||||||
}
|
|
||||||
func (p pointer) toStringSlice() *[]string {
|
|
||||||
return p.v.Interface().(*[]string)
|
|
||||||
}
|
|
||||||
func (p pointer) toBytes() *[]byte {
|
|
||||||
return p.v.Interface().(*[]byte)
|
|
||||||
}
|
|
||||||
func (p pointer) toBytesSlice() *[][]byte {
|
|
||||||
return p.v.Interface().(*[][]byte)
|
|
||||||
}
|
|
||||||
func (p pointer) toExtensions() *XXX_InternalExtensions {
|
|
||||||
return p.v.Interface().(*XXX_InternalExtensions)
|
|
||||||
}
|
|
||||||
func (p pointer) toOldExtensions() *map[int32]Extension {
|
|
||||||
return p.v.Interface().(*map[int32]Extension)
|
|
||||||
}
|
|
||||||
func (p pointer) getPointer() pointer {
|
|
||||||
return pointer{v: p.v.Elem()}
|
|
||||||
}
|
|
||||||
func (p pointer) setPointer(q pointer) {
|
|
||||||
p.v.Elem().Set(q.v)
|
|
||||||
}
|
|
||||||
func (p pointer) appendPointer(q pointer) {
|
|
||||||
grow(p.v.Elem()).Set(q.v)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPointerSlice copies []*T from p as a new []pointer.
|
|
||||||
// This behavior differs from the implementation in pointer_unsafe.go.
|
|
||||||
func (p pointer) getPointerSlice() []pointer {
|
|
||||||
if p.v.IsNil() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
n := p.v.Elem().Len()
|
|
||||||
s := make([]pointer, n)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
s[i] = pointer{v: p.v.Elem().Index(i)}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// setPointerSlice copies []pointer into p as a new []*T.
|
|
||||||
// This behavior differs from the implementation in pointer_unsafe.go.
|
|
||||||
func (p pointer) setPointerSlice(v []pointer) {
|
|
||||||
if v == nil {
|
|
||||||
p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
|
|
||||||
for _, p := range v {
|
|
||||||
s = reflect.Append(s, p.v)
|
|
||||||
}
|
|
||||||
p.v.Elem().Set(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInterfacePointer returns a pointer that points to the
|
|
||||||
// interface data of the interface pointed by p.
|
|
||||||
func (p pointer) getInterfacePointer() pointer {
|
|
||||||
if p.v.Elem().IsNil() {
|
|
||||||
return pointer{v: p.v.Elem()}
|
|
||||||
}
|
|
||||||
return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
|
|
||||||
// TODO: check that p.v.Type().Elem() == t?
|
|
||||||
return p.v
|
|
||||||
}
|
|
||||||
|
|
||||||
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
return *p
|
|
||||||
}
|
|
||||||
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
*p = v
|
|
||||||
}
|
|
||||||
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
return *p
|
|
||||||
}
|
|
||||||
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
*p = v
|
|
||||||
}
|
|
||||||
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
return *p
|
|
||||||
}
|
|
||||||
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
*p = v
|
|
||||||
}
|
|
||||||
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
return *p
|
|
||||||
}
|
|
||||||
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
|
|
||||||
atomicLock.Lock()
|
|
||||||
defer atomicLock.Unlock()
|
|
||||||
*p = v
|
|
||||||
}
|
|
||||||
|
|
||||||
var atomicLock sync.Mutex
|
|
313
vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
generated
vendored
313
vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
generated
vendored
@ -1,313 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2012 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// +build !purego,!appengine,!js
|
|
||||||
|
|
||||||
// This file contains the implementation of the proto field accesses using package unsafe.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"sync/atomic"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
const unsafeAllowed = true
|
|
||||||
|
|
||||||
// A field identifies a field in a struct, accessible from a pointer.
|
|
||||||
// In this implementation, a field is identified by its byte offset from the start of the struct.
|
|
||||||
type field uintptr
|
|
||||||
|
|
||||||
// toField returns a field equivalent to the given reflect field.
|
|
||||||
func toField(f *reflect.StructField) field {
|
|
||||||
return field(f.Offset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalidField is an invalid field identifier.
|
|
||||||
const invalidField = ^field(0)
|
|
||||||
|
|
||||||
// zeroField is a noop when calling pointer.offset.
|
|
||||||
const zeroField = field(0)
|
|
||||||
|
|
||||||
// IsValid reports whether the field identifier is valid.
|
|
||||||
func (f field) IsValid() bool {
|
|
||||||
return f != invalidField
|
|
||||||
}
|
|
||||||
|
|
||||||
// The pointer type below is for the new table-driven encoder/decoder.
|
|
||||||
// The implementation here uses unsafe.Pointer to create a generic pointer.
|
|
||||||
// In pointer_reflect.go we use reflect instead of unsafe to implement
|
|
||||||
// the same (but slower) interface.
|
|
||||||
type pointer struct {
|
|
||||||
p unsafe.Pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
// size of pointer
|
|
||||||
var ptrSize = unsafe.Sizeof(uintptr(0))
|
|
||||||
|
|
||||||
// toPointer converts an interface of pointer type to a pointer
|
|
||||||
// that points to the same target.
|
|
||||||
func toPointer(i *Message) pointer {
|
|
||||||
// Super-tricky - read pointer out of data word of interface value.
|
|
||||||
// Saves ~25ns over the equivalent:
|
|
||||||
// return valToPointer(reflect.ValueOf(*i))
|
|
||||||
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
|
||||||
}
|
|
||||||
|
|
||||||
// toAddrPointer converts an interface to a pointer that points to
|
|
||||||
// the interface data.
|
|
||||||
func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
|
|
||||||
// Super-tricky - read or get the address of data word of interface value.
|
|
||||||
if isptr {
|
|
||||||
// The interface is of pointer type, thus it is a direct interface.
|
|
||||||
// The data word is the pointer data itself. We take its address.
|
|
||||||
p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
|
|
||||||
} else {
|
|
||||||
// The interface is not of pointer type. The data word is the pointer
|
|
||||||
// to the data.
|
|
||||||
p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
|
||||||
}
|
|
||||||
if deref {
|
|
||||||
p.p = *(*unsafe.Pointer)(p.p)
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// valToPointer converts v to a pointer. v must be of pointer type.
|
|
||||||
func valToPointer(v reflect.Value) pointer {
|
|
||||||
return pointer{p: unsafe.Pointer(v.Pointer())}
|
|
||||||
}
|
|
||||||
|
|
||||||
// offset converts from a pointer to a structure to a pointer to
|
|
||||||
// one of its fields.
|
|
||||||
func (p pointer) offset(f field) pointer {
|
|
||||||
// For safety, we should panic if !f.IsValid, however calling panic causes
|
|
||||||
// this to no longer be inlineable, which is a serious performance cost.
|
|
||||||
/*
|
|
||||||
if !f.IsValid() {
|
|
||||||
panic("invalid field")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) isNil() bool {
|
|
||||||
return p.p == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) toInt64() *int64 {
|
|
||||||
return (*int64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt64Ptr() **int64 {
|
|
||||||
return (**int64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt64Slice() *[]int64 {
|
|
||||||
return (*[]int64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt32() *int32 {
|
|
||||||
return (*int32)(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
|
|
||||||
/*
|
|
||||||
func (p pointer) toInt32Ptr() **int32 {
|
|
||||||
return (**int32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toInt32Slice() *[]int32 {
|
|
||||||
return (*[]int32)(p.p)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (p pointer) getInt32Ptr() *int32 {
|
|
||||||
return *(**int32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) setInt32Ptr(v int32) {
|
|
||||||
*(**int32)(p.p) = &v
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInt32Slice loads a []int32 from p.
|
|
||||||
// The value returned is aliased with the original slice.
|
|
||||||
// This behavior differs from the implementation in pointer_reflect.go.
|
|
||||||
func (p pointer) getInt32Slice() []int32 {
|
|
||||||
return *(*[]int32)(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setInt32Slice stores a []int32 to p.
|
|
||||||
// The value set is aliased with the input slice.
|
|
||||||
// This behavior differs from the implementation in pointer_reflect.go.
|
|
||||||
func (p pointer) setInt32Slice(v []int32) {
|
|
||||||
*(*[]int32)(p.p) = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
|
|
||||||
func (p pointer) appendInt32Slice(v int32) {
|
|
||||||
s := (*[]int32)(p.p)
|
|
||||||
*s = append(*s, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p pointer) toUint64() *uint64 {
|
|
||||||
return (*uint64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint64Ptr() **uint64 {
|
|
||||||
return (**uint64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint64Slice() *[]uint64 {
|
|
||||||
return (*[]uint64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32() *uint32 {
|
|
||||||
return (*uint32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32Ptr() **uint32 {
|
|
||||||
return (**uint32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toUint32Slice() *[]uint32 {
|
|
||||||
return (*[]uint32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBool() *bool {
|
|
||||||
return (*bool)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBoolPtr() **bool {
|
|
||||||
return (**bool)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBoolSlice() *[]bool {
|
|
||||||
return (*[]bool)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64() *float64 {
|
|
||||||
return (*float64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64Ptr() **float64 {
|
|
||||||
return (**float64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat64Slice() *[]float64 {
|
|
||||||
return (*[]float64)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32() *float32 {
|
|
||||||
return (*float32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32Ptr() **float32 {
|
|
||||||
return (**float32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toFloat32Slice() *[]float32 {
|
|
||||||
return (*[]float32)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toString() *string {
|
|
||||||
return (*string)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toStringPtr() **string {
|
|
||||||
return (**string)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toStringSlice() *[]string {
|
|
||||||
return (*[]string)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBytes() *[]byte {
|
|
||||||
return (*[]byte)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toBytesSlice() *[][]byte {
|
|
||||||
return (*[][]byte)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toExtensions() *XXX_InternalExtensions {
|
|
||||||
return (*XXX_InternalExtensions)(p.p)
|
|
||||||
}
|
|
||||||
func (p pointer) toOldExtensions() *map[int32]Extension {
|
|
||||||
return (*map[int32]Extension)(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPointerSlice loads []*T from p as a []pointer.
|
|
||||||
// The value returned is aliased with the original slice.
|
|
||||||
// This behavior differs from the implementation in pointer_reflect.go.
|
|
||||||
func (p pointer) getPointerSlice() []pointer {
|
|
||||||
// Super-tricky - p should point to a []*T where T is a
|
|
||||||
// message type. We load it as []pointer.
|
|
||||||
return *(*[]pointer)(p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// setPointerSlice stores []pointer into p as a []*T.
|
|
||||||
// The value set is aliased with the input slice.
|
|
||||||
// This behavior differs from the implementation in pointer_reflect.go.
|
|
||||||
func (p pointer) setPointerSlice(v []pointer) {
|
|
||||||
// Super-tricky - p should point to a []*T where T is a
|
|
||||||
// message type. We store it as []pointer.
|
|
||||||
*(*[]pointer)(p.p) = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPointer loads the pointer at p and returns it.
|
|
||||||
func (p pointer) getPointer() pointer {
|
|
||||||
return pointer{p: *(*unsafe.Pointer)(p.p)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// setPointer stores the pointer q at p.
|
|
||||||
func (p pointer) setPointer(q pointer) {
|
|
||||||
*(*unsafe.Pointer)(p.p) = q.p
|
|
||||||
}
|
|
||||||
|
|
||||||
// append q to the slice pointed to by p.
|
|
||||||
func (p pointer) appendPointer(q pointer) {
|
|
||||||
s := (*[]unsafe.Pointer)(p.p)
|
|
||||||
*s = append(*s, q.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getInterfacePointer returns a pointer that points to the
|
|
||||||
// interface data of the interface pointed by p.
|
|
||||||
func (p pointer) getInterfacePointer() pointer {
|
|
||||||
// Super-tricky - read pointer out of data word of interface value.
|
|
||||||
return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
|
|
||||||
}
|
|
||||||
|
|
||||||
// asPointerTo returns a reflect.Value that is a pointer to an
|
|
||||||
// object of type t stored at p.
|
|
||||||
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
|
|
||||||
return reflect.NewAt(t, p.p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
|
|
||||||
return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
|
||||||
}
|
|
||||||
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
|
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
|
||||||
}
|
|
||||||
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
|
|
||||||
return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
|
||||||
}
|
|
||||||
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
|
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
|
||||||
}
|
|
||||||
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
|
|
||||||
return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
|
||||||
}
|
|
||||||
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
|
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
|
||||||
}
|
|
||||||
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
|
|
||||||
return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
|
|
||||||
}
|
|
||||||
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
|
|
||||||
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
|
|
||||||
}
|
|
2776
vendor/github.com/golang/protobuf/proto/table_marshal.go
generated
vendored
2776
vendor/github.com/golang/protobuf/proto/table_marshal.go
generated
vendored
File diff suppressed because it is too large
Load Diff
654
vendor/github.com/golang/protobuf/proto/table_merge.go
generated
vendored
654
vendor/github.com/golang/protobuf/proto/table_merge.go
generated
vendored
@ -1,654 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Merge merges the src message into dst.
|
|
||||||
// This assumes that dst and src of the same type and are non-nil.
|
|
||||||
func (a *InternalMessageInfo) Merge(dst, src Message) {
|
|
||||||
mi := atomicLoadMergeInfo(&a.merge)
|
|
||||||
if mi == nil {
|
|
||||||
mi = getMergeInfo(reflect.TypeOf(dst).Elem())
|
|
||||||
atomicStoreMergeInfo(&a.merge, mi)
|
|
||||||
}
|
|
||||||
mi.merge(toPointer(&dst), toPointer(&src))
|
|
||||||
}
|
|
||||||
|
|
||||||
type mergeInfo struct {
|
|
||||||
typ reflect.Type
|
|
||||||
|
|
||||||
initialized int32 // 0: only typ is valid, 1: everything is valid
|
|
||||||
lock sync.Mutex
|
|
||||||
|
|
||||||
fields []mergeFieldInfo
|
|
||||||
unrecognized field // Offset of XXX_unrecognized
|
|
||||||
}
|
|
||||||
|
|
||||||
type mergeFieldInfo struct {
|
|
||||||
field field // Offset of field, guaranteed to be valid
|
|
||||||
|
|
||||||
// isPointer reports whether the value in the field is a pointer.
|
|
||||||
// This is true for the following situations:
|
|
||||||
// * Pointer to struct
|
|
||||||
// * Pointer to basic type (proto2 only)
|
|
||||||
// * Slice (first value in slice header is a pointer)
|
|
||||||
// * String (first value in string header is a pointer)
|
|
||||||
isPointer bool
|
|
||||||
|
|
||||||
// basicWidth reports the width of the field assuming that it is directly
|
|
||||||
// embedded in the struct (as is the case for basic types in proto3).
|
|
||||||
// The possible values are:
|
|
||||||
// 0: invalid
|
|
||||||
// 1: bool
|
|
||||||
// 4: int32, uint32, float32
|
|
||||||
// 8: int64, uint64, float64
|
|
||||||
basicWidth int
|
|
||||||
|
|
||||||
// Where dst and src are pointers to the types being merged.
|
|
||||||
merge func(dst, src pointer)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
mergeInfoMap = map[reflect.Type]*mergeInfo{}
|
|
||||||
mergeInfoLock sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func getMergeInfo(t reflect.Type) *mergeInfo {
|
|
||||||
mergeInfoLock.Lock()
|
|
||||||
defer mergeInfoLock.Unlock()
|
|
||||||
mi := mergeInfoMap[t]
|
|
||||||
if mi == nil {
|
|
||||||
mi = &mergeInfo{typ: t}
|
|
||||||
mergeInfoMap[t] = mi
|
|
||||||
}
|
|
||||||
return mi
|
|
||||||
}
|
|
||||||
|
|
||||||
// merge merges src into dst assuming they are both of type *mi.typ.
|
|
||||||
func (mi *mergeInfo) merge(dst, src pointer) {
|
|
||||||
if dst.isNil() {
|
|
||||||
panic("proto: nil destination")
|
|
||||||
}
|
|
||||||
if src.isNil() {
|
|
||||||
return // Nothing to do.
|
|
||||||
}
|
|
||||||
|
|
||||||
if atomic.LoadInt32(&mi.initialized) == 0 {
|
|
||||||
mi.computeMergeInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, fi := range mi.fields {
|
|
||||||
sfp := src.offset(fi.field)
|
|
||||||
|
|
||||||
// As an optimization, we can avoid the merge function call cost
|
|
||||||
// if we know for sure that the source will have no effect
|
|
||||||
// by checking if it is the zero value.
|
|
||||||
if unsafeAllowed {
|
|
||||||
if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fi.basicWidth > 0 {
|
|
||||||
switch {
|
|
||||||
case fi.basicWidth == 1 && !*sfp.toBool():
|
|
||||||
continue
|
|
||||||
case fi.basicWidth == 4 && *sfp.toUint32() == 0:
|
|
||||||
continue
|
|
||||||
case fi.basicWidth == 8 && *sfp.toUint64() == 0:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dfp := dst.offset(fi.field)
|
|
||||||
fi.merge(dfp, sfp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make this faster?
|
|
||||||
out := dst.asPointerTo(mi.typ).Elem()
|
|
||||||
in := src.asPointerTo(mi.typ).Elem()
|
|
||||||
if emIn, err := extendable(in.Addr().Interface()); err == nil {
|
|
||||||
emOut, _ := extendable(out.Addr().Interface())
|
|
||||||
mIn, muIn := emIn.extensionsRead()
|
|
||||||
if mIn != nil {
|
|
||||||
mOut := emOut.extensionsWrite()
|
|
||||||
muIn.Lock()
|
|
||||||
mergeExtension(mOut, mIn)
|
|
||||||
muIn.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if mi.unrecognized.IsValid() {
|
|
||||||
if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
|
|
||||||
*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mi *mergeInfo) computeMergeInfo() {
|
|
||||||
mi.lock.Lock()
|
|
||||||
defer mi.lock.Unlock()
|
|
||||||
if mi.initialized != 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := mi.typ
|
|
||||||
n := t.NumField()
|
|
||||||
|
|
||||||
props := GetProperties(t)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
f := t.Field(i)
|
|
||||||
if strings.HasPrefix(f.Name, "XXX_") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
mfi := mergeFieldInfo{field: toField(&f)}
|
|
||||||
tf := f.Type
|
|
||||||
|
|
||||||
// As an optimization, we can avoid the merge function call cost
|
|
||||||
// if we know for sure that the source will have no effect
|
|
||||||
// by checking if it is the zero value.
|
|
||||||
if unsafeAllowed {
|
|
||||||
switch tf.Kind() {
|
|
||||||
case reflect.Ptr, reflect.Slice, reflect.String:
|
|
||||||
// As a special case, we assume slices and strings are pointers
|
|
||||||
// since we know that the first field in the SliceSlice or
|
|
||||||
// StringHeader is a data pointer.
|
|
||||||
mfi.isPointer = true
|
|
||||||
case reflect.Bool:
|
|
||||||
mfi.basicWidth = 1
|
|
||||||
case reflect.Int32, reflect.Uint32, reflect.Float32:
|
|
||||||
mfi.basicWidth = 4
|
|
||||||
case reflect.Int64, reflect.Uint64, reflect.Float64:
|
|
||||||
mfi.basicWidth = 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap tf to get at its most basic type.
|
|
||||||
var isPointer, isSlice bool
|
|
||||||
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
|
|
||||||
isSlice = true
|
|
||||||
tf = tf.Elem()
|
|
||||||
}
|
|
||||||
if tf.Kind() == reflect.Ptr {
|
|
||||||
isPointer = true
|
|
||||||
tf = tf.Elem()
|
|
||||||
}
|
|
||||||
if isPointer && isSlice && tf.Kind() != reflect.Struct {
|
|
||||||
panic("both pointer and slice for basic type in " + tf.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tf.Kind() {
|
|
||||||
case reflect.Int32:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []int32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
|
|
||||||
/*
|
|
||||||
sfsp := src.toInt32Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toInt32Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []int64{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
sfs := src.getInt32Slice()
|
|
||||||
if sfs != nil {
|
|
||||||
dfs := dst.getInt32Slice()
|
|
||||||
dfs = append(dfs, sfs...)
|
|
||||||
if dfs == nil {
|
|
||||||
dfs = []int32{}
|
|
||||||
}
|
|
||||||
dst.setInt32Slice(dfs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *int32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
|
|
||||||
/*
|
|
||||||
sfpp := src.toInt32Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toInt32Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Int32(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
sfp := src.getInt32Ptr()
|
|
||||||
if sfp != nil {
|
|
||||||
dfp := dst.getInt32Ptr()
|
|
||||||
if dfp == nil {
|
|
||||||
dst.setInt32Ptr(*sfp)
|
|
||||||
} else {
|
|
||||||
*dfp = *sfp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., int32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toInt32(); v != 0 {
|
|
||||||
*dst.toInt32() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Int64:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []int64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toInt64Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toInt64Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []int64{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *int64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toInt64Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toInt64Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Int64(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., int64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toInt64(); v != 0 {
|
|
||||||
*dst.toInt64() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Uint32:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []uint32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toUint32Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toUint32Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []uint32{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *uint32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toUint32Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toUint32Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Uint32(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., uint32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toUint32(); v != 0 {
|
|
||||||
*dst.toUint32() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Uint64:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []uint64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toUint64Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toUint64Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []uint64{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *uint64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toUint64Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toUint64Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Uint64(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., uint64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toUint64(); v != 0 {
|
|
||||||
*dst.toUint64() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Float32:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []float32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toFloat32Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toFloat32Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []float32{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *float32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toFloat32Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toFloat32Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Float32(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., float32
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toFloat32(); v != 0 {
|
|
||||||
*dst.toFloat32() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Float64:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []float64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toFloat64Slice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toFloat64Slice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []float64{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *float64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toFloat64Ptr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toFloat64Ptr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Float64(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., float64
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toFloat64(); v != 0 {
|
|
||||||
*dst.toFloat64() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Bool:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []bool
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toBoolSlice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toBoolSlice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []bool{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *bool
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toBoolPtr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toBoolPtr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = Bool(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., bool
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toBool(); v {
|
|
||||||
*dst.toBool() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
switch {
|
|
||||||
case isSlice: // E.g., []string
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfsp := src.toStringSlice()
|
|
||||||
if *sfsp != nil {
|
|
||||||
dfsp := dst.toStringSlice()
|
|
||||||
*dfsp = append(*dfsp, *sfsp...)
|
|
||||||
if *dfsp == nil {
|
|
||||||
*dfsp = []string{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case isPointer: // E.g., *string
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sfpp := src.toStringPtr()
|
|
||||||
if *sfpp != nil {
|
|
||||||
dfpp := dst.toStringPtr()
|
|
||||||
if *dfpp == nil {
|
|
||||||
*dfpp = String(**sfpp)
|
|
||||||
} else {
|
|
||||||
**dfpp = **sfpp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., string
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
if v := *src.toString(); v != "" {
|
|
||||||
*dst.toString() = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Slice:
|
|
||||||
isProto3 := props.Prop[i].proto3
|
|
||||||
switch {
|
|
||||||
case isPointer:
|
|
||||||
panic("bad pointer in byte slice case in " + tf.Name())
|
|
||||||
case tf.Elem().Kind() != reflect.Uint8:
|
|
||||||
panic("bad element kind in byte slice case in " + tf.Name())
|
|
||||||
case isSlice: // E.g., [][]byte
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sbsp := src.toBytesSlice()
|
|
||||||
if *sbsp != nil {
|
|
||||||
dbsp := dst.toBytesSlice()
|
|
||||||
for _, sb := range *sbsp {
|
|
||||||
if sb == nil {
|
|
||||||
*dbsp = append(*dbsp, nil)
|
|
||||||
} else {
|
|
||||||
*dbsp = append(*dbsp, append([]byte{}, sb...))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if *dbsp == nil {
|
|
||||||
*dbsp = [][]byte{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., []byte
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sbp := src.toBytes()
|
|
||||||
if *sbp != nil {
|
|
||||||
dbp := dst.toBytes()
|
|
||||||
if !isProto3 || len(*sbp) > 0 {
|
|
||||||
*dbp = append([]byte{}, *sbp...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
switch {
|
|
||||||
case !isPointer:
|
|
||||||
panic(fmt.Sprintf("message field %s without pointer", tf))
|
|
||||||
case isSlice: // E.g., []*pb.T
|
|
||||||
mi := getMergeInfo(tf)
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sps := src.getPointerSlice()
|
|
||||||
if sps != nil {
|
|
||||||
dps := dst.getPointerSlice()
|
|
||||||
for _, sp := range sps {
|
|
||||||
var dp pointer
|
|
||||||
if !sp.isNil() {
|
|
||||||
dp = valToPointer(reflect.New(tf))
|
|
||||||
mi.merge(dp, sp)
|
|
||||||
}
|
|
||||||
dps = append(dps, dp)
|
|
||||||
}
|
|
||||||
if dps == nil {
|
|
||||||
dps = []pointer{}
|
|
||||||
}
|
|
||||||
dst.setPointerSlice(dps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // E.g., *pb.T
|
|
||||||
mi := getMergeInfo(tf)
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sp := src.getPointer()
|
|
||||||
if !sp.isNil() {
|
|
||||||
dp := dst.getPointer()
|
|
||||||
if dp.isNil() {
|
|
||||||
dp = valToPointer(reflect.New(tf))
|
|
||||||
dst.setPointer(dp)
|
|
||||||
}
|
|
||||||
mi.merge(dp, sp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Map:
|
|
||||||
switch {
|
|
||||||
case isPointer || isSlice:
|
|
||||||
panic("bad pointer or slice in map case in " + tf.Name())
|
|
||||||
default: // E.g., map[K]V
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
sm := src.asPointerTo(tf).Elem()
|
|
||||||
if sm.Len() == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dm := dst.asPointerTo(tf).Elem()
|
|
||||||
if dm.IsNil() {
|
|
||||||
dm.Set(reflect.MakeMap(tf))
|
|
||||||
}
|
|
||||||
|
|
||||||
switch tf.Elem().Kind() {
|
|
||||||
case reflect.Ptr: // Proto struct (e.g., *T)
|
|
||||||
for _, key := range sm.MapKeys() {
|
|
||||||
val := sm.MapIndex(key)
|
|
||||||
val = reflect.ValueOf(Clone(val.Interface().(Message)))
|
|
||||||
dm.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
|
|
||||||
for _, key := range sm.MapKeys() {
|
|
||||||
val := sm.MapIndex(key)
|
|
||||||
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
|
|
||||||
dm.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
default: // Basic type (e.g., string)
|
|
||||||
for _, key := range sm.MapKeys() {
|
|
||||||
val := sm.MapIndex(key)
|
|
||||||
dm.SetMapIndex(key, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case reflect.Interface:
|
|
||||||
// Must be oneof field.
|
|
||||||
switch {
|
|
||||||
case isPointer || isSlice:
|
|
||||||
panic("bad pointer or slice in interface case in " + tf.Name())
|
|
||||||
default: // E.g., interface{}
|
|
||||||
// TODO: Make this faster?
|
|
||||||
mfi.merge = func(dst, src pointer) {
|
|
||||||
su := src.asPointerTo(tf).Elem()
|
|
||||||
if !su.IsNil() {
|
|
||||||
du := dst.asPointerTo(tf).Elem()
|
|
||||||
typ := su.Elem().Type()
|
|
||||||
if du.IsNil() || du.Elem().Type() != typ {
|
|
||||||
du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
|
|
||||||
}
|
|
||||||
sv := su.Elem().Elem().Field(0)
|
|
||||||
if sv.Kind() == reflect.Ptr && sv.IsNil() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dv := du.Elem().Elem().Field(0)
|
|
||||||
if dv.Kind() == reflect.Ptr && dv.IsNil() {
|
|
||||||
dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
|
|
||||||
}
|
|
||||||
switch sv.Type().Kind() {
|
|
||||||
case reflect.Ptr: // Proto struct (e.g., *T)
|
|
||||||
Merge(dv.Interface().(Message), sv.Interface().(Message))
|
|
||||||
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
|
|
||||||
dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
|
|
||||||
default: // Basic type (e.g., string)
|
|
||||||
dv.Set(sv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("merger not found for type:%s", tf))
|
|
||||||
}
|
|
||||||
mi.fields = append(mi.fields, mfi)
|
|
||||||
}
|
|
||||||
|
|
||||||
mi.unrecognized = invalidField
|
|
||||||
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
|
|
||||||
if f.Type != reflect.TypeOf([]byte{}) {
|
|
||||||
panic("expected XXX_unrecognized to be of type []byte")
|
|
||||||
}
|
|
||||||
mi.unrecognized = toField(&f)
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.StoreInt32(&mi.initialized, 1)
|
|
||||||
}
|
|
2053
vendor/github.com/golang/protobuf/proto/table_unmarshal.go
generated
vendored
2053
vendor/github.com/golang/protobuf/proto/table_unmarshal.go
generated
vendored
File diff suppressed because it is too large
Load Diff
845
vendor/github.com/golang/protobuf/proto/text.go
generated
vendored
845
vendor/github.com/golang/protobuf/proto/text.go
generated
vendored
@ -1,845 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
// Functions for writing the text protocol buffer format.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
newline = []byte("\n")
|
|
||||||
spaces = []byte(" ")
|
|
||||||
endBraceNewline = []byte("}\n")
|
|
||||||
backslashN = []byte{'\\', 'n'}
|
|
||||||
backslashR = []byte{'\\', 'r'}
|
|
||||||
backslashT = []byte{'\\', 't'}
|
|
||||||
backslashDQ = []byte{'\\', '"'}
|
|
||||||
backslashBS = []byte{'\\', '\\'}
|
|
||||||
posInf = []byte("inf")
|
|
||||||
negInf = []byte("-inf")
|
|
||||||
nan = []byte("nan")
|
|
||||||
)
|
|
||||||
|
|
||||||
type writer interface {
|
|
||||||
io.Writer
|
|
||||||
WriteByte(byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// textWriter is an io.Writer that tracks its indentation level.
|
|
||||||
type textWriter struct {
|
|
||||||
ind int
|
|
||||||
complete bool // if the current position is a complete line
|
|
||||||
compact bool // whether to write out as a one-liner
|
|
||||||
w writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) WriteString(s string) (n int, err error) {
|
|
||||||
if !strings.Contains(s, "\n") {
|
|
||||||
if !w.compact && w.complete {
|
|
||||||
w.writeIndent()
|
|
||||||
}
|
|
||||||
w.complete = false
|
|
||||||
return io.WriteString(w.w, s)
|
|
||||||
}
|
|
||||||
// WriteString is typically called without newlines, so this
|
|
||||||
// codepath and its copy are rare. We copy to avoid
|
|
||||||
// duplicating all of Write's logic here.
|
|
||||||
return w.Write([]byte(s))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) Write(p []byte) (n int, err error) {
|
|
||||||
newlines := bytes.Count(p, newline)
|
|
||||||
if newlines == 0 {
|
|
||||||
if !w.compact && w.complete {
|
|
||||||
w.writeIndent()
|
|
||||||
}
|
|
||||||
n, err = w.w.Write(p)
|
|
||||||
w.complete = false
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
frags := bytes.SplitN(p, newline, newlines+1)
|
|
||||||
if w.compact {
|
|
||||||
for i, frag := range frags {
|
|
||||||
if i > 0 {
|
|
||||||
if err := w.w.WriteByte(' '); err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
nn, err := w.w.Write(frag)
|
|
||||||
n += nn
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, frag := range frags {
|
|
||||||
if w.complete {
|
|
||||||
w.writeIndent()
|
|
||||||
}
|
|
||||||
nn, err := w.w.Write(frag)
|
|
||||||
n += nn
|
|
||||||
if err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
if i+1 < len(frags) {
|
|
||||||
if err := w.w.WriteByte('\n'); err != nil {
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
n++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.complete = len(frags[len(frags)-1]) == 0
|
|
||||||
return n, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) WriteByte(c byte) error {
|
|
||||||
if w.compact && c == '\n' {
|
|
||||||
c = ' '
|
|
||||||
}
|
|
||||||
if !w.compact && w.complete {
|
|
||||||
w.writeIndent()
|
|
||||||
}
|
|
||||||
err := w.w.WriteByte(c)
|
|
||||||
w.complete = c == '\n'
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) indent() { w.ind++ }
|
|
||||||
|
|
||||||
func (w *textWriter) unindent() {
|
|
||||||
if w.ind == 0 {
|
|
||||||
log.Print("proto: textWriter unindented too far")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.ind--
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeName(w *textWriter, props *Properties) error {
|
|
||||||
if _, err := w.WriteString(props.OrigName); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if props.Wire != "group" {
|
|
||||||
return w.WriteByte(':')
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func requiresQuotes(u string) bool {
|
|
||||||
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
|
|
||||||
for _, ch := range u {
|
|
||||||
switch {
|
|
||||||
case ch == '.' || ch == '/' || ch == '_':
|
|
||||||
continue
|
|
||||||
case '0' <= ch && ch <= '9':
|
|
||||||
continue
|
|
||||||
case 'A' <= ch && ch <= 'Z':
|
|
||||||
continue
|
|
||||||
case 'a' <= ch && ch <= 'z':
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// isAny reports whether sv is a google.protobuf.Any message
|
|
||||||
func isAny(sv reflect.Value) bool {
|
|
||||||
type wkt interface {
|
|
||||||
XXX_WellKnownType() string
|
|
||||||
}
|
|
||||||
t, ok := sv.Addr().Interface().(wkt)
|
|
||||||
return ok && t.XXX_WellKnownType() == "Any"
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeProto3Any writes an expanded google.protobuf.Any message.
|
|
||||||
//
|
|
||||||
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
|
|
||||||
// required messages are not linked in).
|
|
||||||
//
|
|
||||||
// It returns (true, error) when sv was written in expanded format or an error
|
|
||||||
// was encountered.
|
|
||||||
func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
|
|
||||||
turl := sv.FieldByName("TypeUrl")
|
|
||||||
val := sv.FieldByName("Value")
|
|
||||||
if !turl.IsValid() || !val.IsValid() {
|
|
||||||
return true, errors.New("proto: invalid google.protobuf.Any message")
|
|
||||||
}
|
|
||||||
|
|
||||||
b, ok := val.Interface().([]byte)
|
|
||||||
if !ok {
|
|
||||||
return true, errors.New("proto: invalid google.protobuf.Any message")
|
|
||||||
}
|
|
||||||
|
|
||||||
parts := strings.Split(turl.String(), "/")
|
|
||||||
mt := MessageType(parts[len(parts)-1])
|
|
||||||
if mt == nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
m := reflect.New(mt.Elem())
|
|
||||||
if err := Unmarshal(b, m.Interface().(Message)); err != nil {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
w.Write([]byte("["))
|
|
||||||
u := turl.String()
|
|
||||||
if requiresQuotes(u) {
|
|
||||||
writeString(w, u)
|
|
||||||
} else {
|
|
||||||
w.Write([]byte(u))
|
|
||||||
}
|
|
||||||
if w.compact {
|
|
||||||
w.Write([]byte("]:<"))
|
|
||||||
} else {
|
|
||||||
w.Write([]byte("]: <\n"))
|
|
||||||
w.ind++
|
|
||||||
}
|
|
||||||
if err := tm.writeStruct(w, m.Elem()); err != nil {
|
|
||||||
return true, err
|
|
||||||
}
|
|
||||||
if w.compact {
|
|
||||||
w.Write([]byte("> "))
|
|
||||||
} else {
|
|
||||||
w.ind--
|
|
||||||
w.Write([]byte(">\n"))
|
|
||||||
}
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
|
|
||||||
if tm.ExpandAny && isAny(sv) {
|
|
||||||
if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st := sv.Type()
|
|
||||||
sprops := GetProperties(st)
|
|
||||||
for i := 0; i < sv.NumField(); i++ {
|
|
||||||
fv := sv.Field(i)
|
|
||||||
props := sprops.Prop[i]
|
|
||||||
name := st.Field(i).Name
|
|
||||||
|
|
||||||
if name == "XXX_NoUnkeyedLiteral" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(name, "XXX_") {
|
|
||||||
// There are two XXX_ fields:
|
|
||||||
// XXX_unrecognized []byte
|
|
||||||
// XXX_extensions map[int32]proto.Extension
|
|
||||||
// The first is handled here;
|
|
||||||
// the second is handled at the bottom of this function.
|
|
||||||
if name == "XXX_unrecognized" && !fv.IsNil() {
|
|
||||||
if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fv.Kind() == reflect.Ptr && fv.IsNil() {
|
|
||||||
// Field not filled in. This could be an optional field or
|
|
||||||
// a required field that wasn't filled in. Either way, there
|
|
||||||
// isn't anything we can show for it.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fv.Kind() == reflect.Slice && fv.IsNil() {
|
|
||||||
// Repeated field that is empty, or a bytes field that is unused.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if props.Repeated && fv.Kind() == reflect.Slice {
|
|
||||||
// Repeated field.
|
|
||||||
for j := 0; j < fv.Len(); j++ {
|
|
||||||
if err := writeName(w, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v := fv.Index(j)
|
|
||||||
if v.Kind() == reflect.Ptr && v.IsNil() {
|
|
||||||
// A nil message in a repeated field is not valid,
|
|
||||||
// but we can handle that more gracefully than panicking.
|
|
||||||
if _, err := w.Write([]byte("<nil>\n")); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := tm.writeAny(w, v, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fv.Kind() == reflect.Map {
|
|
||||||
// Map fields are rendered as a repeated struct with key/value fields.
|
|
||||||
keys := fv.MapKeys()
|
|
||||||
sort.Sort(mapKeys(keys))
|
|
||||||
for _, key := range keys {
|
|
||||||
val := fv.MapIndex(key)
|
|
||||||
if err := writeName(w, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// open struct
|
|
||||||
if err := w.WriteByte('<'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.indent()
|
|
||||||
// key
|
|
||||||
if _, err := w.WriteString("key:"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// nil values aren't legal, but we can avoid panicking because of them.
|
|
||||||
if val.Kind() != reflect.Ptr || !val.IsNil() {
|
|
||||||
// value
|
|
||||||
if _, err := w.WriteString("value:"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := tm.writeAny(w, val, props.MapValProp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// close struct
|
|
||||||
w.unindent()
|
|
||||||
if err := w.WriteByte('>'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
|
|
||||||
// empty bytes field
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
|
|
||||||
// proto3 non-repeated scalar field; skip if zero value
|
|
||||||
if isProto3Zero(fv) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if fv.Kind() == reflect.Interface {
|
|
||||||
// Check if it is a oneof.
|
|
||||||
if st.Field(i).Tag.Get("protobuf_oneof") != "" {
|
|
||||||
// fv is nil, or holds a pointer to generated struct.
|
|
||||||
// That generated struct has exactly one field,
|
|
||||||
// which has a protobuf struct tag.
|
|
||||||
if fv.IsNil() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
inner := fv.Elem().Elem() // interface -> *T -> T
|
|
||||||
tag := inner.Type().Field(0).Tag.Get("protobuf")
|
|
||||||
props = new(Properties) // Overwrite the outer props var, but not its pointee.
|
|
||||||
props.Parse(tag)
|
|
||||||
// Write the value in the oneof, not the oneof itself.
|
|
||||||
fv = inner.Field(0)
|
|
||||||
|
|
||||||
// Special case to cope with malformed messages gracefully:
|
|
||||||
// If the value in the oneof is a nil pointer, don't panic
|
|
||||||
// in writeAny.
|
|
||||||
if fv.Kind() == reflect.Ptr && fv.IsNil() {
|
|
||||||
// Use errors.New so writeAny won't render quotes.
|
|
||||||
msg := errors.New("/* nil */")
|
|
||||||
fv = reflect.ValueOf(&msg).Elem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := writeName(w, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enums have a String method, so writeAny will work fine.
|
|
||||||
if err := tm.writeAny(w, fv, props); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extensions (the XXX_extensions field).
|
|
||||||
pv := sv.Addr()
|
|
||||||
if _, err := extendable(pv.Interface()); err == nil {
|
|
||||||
if err := tm.writeExtensions(w, pv); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
|
||||||
|
|
||||||
// writeAny writes an arbitrary field.
|
|
||||||
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
|
|
||||||
v = reflect.Indirect(v)
|
|
||||||
|
|
||||||
// Floats have special cases.
|
|
||||||
if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
|
|
||||||
x := v.Float()
|
|
||||||
var b []byte
|
|
||||||
switch {
|
|
||||||
case math.IsInf(x, 1):
|
|
||||||
b = posInf
|
|
||||||
case math.IsInf(x, -1):
|
|
||||||
b = negInf
|
|
||||||
case math.IsNaN(x):
|
|
||||||
b = nan
|
|
||||||
}
|
|
||||||
if b != nil {
|
|
||||||
_, err := w.Write(b)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Other values are handled below.
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't attempt to serialise every possible value type; only those
|
|
||||||
// that can occur in protocol buffers.
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
// Should only be a []byte; repeated fields are handled in writeStruct.
|
|
||||||
if err := writeString(w, string(v.Bytes())); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case reflect.String:
|
|
||||||
if err := writeString(w, v.String()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
// Required/optional group/message.
|
|
||||||
var bra, ket byte = '<', '>'
|
|
||||||
if props != nil && props.Wire == "group" {
|
|
||||||
bra, ket = '{', '}'
|
|
||||||
}
|
|
||||||
if err := w.WriteByte(bra); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.indent()
|
|
||||||
if v.CanAddr() {
|
|
||||||
// Calling v.Interface on a struct causes the reflect package to
|
|
||||||
// copy the entire struct. This is racy with the new Marshaler
|
|
||||||
// since we atomically update the XXX_sizecache.
|
|
||||||
//
|
|
||||||
// Thus, we retrieve a pointer to the struct if possible to avoid
|
|
||||||
// a race since v.Interface on the pointer doesn't copy the struct.
|
|
||||||
//
|
|
||||||
// If v is not addressable, then we are not worried about a race
|
|
||||||
// since it implies that the binary Marshaler cannot possibly be
|
|
||||||
// mutating this value.
|
|
||||||
v = v.Addr()
|
|
||||||
}
|
|
||||||
if v.Type().Implements(textMarshalerType) {
|
|
||||||
text, err := v.Interface().(encoding.TextMarshaler).MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = w.Write(text); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if v.Kind() == reflect.Ptr {
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
if err := tm.writeStruct(w, v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.unindent()
|
|
||||||
if err := w.WriteByte(ket); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
_, err := fmt.Fprint(w, v.Interface())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// equivalent to C's isprint.
|
|
||||||
func isprint(c byte) bool {
|
|
||||||
return c >= 0x20 && c < 0x7f
|
|
||||||
}
|
|
||||||
|
|
||||||
// writeString writes a string in the protocol buffer text format.
|
|
||||||
// It is similar to strconv.Quote except we don't use Go escape sequences,
|
|
||||||
// we treat the string as a byte sequence, and we use octal escapes.
|
|
||||||
// These differences are to maintain interoperability with the other
|
|
||||||
// languages' implementations of the text format.
|
|
||||||
func writeString(w *textWriter, s string) error {
|
|
||||||
// use WriteByte here to get any needed indent
|
|
||||||
if err := w.WriteByte('"'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Loop over the bytes, not the runes.
|
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
var err error
|
|
||||||
// Divergence from C++: we don't escape apostrophes.
|
|
||||||
// There's no need to escape them, and the C++ parser
|
|
||||||
// copes with a naked apostrophe.
|
|
||||||
switch c := s[i]; c {
|
|
||||||
case '\n':
|
|
||||||
_, err = w.w.Write(backslashN)
|
|
||||||
case '\r':
|
|
||||||
_, err = w.w.Write(backslashR)
|
|
||||||
case '\t':
|
|
||||||
_, err = w.w.Write(backslashT)
|
|
||||||
case '"':
|
|
||||||
_, err = w.w.Write(backslashDQ)
|
|
||||||
case '\\':
|
|
||||||
_, err = w.w.Write(backslashBS)
|
|
||||||
default:
|
|
||||||
if isprint(c) {
|
|
||||||
err = w.w.WriteByte(c)
|
|
||||||
} else {
|
|
||||||
_, err = fmt.Fprintf(w.w, "\\%03o", c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.WriteByte('"')
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeUnknownStruct(w *textWriter, data []byte) (err error) {
|
|
||||||
if !w.compact {
|
|
||||||
if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b := NewBuffer(data)
|
|
||||||
for b.index < len(b.buf) {
|
|
||||||
x, err := b.DecodeVarint()
|
|
||||||
if err != nil {
|
|
||||||
_, err := fmt.Fprintf(w, "/* %v */\n", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
wire, tag := x&7, x>>3
|
|
||||||
if wire == WireEndGroup {
|
|
||||||
w.unindent()
|
|
||||||
if _, err := w.Write(endBraceNewline); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := fmt.Fprint(w, tag); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if wire != WireStartGroup {
|
|
||||||
if err := w.WriteByte(':'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !w.compact || wire == WireStartGroup {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch wire {
|
|
||||||
case WireBytes:
|
|
||||||
buf, e := b.DecodeRawBytes(false)
|
|
||||||
if e == nil {
|
|
||||||
_, err = fmt.Fprintf(w, "%q", buf)
|
|
||||||
} else {
|
|
||||||
_, err = fmt.Fprintf(w, "/* %v */", e)
|
|
||||||
}
|
|
||||||
case WireFixed32:
|
|
||||||
x, err = b.DecodeFixed32()
|
|
||||||
err = writeUnknownInt(w, x, err)
|
|
||||||
case WireFixed64:
|
|
||||||
x, err = b.DecodeFixed64()
|
|
||||||
err = writeUnknownInt(w, x, err)
|
|
||||||
case WireStartGroup:
|
|
||||||
err = w.WriteByte('{')
|
|
||||||
w.indent()
|
|
||||||
case WireVarint:
|
|
||||||
x, err = b.DecodeVarint()
|
|
||||||
err = writeUnknownInt(w, x, err)
|
|
||||||
default:
|
|
||||||
_, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeUnknownInt(w *textWriter, x uint64, err error) error {
|
|
||||||
if err == nil {
|
|
||||||
_, err = fmt.Fprint(w, x)
|
|
||||||
} else {
|
|
||||||
_, err = fmt.Fprintf(w, "/* %v */", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
type int32Slice []int32
|
|
||||||
|
|
||||||
func (s int32Slice) Len() int { return len(s) }
|
|
||||||
func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
|
|
||||||
func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
|
|
||||||
// writeExtensions writes all the extensions in pv.
|
|
||||||
// pv is assumed to be a pointer to a protocol message struct that is extendable.
|
|
||||||
func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
|
|
||||||
emap := extensionMaps[pv.Type().Elem()]
|
|
||||||
ep, _ := extendable(pv.Interface())
|
|
||||||
|
|
||||||
// Order the extensions by ID.
|
|
||||||
// This isn't strictly necessary, but it will give us
|
|
||||||
// canonical output, which will also make testing easier.
|
|
||||||
m, mu := ep.extensionsRead()
|
|
||||||
if m == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
ids := make([]int32, 0, len(m))
|
|
||||||
for id := range m {
|
|
||||||
ids = append(ids, id)
|
|
||||||
}
|
|
||||||
sort.Sort(int32Slice(ids))
|
|
||||||
mu.Unlock()
|
|
||||||
|
|
||||||
for _, extNum := range ids {
|
|
||||||
ext := m[extNum]
|
|
||||||
var desc *ExtensionDesc
|
|
||||||
if emap != nil {
|
|
||||||
desc = emap[extNum]
|
|
||||||
}
|
|
||||||
if desc == nil {
|
|
||||||
// Unknown extension.
|
|
||||||
if err := writeUnknownStruct(w, ext.enc); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pb, err := GetExtension(ep, desc)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed getting extension: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repeated extensions will appear as a slice.
|
|
||||||
if !desc.repeated() {
|
|
||||||
if err := tm.writeExtension(w, desc.Name, pb); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v := reflect.ValueOf(pb)
|
|
||||||
for i := 0; i < v.Len(); i++ {
|
|
||||||
if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
|
|
||||||
if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !w.compact {
|
|
||||||
if err := w.WriteByte(' '); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := w.WriteByte('\n'); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *textWriter) writeIndent() {
|
|
||||||
if !w.complete {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
remain := w.ind * 2
|
|
||||||
for remain > 0 {
|
|
||||||
n := remain
|
|
||||||
if n > len(spaces) {
|
|
||||||
n = len(spaces)
|
|
||||||
}
|
|
||||||
w.w.Write(spaces[:n])
|
|
||||||
remain -= n
|
|
||||||
}
|
|
||||||
w.complete = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// TextMarshaler is a configurable text format marshaler.
|
|
||||||
type TextMarshaler struct {
|
|
||||||
Compact bool // use compact text format (one line).
|
|
||||||
ExpandAny bool // expand google.protobuf.Any messages of known types
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal writes a given protocol buffer in text format.
|
|
||||||
// The only errors returned are from w.
|
|
||||||
func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
|
|
||||||
val := reflect.ValueOf(pb)
|
|
||||||
if pb == nil || val.IsNil() {
|
|
||||||
w.Write([]byte("<nil>"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var bw *bufio.Writer
|
|
||||||
ww, ok := w.(writer)
|
|
||||||
if !ok {
|
|
||||||
bw = bufio.NewWriter(w)
|
|
||||||
ww = bw
|
|
||||||
}
|
|
||||||
aw := &textWriter{
|
|
||||||
w: ww,
|
|
||||||
complete: true,
|
|
||||||
compact: tm.Compact,
|
|
||||||
}
|
|
||||||
|
|
||||||
if etm, ok := pb.(encoding.TextMarshaler); ok {
|
|
||||||
text, err := etm.MarshalText()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = aw.Write(text); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if bw != nil {
|
|
||||||
return bw.Flush()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Dereference the received pointer so we don't have outer < and >.
|
|
||||||
v := reflect.Indirect(val)
|
|
||||||
if err := tm.writeStruct(aw, v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if bw != nil {
|
|
||||||
return bw.Flush()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text is the same as Marshal, but returns the string directly.
|
|
||||||
func (tm *TextMarshaler) Text(pb Message) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
tm.Marshal(&buf, pb)
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
defaultTextMarshaler = TextMarshaler{}
|
|
||||||
compactTextMarshaler = TextMarshaler{Compact: true}
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: consider removing some of the Marshal functions below.
|
|
||||||
|
|
||||||
// MarshalText writes a given protocol buffer in text format.
|
|
||||||
// The only errors returned are from w.
|
|
||||||
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
|
|
||||||
|
|
||||||
// MarshalTextString is the same as MarshalText, but returns the string directly.
|
|
||||||
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
|
|
||||||
|
|
||||||
// CompactText writes a given protocol buffer in compact text format (one line).
|
|
||||||
func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
|
|
||||||
|
|
||||||
// CompactTextString is the same as CompactText, but returns the string directly.
|
|
||||||
func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }
|
|
880
vendor/github.com/golang/protobuf/proto/text_parser.go
generated
vendored
880
vendor/github.com/golang/protobuf/proto/text_parser.go
generated
vendored
@ -1,880 +0,0 @@
|
|||||||
// Go support for Protocol Buffers - Google's data interchange format
|
|
||||||
//
|
|
||||||
// Copyright 2010 The Go Authors. All rights reserved.
|
|
||||||
// https://github.com/golang/protobuf
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
package proto
|
|
||||||
|
|
||||||
// Functions for parsing the Text protocol buffer format.
|
|
||||||
// TODO: message sets.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Error string emitted when deserializing Any and fields are already set
|
|
||||||
const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set"
|
|
||||||
|
|
||||||
type ParseError struct {
|
|
||||||
Message string
|
|
||||||
Line int // 1-based line number
|
|
||||||
Offset int // 0-based byte offset from start of input
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *ParseError) Error() string {
|
|
||||||
if p.Line == 1 {
|
|
||||||
// show offset only for first line
|
|
||||||
return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("line %d: %v", p.Line, p.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
type token struct {
|
|
||||||
value string
|
|
||||||
err *ParseError
|
|
||||||
line int // line number
|
|
||||||
offset int // byte number from start of input, not start of line
|
|
||||||
unquoted string // the unquoted version of value, if it was a quoted string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *token) String() string {
|
|
||||||
if t.err == nil {
|
|
||||||
return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("parse error: %v", t.err)
|
|
||||||
}
|
|
||||||
|
|
||||||
type textParser struct {
|
|
||||||
s string // remaining input
|
|
||||||
done bool // whether the parsing is finished (success or error)
|
|
||||||
backed bool // whether back() was called
|
|
||||||
offset, line int
|
|
||||||
cur token
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTextParser(s string) *textParser {
|
|
||||||
p := new(textParser)
|
|
||||||
p.s = s
|
|
||||||
p.line = 1
|
|
||||||
p.cur.line = 1
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
|
|
||||||
pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
|
|
||||||
p.cur.err = pe
|
|
||||||
p.done = true
|
|
||||||
return pe
|
|
||||||
}
|
|
||||||
|
|
||||||
// Numbers and identifiers are matched by [-+._A-Za-z0-9]
|
|
||||||
func isIdentOrNumberChar(c byte) bool {
|
|
||||||
switch {
|
|
||||||
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
|
|
||||||
return true
|
|
||||||
case '0' <= c && c <= '9':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
switch c {
|
|
||||||
case '-', '+', '.', '_':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isWhitespace(c byte) bool {
|
|
||||||
switch c {
|
|
||||||
case ' ', '\t', '\n', '\r':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isQuote(c byte) bool {
|
|
||||||
switch c {
|
|
||||||
case '"', '\'':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) skipWhitespace() {
|
|
||||||
i := 0
|
|
||||||
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
|
|
||||||
if p.s[i] == '#' {
|
|
||||||
// comment; skip to end of line or input
|
|
||||||
for i < len(p.s) && p.s[i] != '\n' {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i == len(p.s) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if p.s[i] == '\n' {
|
|
||||||
p.line++
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
p.offset += i
|
|
||||||
p.s = p.s[i:len(p.s)]
|
|
||||||
if len(p.s) == 0 {
|
|
||||||
p.done = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) advance() {
|
|
||||||
// Skip whitespace
|
|
||||||
p.skipWhitespace()
|
|
||||||
if p.done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start of non-whitespace
|
|
||||||
p.cur.err = nil
|
|
||||||
p.cur.offset, p.cur.line = p.offset, p.line
|
|
||||||
p.cur.unquoted = ""
|
|
||||||
switch p.s[0] {
|
|
||||||
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
|
|
||||||
// Single symbol
|
|
||||||
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
|
|
||||||
case '"', '\'':
|
|
||||||
// Quoted string
|
|
||||||
i := 1
|
|
||||||
for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
|
|
||||||
if p.s[i] == '\\' && i+1 < len(p.s) {
|
|
||||||
// skip escaped char
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i >= len(p.s) || p.s[i] != p.s[0] {
|
|
||||||
p.errorf("unmatched quote")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
|
|
||||||
if err != nil {
|
|
||||||
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
|
|
||||||
p.cur.unquoted = unq
|
|
||||||
default:
|
|
||||||
i := 0
|
|
||||||
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if i == 0 {
|
|
||||||
p.errorf("unexpected byte %#x", p.s[0])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
|
|
||||||
}
|
|
||||||
p.offset += len(p.cur.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
errBadUTF8 = errors.New("proto: bad UTF-8")
|
|
||||||
)
|
|
||||||
|
|
||||||
func unquoteC(s string, quote rune) (string, error) {
|
|
||||||
// This is based on C++'s tokenizer.cc.
|
|
||||||
// Despite its name, this is *not* parsing C syntax.
|
|
||||||
// For instance, "\0" is an invalid quoted string.
|
|
||||||
|
|
||||||
// Avoid allocation in trivial cases.
|
|
||||||
simple := true
|
|
||||||
for _, r := range s {
|
|
||||||
if r == '\\' || r == quote {
|
|
||||||
simple = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if simple {
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, 0, 3*len(s)/2)
|
|
||||||
for len(s) > 0 {
|
|
||||||
r, n := utf8.DecodeRuneInString(s)
|
|
||||||
if r == utf8.RuneError && n == 1 {
|
|
||||||
return "", errBadUTF8
|
|
||||||
}
|
|
||||||
s = s[n:]
|
|
||||||
if r != '\\' {
|
|
||||||
if r < utf8.RuneSelf {
|
|
||||||
buf = append(buf, byte(r))
|
|
||||||
} else {
|
|
||||||
buf = append(buf, string(r)...)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ch, tail, err := unescape(s)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
buf = append(buf, ch...)
|
|
||||||
s = tail
|
|
||||||
}
|
|
||||||
return string(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func unescape(s string) (ch string, tail string, err error) {
|
|
||||||
r, n := utf8.DecodeRuneInString(s)
|
|
||||||
if r == utf8.RuneError && n == 1 {
|
|
||||||
return "", "", errBadUTF8
|
|
||||||
}
|
|
||||||
s = s[n:]
|
|
||||||
switch r {
|
|
||||||
case 'a':
|
|
||||||
return "\a", s, nil
|
|
||||||
case 'b':
|
|
||||||
return "\b", s, nil
|
|
||||||
case 'f':
|
|
||||||
return "\f", s, nil
|
|
||||||
case 'n':
|
|
||||||
return "\n", s, nil
|
|
||||||
case 'r':
|
|
||||||
return "\r", s, nil
|
|
||||||
case 't':
|
|
||||||
return "\t", s, nil
|
|
||||||
case 'v':
|
|
||||||
return "\v", s, nil
|
|
||||||
case '?':
|
|
||||||
return "?", s, nil // trigraph workaround
|
|
||||||
case '\'', '"', '\\':
|
|
||||||
return string(r), s, nil
|
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
|
||||||
if len(s) < 2 {
|
|
||||||
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
|
|
||||||
}
|
|
||||||
ss := string(r) + s[:2]
|
|
||||||
s = s[2:]
|
|
||||||
i, err := strconv.ParseUint(ss, 8, 8)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
|
|
||||||
}
|
|
||||||
return string([]byte{byte(i)}), s, nil
|
|
||||||
case 'x', 'X', 'u', 'U':
|
|
||||||
var n int
|
|
||||||
switch r {
|
|
||||||
case 'x', 'X':
|
|
||||||
n = 2
|
|
||||||
case 'u':
|
|
||||||
n = 4
|
|
||||||
case 'U':
|
|
||||||
n = 8
|
|
||||||
}
|
|
||||||
if len(s) < n {
|
|
||||||
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
|
|
||||||
}
|
|
||||||
ss := s[:n]
|
|
||||||
s = s[n:]
|
|
||||||
i, err := strconv.ParseUint(ss, 16, 64)
|
|
||||||
if err != nil {
|
|
||||||
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
|
|
||||||
}
|
|
||||||
if r == 'x' || r == 'X' {
|
|
||||||
return string([]byte{byte(i)}), s, nil
|
|
||||||
}
|
|
||||||
if i > utf8.MaxRune {
|
|
||||||
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
|
|
||||||
}
|
|
||||||
return string(i), s, nil
|
|
||||||
}
|
|
||||||
return "", "", fmt.Errorf(`unknown escape \%c`, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Back off the parser by one token. Can only be done between calls to next().
|
|
||||||
// It makes the next advance() a no-op.
|
|
||||||
func (p *textParser) back() { p.backed = true }
|
|
||||||
|
|
||||||
// Advances the parser and returns the new current token.
|
|
||||||
func (p *textParser) next() *token {
|
|
||||||
if p.backed || p.done {
|
|
||||||
p.backed = false
|
|
||||||
return &p.cur
|
|
||||||
}
|
|
||||||
p.advance()
|
|
||||||
if p.done {
|
|
||||||
p.cur.value = ""
|
|
||||||
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
|
|
||||||
// Look for multiple quoted strings separated by whitespace,
|
|
||||||
// and concatenate them.
|
|
||||||
cat := p.cur
|
|
||||||
for {
|
|
||||||
p.skipWhitespace()
|
|
||||||
if p.done || !isQuote(p.s[0]) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
p.advance()
|
|
||||||
if p.cur.err != nil {
|
|
||||||
return &p.cur
|
|
||||||
}
|
|
||||||
cat.value += " " + p.cur.value
|
|
||||||
cat.unquoted += p.cur.unquoted
|
|
||||||
}
|
|
||||||
p.done = false // parser may have seen EOF, but we want to return cat
|
|
||||||
p.cur = cat
|
|
||||||
}
|
|
||||||
return &p.cur
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) consumeToken(s string) error {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value != s {
|
|
||||||
p.back()
|
|
||||||
return p.errorf("expected %q, found %q", s, tok.value)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a RequiredNotSetError indicating which required field was not set.
|
|
||||||
func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError {
|
|
||||||
st := sv.Type()
|
|
||||||
sprops := GetProperties(st)
|
|
||||||
for i := 0; i < st.NumField(); i++ {
|
|
||||||
if !isNil(sv.Field(i)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
props := sprops.Prop[i]
|
|
||||||
if props.Required {
|
|
||||||
return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &RequiredNotSetError{fmt.Sprintf("%v.<unknown field name>", st)} // should not happen
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the index in the struct for the named field, as well as the parsed tag properties.
|
|
||||||
func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
|
|
||||||
i, ok := sprops.decoderOrigNames[name]
|
|
||||||
if ok {
|
|
||||||
return i, sprops.Prop[i], true
|
|
||||||
}
|
|
||||||
return -1, nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume a ':' from the input stream (if the next token is a colon),
|
|
||||||
// returning an error if a colon is needed but not present.
|
|
||||||
func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value != ":" {
|
|
||||||
// Colon is optional when the field is a group or message.
|
|
||||||
needColon := true
|
|
||||||
switch props.Wire {
|
|
||||||
case "group":
|
|
||||||
needColon = false
|
|
||||||
case "bytes":
|
|
||||||
// A "bytes" field is either a message, a string, or a repeated field;
|
|
||||||
// those three become *T, *string and []T respectively, so we can check for
|
|
||||||
// this field being a pointer to a non-string.
|
|
||||||
if typ.Kind() == reflect.Ptr {
|
|
||||||
// *T or *string
|
|
||||||
if typ.Elem().Kind() == reflect.String {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else if typ.Kind() == reflect.Slice {
|
|
||||||
// []T or []*T
|
|
||||||
if typ.Elem().Kind() != reflect.Ptr {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else if typ.Kind() == reflect.String {
|
|
||||||
// The proto3 exception is for a string field,
|
|
||||||
// which requires a colon.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
needColon = false
|
|
||||||
}
|
|
||||||
if needColon {
|
|
||||||
return p.errorf("expected ':', found %q", tok.value)
|
|
||||||
}
|
|
||||||
p.back()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
|
|
||||||
st := sv.Type()
|
|
||||||
sprops := GetProperties(st)
|
|
||||||
reqCount := sprops.reqCount
|
|
||||||
var reqFieldErr error
|
|
||||||
fieldSet := make(map[string]bool)
|
|
||||||
// A struct is a sequence of "name: value", terminated by one of
|
|
||||||
// '>' or '}', or the end of the input. A name may also be
|
|
||||||
// "[extension]" or "[type/url]".
|
|
||||||
//
|
|
||||||
// The whole struct can also be an expanded Any message, like:
|
|
||||||
// [type/url] < ... struct contents ... >
|
|
||||||
for {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value == terminator {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if tok.value == "[" {
|
|
||||||
// Looks like an extension or an Any.
|
|
||||||
//
|
|
||||||
// TODO: Check whether we need to handle
|
|
||||||
// namespace rooted names (e.g. ".something.Foo").
|
|
||||||
extName, err := p.consumeExtName()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if s := strings.LastIndex(extName, "/"); s >= 0 {
|
|
||||||
// If it contains a slash, it's an Any type URL.
|
|
||||||
messageName := extName[s+1:]
|
|
||||||
mt := MessageType(messageName)
|
|
||||||
if mt == nil {
|
|
||||||
return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
|
|
||||||
}
|
|
||||||
tok = p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
// consume an optional colon
|
|
||||||
if tok.value == ":" {
|
|
||||||
tok = p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var terminator string
|
|
||||||
switch tok.value {
|
|
||||||
case "<":
|
|
||||||
terminator = ">"
|
|
||||||
case "{":
|
|
||||||
terminator = "}"
|
|
||||||
default:
|
|
||||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
|
||||||
}
|
|
||||||
v := reflect.New(mt.Elem())
|
|
||||||
if pe := p.readStruct(v.Elem(), terminator); pe != nil {
|
|
||||||
return pe
|
|
||||||
}
|
|
||||||
b, err := Marshal(v.Interface().(Message))
|
|
||||||
if err != nil {
|
|
||||||
return p.errorf("failed to marshal message of type %q: %v", messageName, err)
|
|
||||||
}
|
|
||||||
if fieldSet["type_url"] {
|
|
||||||
return p.errorf(anyRepeatedlyUnpacked, "type_url")
|
|
||||||
}
|
|
||||||
if fieldSet["value"] {
|
|
||||||
return p.errorf(anyRepeatedlyUnpacked, "value")
|
|
||||||
}
|
|
||||||
sv.FieldByName("TypeUrl").SetString(extName)
|
|
||||||
sv.FieldByName("Value").SetBytes(b)
|
|
||||||
fieldSet["type_url"] = true
|
|
||||||
fieldSet["value"] = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var desc *ExtensionDesc
|
|
||||||
// This could be faster, but it's functional.
|
|
||||||
// TODO: Do something smarter than a linear scan.
|
|
||||||
for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
|
|
||||||
if d.Name == extName {
|
|
||||||
desc = d
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if desc == nil {
|
|
||||||
return p.errorf("unrecognized extension %q", extName)
|
|
||||||
}
|
|
||||||
|
|
||||||
props := &Properties{}
|
|
||||||
props.Parse(desc.Tag)
|
|
||||||
|
|
||||||
typ := reflect.TypeOf(desc.ExtensionType)
|
|
||||||
if err := p.checkForColon(props, typ); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rep := desc.repeated()
|
|
||||||
|
|
||||||
// Read the extension structure, and set it in
|
|
||||||
// the value we're constructing.
|
|
||||||
var ext reflect.Value
|
|
||||||
if !rep {
|
|
||||||
ext = reflect.New(typ).Elem()
|
|
||||||
} else {
|
|
||||||
ext = reflect.New(typ.Elem()).Elem()
|
|
||||||
}
|
|
||||||
if err := p.readAny(ext, props); err != nil {
|
|
||||||
if _, ok := err.(*RequiredNotSetError); !ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
reqFieldErr = err
|
|
||||||
}
|
|
||||||
ep := sv.Addr().Interface().(Message)
|
|
||||||
if !rep {
|
|
||||||
SetExtension(ep, desc, ext.Interface())
|
|
||||||
} else {
|
|
||||||
old, err := GetExtension(ep, desc)
|
|
||||||
var sl reflect.Value
|
|
||||||
if err == nil {
|
|
||||||
sl = reflect.ValueOf(old) // existing slice
|
|
||||||
} else {
|
|
||||||
sl = reflect.MakeSlice(typ, 0, 1)
|
|
||||||
}
|
|
||||||
sl = reflect.Append(sl, ext)
|
|
||||||
SetExtension(ep, desc, sl.Interface())
|
|
||||||
}
|
|
||||||
if err := p.consumeOptionalSeparator(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a normal, non-extension field.
|
|
||||||
name := tok.value
|
|
||||||
var dst reflect.Value
|
|
||||||
fi, props, ok := structFieldByName(sprops, name)
|
|
||||||
if ok {
|
|
||||||
dst = sv.Field(fi)
|
|
||||||
} else if oop, ok := sprops.OneofTypes[name]; ok {
|
|
||||||
// It is a oneof.
|
|
||||||
props = oop.Prop
|
|
||||||
nv := reflect.New(oop.Type.Elem())
|
|
||||||
dst = nv.Elem().Field(0)
|
|
||||||
field := sv.Field(oop.Field)
|
|
||||||
if !field.IsNil() {
|
|
||||||
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name)
|
|
||||||
}
|
|
||||||
field.Set(nv)
|
|
||||||
}
|
|
||||||
if !dst.IsValid() {
|
|
||||||
return p.errorf("unknown field name %q in %v", name, st)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dst.Kind() == reflect.Map {
|
|
||||||
// Consume any colon.
|
|
||||||
if err := p.checkForColon(props, dst.Type()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct the map if it doesn't already exist.
|
|
||||||
if dst.IsNil() {
|
|
||||||
dst.Set(reflect.MakeMap(dst.Type()))
|
|
||||||
}
|
|
||||||
key := reflect.New(dst.Type().Key()).Elem()
|
|
||||||
val := reflect.New(dst.Type().Elem()).Elem()
|
|
||||||
|
|
||||||
// The map entry should be this sequence of tokens:
|
|
||||||
// < key : KEY value : VALUE >
|
|
||||||
// However, implementations may omit key or value, and technically
|
|
||||||
// we should support them in any order. See b/28924776 for a time
|
|
||||||
// this went wrong.
|
|
||||||
|
|
||||||
tok := p.next()
|
|
||||||
var terminator string
|
|
||||||
switch tok.value {
|
|
||||||
case "<":
|
|
||||||
terminator = ">"
|
|
||||||
case "{":
|
|
||||||
terminator = "}"
|
|
||||||
default:
|
|
||||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value == terminator {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
switch tok.value {
|
|
||||||
case "key":
|
|
||||||
if err := p.consumeToken(":"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := p.readAny(key, props.MapKeyProp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := p.consumeOptionalSeparator(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "value":
|
|
||||||
if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := p.readAny(val, props.MapValProp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := p.consumeOptionalSeparator(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
p.back()
|
|
||||||
return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dst.SetMapIndex(key, val)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that it's not already set if it's not a repeated field.
|
|
||||||
if !props.Repeated && fieldSet[name] {
|
|
||||||
return p.errorf("non-repeated field %q was repeated", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.checkForColon(props, dst.Type()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse into the field.
|
|
||||||
fieldSet[name] = true
|
|
||||||
if err := p.readAny(dst, props); err != nil {
|
|
||||||
if _, ok := err.(*RequiredNotSetError); !ok {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
reqFieldErr = err
|
|
||||||
}
|
|
||||||
if props.Required {
|
|
||||||
reqCount--
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.consumeOptionalSeparator(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if reqCount > 0 {
|
|
||||||
return p.missingRequiredFieldError(sv)
|
|
||||||
}
|
|
||||||
return reqFieldErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// consumeExtName consumes extension name or expanded Any type URL and the
|
|
||||||
// following ']'. It returns the name or URL consumed.
|
|
||||||
func (p *textParser) consumeExtName() (string, error) {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return "", tok.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If extension name or type url is quoted, it's a single token.
|
|
||||||
if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
|
|
||||||
name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return name, p.consumeToken("]")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume everything up to "]"
|
|
||||||
var parts []string
|
|
||||||
for tok.value != "]" {
|
|
||||||
parts = append(parts, tok.value)
|
|
||||||
tok = p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
|
|
||||||
}
|
|
||||||
if p.done && tok.value != "]" {
|
|
||||||
return "", p.errorf("unclosed type_url or extension name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.Join(parts, ""), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// consumeOptionalSeparator consumes an optional semicolon or comma.
|
|
||||||
// It is used in readStruct to provide backward compatibility.
|
|
||||||
func (p *textParser) consumeOptionalSeparator() error {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value != ";" && tok.value != "," {
|
|
||||||
p.back()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *textParser) readAny(v reflect.Value, props *Properties) error {
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value == "" {
|
|
||||||
return p.errorf("unexpected EOF")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch fv := v; fv.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
at := v.Type()
|
|
||||||
if at.Elem().Kind() == reflect.Uint8 {
|
|
||||||
// Special case for []byte
|
|
||||||
if tok.value[0] != '"' && tok.value[0] != '\'' {
|
|
||||||
// Deliberately written out here, as the error after
|
|
||||||
// this switch statement would write "invalid []byte: ...",
|
|
||||||
// which is not as user-friendly.
|
|
||||||
return p.errorf("invalid string: %v", tok.value)
|
|
||||||
}
|
|
||||||
bytes := []byte(tok.unquoted)
|
|
||||||
fv.Set(reflect.ValueOf(bytes))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Repeated field.
|
|
||||||
if tok.value == "[" {
|
|
||||||
// Repeated field with list notation, like [1,2,3].
|
|
||||||
for {
|
|
||||||
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
|
|
||||||
err := p.readAny(fv.Index(fv.Len()-1), props)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tok := p.next()
|
|
||||||
if tok.err != nil {
|
|
||||||
return tok.err
|
|
||||||
}
|
|
||||||
if tok.value == "]" {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if tok.value != "," {
|
|
||||||
return p.errorf("Expected ']' or ',' found %q", tok.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// One value of the repeated field.
|
|
||||||
p.back()
|
|
||||||
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
|
|
||||||
return p.readAny(fv.Index(fv.Len()-1), props)
|
|
||||||
case reflect.Bool:
|
|
||||||
// true/1/t/True or false/f/0/False.
|
|
||||||
switch tok.value {
|
|
||||||
case "true", "1", "t", "True":
|
|
||||||
fv.SetBool(true)
|
|
||||||
return nil
|
|
||||||
case "false", "0", "f", "False":
|
|
||||||
fv.SetBool(false)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
v := tok.value
|
|
||||||
// Ignore 'f' for compatibility with output generated by C++, but don't
|
|
||||||
// remove 'f' when the value is "-inf" or "inf".
|
|
||||||
if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" {
|
|
||||||
v = v[:len(v)-1]
|
|
||||||
}
|
|
||||||
if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil {
|
|
||||||
fv.SetFloat(f)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Int32:
|
|
||||||
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
|
|
||||||
fv.SetInt(x)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(props.Enum) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
m, ok := enumValueMaps[props.Enum]
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
x, ok := m[tok.value]
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fv.SetInt(int64(x))
|
|
||||||
return nil
|
|
||||||
case reflect.Int64:
|
|
||||||
if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
|
|
||||||
fv.SetInt(x)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
case reflect.Ptr:
|
|
||||||
// A basic field (indirected through pointer), or a repeated message/group
|
|
||||||
p.back()
|
|
||||||
fv.Set(reflect.New(fv.Type().Elem()))
|
|
||||||
return p.readAny(fv.Elem(), props)
|
|
||||||
case reflect.String:
|
|
||||||
if tok.value[0] == '"' || tok.value[0] == '\'' {
|
|
||||||
fv.SetString(tok.unquoted)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Struct:
|
|
||||||
var terminator string
|
|
||||||
switch tok.value {
|
|
||||||
case "{":
|
|
||||||
terminator = "}"
|
|
||||||
case "<":
|
|
||||||
terminator = ">"
|
|
||||||
default:
|
|
||||||
return p.errorf("expected '{' or '<', found %q", tok.value)
|
|
||||||
}
|
|
||||||
// TODO: Handle nested messages which implement encoding.TextUnmarshaler.
|
|
||||||
return p.readStruct(fv, terminator)
|
|
||||||
case reflect.Uint32:
|
|
||||||
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
|
|
||||||
fv.SetUint(uint64(x))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case reflect.Uint64:
|
|
||||||
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
|
|
||||||
fv.SetUint(x)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return p.errorf("invalid %v: %v", v.Type(), tok.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
|
|
||||||
// before starting to unmarshal, so any existing data in pb is always removed.
|
|
||||||
// If a required field is not set and no other error occurs,
|
|
||||||
// UnmarshalText returns *RequiredNotSetError.
|
|
||||||
func UnmarshalText(s string, pb Message) error {
|
|
||||||
if um, ok := pb.(encoding.TextUnmarshaler); ok {
|
|
||||||
return um.UnmarshalText([]byte(s))
|
|
||||||
}
|
|
||||||
pb.Reset()
|
|
||||||
v := reflect.ValueOf(pb)
|
|
||||||
return newTextParser(s).readStruct(v.Elem(), "")
|
|
||||||
}
|
|
155
vendor/github.com/golang/protobuf/ptypes/any/any.proto
generated
vendored
155
vendor/github.com/golang/protobuf/ptypes/any/any.proto
generated
vendored
@ -1,155 +0,0 @@
|
|||||||
// Protocol Buffers - Google's data interchange format
|
|
||||||
// Copyright 2008 Google Inc. All rights reserved.
|
|
||||||
// https://developers.google.com/protocol-buffers/
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package google.protobuf;
|
|
||||||
|
|
||||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
|
||||||
option go_package = "github.com/golang/protobuf/ptypes/any";
|
|
||||||
option java_package = "com.google.protobuf";
|
|
||||||
option java_outer_classname = "AnyProto";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
option objc_class_prefix = "GPB";
|
|
||||||
|
|
||||||
// `Any` contains an arbitrary serialized protocol buffer message along with a
|
|
||||||
// URL that describes the type of the serialized message.
|
|
||||||
//
|
|
||||||
// Protobuf library provides support to pack/unpack Any values in the form
|
|
||||||
// of utility functions or additional generated methods of the Any type.
|
|
||||||
//
|
|
||||||
// Example 1: Pack and unpack a message in C++.
|
|
||||||
//
|
|
||||||
// Foo foo = ...;
|
|
||||||
// Any any;
|
|
||||||
// any.PackFrom(foo);
|
|
||||||
// ...
|
|
||||||
// if (any.UnpackTo(&foo)) {
|
|
||||||
// ...
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Example 2: Pack and unpack a message in Java.
|
|
||||||
//
|
|
||||||
// Foo foo = ...;
|
|
||||||
// Any any = Any.pack(foo);
|
|
||||||
// ...
|
|
||||||
// if (any.is(Foo.class)) {
|
|
||||||
// foo = any.unpack(Foo.class);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Example 3: Pack and unpack a message in Python.
|
|
||||||
//
|
|
||||||
// foo = Foo(...)
|
|
||||||
// any = Any()
|
|
||||||
// any.Pack(foo)
|
|
||||||
// ...
|
|
||||||
// if any.Is(Foo.DESCRIPTOR):
|
|
||||||
// any.Unpack(foo)
|
|
||||||
// ...
|
|
||||||
//
|
|
||||||
// Example 4: Pack and unpack a message in Go
|
|
||||||
//
|
|
||||||
// foo := &pb.Foo{...}
|
|
||||||
// any, err := ptypes.MarshalAny(foo)
|
|
||||||
// ...
|
|
||||||
// foo := &pb.Foo{}
|
|
||||||
// if err := ptypes.UnmarshalAny(any, foo); err != nil {
|
|
||||||
// ...
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// The pack methods provided by protobuf library will by default use
|
|
||||||
// 'type.googleapis.com/full.type.name' as the type URL and the unpack
|
|
||||||
// methods only use the fully qualified type name after the last '/'
|
|
||||||
// in the type URL, for example "foo.bar.com/x/y.z" will yield type
|
|
||||||
// name "y.z".
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// JSON
|
|
||||||
// ====
|
|
||||||
// The JSON representation of an `Any` value uses the regular
|
|
||||||
// representation of the deserialized, embedded message, with an
|
|
||||||
// additional field `@type` which contains the type URL. Example:
|
|
||||||
//
|
|
||||||
// package google.profile;
|
|
||||||
// message Person {
|
|
||||||
// string first_name = 1;
|
|
||||||
// string last_name = 2;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// {
|
|
||||||
// "@type": "type.googleapis.com/google.profile.Person",
|
|
||||||
// "firstName": <string>,
|
|
||||||
// "lastName": <string>
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// If the embedded message type is well-known and has a custom JSON
|
|
||||||
// representation, that representation will be embedded adding a field
|
|
||||||
// `value` which holds the custom JSON in addition to the `@type`
|
|
||||||
// field. Example (for message [google.protobuf.Duration][]):
|
|
||||||
//
|
|
||||||
// {
|
|
||||||
// "@type": "type.googleapis.com/google.protobuf.Duration",
|
|
||||||
// "value": "1.212s"
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
message Any {
|
|
||||||
// A URL/resource name that uniquely identifies the type of the serialized
|
|
||||||
// protocol buffer message. This string must contain at least
|
|
||||||
// one "/" character. The last segment of the URL's path must represent
|
|
||||||
// the fully qualified name of the type (as in
|
|
||||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
|
||||||
// (e.g., leading "." is not accepted).
|
|
||||||
//
|
|
||||||
// In practice, teams usually precompile into the binary all types that they
|
|
||||||
// expect it to use in the context of Any. However, for URLs which use the
|
|
||||||
// scheme `http`, `https`, or no scheme, one can optionally set up a type
|
|
||||||
// server that maps type URLs to message definitions as follows:
|
|
||||||
//
|
|
||||||
// * If no scheme is provided, `https` is assumed.
|
|
||||||
// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
|
|
||||||
// value in binary format, or produce an error.
|
|
||||||
// * Applications are allowed to cache lookup results based on the
|
|
||||||
// URL, or have them precompiled into a binary to avoid any
|
|
||||||
// lookup. Therefore, binary compatibility needs to be preserved
|
|
||||||
// on changes to types. (Use versioned type names to manage
|
|
||||||
// breaking changes.)
|
|
||||||
//
|
|
||||||
// Note: this functionality is not currently available in the official
|
|
||||||
// protobuf release, and it is not used for type URLs beginning with
|
|
||||||
// type.googleapis.com.
|
|
||||||
//
|
|
||||||
// Schemes other than `http`, `https` (or the empty scheme) might be
|
|
||||||
// used with implementation specific semantics.
|
|
||||||
//
|
|
||||||
string type_url = 1;
|
|
||||||
|
|
||||||
// Must be a valid serialized protocol buffer of the above specified type.
|
|
||||||
bytes value = 2;
|
|
||||||
}
|
|
116
vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
generated
vendored
116
vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
generated
vendored
@ -1,116 +0,0 @@
|
|||||||
// Protocol Buffers - Google's data interchange format
|
|
||||||
// Copyright 2008 Google Inc. All rights reserved.
|
|
||||||
// https://developers.google.com/protocol-buffers/
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package google.protobuf;
|
|
||||||
|
|
||||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
|
||||||
option cc_enable_arenas = true;
|
|
||||||
option go_package = "github.com/golang/protobuf/ptypes/duration";
|
|
||||||
option java_package = "com.google.protobuf";
|
|
||||||
option java_outer_classname = "DurationProto";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
option objc_class_prefix = "GPB";
|
|
||||||
|
|
||||||
// A Duration represents a signed, fixed-length span of time represented
|
|
||||||
// as a count of seconds and fractions of seconds at nanosecond
|
|
||||||
// resolution. It is independent of any calendar and concepts like "day"
|
|
||||||
// or "month". It is related to Timestamp in that the difference between
|
|
||||||
// two Timestamp values is a Duration and it can be added or subtracted
|
|
||||||
// from a Timestamp. Range is approximately +-10,000 years.
|
|
||||||
//
|
|
||||||
// # Examples
|
|
||||||
//
|
|
||||||
// Example 1: Compute Duration from two Timestamps in pseudo code.
|
|
||||||
//
|
|
||||||
// Timestamp start = ...;
|
|
||||||
// Timestamp end = ...;
|
|
||||||
// Duration duration = ...;
|
|
||||||
//
|
|
||||||
// duration.seconds = end.seconds - start.seconds;
|
|
||||||
// duration.nanos = end.nanos - start.nanos;
|
|
||||||
//
|
|
||||||
// if (duration.seconds < 0 && duration.nanos > 0) {
|
|
||||||
// duration.seconds += 1;
|
|
||||||
// duration.nanos -= 1000000000;
|
|
||||||
// } else if (duration.seconds > 0 && duration.nanos < 0) {
|
|
||||||
// duration.seconds -= 1;
|
|
||||||
// duration.nanos += 1000000000;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
|
|
||||||
//
|
|
||||||
// Timestamp start = ...;
|
|
||||||
// Duration duration = ...;
|
|
||||||
// Timestamp end = ...;
|
|
||||||
//
|
|
||||||
// end.seconds = start.seconds + duration.seconds;
|
|
||||||
// end.nanos = start.nanos + duration.nanos;
|
|
||||||
//
|
|
||||||
// if (end.nanos < 0) {
|
|
||||||
// end.seconds -= 1;
|
|
||||||
// end.nanos += 1000000000;
|
|
||||||
// } else if (end.nanos >= 1000000000) {
|
|
||||||
// end.seconds += 1;
|
|
||||||
// end.nanos -= 1000000000;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Example 3: Compute Duration from datetime.timedelta in Python.
|
|
||||||
//
|
|
||||||
// td = datetime.timedelta(days=3, minutes=10)
|
|
||||||
// duration = Duration()
|
|
||||||
// duration.FromTimedelta(td)
|
|
||||||
//
|
|
||||||
// # JSON Mapping
|
|
||||||
//
|
|
||||||
// In JSON format, the Duration type is encoded as a string rather than an
|
|
||||||
// object, where the string ends in the suffix "s" (indicating seconds) and
|
|
||||||
// is preceded by the number of seconds, with nanoseconds expressed as
|
|
||||||
// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
|
|
||||||
// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
|
|
||||||
// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
|
|
||||||
// microsecond should be expressed in JSON format as "3.000001s".
|
|
||||||
//
|
|
||||||
//
|
|
||||||
message Duration {
|
|
||||||
// Signed seconds of the span of time. Must be from -315,576,000,000
|
|
||||||
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
|
|
||||||
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
|
|
||||||
int64 seconds = 1;
|
|
||||||
|
|
||||||
// Signed fractions of a second at nanosecond resolution of the span
|
|
||||||
// of time. Durations less than one second are represented with a 0
|
|
||||||
// `seconds` field and a positive or negative `nanos` field. For durations
|
|
||||||
// of one second or more, a non-zero value for the `nanos` field must be
|
|
||||||
// of the same sign as the `seconds` field. Must be from -999,999,999
|
|
||||||
// to +999,999,999 inclusive.
|
|
||||||
int32 nanos = 2;
|
|
||||||
}
|
|
138
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
generated
vendored
138
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
generated
vendored
@ -1,138 +0,0 @@
|
|||||||
// Protocol Buffers - Google's data interchange format
|
|
||||||
// Copyright 2008 Google Inc. All rights reserved.
|
|
||||||
// https://developers.google.com/protocol-buffers/
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions are
|
|
||||||
// met:
|
|
||||||
//
|
|
||||||
// * Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
// * Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following disclaimer
|
|
||||||
// in the documentation and/or other materials provided with the
|
|
||||||
// distribution.
|
|
||||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived from
|
|
||||||
// this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package google.protobuf;
|
|
||||||
|
|
||||||
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
|
|
||||||
option cc_enable_arenas = true;
|
|
||||||
option go_package = "github.com/golang/protobuf/ptypes/timestamp";
|
|
||||||
option java_package = "com.google.protobuf";
|
|
||||||
option java_outer_classname = "TimestampProto";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
option objc_class_prefix = "GPB";
|
|
||||||
|
|
||||||
// A Timestamp represents a point in time independent of any time zone or local
|
|
||||||
// calendar, encoded as a count of seconds and fractions of seconds at
|
|
||||||
// nanosecond resolution. The count is relative to an epoch at UTC midnight on
|
|
||||||
// January 1, 1970, in the proleptic Gregorian calendar which extends the
|
|
||||||
// Gregorian calendar backwards to year one.
|
|
||||||
//
|
|
||||||
// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
|
|
||||||
// second table is needed for interpretation, using a [24-hour linear
|
|
||||||
// smear](https://developers.google.com/time/smear).
|
|
||||||
//
|
|
||||||
// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
|
|
||||||
// restricting to that range, we ensure that we can convert to and from [RFC
|
|
||||||
// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
|
|
||||||
//
|
|
||||||
// # Examples
|
|
||||||
//
|
|
||||||
// Example 1: Compute Timestamp from POSIX `time()`.
|
|
||||||
//
|
|
||||||
// Timestamp timestamp;
|
|
||||||
// timestamp.set_seconds(time(NULL));
|
|
||||||
// timestamp.set_nanos(0);
|
|
||||||
//
|
|
||||||
// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
|
|
||||||
//
|
|
||||||
// struct timeval tv;
|
|
||||||
// gettimeofday(&tv, NULL);
|
|
||||||
//
|
|
||||||
// Timestamp timestamp;
|
|
||||||
// timestamp.set_seconds(tv.tv_sec);
|
|
||||||
// timestamp.set_nanos(tv.tv_usec * 1000);
|
|
||||||
//
|
|
||||||
// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
|
|
||||||
//
|
|
||||||
// FILETIME ft;
|
|
||||||
// GetSystemTimeAsFileTime(&ft);
|
|
||||||
// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
|
|
||||||
//
|
|
||||||
// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
|
|
||||||
// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
|
|
||||||
// Timestamp timestamp;
|
|
||||||
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
|
|
||||||
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
|
|
||||||
//
|
|
||||||
// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
|
|
||||||
//
|
|
||||||
// long millis = System.currentTimeMillis();
|
|
||||||
//
|
|
||||||
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
|
|
||||||
// .setNanos((int) ((millis % 1000) * 1000000)).build();
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Example 5: Compute Timestamp from current time in Python.
|
|
||||||
//
|
|
||||||
// timestamp = Timestamp()
|
|
||||||
// timestamp.GetCurrentTime()
|
|
||||||
//
|
|
||||||
// # JSON Mapping
|
|
||||||
//
|
|
||||||
// In JSON format, the Timestamp type is encoded as a string in the
|
|
||||||
// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
|
|
||||||
// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
|
|
||||||
// where {year} is always expressed using four digits while {month}, {day},
|
|
||||||
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
|
|
||||||
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
|
|
||||||
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
|
|
||||||
// is required. A proto3 JSON serializer should always use UTC (as indicated by
|
|
||||||
// "Z") when printing the Timestamp type and a proto3 JSON parser should be
|
|
||||||
// able to accept both UTC and other timezones (as indicated by an offset).
|
|
||||||
//
|
|
||||||
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
|
|
||||||
// 01:30 UTC on January 15, 2017.
|
|
||||||
//
|
|
||||||
// In JavaScript, one can convert a Date object to this format using the
|
|
||||||
// standard
|
|
||||||
// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
|
|
||||||
// method. In Python, a standard `datetime.datetime` object can be converted
|
|
||||||
// to this format using
|
|
||||||
// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
|
|
||||||
// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
|
|
||||||
// the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
|
||||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
|
|
||||||
// ) to obtain a formatter capable of generating timestamps in this format.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
message Timestamp {
|
|
||||||
// Represents seconds of UTC time since Unix epoch
|
|
||||||
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
|
|
||||||
// 9999-12-31T23:59:59Z inclusive.
|
|
||||||
int64 seconds = 1;
|
|
||||||
|
|
||||||
// Non-negative fractions of a second at nanosecond resolution. Negative
|
|
||||||
// second values with fractions must still have non-negative nanos values
|
|
||||||
// that count forward in time. Must be from 0 to 999,999,999
|
|
||||||
// inclusive.
|
|
||||||
int32 nanos = 2;
|
|
||||||
}
|
|
23
vendor/golang.org/x/net/internal/socket/sys_bsdvar.go
generated
vendored
23
vendor/golang.org/x/net/internal/socket/sys_bsdvar.go
generated
vendored
@ -1,23 +0,0 @@
|
|||||||
// Copyright 2017 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 freebsd netbsd openbsd
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func probeProtocolStack() int {
|
|
||||||
if (runtime.GOOS == "netbsd" || runtime.GOOS == "openbsd") && runtime.GOARCH == "arm" {
|
|
||||||
return 8
|
|
||||||
}
|
|
||||||
if runtime.GOOS == "aix" {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
var p uintptr
|
|
||||||
return int(unsafe.Sizeof(p))
|
|
||||||
}
|
|
7
vendor/golang.org/x/net/internal/socket/sys_darwin.go
generated
vendored
7
vendor/golang.org/x/net/internal/socket/sys_darwin.go
generated
vendored
@ -1,7 +0,0 @@
|
|||||||
// Copyright 2017 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 socket
|
|
||||||
|
|
||||||
func probeProtocolStack() int { return 4 }
|
|
32
vendor/golang.org/x/net/internal/socket/sys_dragonfly.go
generated
vendored
32
vendor/golang.org/x/net/internal/socket/sys_dragonfly.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
// Copyright 2017 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 socket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// See version list in https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/param.h
|
|
||||||
var (
|
|
||||||
osreldateOnce sync.Once
|
|
||||||
osreldate uint32
|
|
||||||
)
|
|
||||||
|
|
||||||
// First __DragonFly_version after September 2019 ABI changes
|
|
||||||
// http://lists.dragonflybsd.org/pipermail/users/2019-September/358280.html
|
|
||||||
const _dragonflyABIChangeVersion = 500705
|
|
||||||
|
|
||||||
func probeProtocolStack() int {
|
|
||||||
osreldateOnce.Do(func() { osreldate, _ = syscall.SysctlUint32("kern.osreldate") })
|
|
||||||
var p uintptr
|
|
||||||
if int(unsafe.Sizeof(p)) == 8 && osreldate >= _dragonflyABIChangeVersion {
|
|
||||||
return int(unsafe.Sizeof(p))
|
|
||||||
}
|
|
||||||
// 64-bit Dragonfly before the September 2019 ABI changes still requires
|
|
||||||
// 32-bit aligned access to network subsystem.
|
|
||||||
return 4
|
|
||||||
}
|
|
33
vendor/golang.org/x/net/internal/socket/sys_go1_11_darwin.go
generated
vendored
33
vendor/golang.org/x/net/internal/socket/sys_go1_11_darwin.go
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
// Copyright 2018 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 !go1.12
|
|
||||||
|
|
||||||
package socket
|
|
||||||
|
|
||||||
import (
|
|
||||||
"syscall"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getsockopt(s uintptr, level, name int, b []byte) (int, error) {
|
|
||||||
l := uint32(len(b))
|
|
||||||
_, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(unsafe.Pointer(&l)), 0)
|
|
||||||
return int(l), errnoErr(errno)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setsockopt(s uintptr, level, name int, b []byte) error {
|
|
||||||
_, _, errno := syscall.Syscall6(syscall.SYS_SETSOCKOPT, s, uintptr(level), uintptr(name), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), 0)
|
|
||||||
return errnoErr(errno)
|
|
||||||
}
|
|
||||||
|
|
||||||
func recvmsg(s uintptr, h *msghdr, flags int) (int, error) {
|
|
||||||
n, _, errno := syscall.Syscall(syscall.SYS_RECVMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
|
|
||||||
return int(n), errnoErr(errno)
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendmsg(s uintptr, h *msghdr, flags int) (int, error) {
|
|
||||||
n, _, errno := syscall.Syscall(syscall.SYS_SENDMSG, s, uintptr(unsafe.Pointer(h)), uintptr(flags))
|
|
||||||
return int(n), errnoErr(errno)
|
|
||||||
}
|
|
9
vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_darwin_386.1_11.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
// Copyright 2019 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 darwin,386,!go1.12
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
|
|
9
vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go
generated
vendored
9
vendor/golang.org/x/sys/unix/syscall_darwin_amd64.1_11.go
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
// Copyright 2019 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 darwin,amd64,!go1.12
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
|
|
11
vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go
generated
vendored
11
vendor/golang.org/x/sys/unix/syscall_darwin_arm.1_11.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
// Copyright 2019 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 darwin,arm,!go1.12
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
|
||||||
return 0, ENOSYS
|
|
||||||
}
|
|
11
vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go
generated
vendored
11
vendor/golang.org/x/sys/unix/syscall_darwin_arm64.1_11.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
// Copyright 2019 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 darwin,arm64,!go1.12
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
|
|
||||||
return 0, ENOSYS
|
|
||||||
}
|
|
1811
vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go
generated
vendored
1811
vendor/golang.org/x/sys/unix/zsyscall_darwin_386.1_11.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1811
vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go
generated
vendored
1811
vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.1_11.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1784
vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go
generated
vendored
1784
vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.1_11.go
generated
vendored
File diff suppressed because it is too large
Load Diff
1784
vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go
generated
vendored
1784
vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.1_11.go
generated
vendored
File diff suppressed because it is too large
Load Diff
436
vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go
generated
vendored
436
vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go
generated
vendored
@ -1,436 +0,0 @@
|
|||||||
// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/sys/syscall.h
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build 386,darwin
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
const (
|
|
||||||
SYS_SYSCALL = 0
|
|
||||||
SYS_EXIT = 1
|
|
||||||
SYS_FORK = 2
|
|
||||||
SYS_READ = 3
|
|
||||||
SYS_WRITE = 4
|
|
||||||
SYS_OPEN = 5
|
|
||||||
SYS_CLOSE = 6
|
|
||||||
SYS_WAIT4 = 7
|
|
||||||
SYS_LINK = 9
|
|
||||||
SYS_UNLINK = 10
|
|
||||||
SYS_CHDIR = 12
|
|
||||||
SYS_FCHDIR = 13
|
|
||||||
SYS_MKNOD = 14
|
|
||||||
SYS_CHMOD = 15
|
|
||||||
SYS_CHOWN = 16
|
|
||||||
SYS_GETFSSTAT = 18
|
|
||||||
SYS_GETPID = 20
|
|
||||||
SYS_SETUID = 23
|
|
||||||
SYS_GETUID = 24
|
|
||||||
SYS_GETEUID = 25
|
|
||||||
SYS_PTRACE = 26
|
|
||||||
SYS_RECVMSG = 27
|
|
||||||
SYS_SENDMSG = 28
|
|
||||||
SYS_RECVFROM = 29
|
|
||||||
SYS_ACCEPT = 30
|
|
||||||
SYS_GETPEERNAME = 31
|
|
||||||
SYS_GETSOCKNAME = 32
|
|
||||||
SYS_ACCESS = 33
|
|
||||||
SYS_CHFLAGS = 34
|
|
||||||
SYS_FCHFLAGS = 35
|
|
||||||
SYS_SYNC = 36
|
|
||||||
SYS_KILL = 37
|
|
||||||
SYS_GETPPID = 39
|
|
||||||
SYS_DUP = 41
|
|
||||||
SYS_PIPE = 42
|
|
||||||
SYS_GETEGID = 43
|
|
||||||
SYS_SIGACTION = 46
|
|
||||||
SYS_GETGID = 47
|
|
||||||
SYS_SIGPROCMASK = 48
|
|
||||||
SYS_GETLOGIN = 49
|
|
||||||
SYS_SETLOGIN = 50
|
|
||||||
SYS_ACCT = 51
|
|
||||||
SYS_SIGPENDING = 52
|
|
||||||
SYS_SIGALTSTACK = 53
|
|
||||||
SYS_IOCTL = 54
|
|
||||||
SYS_REBOOT = 55
|
|
||||||
SYS_REVOKE = 56
|
|
||||||
SYS_SYMLINK = 57
|
|
||||||
SYS_READLINK = 58
|
|
||||||
SYS_EXECVE = 59
|
|
||||||
SYS_UMASK = 60
|
|
||||||
SYS_CHROOT = 61
|
|
||||||
SYS_MSYNC = 65
|
|
||||||
SYS_VFORK = 66
|
|
||||||
SYS_MUNMAP = 73
|
|
||||||
SYS_MPROTECT = 74
|
|
||||||
SYS_MADVISE = 75
|
|
||||||
SYS_MINCORE = 78
|
|
||||||
SYS_GETGROUPS = 79
|
|
||||||
SYS_SETGROUPS = 80
|
|
||||||
SYS_GETPGRP = 81
|
|
||||||
SYS_SETPGID = 82
|
|
||||||
SYS_SETITIMER = 83
|
|
||||||
SYS_SWAPON = 85
|
|
||||||
SYS_GETITIMER = 86
|
|
||||||
SYS_GETDTABLESIZE = 89
|
|
||||||
SYS_DUP2 = 90
|
|
||||||
SYS_FCNTL = 92
|
|
||||||
SYS_SELECT = 93
|
|
||||||
SYS_FSYNC = 95
|
|
||||||
SYS_SETPRIORITY = 96
|
|
||||||
SYS_SOCKET = 97
|
|
||||||
SYS_CONNECT = 98
|
|
||||||
SYS_GETPRIORITY = 100
|
|
||||||
SYS_BIND = 104
|
|
||||||
SYS_SETSOCKOPT = 105
|
|
||||||
SYS_LISTEN = 106
|
|
||||||
SYS_SIGSUSPEND = 111
|
|
||||||
SYS_GETTIMEOFDAY = 116
|
|
||||||
SYS_GETRUSAGE = 117
|
|
||||||
SYS_GETSOCKOPT = 118
|
|
||||||
SYS_READV = 120
|
|
||||||
SYS_WRITEV = 121
|
|
||||||
SYS_SETTIMEOFDAY = 122
|
|
||||||
SYS_FCHOWN = 123
|
|
||||||
SYS_FCHMOD = 124
|
|
||||||
SYS_SETREUID = 126
|
|
||||||
SYS_SETREGID = 127
|
|
||||||
SYS_RENAME = 128
|
|
||||||
SYS_FLOCK = 131
|
|
||||||
SYS_MKFIFO = 132
|
|
||||||
SYS_SENDTO = 133
|
|
||||||
SYS_SHUTDOWN = 134
|
|
||||||
SYS_SOCKETPAIR = 135
|
|
||||||
SYS_MKDIR = 136
|
|
||||||
SYS_RMDIR = 137
|
|
||||||
SYS_UTIMES = 138
|
|
||||||
SYS_FUTIMES = 139
|
|
||||||
SYS_ADJTIME = 140
|
|
||||||
SYS_GETHOSTUUID = 142
|
|
||||||
SYS_SETSID = 147
|
|
||||||
SYS_GETPGID = 151
|
|
||||||
SYS_SETPRIVEXEC = 152
|
|
||||||
SYS_PREAD = 153
|
|
||||||
SYS_PWRITE = 154
|
|
||||||
SYS_NFSSVC = 155
|
|
||||||
SYS_STATFS = 157
|
|
||||||
SYS_FSTATFS = 158
|
|
||||||
SYS_UNMOUNT = 159
|
|
||||||
SYS_GETFH = 161
|
|
||||||
SYS_QUOTACTL = 165
|
|
||||||
SYS_MOUNT = 167
|
|
||||||
SYS_CSOPS = 169
|
|
||||||
SYS_CSOPS_AUDITTOKEN = 170
|
|
||||||
SYS_WAITID = 173
|
|
||||||
SYS_KDEBUG_TYPEFILTER = 177
|
|
||||||
SYS_KDEBUG_TRACE_STRING = 178
|
|
||||||
SYS_KDEBUG_TRACE64 = 179
|
|
||||||
SYS_KDEBUG_TRACE = 180
|
|
||||||
SYS_SETGID = 181
|
|
||||||
SYS_SETEGID = 182
|
|
||||||
SYS_SETEUID = 183
|
|
||||||
SYS_SIGRETURN = 184
|
|
||||||
SYS_THREAD_SELFCOUNTS = 186
|
|
||||||
SYS_FDATASYNC = 187
|
|
||||||
SYS_STAT = 188
|
|
||||||
SYS_FSTAT = 189
|
|
||||||
SYS_LSTAT = 190
|
|
||||||
SYS_PATHCONF = 191
|
|
||||||
SYS_FPATHCONF = 192
|
|
||||||
SYS_GETRLIMIT = 194
|
|
||||||
SYS_SETRLIMIT = 195
|
|
||||||
SYS_GETDIRENTRIES = 196
|
|
||||||
SYS_MMAP = 197
|
|
||||||
SYS_LSEEK = 199
|
|
||||||
SYS_TRUNCATE = 200
|
|
||||||
SYS_FTRUNCATE = 201
|
|
||||||
SYS_SYSCTL = 202
|
|
||||||
SYS_MLOCK = 203
|
|
||||||
SYS_MUNLOCK = 204
|
|
||||||
SYS_UNDELETE = 205
|
|
||||||
SYS_OPEN_DPROTECTED_NP = 216
|
|
||||||
SYS_GETATTRLIST = 220
|
|
||||||
SYS_SETATTRLIST = 221
|
|
||||||
SYS_GETDIRENTRIESATTR = 222
|
|
||||||
SYS_EXCHANGEDATA = 223
|
|
||||||
SYS_SEARCHFS = 225
|
|
||||||
SYS_DELETE = 226
|
|
||||||
SYS_COPYFILE = 227
|
|
||||||
SYS_FGETATTRLIST = 228
|
|
||||||
SYS_FSETATTRLIST = 229
|
|
||||||
SYS_POLL = 230
|
|
||||||
SYS_WATCHEVENT = 231
|
|
||||||
SYS_WAITEVENT = 232
|
|
||||||
SYS_MODWATCH = 233
|
|
||||||
SYS_GETXATTR = 234
|
|
||||||
SYS_FGETXATTR = 235
|
|
||||||
SYS_SETXATTR = 236
|
|
||||||
SYS_FSETXATTR = 237
|
|
||||||
SYS_REMOVEXATTR = 238
|
|
||||||
SYS_FREMOVEXATTR = 239
|
|
||||||
SYS_LISTXATTR = 240
|
|
||||||
SYS_FLISTXATTR = 241
|
|
||||||
SYS_FSCTL = 242
|
|
||||||
SYS_INITGROUPS = 243
|
|
||||||
SYS_POSIX_SPAWN = 244
|
|
||||||
SYS_FFSCTL = 245
|
|
||||||
SYS_NFSCLNT = 247
|
|
||||||
SYS_FHOPEN = 248
|
|
||||||
SYS_MINHERIT = 250
|
|
||||||
SYS_SEMSYS = 251
|
|
||||||
SYS_MSGSYS = 252
|
|
||||||
SYS_SHMSYS = 253
|
|
||||||
SYS_SEMCTL = 254
|
|
||||||
SYS_SEMGET = 255
|
|
||||||
SYS_SEMOP = 256
|
|
||||||
SYS_MSGCTL = 258
|
|
||||||
SYS_MSGGET = 259
|
|
||||||
SYS_MSGSND = 260
|
|
||||||
SYS_MSGRCV = 261
|
|
||||||
SYS_SHMAT = 262
|
|
||||||
SYS_SHMCTL = 263
|
|
||||||
SYS_SHMDT = 264
|
|
||||||
SYS_SHMGET = 265
|
|
||||||
SYS_SHM_OPEN = 266
|
|
||||||
SYS_SHM_UNLINK = 267
|
|
||||||
SYS_SEM_OPEN = 268
|
|
||||||
SYS_SEM_CLOSE = 269
|
|
||||||
SYS_SEM_UNLINK = 270
|
|
||||||
SYS_SEM_WAIT = 271
|
|
||||||
SYS_SEM_TRYWAIT = 272
|
|
||||||
SYS_SEM_POST = 273
|
|
||||||
SYS_SYSCTLBYNAME = 274
|
|
||||||
SYS_OPEN_EXTENDED = 277
|
|
||||||
SYS_UMASK_EXTENDED = 278
|
|
||||||
SYS_STAT_EXTENDED = 279
|
|
||||||
SYS_LSTAT_EXTENDED = 280
|
|
||||||
SYS_FSTAT_EXTENDED = 281
|
|
||||||
SYS_CHMOD_EXTENDED = 282
|
|
||||||
SYS_FCHMOD_EXTENDED = 283
|
|
||||||
SYS_ACCESS_EXTENDED = 284
|
|
||||||
SYS_SETTID = 285
|
|
||||||
SYS_GETTID = 286
|
|
||||||
SYS_SETSGROUPS = 287
|
|
||||||
SYS_GETSGROUPS = 288
|
|
||||||
SYS_SETWGROUPS = 289
|
|
||||||
SYS_GETWGROUPS = 290
|
|
||||||
SYS_MKFIFO_EXTENDED = 291
|
|
||||||
SYS_MKDIR_EXTENDED = 292
|
|
||||||
SYS_IDENTITYSVC = 293
|
|
||||||
SYS_SHARED_REGION_CHECK_NP = 294
|
|
||||||
SYS_VM_PRESSURE_MONITOR = 296
|
|
||||||
SYS_PSYNCH_RW_LONGRDLOCK = 297
|
|
||||||
SYS_PSYNCH_RW_YIELDWRLOCK = 298
|
|
||||||
SYS_PSYNCH_RW_DOWNGRADE = 299
|
|
||||||
SYS_PSYNCH_RW_UPGRADE = 300
|
|
||||||
SYS_PSYNCH_MUTEXWAIT = 301
|
|
||||||
SYS_PSYNCH_MUTEXDROP = 302
|
|
||||||
SYS_PSYNCH_CVBROAD = 303
|
|
||||||
SYS_PSYNCH_CVSIGNAL = 304
|
|
||||||
SYS_PSYNCH_CVWAIT = 305
|
|
||||||
SYS_PSYNCH_RW_RDLOCK = 306
|
|
||||||
SYS_PSYNCH_RW_WRLOCK = 307
|
|
||||||
SYS_PSYNCH_RW_UNLOCK = 308
|
|
||||||
SYS_PSYNCH_RW_UNLOCK2 = 309
|
|
||||||
SYS_GETSID = 310
|
|
||||||
SYS_SETTID_WITH_PID = 311
|
|
||||||
SYS_PSYNCH_CVCLRPREPOST = 312
|
|
||||||
SYS_AIO_FSYNC = 313
|
|
||||||
SYS_AIO_RETURN = 314
|
|
||||||
SYS_AIO_SUSPEND = 315
|
|
||||||
SYS_AIO_CANCEL = 316
|
|
||||||
SYS_AIO_ERROR = 317
|
|
||||||
SYS_AIO_READ = 318
|
|
||||||
SYS_AIO_WRITE = 319
|
|
||||||
SYS_LIO_LISTIO = 320
|
|
||||||
SYS_IOPOLICYSYS = 322
|
|
||||||
SYS_PROCESS_POLICY = 323
|
|
||||||
SYS_MLOCKALL = 324
|
|
||||||
SYS_MUNLOCKALL = 325
|
|
||||||
SYS_ISSETUGID = 327
|
|
||||||
SYS___PTHREAD_KILL = 328
|
|
||||||
SYS___PTHREAD_SIGMASK = 329
|
|
||||||
SYS___SIGWAIT = 330
|
|
||||||
SYS___DISABLE_THREADSIGNAL = 331
|
|
||||||
SYS___PTHREAD_MARKCANCEL = 332
|
|
||||||
SYS___PTHREAD_CANCELED = 333
|
|
||||||
SYS___SEMWAIT_SIGNAL = 334
|
|
||||||
SYS_PROC_INFO = 336
|
|
||||||
SYS_SENDFILE = 337
|
|
||||||
SYS_STAT64 = 338
|
|
||||||
SYS_FSTAT64 = 339
|
|
||||||
SYS_LSTAT64 = 340
|
|
||||||
SYS_STAT64_EXTENDED = 341
|
|
||||||
SYS_LSTAT64_EXTENDED = 342
|
|
||||||
SYS_FSTAT64_EXTENDED = 343
|
|
||||||
SYS_GETDIRENTRIES64 = 344
|
|
||||||
SYS_STATFS64 = 345
|
|
||||||
SYS_FSTATFS64 = 346
|
|
||||||
SYS_GETFSSTAT64 = 347
|
|
||||||
SYS___PTHREAD_CHDIR = 348
|
|
||||||
SYS___PTHREAD_FCHDIR = 349
|
|
||||||
SYS_AUDIT = 350
|
|
||||||
SYS_AUDITON = 351
|
|
||||||
SYS_GETAUID = 353
|
|
||||||
SYS_SETAUID = 354
|
|
||||||
SYS_GETAUDIT_ADDR = 357
|
|
||||||
SYS_SETAUDIT_ADDR = 358
|
|
||||||
SYS_AUDITCTL = 359
|
|
||||||
SYS_BSDTHREAD_CREATE = 360
|
|
||||||
SYS_BSDTHREAD_TERMINATE = 361
|
|
||||||
SYS_KQUEUE = 362
|
|
||||||
SYS_KEVENT = 363
|
|
||||||
SYS_LCHOWN = 364
|
|
||||||
SYS_BSDTHREAD_REGISTER = 366
|
|
||||||
SYS_WORKQ_OPEN = 367
|
|
||||||
SYS_WORKQ_KERNRETURN = 368
|
|
||||||
SYS_KEVENT64 = 369
|
|
||||||
SYS___OLD_SEMWAIT_SIGNAL = 370
|
|
||||||
SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371
|
|
||||||
SYS_THREAD_SELFID = 372
|
|
||||||
SYS_LEDGER = 373
|
|
||||||
SYS_KEVENT_QOS = 374
|
|
||||||
SYS_KEVENT_ID = 375
|
|
||||||
SYS___MAC_EXECVE = 380
|
|
||||||
SYS___MAC_SYSCALL = 381
|
|
||||||
SYS___MAC_GET_FILE = 382
|
|
||||||
SYS___MAC_SET_FILE = 383
|
|
||||||
SYS___MAC_GET_LINK = 384
|
|
||||||
SYS___MAC_SET_LINK = 385
|
|
||||||
SYS___MAC_GET_PROC = 386
|
|
||||||
SYS___MAC_SET_PROC = 387
|
|
||||||
SYS___MAC_GET_FD = 388
|
|
||||||
SYS___MAC_SET_FD = 389
|
|
||||||
SYS___MAC_GET_PID = 390
|
|
||||||
SYS_PSELECT = 394
|
|
||||||
SYS_PSELECT_NOCANCEL = 395
|
|
||||||
SYS_READ_NOCANCEL = 396
|
|
||||||
SYS_WRITE_NOCANCEL = 397
|
|
||||||
SYS_OPEN_NOCANCEL = 398
|
|
||||||
SYS_CLOSE_NOCANCEL = 399
|
|
||||||
SYS_WAIT4_NOCANCEL = 400
|
|
||||||
SYS_RECVMSG_NOCANCEL = 401
|
|
||||||
SYS_SENDMSG_NOCANCEL = 402
|
|
||||||
SYS_RECVFROM_NOCANCEL = 403
|
|
||||||
SYS_ACCEPT_NOCANCEL = 404
|
|
||||||
SYS_MSYNC_NOCANCEL = 405
|
|
||||||
SYS_FCNTL_NOCANCEL = 406
|
|
||||||
SYS_SELECT_NOCANCEL = 407
|
|
||||||
SYS_FSYNC_NOCANCEL = 408
|
|
||||||
SYS_CONNECT_NOCANCEL = 409
|
|
||||||
SYS_SIGSUSPEND_NOCANCEL = 410
|
|
||||||
SYS_READV_NOCANCEL = 411
|
|
||||||
SYS_WRITEV_NOCANCEL = 412
|
|
||||||
SYS_SENDTO_NOCANCEL = 413
|
|
||||||
SYS_PREAD_NOCANCEL = 414
|
|
||||||
SYS_PWRITE_NOCANCEL = 415
|
|
||||||
SYS_WAITID_NOCANCEL = 416
|
|
||||||
SYS_POLL_NOCANCEL = 417
|
|
||||||
SYS_MSGSND_NOCANCEL = 418
|
|
||||||
SYS_MSGRCV_NOCANCEL = 419
|
|
||||||
SYS_SEM_WAIT_NOCANCEL = 420
|
|
||||||
SYS_AIO_SUSPEND_NOCANCEL = 421
|
|
||||||
SYS___SIGWAIT_NOCANCEL = 422
|
|
||||||
SYS___SEMWAIT_SIGNAL_NOCANCEL = 423
|
|
||||||
SYS___MAC_MOUNT = 424
|
|
||||||
SYS___MAC_GET_MOUNT = 425
|
|
||||||
SYS___MAC_GETFSSTAT = 426
|
|
||||||
SYS_FSGETPATH = 427
|
|
||||||
SYS_AUDIT_SESSION_SELF = 428
|
|
||||||
SYS_AUDIT_SESSION_JOIN = 429
|
|
||||||
SYS_FILEPORT_MAKEPORT = 430
|
|
||||||
SYS_FILEPORT_MAKEFD = 431
|
|
||||||
SYS_AUDIT_SESSION_PORT = 432
|
|
||||||
SYS_PID_SUSPEND = 433
|
|
||||||
SYS_PID_RESUME = 434
|
|
||||||
SYS_PID_HIBERNATE = 435
|
|
||||||
SYS_PID_SHUTDOWN_SOCKETS = 436
|
|
||||||
SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438
|
|
||||||
SYS_KAS_INFO = 439
|
|
||||||
SYS_MEMORYSTATUS_CONTROL = 440
|
|
||||||
SYS_GUARDED_OPEN_NP = 441
|
|
||||||
SYS_GUARDED_CLOSE_NP = 442
|
|
||||||
SYS_GUARDED_KQUEUE_NP = 443
|
|
||||||
SYS_CHANGE_FDGUARD_NP = 444
|
|
||||||
SYS_USRCTL = 445
|
|
||||||
SYS_PROC_RLIMIT_CONTROL = 446
|
|
||||||
SYS_CONNECTX = 447
|
|
||||||
SYS_DISCONNECTX = 448
|
|
||||||
SYS_PEELOFF = 449
|
|
||||||
SYS_SOCKET_DELEGATE = 450
|
|
||||||
SYS_TELEMETRY = 451
|
|
||||||
SYS_PROC_UUID_POLICY = 452
|
|
||||||
SYS_MEMORYSTATUS_GET_LEVEL = 453
|
|
||||||
SYS_SYSTEM_OVERRIDE = 454
|
|
||||||
SYS_VFS_PURGE = 455
|
|
||||||
SYS_SFI_CTL = 456
|
|
||||||
SYS_SFI_PIDCTL = 457
|
|
||||||
SYS_COALITION = 458
|
|
||||||
SYS_COALITION_INFO = 459
|
|
||||||
SYS_NECP_MATCH_POLICY = 460
|
|
||||||
SYS_GETATTRLISTBULK = 461
|
|
||||||
SYS_CLONEFILEAT = 462
|
|
||||||
SYS_OPENAT = 463
|
|
||||||
SYS_OPENAT_NOCANCEL = 464
|
|
||||||
SYS_RENAMEAT = 465
|
|
||||||
SYS_FACCESSAT = 466
|
|
||||||
SYS_FCHMODAT = 467
|
|
||||||
SYS_FCHOWNAT = 468
|
|
||||||
SYS_FSTATAT = 469
|
|
||||||
SYS_FSTATAT64 = 470
|
|
||||||
SYS_LINKAT = 471
|
|
||||||
SYS_UNLINKAT = 472
|
|
||||||
SYS_READLINKAT = 473
|
|
||||||
SYS_SYMLINKAT = 474
|
|
||||||
SYS_MKDIRAT = 475
|
|
||||||
SYS_GETATTRLISTAT = 476
|
|
||||||
SYS_PROC_TRACE_LOG = 477
|
|
||||||
SYS_BSDTHREAD_CTL = 478
|
|
||||||
SYS_OPENBYID_NP = 479
|
|
||||||
SYS_RECVMSG_X = 480
|
|
||||||
SYS_SENDMSG_X = 481
|
|
||||||
SYS_THREAD_SELFUSAGE = 482
|
|
||||||
SYS_CSRCTL = 483
|
|
||||||
SYS_GUARDED_OPEN_DPROTECTED_NP = 484
|
|
||||||
SYS_GUARDED_WRITE_NP = 485
|
|
||||||
SYS_GUARDED_PWRITE_NP = 486
|
|
||||||
SYS_GUARDED_WRITEV_NP = 487
|
|
||||||
SYS_RENAMEATX_NP = 488
|
|
||||||
SYS_MREMAP_ENCRYPTED = 489
|
|
||||||
SYS_NETAGENT_TRIGGER = 490
|
|
||||||
SYS_STACK_SNAPSHOT_WITH_CONFIG = 491
|
|
||||||
SYS_MICROSTACKSHOT = 492
|
|
||||||
SYS_GRAB_PGO_DATA = 493
|
|
||||||
SYS_PERSONA = 494
|
|
||||||
SYS_WORK_INTERVAL_CTL = 499
|
|
||||||
SYS_GETENTROPY = 500
|
|
||||||
SYS_NECP_OPEN = 501
|
|
||||||
SYS_NECP_CLIENT_ACTION = 502
|
|
||||||
SYS___NEXUS_OPEN = 503
|
|
||||||
SYS___NEXUS_REGISTER = 504
|
|
||||||
SYS___NEXUS_DEREGISTER = 505
|
|
||||||
SYS___NEXUS_CREATE = 506
|
|
||||||
SYS___NEXUS_DESTROY = 507
|
|
||||||
SYS___NEXUS_GET_OPT = 508
|
|
||||||
SYS___NEXUS_SET_OPT = 509
|
|
||||||
SYS___CHANNEL_OPEN = 510
|
|
||||||
SYS___CHANNEL_GET_INFO = 511
|
|
||||||
SYS___CHANNEL_SYNC = 512
|
|
||||||
SYS___CHANNEL_GET_OPT = 513
|
|
||||||
SYS___CHANNEL_SET_OPT = 514
|
|
||||||
SYS_ULOCK_WAIT = 515
|
|
||||||
SYS_ULOCK_WAKE = 516
|
|
||||||
SYS_FCLONEFILEAT = 517
|
|
||||||
SYS_FS_SNAPSHOT = 518
|
|
||||||
SYS_TERMINATE_WITH_PAYLOAD = 520
|
|
||||||
SYS_ABORT_WITH_PAYLOAD = 521
|
|
||||||
SYS_NECP_SESSION_OPEN = 522
|
|
||||||
SYS_NECP_SESSION_ACTION = 523
|
|
||||||
SYS_SETATTRLISTAT = 524
|
|
||||||
SYS_NET_QOS_GUIDELINE = 525
|
|
||||||
SYS_FMOUNT = 526
|
|
||||||
SYS_NTP_ADJTIME = 527
|
|
||||||
SYS_NTP_GETTIME = 528
|
|
||||||
SYS_OS_FAULT_WITH_PAYLOAD = 529
|
|
||||||
SYS_MAXSYSCALL = 530
|
|
||||||
SYS_INVALID = 63
|
|
||||||
)
|
|
438
vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go
generated
vendored
438
vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go
generated
vendored
@ -1,438 +0,0 @@
|
|||||||
// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/sys/syscall.h
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build amd64,darwin
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
const (
|
|
||||||
SYS_SYSCALL = 0
|
|
||||||
SYS_EXIT = 1
|
|
||||||
SYS_FORK = 2
|
|
||||||
SYS_READ = 3
|
|
||||||
SYS_WRITE = 4
|
|
||||||
SYS_OPEN = 5
|
|
||||||
SYS_CLOSE = 6
|
|
||||||
SYS_WAIT4 = 7
|
|
||||||
SYS_LINK = 9
|
|
||||||
SYS_UNLINK = 10
|
|
||||||
SYS_CHDIR = 12
|
|
||||||
SYS_FCHDIR = 13
|
|
||||||
SYS_MKNOD = 14
|
|
||||||
SYS_CHMOD = 15
|
|
||||||
SYS_CHOWN = 16
|
|
||||||
SYS_GETFSSTAT = 18
|
|
||||||
SYS_GETPID = 20
|
|
||||||
SYS_SETUID = 23
|
|
||||||
SYS_GETUID = 24
|
|
||||||
SYS_GETEUID = 25
|
|
||||||
SYS_PTRACE = 26
|
|
||||||
SYS_RECVMSG = 27
|
|
||||||
SYS_SENDMSG = 28
|
|
||||||
SYS_RECVFROM = 29
|
|
||||||
SYS_ACCEPT = 30
|
|
||||||
SYS_GETPEERNAME = 31
|
|
||||||
SYS_GETSOCKNAME = 32
|
|
||||||
SYS_ACCESS = 33
|
|
||||||
SYS_CHFLAGS = 34
|
|
||||||
SYS_FCHFLAGS = 35
|
|
||||||
SYS_SYNC = 36
|
|
||||||
SYS_KILL = 37
|
|
||||||
SYS_GETPPID = 39
|
|
||||||
SYS_DUP = 41
|
|
||||||
SYS_PIPE = 42
|
|
||||||
SYS_GETEGID = 43
|
|
||||||
SYS_SIGACTION = 46
|
|
||||||
SYS_GETGID = 47
|
|
||||||
SYS_SIGPROCMASK = 48
|
|
||||||
SYS_GETLOGIN = 49
|
|
||||||
SYS_SETLOGIN = 50
|
|
||||||
SYS_ACCT = 51
|
|
||||||
SYS_SIGPENDING = 52
|
|
||||||
SYS_SIGALTSTACK = 53
|
|
||||||
SYS_IOCTL = 54
|
|
||||||
SYS_REBOOT = 55
|
|
||||||
SYS_REVOKE = 56
|
|
||||||
SYS_SYMLINK = 57
|
|
||||||
SYS_READLINK = 58
|
|
||||||
SYS_EXECVE = 59
|
|
||||||
SYS_UMASK = 60
|
|
||||||
SYS_CHROOT = 61
|
|
||||||
SYS_MSYNC = 65
|
|
||||||
SYS_VFORK = 66
|
|
||||||
SYS_MUNMAP = 73
|
|
||||||
SYS_MPROTECT = 74
|
|
||||||
SYS_MADVISE = 75
|
|
||||||
SYS_MINCORE = 78
|
|
||||||
SYS_GETGROUPS = 79
|
|
||||||
SYS_SETGROUPS = 80
|
|
||||||
SYS_GETPGRP = 81
|
|
||||||
SYS_SETPGID = 82
|
|
||||||
SYS_SETITIMER = 83
|
|
||||||
SYS_SWAPON = 85
|
|
||||||
SYS_GETITIMER = 86
|
|
||||||
SYS_GETDTABLESIZE = 89
|
|
||||||
SYS_DUP2 = 90
|
|
||||||
SYS_FCNTL = 92
|
|
||||||
SYS_SELECT = 93
|
|
||||||
SYS_FSYNC = 95
|
|
||||||
SYS_SETPRIORITY = 96
|
|
||||||
SYS_SOCKET = 97
|
|
||||||
SYS_CONNECT = 98
|
|
||||||
SYS_GETPRIORITY = 100
|
|
||||||
SYS_BIND = 104
|
|
||||||
SYS_SETSOCKOPT = 105
|
|
||||||
SYS_LISTEN = 106
|
|
||||||
SYS_SIGSUSPEND = 111
|
|
||||||
SYS_GETTIMEOFDAY = 116
|
|
||||||
SYS_GETRUSAGE = 117
|
|
||||||
SYS_GETSOCKOPT = 118
|
|
||||||
SYS_READV = 120
|
|
||||||
SYS_WRITEV = 121
|
|
||||||
SYS_SETTIMEOFDAY = 122
|
|
||||||
SYS_FCHOWN = 123
|
|
||||||
SYS_FCHMOD = 124
|
|
||||||
SYS_SETREUID = 126
|
|
||||||
SYS_SETREGID = 127
|
|
||||||
SYS_RENAME = 128
|
|
||||||
SYS_FLOCK = 131
|
|
||||||
SYS_MKFIFO = 132
|
|
||||||
SYS_SENDTO = 133
|
|
||||||
SYS_SHUTDOWN = 134
|
|
||||||
SYS_SOCKETPAIR = 135
|
|
||||||
SYS_MKDIR = 136
|
|
||||||
SYS_RMDIR = 137
|
|
||||||
SYS_UTIMES = 138
|
|
||||||
SYS_FUTIMES = 139
|
|
||||||
SYS_ADJTIME = 140
|
|
||||||
SYS_GETHOSTUUID = 142
|
|
||||||
SYS_SETSID = 147
|
|
||||||
SYS_GETPGID = 151
|
|
||||||
SYS_SETPRIVEXEC = 152
|
|
||||||
SYS_PREAD = 153
|
|
||||||
SYS_PWRITE = 154
|
|
||||||
SYS_NFSSVC = 155
|
|
||||||
SYS_STATFS = 157
|
|
||||||
SYS_FSTATFS = 158
|
|
||||||
SYS_UNMOUNT = 159
|
|
||||||
SYS_GETFH = 161
|
|
||||||
SYS_QUOTACTL = 165
|
|
||||||
SYS_MOUNT = 167
|
|
||||||
SYS_CSOPS = 169
|
|
||||||
SYS_CSOPS_AUDITTOKEN = 170
|
|
||||||
SYS_WAITID = 173
|
|
||||||
SYS_KDEBUG_TYPEFILTER = 177
|
|
||||||
SYS_KDEBUG_TRACE_STRING = 178
|
|
||||||
SYS_KDEBUG_TRACE64 = 179
|
|
||||||
SYS_KDEBUG_TRACE = 180
|
|
||||||
SYS_SETGID = 181
|
|
||||||
SYS_SETEGID = 182
|
|
||||||
SYS_SETEUID = 183
|
|
||||||
SYS_SIGRETURN = 184
|
|
||||||
SYS_THREAD_SELFCOUNTS = 186
|
|
||||||
SYS_FDATASYNC = 187
|
|
||||||
SYS_STAT = 188
|
|
||||||
SYS_FSTAT = 189
|
|
||||||
SYS_LSTAT = 190
|
|
||||||
SYS_PATHCONF = 191
|
|
||||||
SYS_FPATHCONF = 192
|
|
||||||
SYS_GETRLIMIT = 194
|
|
||||||
SYS_SETRLIMIT = 195
|
|
||||||
SYS_GETDIRENTRIES = 196
|
|
||||||
SYS_MMAP = 197
|
|
||||||
SYS_LSEEK = 199
|
|
||||||
SYS_TRUNCATE = 200
|
|
||||||
SYS_FTRUNCATE = 201
|
|
||||||
SYS_SYSCTL = 202
|
|
||||||
SYS_MLOCK = 203
|
|
||||||
SYS_MUNLOCK = 204
|
|
||||||
SYS_UNDELETE = 205
|
|
||||||
SYS_OPEN_DPROTECTED_NP = 216
|
|
||||||
SYS_GETATTRLIST = 220
|
|
||||||
SYS_SETATTRLIST = 221
|
|
||||||
SYS_GETDIRENTRIESATTR = 222
|
|
||||||
SYS_EXCHANGEDATA = 223
|
|
||||||
SYS_SEARCHFS = 225
|
|
||||||
SYS_DELETE = 226
|
|
||||||
SYS_COPYFILE = 227
|
|
||||||
SYS_FGETATTRLIST = 228
|
|
||||||
SYS_FSETATTRLIST = 229
|
|
||||||
SYS_POLL = 230
|
|
||||||
SYS_WATCHEVENT = 231
|
|
||||||
SYS_WAITEVENT = 232
|
|
||||||
SYS_MODWATCH = 233
|
|
||||||
SYS_GETXATTR = 234
|
|
||||||
SYS_FGETXATTR = 235
|
|
||||||
SYS_SETXATTR = 236
|
|
||||||
SYS_FSETXATTR = 237
|
|
||||||
SYS_REMOVEXATTR = 238
|
|
||||||
SYS_FREMOVEXATTR = 239
|
|
||||||
SYS_LISTXATTR = 240
|
|
||||||
SYS_FLISTXATTR = 241
|
|
||||||
SYS_FSCTL = 242
|
|
||||||
SYS_INITGROUPS = 243
|
|
||||||
SYS_POSIX_SPAWN = 244
|
|
||||||
SYS_FFSCTL = 245
|
|
||||||
SYS_NFSCLNT = 247
|
|
||||||
SYS_FHOPEN = 248
|
|
||||||
SYS_MINHERIT = 250
|
|
||||||
SYS_SEMSYS = 251
|
|
||||||
SYS_MSGSYS = 252
|
|
||||||
SYS_SHMSYS = 253
|
|
||||||
SYS_SEMCTL = 254
|
|
||||||
SYS_SEMGET = 255
|
|
||||||
SYS_SEMOP = 256
|
|
||||||
SYS_MSGCTL = 258
|
|
||||||
SYS_MSGGET = 259
|
|
||||||
SYS_MSGSND = 260
|
|
||||||
SYS_MSGRCV = 261
|
|
||||||
SYS_SHMAT = 262
|
|
||||||
SYS_SHMCTL = 263
|
|
||||||
SYS_SHMDT = 264
|
|
||||||
SYS_SHMGET = 265
|
|
||||||
SYS_SHM_OPEN = 266
|
|
||||||
SYS_SHM_UNLINK = 267
|
|
||||||
SYS_SEM_OPEN = 268
|
|
||||||
SYS_SEM_CLOSE = 269
|
|
||||||
SYS_SEM_UNLINK = 270
|
|
||||||
SYS_SEM_WAIT = 271
|
|
||||||
SYS_SEM_TRYWAIT = 272
|
|
||||||
SYS_SEM_POST = 273
|
|
||||||
SYS_SYSCTLBYNAME = 274
|
|
||||||
SYS_OPEN_EXTENDED = 277
|
|
||||||
SYS_UMASK_EXTENDED = 278
|
|
||||||
SYS_STAT_EXTENDED = 279
|
|
||||||
SYS_LSTAT_EXTENDED = 280
|
|
||||||
SYS_FSTAT_EXTENDED = 281
|
|
||||||
SYS_CHMOD_EXTENDED = 282
|
|
||||||
SYS_FCHMOD_EXTENDED = 283
|
|
||||||
SYS_ACCESS_EXTENDED = 284
|
|
||||||
SYS_SETTID = 285
|
|
||||||
SYS_GETTID = 286
|
|
||||||
SYS_SETSGROUPS = 287
|
|
||||||
SYS_GETSGROUPS = 288
|
|
||||||
SYS_SETWGROUPS = 289
|
|
||||||
SYS_GETWGROUPS = 290
|
|
||||||
SYS_MKFIFO_EXTENDED = 291
|
|
||||||
SYS_MKDIR_EXTENDED = 292
|
|
||||||
SYS_IDENTITYSVC = 293
|
|
||||||
SYS_SHARED_REGION_CHECK_NP = 294
|
|
||||||
SYS_VM_PRESSURE_MONITOR = 296
|
|
||||||
SYS_PSYNCH_RW_LONGRDLOCK = 297
|
|
||||||
SYS_PSYNCH_RW_YIELDWRLOCK = 298
|
|
||||||
SYS_PSYNCH_RW_DOWNGRADE = 299
|
|
||||||
SYS_PSYNCH_RW_UPGRADE = 300
|
|
||||||
SYS_PSYNCH_MUTEXWAIT = 301
|
|
||||||
SYS_PSYNCH_MUTEXDROP = 302
|
|
||||||
SYS_PSYNCH_CVBROAD = 303
|
|
||||||
SYS_PSYNCH_CVSIGNAL = 304
|
|
||||||
SYS_PSYNCH_CVWAIT = 305
|
|
||||||
SYS_PSYNCH_RW_RDLOCK = 306
|
|
||||||
SYS_PSYNCH_RW_WRLOCK = 307
|
|
||||||
SYS_PSYNCH_RW_UNLOCK = 308
|
|
||||||
SYS_PSYNCH_RW_UNLOCK2 = 309
|
|
||||||
SYS_GETSID = 310
|
|
||||||
SYS_SETTID_WITH_PID = 311
|
|
||||||
SYS_PSYNCH_CVCLRPREPOST = 312
|
|
||||||
SYS_AIO_FSYNC = 313
|
|
||||||
SYS_AIO_RETURN = 314
|
|
||||||
SYS_AIO_SUSPEND = 315
|
|
||||||
SYS_AIO_CANCEL = 316
|
|
||||||
SYS_AIO_ERROR = 317
|
|
||||||
SYS_AIO_READ = 318
|
|
||||||
SYS_AIO_WRITE = 319
|
|
||||||
SYS_LIO_LISTIO = 320
|
|
||||||
SYS_IOPOLICYSYS = 322
|
|
||||||
SYS_PROCESS_POLICY = 323
|
|
||||||
SYS_MLOCKALL = 324
|
|
||||||
SYS_MUNLOCKALL = 325
|
|
||||||
SYS_ISSETUGID = 327
|
|
||||||
SYS___PTHREAD_KILL = 328
|
|
||||||
SYS___PTHREAD_SIGMASK = 329
|
|
||||||
SYS___SIGWAIT = 330
|
|
||||||
SYS___DISABLE_THREADSIGNAL = 331
|
|
||||||
SYS___PTHREAD_MARKCANCEL = 332
|
|
||||||
SYS___PTHREAD_CANCELED = 333
|
|
||||||
SYS___SEMWAIT_SIGNAL = 334
|
|
||||||
SYS_PROC_INFO = 336
|
|
||||||
SYS_SENDFILE = 337
|
|
||||||
SYS_STAT64 = 338
|
|
||||||
SYS_FSTAT64 = 339
|
|
||||||
SYS_LSTAT64 = 340
|
|
||||||
SYS_STAT64_EXTENDED = 341
|
|
||||||
SYS_LSTAT64_EXTENDED = 342
|
|
||||||
SYS_FSTAT64_EXTENDED = 343
|
|
||||||
SYS_GETDIRENTRIES64 = 344
|
|
||||||
SYS_STATFS64 = 345
|
|
||||||
SYS_FSTATFS64 = 346
|
|
||||||
SYS_GETFSSTAT64 = 347
|
|
||||||
SYS___PTHREAD_CHDIR = 348
|
|
||||||
SYS___PTHREAD_FCHDIR = 349
|
|
||||||
SYS_AUDIT = 350
|
|
||||||
SYS_AUDITON = 351
|
|
||||||
SYS_GETAUID = 353
|
|
||||||
SYS_SETAUID = 354
|
|
||||||
SYS_GETAUDIT_ADDR = 357
|
|
||||||
SYS_SETAUDIT_ADDR = 358
|
|
||||||
SYS_AUDITCTL = 359
|
|
||||||
SYS_BSDTHREAD_CREATE = 360
|
|
||||||
SYS_BSDTHREAD_TERMINATE = 361
|
|
||||||
SYS_KQUEUE = 362
|
|
||||||
SYS_KEVENT = 363
|
|
||||||
SYS_LCHOWN = 364
|
|
||||||
SYS_BSDTHREAD_REGISTER = 366
|
|
||||||
SYS_WORKQ_OPEN = 367
|
|
||||||
SYS_WORKQ_KERNRETURN = 368
|
|
||||||
SYS_KEVENT64 = 369
|
|
||||||
SYS___OLD_SEMWAIT_SIGNAL = 370
|
|
||||||
SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371
|
|
||||||
SYS_THREAD_SELFID = 372
|
|
||||||
SYS_LEDGER = 373
|
|
||||||
SYS_KEVENT_QOS = 374
|
|
||||||
SYS_KEVENT_ID = 375
|
|
||||||
SYS___MAC_EXECVE = 380
|
|
||||||
SYS___MAC_SYSCALL = 381
|
|
||||||
SYS___MAC_GET_FILE = 382
|
|
||||||
SYS___MAC_SET_FILE = 383
|
|
||||||
SYS___MAC_GET_LINK = 384
|
|
||||||
SYS___MAC_SET_LINK = 385
|
|
||||||
SYS___MAC_GET_PROC = 386
|
|
||||||
SYS___MAC_SET_PROC = 387
|
|
||||||
SYS___MAC_GET_FD = 388
|
|
||||||
SYS___MAC_SET_FD = 389
|
|
||||||
SYS___MAC_GET_PID = 390
|
|
||||||
SYS_PSELECT = 394
|
|
||||||
SYS_PSELECT_NOCANCEL = 395
|
|
||||||
SYS_READ_NOCANCEL = 396
|
|
||||||
SYS_WRITE_NOCANCEL = 397
|
|
||||||
SYS_OPEN_NOCANCEL = 398
|
|
||||||
SYS_CLOSE_NOCANCEL = 399
|
|
||||||
SYS_WAIT4_NOCANCEL = 400
|
|
||||||
SYS_RECVMSG_NOCANCEL = 401
|
|
||||||
SYS_SENDMSG_NOCANCEL = 402
|
|
||||||
SYS_RECVFROM_NOCANCEL = 403
|
|
||||||
SYS_ACCEPT_NOCANCEL = 404
|
|
||||||
SYS_MSYNC_NOCANCEL = 405
|
|
||||||
SYS_FCNTL_NOCANCEL = 406
|
|
||||||
SYS_SELECT_NOCANCEL = 407
|
|
||||||
SYS_FSYNC_NOCANCEL = 408
|
|
||||||
SYS_CONNECT_NOCANCEL = 409
|
|
||||||
SYS_SIGSUSPEND_NOCANCEL = 410
|
|
||||||
SYS_READV_NOCANCEL = 411
|
|
||||||
SYS_WRITEV_NOCANCEL = 412
|
|
||||||
SYS_SENDTO_NOCANCEL = 413
|
|
||||||
SYS_PREAD_NOCANCEL = 414
|
|
||||||
SYS_PWRITE_NOCANCEL = 415
|
|
||||||
SYS_WAITID_NOCANCEL = 416
|
|
||||||
SYS_POLL_NOCANCEL = 417
|
|
||||||
SYS_MSGSND_NOCANCEL = 418
|
|
||||||
SYS_MSGRCV_NOCANCEL = 419
|
|
||||||
SYS_SEM_WAIT_NOCANCEL = 420
|
|
||||||
SYS_AIO_SUSPEND_NOCANCEL = 421
|
|
||||||
SYS___SIGWAIT_NOCANCEL = 422
|
|
||||||
SYS___SEMWAIT_SIGNAL_NOCANCEL = 423
|
|
||||||
SYS___MAC_MOUNT = 424
|
|
||||||
SYS___MAC_GET_MOUNT = 425
|
|
||||||
SYS___MAC_GETFSSTAT = 426
|
|
||||||
SYS_FSGETPATH = 427
|
|
||||||
SYS_AUDIT_SESSION_SELF = 428
|
|
||||||
SYS_AUDIT_SESSION_JOIN = 429
|
|
||||||
SYS_FILEPORT_MAKEPORT = 430
|
|
||||||
SYS_FILEPORT_MAKEFD = 431
|
|
||||||
SYS_AUDIT_SESSION_PORT = 432
|
|
||||||
SYS_PID_SUSPEND = 433
|
|
||||||
SYS_PID_RESUME = 434
|
|
||||||
SYS_PID_HIBERNATE = 435
|
|
||||||
SYS_PID_SHUTDOWN_SOCKETS = 436
|
|
||||||
SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438
|
|
||||||
SYS_KAS_INFO = 439
|
|
||||||
SYS_MEMORYSTATUS_CONTROL = 440
|
|
||||||
SYS_GUARDED_OPEN_NP = 441
|
|
||||||
SYS_GUARDED_CLOSE_NP = 442
|
|
||||||
SYS_GUARDED_KQUEUE_NP = 443
|
|
||||||
SYS_CHANGE_FDGUARD_NP = 444
|
|
||||||
SYS_USRCTL = 445
|
|
||||||
SYS_PROC_RLIMIT_CONTROL = 446
|
|
||||||
SYS_CONNECTX = 447
|
|
||||||
SYS_DISCONNECTX = 448
|
|
||||||
SYS_PEELOFF = 449
|
|
||||||
SYS_SOCKET_DELEGATE = 450
|
|
||||||
SYS_TELEMETRY = 451
|
|
||||||
SYS_PROC_UUID_POLICY = 452
|
|
||||||
SYS_MEMORYSTATUS_GET_LEVEL = 453
|
|
||||||
SYS_SYSTEM_OVERRIDE = 454
|
|
||||||
SYS_VFS_PURGE = 455
|
|
||||||
SYS_SFI_CTL = 456
|
|
||||||
SYS_SFI_PIDCTL = 457
|
|
||||||
SYS_COALITION = 458
|
|
||||||
SYS_COALITION_INFO = 459
|
|
||||||
SYS_NECP_MATCH_POLICY = 460
|
|
||||||
SYS_GETATTRLISTBULK = 461
|
|
||||||
SYS_CLONEFILEAT = 462
|
|
||||||
SYS_OPENAT = 463
|
|
||||||
SYS_OPENAT_NOCANCEL = 464
|
|
||||||
SYS_RENAMEAT = 465
|
|
||||||
SYS_FACCESSAT = 466
|
|
||||||
SYS_FCHMODAT = 467
|
|
||||||
SYS_FCHOWNAT = 468
|
|
||||||
SYS_FSTATAT = 469
|
|
||||||
SYS_FSTATAT64 = 470
|
|
||||||
SYS_LINKAT = 471
|
|
||||||
SYS_UNLINKAT = 472
|
|
||||||
SYS_READLINKAT = 473
|
|
||||||
SYS_SYMLINKAT = 474
|
|
||||||
SYS_MKDIRAT = 475
|
|
||||||
SYS_GETATTRLISTAT = 476
|
|
||||||
SYS_PROC_TRACE_LOG = 477
|
|
||||||
SYS_BSDTHREAD_CTL = 478
|
|
||||||
SYS_OPENBYID_NP = 479
|
|
||||||
SYS_RECVMSG_X = 480
|
|
||||||
SYS_SENDMSG_X = 481
|
|
||||||
SYS_THREAD_SELFUSAGE = 482
|
|
||||||
SYS_CSRCTL = 483
|
|
||||||
SYS_GUARDED_OPEN_DPROTECTED_NP = 484
|
|
||||||
SYS_GUARDED_WRITE_NP = 485
|
|
||||||
SYS_GUARDED_PWRITE_NP = 486
|
|
||||||
SYS_GUARDED_WRITEV_NP = 487
|
|
||||||
SYS_RENAMEATX_NP = 488
|
|
||||||
SYS_MREMAP_ENCRYPTED = 489
|
|
||||||
SYS_NETAGENT_TRIGGER = 490
|
|
||||||
SYS_STACK_SNAPSHOT_WITH_CONFIG = 491
|
|
||||||
SYS_MICROSTACKSHOT = 492
|
|
||||||
SYS_GRAB_PGO_DATA = 493
|
|
||||||
SYS_PERSONA = 494
|
|
||||||
SYS_WORK_INTERVAL_CTL = 499
|
|
||||||
SYS_GETENTROPY = 500
|
|
||||||
SYS_NECP_OPEN = 501
|
|
||||||
SYS_NECP_CLIENT_ACTION = 502
|
|
||||||
SYS___NEXUS_OPEN = 503
|
|
||||||
SYS___NEXUS_REGISTER = 504
|
|
||||||
SYS___NEXUS_DEREGISTER = 505
|
|
||||||
SYS___NEXUS_CREATE = 506
|
|
||||||
SYS___NEXUS_DESTROY = 507
|
|
||||||
SYS___NEXUS_GET_OPT = 508
|
|
||||||
SYS___NEXUS_SET_OPT = 509
|
|
||||||
SYS___CHANNEL_OPEN = 510
|
|
||||||
SYS___CHANNEL_GET_INFO = 511
|
|
||||||
SYS___CHANNEL_SYNC = 512
|
|
||||||
SYS___CHANNEL_GET_OPT = 513
|
|
||||||
SYS___CHANNEL_SET_OPT = 514
|
|
||||||
SYS_ULOCK_WAIT = 515
|
|
||||||
SYS_ULOCK_WAKE = 516
|
|
||||||
SYS_FCLONEFILEAT = 517
|
|
||||||
SYS_FS_SNAPSHOT = 518
|
|
||||||
SYS_TERMINATE_WITH_PAYLOAD = 520
|
|
||||||
SYS_ABORT_WITH_PAYLOAD = 521
|
|
||||||
SYS_NECP_SESSION_OPEN = 522
|
|
||||||
SYS_NECP_SESSION_ACTION = 523
|
|
||||||
SYS_SETATTRLISTAT = 524
|
|
||||||
SYS_NET_QOS_GUIDELINE = 525
|
|
||||||
SYS_FMOUNT = 526
|
|
||||||
SYS_NTP_ADJTIME = 527
|
|
||||||
SYS_NTP_GETTIME = 528
|
|
||||||
SYS_OS_FAULT_WITH_PAYLOAD = 529
|
|
||||||
SYS_KQUEUE_WORKLOOP_CTL = 530
|
|
||||||
SYS___MACH_BRIDGE_REMOTE_TIME = 531
|
|
||||||
SYS_MAXSYSCALL = 532
|
|
||||||
SYS_INVALID = 63
|
|
||||||
)
|
|
436
vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go
generated
vendored
436
vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go
generated
vendored
@ -1,436 +0,0 @@
|
|||||||
// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/sys/syscall.h
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build arm,darwin
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
const (
|
|
||||||
SYS_SYSCALL = 0
|
|
||||||
SYS_EXIT = 1
|
|
||||||
SYS_FORK = 2
|
|
||||||
SYS_READ = 3
|
|
||||||
SYS_WRITE = 4
|
|
||||||
SYS_OPEN = 5
|
|
||||||
SYS_CLOSE = 6
|
|
||||||
SYS_WAIT4 = 7
|
|
||||||
SYS_LINK = 9
|
|
||||||
SYS_UNLINK = 10
|
|
||||||
SYS_CHDIR = 12
|
|
||||||
SYS_FCHDIR = 13
|
|
||||||
SYS_MKNOD = 14
|
|
||||||
SYS_CHMOD = 15
|
|
||||||
SYS_CHOWN = 16
|
|
||||||
SYS_GETFSSTAT = 18
|
|
||||||
SYS_GETPID = 20
|
|
||||||
SYS_SETUID = 23
|
|
||||||
SYS_GETUID = 24
|
|
||||||
SYS_GETEUID = 25
|
|
||||||
SYS_PTRACE = 26
|
|
||||||
SYS_RECVMSG = 27
|
|
||||||
SYS_SENDMSG = 28
|
|
||||||
SYS_RECVFROM = 29
|
|
||||||
SYS_ACCEPT = 30
|
|
||||||
SYS_GETPEERNAME = 31
|
|
||||||
SYS_GETSOCKNAME = 32
|
|
||||||
SYS_ACCESS = 33
|
|
||||||
SYS_CHFLAGS = 34
|
|
||||||
SYS_FCHFLAGS = 35
|
|
||||||
SYS_SYNC = 36
|
|
||||||
SYS_KILL = 37
|
|
||||||
SYS_GETPPID = 39
|
|
||||||
SYS_DUP = 41
|
|
||||||
SYS_PIPE = 42
|
|
||||||
SYS_GETEGID = 43
|
|
||||||
SYS_SIGACTION = 46
|
|
||||||
SYS_GETGID = 47
|
|
||||||
SYS_SIGPROCMASK = 48
|
|
||||||
SYS_GETLOGIN = 49
|
|
||||||
SYS_SETLOGIN = 50
|
|
||||||
SYS_ACCT = 51
|
|
||||||
SYS_SIGPENDING = 52
|
|
||||||
SYS_SIGALTSTACK = 53
|
|
||||||
SYS_IOCTL = 54
|
|
||||||
SYS_REBOOT = 55
|
|
||||||
SYS_REVOKE = 56
|
|
||||||
SYS_SYMLINK = 57
|
|
||||||
SYS_READLINK = 58
|
|
||||||
SYS_EXECVE = 59
|
|
||||||
SYS_UMASK = 60
|
|
||||||
SYS_CHROOT = 61
|
|
||||||
SYS_MSYNC = 65
|
|
||||||
SYS_VFORK = 66
|
|
||||||
SYS_MUNMAP = 73
|
|
||||||
SYS_MPROTECT = 74
|
|
||||||
SYS_MADVISE = 75
|
|
||||||
SYS_MINCORE = 78
|
|
||||||
SYS_GETGROUPS = 79
|
|
||||||
SYS_SETGROUPS = 80
|
|
||||||
SYS_GETPGRP = 81
|
|
||||||
SYS_SETPGID = 82
|
|
||||||
SYS_SETITIMER = 83
|
|
||||||
SYS_SWAPON = 85
|
|
||||||
SYS_GETITIMER = 86
|
|
||||||
SYS_GETDTABLESIZE = 89
|
|
||||||
SYS_DUP2 = 90
|
|
||||||
SYS_FCNTL = 92
|
|
||||||
SYS_SELECT = 93
|
|
||||||
SYS_FSYNC = 95
|
|
||||||
SYS_SETPRIORITY = 96
|
|
||||||
SYS_SOCKET = 97
|
|
||||||
SYS_CONNECT = 98
|
|
||||||
SYS_GETPRIORITY = 100
|
|
||||||
SYS_BIND = 104
|
|
||||||
SYS_SETSOCKOPT = 105
|
|
||||||
SYS_LISTEN = 106
|
|
||||||
SYS_SIGSUSPEND = 111
|
|
||||||
SYS_GETTIMEOFDAY = 116
|
|
||||||
SYS_GETRUSAGE = 117
|
|
||||||
SYS_GETSOCKOPT = 118
|
|
||||||
SYS_READV = 120
|
|
||||||
SYS_WRITEV = 121
|
|
||||||
SYS_SETTIMEOFDAY = 122
|
|
||||||
SYS_FCHOWN = 123
|
|
||||||
SYS_FCHMOD = 124
|
|
||||||
SYS_SETREUID = 126
|
|
||||||
SYS_SETREGID = 127
|
|
||||||
SYS_RENAME = 128
|
|
||||||
SYS_FLOCK = 131
|
|
||||||
SYS_MKFIFO = 132
|
|
||||||
SYS_SENDTO = 133
|
|
||||||
SYS_SHUTDOWN = 134
|
|
||||||
SYS_SOCKETPAIR = 135
|
|
||||||
SYS_MKDIR = 136
|
|
||||||
SYS_RMDIR = 137
|
|
||||||
SYS_UTIMES = 138
|
|
||||||
SYS_FUTIMES = 139
|
|
||||||
SYS_ADJTIME = 140
|
|
||||||
SYS_GETHOSTUUID = 142
|
|
||||||
SYS_SETSID = 147
|
|
||||||
SYS_GETPGID = 151
|
|
||||||
SYS_SETPRIVEXEC = 152
|
|
||||||
SYS_PREAD = 153
|
|
||||||
SYS_PWRITE = 154
|
|
||||||
SYS_NFSSVC = 155
|
|
||||||
SYS_STATFS = 157
|
|
||||||
SYS_FSTATFS = 158
|
|
||||||
SYS_UNMOUNT = 159
|
|
||||||
SYS_GETFH = 161
|
|
||||||
SYS_QUOTACTL = 165
|
|
||||||
SYS_MOUNT = 167
|
|
||||||
SYS_CSOPS = 169
|
|
||||||
SYS_CSOPS_AUDITTOKEN = 170
|
|
||||||
SYS_WAITID = 173
|
|
||||||
SYS_KDEBUG_TYPEFILTER = 177
|
|
||||||
SYS_KDEBUG_TRACE_STRING = 178
|
|
||||||
SYS_KDEBUG_TRACE64 = 179
|
|
||||||
SYS_KDEBUG_TRACE = 180
|
|
||||||
SYS_SETGID = 181
|
|
||||||
SYS_SETEGID = 182
|
|
||||||
SYS_SETEUID = 183
|
|
||||||
SYS_SIGRETURN = 184
|
|
||||||
SYS_THREAD_SELFCOUNTS = 186
|
|
||||||
SYS_FDATASYNC = 187
|
|
||||||
SYS_STAT = 188
|
|
||||||
SYS_FSTAT = 189
|
|
||||||
SYS_LSTAT = 190
|
|
||||||
SYS_PATHCONF = 191
|
|
||||||
SYS_FPATHCONF = 192
|
|
||||||
SYS_GETRLIMIT = 194
|
|
||||||
SYS_SETRLIMIT = 195
|
|
||||||
SYS_GETDIRENTRIES = 196
|
|
||||||
SYS_MMAP = 197
|
|
||||||
SYS_LSEEK = 199
|
|
||||||
SYS_TRUNCATE = 200
|
|
||||||
SYS_FTRUNCATE = 201
|
|
||||||
SYS_SYSCTL = 202
|
|
||||||
SYS_MLOCK = 203
|
|
||||||
SYS_MUNLOCK = 204
|
|
||||||
SYS_UNDELETE = 205
|
|
||||||
SYS_OPEN_DPROTECTED_NP = 216
|
|
||||||
SYS_GETATTRLIST = 220
|
|
||||||
SYS_SETATTRLIST = 221
|
|
||||||
SYS_GETDIRENTRIESATTR = 222
|
|
||||||
SYS_EXCHANGEDATA = 223
|
|
||||||
SYS_SEARCHFS = 225
|
|
||||||
SYS_DELETE = 226
|
|
||||||
SYS_COPYFILE = 227
|
|
||||||
SYS_FGETATTRLIST = 228
|
|
||||||
SYS_FSETATTRLIST = 229
|
|
||||||
SYS_POLL = 230
|
|
||||||
SYS_WATCHEVENT = 231
|
|
||||||
SYS_WAITEVENT = 232
|
|
||||||
SYS_MODWATCH = 233
|
|
||||||
SYS_GETXATTR = 234
|
|
||||||
SYS_FGETXATTR = 235
|
|
||||||
SYS_SETXATTR = 236
|
|
||||||
SYS_FSETXATTR = 237
|
|
||||||
SYS_REMOVEXATTR = 238
|
|
||||||
SYS_FREMOVEXATTR = 239
|
|
||||||
SYS_LISTXATTR = 240
|
|
||||||
SYS_FLISTXATTR = 241
|
|
||||||
SYS_FSCTL = 242
|
|
||||||
SYS_INITGROUPS = 243
|
|
||||||
SYS_POSIX_SPAWN = 244
|
|
||||||
SYS_FFSCTL = 245
|
|
||||||
SYS_NFSCLNT = 247
|
|
||||||
SYS_FHOPEN = 248
|
|
||||||
SYS_MINHERIT = 250
|
|
||||||
SYS_SEMSYS = 251
|
|
||||||
SYS_MSGSYS = 252
|
|
||||||
SYS_SHMSYS = 253
|
|
||||||
SYS_SEMCTL = 254
|
|
||||||
SYS_SEMGET = 255
|
|
||||||
SYS_SEMOP = 256
|
|
||||||
SYS_MSGCTL = 258
|
|
||||||
SYS_MSGGET = 259
|
|
||||||
SYS_MSGSND = 260
|
|
||||||
SYS_MSGRCV = 261
|
|
||||||
SYS_SHMAT = 262
|
|
||||||
SYS_SHMCTL = 263
|
|
||||||
SYS_SHMDT = 264
|
|
||||||
SYS_SHMGET = 265
|
|
||||||
SYS_SHM_OPEN = 266
|
|
||||||
SYS_SHM_UNLINK = 267
|
|
||||||
SYS_SEM_OPEN = 268
|
|
||||||
SYS_SEM_CLOSE = 269
|
|
||||||
SYS_SEM_UNLINK = 270
|
|
||||||
SYS_SEM_WAIT = 271
|
|
||||||
SYS_SEM_TRYWAIT = 272
|
|
||||||
SYS_SEM_POST = 273
|
|
||||||
SYS_SYSCTLBYNAME = 274
|
|
||||||
SYS_OPEN_EXTENDED = 277
|
|
||||||
SYS_UMASK_EXTENDED = 278
|
|
||||||
SYS_STAT_EXTENDED = 279
|
|
||||||
SYS_LSTAT_EXTENDED = 280
|
|
||||||
SYS_FSTAT_EXTENDED = 281
|
|
||||||
SYS_CHMOD_EXTENDED = 282
|
|
||||||
SYS_FCHMOD_EXTENDED = 283
|
|
||||||
SYS_ACCESS_EXTENDED = 284
|
|
||||||
SYS_SETTID = 285
|
|
||||||
SYS_GETTID = 286
|
|
||||||
SYS_SETSGROUPS = 287
|
|
||||||
SYS_GETSGROUPS = 288
|
|
||||||
SYS_SETWGROUPS = 289
|
|
||||||
SYS_GETWGROUPS = 290
|
|
||||||
SYS_MKFIFO_EXTENDED = 291
|
|
||||||
SYS_MKDIR_EXTENDED = 292
|
|
||||||
SYS_IDENTITYSVC = 293
|
|
||||||
SYS_SHARED_REGION_CHECK_NP = 294
|
|
||||||
SYS_VM_PRESSURE_MONITOR = 296
|
|
||||||
SYS_PSYNCH_RW_LONGRDLOCK = 297
|
|
||||||
SYS_PSYNCH_RW_YIELDWRLOCK = 298
|
|
||||||
SYS_PSYNCH_RW_DOWNGRADE = 299
|
|
||||||
SYS_PSYNCH_RW_UPGRADE = 300
|
|
||||||
SYS_PSYNCH_MUTEXWAIT = 301
|
|
||||||
SYS_PSYNCH_MUTEXDROP = 302
|
|
||||||
SYS_PSYNCH_CVBROAD = 303
|
|
||||||
SYS_PSYNCH_CVSIGNAL = 304
|
|
||||||
SYS_PSYNCH_CVWAIT = 305
|
|
||||||
SYS_PSYNCH_RW_RDLOCK = 306
|
|
||||||
SYS_PSYNCH_RW_WRLOCK = 307
|
|
||||||
SYS_PSYNCH_RW_UNLOCK = 308
|
|
||||||
SYS_PSYNCH_RW_UNLOCK2 = 309
|
|
||||||
SYS_GETSID = 310
|
|
||||||
SYS_SETTID_WITH_PID = 311
|
|
||||||
SYS_PSYNCH_CVCLRPREPOST = 312
|
|
||||||
SYS_AIO_FSYNC = 313
|
|
||||||
SYS_AIO_RETURN = 314
|
|
||||||
SYS_AIO_SUSPEND = 315
|
|
||||||
SYS_AIO_CANCEL = 316
|
|
||||||
SYS_AIO_ERROR = 317
|
|
||||||
SYS_AIO_READ = 318
|
|
||||||
SYS_AIO_WRITE = 319
|
|
||||||
SYS_LIO_LISTIO = 320
|
|
||||||
SYS_IOPOLICYSYS = 322
|
|
||||||
SYS_PROCESS_POLICY = 323
|
|
||||||
SYS_MLOCKALL = 324
|
|
||||||
SYS_MUNLOCKALL = 325
|
|
||||||
SYS_ISSETUGID = 327
|
|
||||||
SYS___PTHREAD_KILL = 328
|
|
||||||
SYS___PTHREAD_SIGMASK = 329
|
|
||||||
SYS___SIGWAIT = 330
|
|
||||||
SYS___DISABLE_THREADSIGNAL = 331
|
|
||||||
SYS___PTHREAD_MARKCANCEL = 332
|
|
||||||
SYS___PTHREAD_CANCELED = 333
|
|
||||||
SYS___SEMWAIT_SIGNAL = 334
|
|
||||||
SYS_PROC_INFO = 336
|
|
||||||
SYS_SENDFILE = 337
|
|
||||||
SYS_STAT64 = 338
|
|
||||||
SYS_FSTAT64 = 339
|
|
||||||
SYS_LSTAT64 = 340
|
|
||||||
SYS_STAT64_EXTENDED = 341
|
|
||||||
SYS_LSTAT64_EXTENDED = 342
|
|
||||||
SYS_FSTAT64_EXTENDED = 343
|
|
||||||
SYS_GETDIRENTRIES64 = 344
|
|
||||||
SYS_STATFS64 = 345
|
|
||||||
SYS_FSTATFS64 = 346
|
|
||||||
SYS_GETFSSTAT64 = 347
|
|
||||||
SYS___PTHREAD_CHDIR = 348
|
|
||||||
SYS___PTHREAD_FCHDIR = 349
|
|
||||||
SYS_AUDIT = 350
|
|
||||||
SYS_AUDITON = 351
|
|
||||||
SYS_GETAUID = 353
|
|
||||||
SYS_SETAUID = 354
|
|
||||||
SYS_GETAUDIT_ADDR = 357
|
|
||||||
SYS_SETAUDIT_ADDR = 358
|
|
||||||
SYS_AUDITCTL = 359
|
|
||||||
SYS_BSDTHREAD_CREATE = 360
|
|
||||||
SYS_BSDTHREAD_TERMINATE = 361
|
|
||||||
SYS_KQUEUE = 362
|
|
||||||
SYS_KEVENT = 363
|
|
||||||
SYS_LCHOWN = 364
|
|
||||||
SYS_BSDTHREAD_REGISTER = 366
|
|
||||||
SYS_WORKQ_OPEN = 367
|
|
||||||
SYS_WORKQ_KERNRETURN = 368
|
|
||||||
SYS_KEVENT64 = 369
|
|
||||||
SYS___OLD_SEMWAIT_SIGNAL = 370
|
|
||||||
SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371
|
|
||||||
SYS_THREAD_SELFID = 372
|
|
||||||
SYS_LEDGER = 373
|
|
||||||
SYS_KEVENT_QOS = 374
|
|
||||||
SYS_KEVENT_ID = 375
|
|
||||||
SYS___MAC_EXECVE = 380
|
|
||||||
SYS___MAC_SYSCALL = 381
|
|
||||||
SYS___MAC_GET_FILE = 382
|
|
||||||
SYS___MAC_SET_FILE = 383
|
|
||||||
SYS___MAC_GET_LINK = 384
|
|
||||||
SYS___MAC_SET_LINK = 385
|
|
||||||
SYS___MAC_GET_PROC = 386
|
|
||||||
SYS___MAC_SET_PROC = 387
|
|
||||||
SYS___MAC_GET_FD = 388
|
|
||||||
SYS___MAC_SET_FD = 389
|
|
||||||
SYS___MAC_GET_PID = 390
|
|
||||||
SYS_PSELECT = 394
|
|
||||||
SYS_PSELECT_NOCANCEL = 395
|
|
||||||
SYS_READ_NOCANCEL = 396
|
|
||||||
SYS_WRITE_NOCANCEL = 397
|
|
||||||
SYS_OPEN_NOCANCEL = 398
|
|
||||||
SYS_CLOSE_NOCANCEL = 399
|
|
||||||
SYS_WAIT4_NOCANCEL = 400
|
|
||||||
SYS_RECVMSG_NOCANCEL = 401
|
|
||||||
SYS_SENDMSG_NOCANCEL = 402
|
|
||||||
SYS_RECVFROM_NOCANCEL = 403
|
|
||||||
SYS_ACCEPT_NOCANCEL = 404
|
|
||||||
SYS_MSYNC_NOCANCEL = 405
|
|
||||||
SYS_FCNTL_NOCANCEL = 406
|
|
||||||
SYS_SELECT_NOCANCEL = 407
|
|
||||||
SYS_FSYNC_NOCANCEL = 408
|
|
||||||
SYS_CONNECT_NOCANCEL = 409
|
|
||||||
SYS_SIGSUSPEND_NOCANCEL = 410
|
|
||||||
SYS_READV_NOCANCEL = 411
|
|
||||||
SYS_WRITEV_NOCANCEL = 412
|
|
||||||
SYS_SENDTO_NOCANCEL = 413
|
|
||||||
SYS_PREAD_NOCANCEL = 414
|
|
||||||
SYS_PWRITE_NOCANCEL = 415
|
|
||||||
SYS_WAITID_NOCANCEL = 416
|
|
||||||
SYS_POLL_NOCANCEL = 417
|
|
||||||
SYS_MSGSND_NOCANCEL = 418
|
|
||||||
SYS_MSGRCV_NOCANCEL = 419
|
|
||||||
SYS_SEM_WAIT_NOCANCEL = 420
|
|
||||||
SYS_AIO_SUSPEND_NOCANCEL = 421
|
|
||||||
SYS___SIGWAIT_NOCANCEL = 422
|
|
||||||
SYS___SEMWAIT_SIGNAL_NOCANCEL = 423
|
|
||||||
SYS___MAC_MOUNT = 424
|
|
||||||
SYS___MAC_GET_MOUNT = 425
|
|
||||||
SYS___MAC_GETFSSTAT = 426
|
|
||||||
SYS_FSGETPATH = 427
|
|
||||||
SYS_AUDIT_SESSION_SELF = 428
|
|
||||||
SYS_AUDIT_SESSION_JOIN = 429
|
|
||||||
SYS_FILEPORT_MAKEPORT = 430
|
|
||||||
SYS_FILEPORT_MAKEFD = 431
|
|
||||||
SYS_AUDIT_SESSION_PORT = 432
|
|
||||||
SYS_PID_SUSPEND = 433
|
|
||||||
SYS_PID_RESUME = 434
|
|
||||||
SYS_PID_HIBERNATE = 435
|
|
||||||
SYS_PID_SHUTDOWN_SOCKETS = 436
|
|
||||||
SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438
|
|
||||||
SYS_KAS_INFO = 439
|
|
||||||
SYS_MEMORYSTATUS_CONTROL = 440
|
|
||||||
SYS_GUARDED_OPEN_NP = 441
|
|
||||||
SYS_GUARDED_CLOSE_NP = 442
|
|
||||||
SYS_GUARDED_KQUEUE_NP = 443
|
|
||||||
SYS_CHANGE_FDGUARD_NP = 444
|
|
||||||
SYS_USRCTL = 445
|
|
||||||
SYS_PROC_RLIMIT_CONTROL = 446
|
|
||||||
SYS_CONNECTX = 447
|
|
||||||
SYS_DISCONNECTX = 448
|
|
||||||
SYS_PEELOFF = 449
|
|
||||||
SYS_SOCKET_DELEGATE = 450
|
|
||||||
SYS_TELEMETRY = 451
|
|
||||||
SYS_PROC_UUID_POLICY = 452
|
|
||||||
SYS_MEMORYSTATUS_GET_LEVEL = 453
|
|
||||||
SYS_SYSTEM_OVERRIDE = 454
|
|
||||||
SYS_VFS_PURGE = 455
|
|
||||||
SYS_SFI_CTL = 456
|
|
||||||
SYS_SFI_PIDCTL = 457
|
|
||||||
SYS_COALITION = 458
|
|
||||||
SYS_COALITION_INFO = 459
|
|
||||||
SYS_NECP_MATCH_POLICY = 460
|
|
||||||
SYS_GETATTRLISTBULK = 461
|
|
||||||
SYS_CLONEFILEAT = 462
|
|
||||||
SYS_OPENAT = 463
|
|
||||||
SYS_OPENAT_NOCANCEL = 464
|
|
||||||
SYS_RENAMEAT = 465
|
|
||||||
SYS_FACCESSAT = 466
|
|
||||||
SYS_FCHMODAT = 467
|
|
||||||
SYS_FCHOWNAT = 468
|
|
||||||
SYS_FSTATAT = 469
|
|
||||||
SYS_FSTATAT64 = 470
|
|
||||||
SYS_LINKAT = 471
|
|
||||||
SYS_UNLINKAT = 472
|
|
||||||
SYS_READLINKAT = 473
|
|
||||||
SYS_SYMLINKAT = 474
|
|
||||||
SYS_MKDIRAT = 475
|
|
||||||
SYS_GETATTRLISTAT = 476
|
|
||||||
SYS_PROC_TRACE_LOG = 477
|
|
||||||
SYS_BSDTHREAD_CTL = 478
|
|
||||||
SYS_OPENBYID_NP = 479
|
|
||||||
SYS_RECVMSG_X = 480
|
|
||||||
SYS_SENDMSG_X = 481
|
|
||||||
SYS_THREAD_SELFUSAGE = 482
|
|
||||||
SYS_CSRCTL = 483
|
|
||||||
SYS_GUARDED_OPEN_DPROTECTED_NP = 484
|
|
||||||
SYS_GUARDED_WRITE_NP = 485
|
|
||||||
SYS_GUARDED_PWRITE_NP = 486
|
|
||||||
SYS_GUARDED_WRITEV_NP = 487
|
|
||||||
SYS_RENAMEATX_NP = 488
|
|
||||||
SYS_MREMAP_ENCRYPTED = 489
|
|
||||||
SYS_NETAGENT_TRIGGER = 490
|
|
||||||
SYS_STACK_SNAPSHOT_WITH_CONFIG = 491
|
|
||||||
SYS_MICROSTACKSHOT = 492
|
|
||||||
SYS_GRAB_PGO_DATA = 493
|
|
||||||
SYS_PERSONA = 494
|
|
||||||
SYS_WORK_INTERVAL_CTL = 499
|
|
||||||
SYS_GETENTROPY = 500
|
|
||||||
SYS_NECP_OPEN = 501
|
|
||||||
SYS_NECP_CLIENT_ACTION = 502
|
|
||||||
SYS___NEXUS_OPEN = 503
|
|
||||||
SYS___NEXUS_REGISTER = 504
|
|
||||||
SYS___NEXUS_DEREGISTER = 505
|
|
||||||
SYS___NEXUS_CREATE = 506
|
|
||||||
SYS___NEXUS_DESTROY = 507
|
|
||||||
SYS___NEXUS_GET_OPT = 508
|
|
||||||
SYS___NEXUS_SET_OPT = 509
|
|
||||||
SYS___CHANNEL_OPEN = 510
|
|
||||||
SYS___CHANNEL_GET_INFO = 511
|
|
||||||
SYS___CHANNEL_SYNC = 512
|
|
||||||
SYS___CHANNEL_GET_OPT = 513
|
|
||||||
SYS___CHANNEL_SET_OPT = 514
|
|
||||||
SYS_ULOCK_WAIT = 515
|
|
||||||
SYS_ULOCK_WAKE = 516
|
|
||||||
SYS_FCLONEFILEAT = 517
|
|
||||||
SYS_FS_SNAPSHOT = 518
|
|
||||||
SYS_TERMINATE_WITH_PAYLOAD = 520
|
|
||||||
SYS_ABORT_WITH_PAYLOAD = 521
|
|
||||||
SYS_NECP_SESSION_OPEN = 522
|
|
||||||
SYS_NECP_SESSION_ACTION = 523
|
|
||||||
SYS_SETATTRLISTAT = 524
|
|
||||||
SYS_NET_QOS_GUIDELINE = 525
|
|
||||||
SYS_FMOUNT = 526
|
|
||||||
SYS_NTP_ADJTIME = 527
|
|
||||||
SYS_NTP_GETTIME = 528
|
|
||||||
SYS_OS_FAULT_WITH_PAYLOAD = 529
|
|
||||||
SYS_MAXSYSCALL = 530
|
|
||||||
SYS_INVALID = 63
|
|
||||||
)
|
|
436
vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go
generated
vendored
436
vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go
generated
vendored
@ -1,436 +0,0 @@
|
|||||||
// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/sys/syscall.h
|
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
|
||||||
|
|
||||||
// +build arm64,darwin
|
|
||||||
|
|
||||||
package unix
|
|
||||||
|
|
||||||
const (
|
|
||||||
SYS_SYSCALL = 0
|
|
||||||
SYS_EXIT = 1
|
|
||||||
SYS_FORK = 2
|
|
||||||
SYS_READ = 3
|
|
||||||
SYS_WRITE = 4
|
|
||||||
SYS_OPEN = 5
|
|
||||||
SYS_CLOSE = 6
|
|
||||||
SYS_WAIT4 = 7
|
|
||||||
SYS_LINK = 9
|
|
||||||
SYS_UNLINK = 10
|
|
||||||
SYS_CHDIR = 12
|
|
||||||
SYS_FCHDIR = 13
|
|
||||||
SYS_MKNOD = 14
|
|
||||||
SYS_CHMOD = 15
|
|
||||||
SYS_CHOWN = 16
|
|
||||||
SYS_GETFSSTAT = 18
|
|
||||||
SYS_GETPID = 20
|
|
||||||
SYS_SETUID = 23
|
|
||||||
SYS_GETUID = 24
|
|
||||||
SYS_GETEUID = 25
|
|
||||||
SYS_PTRACE = 26
|
|
||||||
SYS_RECVMSG = 27
|
|
||||||
SYS_SENDMSG = 28
|
|
||||||
SYS_RECVFROM = 29
|
|
||||||
SYS_ACCEPT = 30
|
|
||||||
SYS_GETPEERNAME = 31
|
|
||||||
SYS_GETSOCKNAME = 32
|
|
||||||
SYS_ACCESS = 33
|
|
||||||
SYS_CHFLAGS = 34
|
|
||||||
SYS_FCHFLAGS = 35
|
|
||||||
SYS_SYNC = 36
|
|
||||||
SYS_KILL = 37
|
|
||||||
SYS_GETPPID = 39
|
|
||||||
SYS_DUP = 41
|
|
||||||
SYS_PIPE = 42
|
|
||||||
SYS_GETEGID = 43
|
|
||||||
SYS_SIGACTION = 46
|
|
||||||
SYS_GETGID = 47
|
|
||||||
SYS_SIGPROCMASK = 48
|
|
||||||
SYS_GETLOGIN = 49
|
|
||||||
SYS_SETLOGIN = 50
|
|
||||||
SYS_ACCT = 51
|
|
||||||
SYS_SIGPENDING = 52
|
|
||||||
SYS_SIGALTSTACK = 53
|
|
||||||
SYS_IOCTL = 54
|
|
||||||
SYS_REBOOT = 55
|
|
||||||
SYS_REVOKE = 56
|
|
||||||
SYS_SYMLINK = 57
|
|
||||||
SYS_READLINK = 58
|
|
||||||
SYS_EXECVE = 59
|
|
||||||
SYS_UMASK = 60
|
|
||||||
SYS_CHROOT = 61
|
|
||||||
SYS_MSYNC = 65
|
|
||||||
SYS_VFORK = 66
|
|
||||||
SYS_MUNMAP = 73
|
|
||||||
SYS_MPROTECT = 74
|
|
||||||
SYS_MADVISE = 75
|
|
||||||
SYS_MINCORE = 78
|
|
||||||
SYS_GETGROUPS = 79
|
|
||||||
SYS_SETGROUPS = 80
|
|
||||||
SYS_GETPGRP = 81
|
|
||||||
SYS_SETPGID = 82
|
|
||||||
SYS_SETITIMER = 83
|
|
||||||
SYS_SWAPON = 85
|
|
||||||
SYS_GETITIMER = 86
|
|
||||||
SYS_GETDTABLESIZE = 89
|
|
||||||
SYS_DUP2 = 90
|
|
||||||
SYS_FCNTL = 92
|
|
||||||
SYS_SELECT = 93
|
|
||||||
SYS_FSYNC = 95
|
|
||||||
SYS_SETPRIORITY = 96
|
|
||||||
SYS_SOCKET = 97
|
|
||||||
SYS_CONNECT = 98
|
|
||||||
SYS_GETPRIORITY = 100
|
|
||||||
SYS_BIND = 104
|
|
||||||
SYS_SETSOCKOPT = 105
|
|
||||||
SYS_LISTEN = 106
|
|
||||||
SYS_SIGSUSPEND = 111
|
|
||||||
SYS_GETTIMEOFDAY = 116
|
|
||||||
SYS_GETRUSAGE = 117
|
|
||||||
SYS_GETSOCKOPT = 118
|
|
||||||
SYS_READV = 120
|
|
||||||
SYS_WRITEV = 121
|
|
||||||
SYS_SETTIMEOFDAY = 122
|
|
||||||
SYS_FCHOWN = 123
|
|
||||||
SYS_FCHMOD = 124
|
|
||||||
SYS_SETREUID = 126
|
|
||||||
SYS_SETREGID = 127
|
|
||||||
SYS_RENAME = 128
|
|
||||||
SYS_FLOCK = 131
|
|
||||||
SYS_MKFIFO = 132
|
|
||||||
SYS_SENDTO = 133
|
|
||||||
SYS_SHUTDOWN = 134
|
|
||||||
SYS_SOCKETPAIR = 135
|
|
||||||
SYS_MKDIR = 136
|
|
||||||
SYS_RMDIR = 137
|
|
||||||
SYS_UTIMES = 138
|
|
||||||
SYS_FUTIMES = 139
|
|
||||||
SYS_ADJTIME = 140
|
|
||||||
SYS_GETHOSTUUID = 142
|
|
||||||
SYS_SETSID = 147
|
|
||||||
SYS_GETPGID = 151
|
|
||||||
SYS_SETPRIVEXEC = 152
|
|
||||||
SYS_PREAD = 153
|
|
||||||
SYS_PWRITE = 154
|
|
||||||
SYS_NFSSVC = 155
|
|
||||||
SYS_STATFS = 157
|
|
||||||
SYS_FSTATFS = 158
|
|
||||||
SYS_UNMOUNT = 159
|
|
||||||
SYS_GETFH = 161
|
|
||||||
SYS_QUOTACTL = 165
|
|
||||||
SYS_MOUNT = 167
|
|
||||||
SYS_CSOPS = 169
|
|
||||||
SYS_CSOPS_AUDITTOKEN = 170
|
|
||||||
SYS_WAITID = 173
|
|
||||||
SYS_KDEBUG_TYPEFILTER = 177
|
|
||||||
SYS_KDEBUG_TRACE_STRING = 178
|
|
||||||
SYS_KDEBUG_TRACE64 = 179
|
|
||||||
SYS_KDEBUG_TRACE = 180
|
|
||||||
SYS_SETGID = 181
|
|
||||||
SYS_SETEGID = 182
|
|
||||||
SYS_SETEUID = 183
|
|
||||||
SYS_SIGRETURN = 184
|
|
||||||
SYS_THREAD_SELFCOUNTS = 186
|
|
||||||
SYS_FDATASYNC = 187
|
|
||||||
SYS_STAT = 188
|
|
||||||
SYS_FSTAT = 189
|
|
||||||
SYS_LSTAT = 190
|
|
||||||
SYS_PATHCONF = 191
|
|
||||||
SYS_FPATHCONF = 192
|
|
||||||
SYS_GETRLIMIT = 194
|
|
||||||
SYS_SETRLIMIT = 195
|
|
||||||
SYS_GETDIRENTRIES = 196
|
|
||||||
SYS_MMAP = 197
|
|
||||||
SYS_LSEEK = 199
|
|
||||||
SYS_TRUNCATE = 200
|
|
||||||
SYS_FTRUNCATE = 201
|
|
||||||
SYS_SYSCTL = 202
|
|
||||||
SYS_MLOCK = 203
|
|
||||||
SYS_MUNLOCK = 204
|
|
||||||
SYS_UNDELETE = 205
|
|
||||||
SYS_OPEN_DPROTECTED_NP = 216
|
|
||||||
SYS_GETATTRLIST = 220
|
|
||||||
SYS_SETATTRLIST = 221
|
|
||||||
SYS_GETDIRENTRIESATTR = 222
|
|
||||||
SYS_EXCHANGEDATA = 223
|
|
||||||
SYS_SEARCHFS = 225
|
|
||||||
SYS_DELETE = 226
|
|
||||||
SYS_COPYFILE = 227
|
|
||||||
SYS_FGETATTRLIST = 228
|
|
||||||
SYS_FSETATTRLIST = 229
|
|
||||||
SYS_POLL = 230
|
|
||||||
SYS_WATCHEVENT = 231
|
|
||||||
SYS_WAITEVENT = 232
|
|
||||||
SYS_MODWATCH = 233
|
|
||||||
SYS_GETXATTR = 234
|
|
||||||
SYS_FGETXATTR = 235
|
|
||||||
SYS_SETXATTR = 236
|
|
||||||
SYS_FSETXATTR = 237
|
|
||||||
SYS_REMOVEXATTR = 238
|
|
||||||
SYS_FREMOVEXATTR = 239
|
|
||||||
SYS_LISTXATTR = 240
|
|
||||||
SYS_FLISTXATTR = 241
|
|
||||||
SYS_FSCTL = 242
|
|
||||||
SYS_INITGROUPS = 243
|
|
||||||
SYS_POSIX_SPAWN = 244
|
|
||||||
SYS_FFSCTL = 245
|
|
||||||
SYS_NFSCLNT = 247
|
|
||||||
SYS_FHOPEN = 248
|
|
||||||
SYS_MINHERIT = 250
|
|
||||||
SYS_SEMSYS = 251
|
|
||||||
SYS_MSGSYS = 252
|
|
||||||
SYS_SHMSYS = 253
|
|
||||||
SYS_SEMCTL = 254
|
|
||||||
SYS_SEMGET = 255
|
|
||||||
SYS_SEMOP = 256
|
|
||||||
SYS_MSGCTL = 258
|
|
||||||
SYS_MSGGET = 259
|
|
||||||
SYS_MSGSND = 260
|
|
||||||
SYS_MSGRCV = 261
|
|
||||||
SYS_SHMAT = 262
|
|
||||||
SYS_SHMCTL = 263
|
|
||||||
SYS_SHMDT = 264
|
|
||||||
SYS_SHMGET = 265
|
|
||||||
SYS_SHM_OPEN = 266
|
|
||||||
SYS_SHM_UNLINK = 267
|
|
||||||
SYS_SEM_OPEN = 268
|
|
||||||
SYS_SEM_CLOSE = 269
|
|
||||||
SYS_SEM_UNLINK = 270
|
|
||||||
SYS_SEM_WAIT = 271
|
|
||||||
SYS_SEM_TRYWAIT = 272
|
|
||||||
SYS_SEM_POST = 273
|
|
||||||
SYS_SYSCTLBYNAME = 274
|
|
||||||
SYS_OPEN_EXTENDED = 277
|
|
||||||
SYS_UMASK_EXTENDED = 278
|
|
||||||
SYS_STAT_EXTENDED = 279
|
|
||||||
SYS_LSTAT_EXTENDED = 280
|
|
||||||
SYS_FSTAT_EXTENDED = 281
|
|
||||||
SYS_CHMOD_EXTENDED = 282
|
|
||||||
SYS_FCHMOD_EXTENDED = 283
|
|
||||||
SYS_ACCESS_EXTENDED = 284
|
|
||||||
SYS_SETTID = 285
|
|
||||||
SYS_GETTID = 286
|
|
||||||
SYS_SETSGROUPS = 287
|
|
||||||
SYS_GETSGROUPS = 288
|
|
||||||
SYS_SETWGROUPS = 289
|
|
||||||
SYS_GETWGROUPS = 290
|
|
||||||
SYS_MKFIFO_EXTENDED = 291
|
|
||||||
SYS_MKDIR_EXTENDED = 292
|
|
||||||
SYS_IDENTITYSVC = 293
|
|
||||||
SYS_SHARED_REGION_CHECK_NP = 294
|
|
||||||
SYS_VM_PRESSURE_MONITOR = 296
|
|
||||||
SYS_PSYNCH_RW_LONGRDLOCK = 297
|
|
||||||
SYS_PSYNCH_RW_YIELDWRLOCK = 298
|
|
||||||
SYS_PSYNCH_RW_DOWNGRADE = 299
|
|
||||||
SYS_PSYNCH_RW_UPGRADE = 300
|
|
||||||
SYS_PSYNCH_MUTEXWAIT = 301
|
|
||||||
SYS_PSYNCH_MUTEXDROP = 302
|
|
||||||
SYS_PSYNCH_CVBROAD = 303
|
|
||||||
SYS_PSYNCH_CVSIGNAL = 304
|
|
||||||
SYS_PSYNCH_CVWAIT = 305
|
|
||||||
SYS_PSYNCH_RW_RDLOCK = 306
|
|
||||||
SYS_PSYNCH_RW_WRLOCK = 307
|
|
||||||
SYS_PSYNCH_RW_UNLOCK = 308
|
|
||||||
SYS_PSYNCH_RW_UNLOCK2 = 309
|
|
||||||
SYS_GETSID = 310
|
|
||||||
SYS_SETTID_WITH_PID = 311
|
|
||||||
SYS_PSYNCH_CVCLRPREPOST = 312
|
|
||||||
SYS_AIO_FSYNC = 313
|
|
||||||
SYS_AIO_RETURN = 314
|
|
||||||
SYS_AIO_SUSPEND = 315
|
|
||||||
SYS_AIO_CANCEL = 316
|
|
||||||
SYS_AIO_ERROR = 317
|
|
||||||
SYS_AIO_READ = 318
|
|
||||||
SYS_AIO_WRITE = 319
|
|
||||||
SYS_LIO_LISTIO = 320
|
|
||||||
SYS_IOPOLICYSYS = 322
|
|
||||||
SYS_PROCESS_POLICY = 323
|
|
||||||
SYS_MLOCKALL = 324
|
|
||||||
SYS_MUNLOCKALL = 325
|
|
||||||
SYS_ISSETUGID = 327
|
|
||||||
SYS___PTHREAD_KILL = 328
|
|
||||||
SYS___PTHREAD_SIGMASK = 329
|
|
||||||
SYS___SIGWAIT = 330
|
|
||||||
SYS___DISABLE_THREADSIGNAL = 331
|
|
||||||
SYS___PTHREAD_MARKCANCEL = 332
|
|
||||||
SYS___PTHREAD_CANCELED = 333
|
|
||||||
SYS___SEMWAIT_SIGNAL = 334
|
|
||||||
SYS_PROC_INFO = 336
|
|
||||||
SYS_SENDFILE = 337
|
|
||||||
SYS_STAT64 = 338
|
|
||||||
SYS_FSTAT64 = 339
|
|
||||||
SYS_LSTAT64 = 340
|
|
||||||
SYS_STAT64_EXTENDED = 341
|
|
||||||
SYS_LSTAT64_EXTENDED = 342
|
|
||||||
SYS_FSTAT64_EXTENDED = 343
|
|
||||||
SYS_GETDIRENTRIES64 = 344
|
|
||||||
SYS_STATFS64 = 345
|
|
||||||
SYS_FSTATFS64 = 346
|
|
||||||
SYS_GETFSSTAT64 = 347
|
|
||||||
SYS___PTHREAD_CHDIR = 348
|
|
||||||
SYS___PTHREAD_FCHDIR = 349
|
|
||||||
SYS_AUDIT = 350
|
|
||||||
SYS_AUDITON = 351
|
|
||||||
SYS_GETAUID = 353
|
|
||||||
SYS_SETAUID = 354
|
|
||||||
SYS_GETAUDIT_ADDR = 357
|
|
||||||
SYS_SETAUDIT_ADDR = 358
|
|
||||||
SYS_AUDITCTL = 359
|
|
||||||
SYS_BSDTHREAD_CREATE = 360
|
|
||||||
SYS_BSDTHREAD_TERMINATE = 361
|
|
||||||
SYS_KQUEUE = 362
|
|
||||||
SYS_KEVENT = 363
|
|
||||||
SYS_LCHOWN = 364
|
|
||||||
SYS_BSDTHREAD_REGISTER = 366
|
|
||||||
SYS_WORKQ_OPEN = 367
|
|
||||||
SYS_WORKQ_KERNRETURN = 368
|
|
||||||
SYS_KEVENT64 = 369
|
|
||||||
SYS___OLD_SEMWAIT_SIGNAL = 370
|
|
||||||
SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371
|
|
||||||
SYS_THREAD_SELFID = 372
|
|
||||||
SYS_LEDGER = 373
|
|
||||||
SYS_KEVENT_QOS = 374
|
|
||||||
SYS_KEVENT_ID = 375
|
|
||||||
SYS___MAC_EXECVE = 380
|
|
||||||
SYS___MAC_SYSCALL = 381
|
|
||||||
SYS___MAC_GET_FILE = 382
|
|
||||||
SYS___MAC_SET_FILE = 383
|
|
||||||
SYS___MAC_GET_LINK = 384
|
|
||||||
SYS___MAC_SET_LINK = 385
|
|
||||||
SYS___MAC_GET_PROC = 386
|
|
||||||
SYS___MAC_SET_PROC = 387
|
|
||||||
SYS___MAC_GET_FD = 388
|
|
||||||
SYS___MAC_SET_FD = 389
|
|
||||||
SYS___MAC_GET_PID = 390
|
|
||||||
SYS_PSELECT = 394
|
|
||||||
SYS_PSELECT_NOCANCEL = 395
|
|
||||||
SYS_READ_NOCANCEL = 396
|
|
||||||
SYS_WRITE_NOCANCEL = 397
|
|
||||||
SYS_OPEN_NOCANCEL = 398
|
|
||||||
SYS_CLOSE_NOCANCEL = 399
|
|
||||||
SYS_WAIT4_NOCANCEL = 400
|
|
||||||
SYS_RECVMSG_NOCANCEL = 401
|
|
||||||
SYS_SENDMSG_NOCANCEL = 402
|
|
||||||
SYS_RECVFROM_NOCANCEL = 403
|
|
||||||
SYS_ACCEPT_NOCANCEL = 404
|
|
||||||
SYS_MSYNC_NOCANCEL = 405
|
|
||||||
SYS_FCNTL_NOCANCEL = 406
|
|
||||||
SYS_SELECT_NOCANCEL = 407
|
|
||||||
SYS_FSYNC_NOCANCEL = 408
|
|
||||||
SYS_CONNECT_NOCANCEL = 409
|
|
||||||
SYS_SIGSUSPEND_NOCANCEL = 410
|
|
||||||
SYS_READV_NOCANCEL = 411
|
|
||||||
SYS_WRITEV_NOCANCEL = 412
|
|
||||||
SYS_SENDTO_NOCANCEL = 413
|
|
||||||
SYS_PREAD_NOCANCEL = 414
|
|
||||||
SYS_PWRITE_NOCANCEL = 415
|
|
||||||
SYS_WAITID_NOCANCEL = 416
|
|
||||||
SYS_POLL_NOCANCEL = 417
|
|
||||||
SYS_MSGSND_NOCANCEL = 418
|
|
||||||
SYS_MSGRCV_NOCANCEL = 419
|
|
||||||
SYS_SEM_WAIT_NOCANCEL = 420
|
|
||||||
SYS_AIO_SUSPEND_NOCANCEL = 421
|
|
||||||
SYS___SIGWAIT_NOCANCEL = 422
|
|
||||||
SYS___SEMWAIT_SIGNAL_NOCANCEL = 423
|
|
||||||
SYS___MAC_MOUNT = 424
|
|
||||||
SYS___MAC_GET_MOUNT = 425
|
|
||||||
SYS___MAC_GETFSSTAT = 426
|
|
||||||
SYS_FSGETPATH = 427
|
|
||||||
SYS_AUDIT_SESSION_SELF = 428
|
|
||||||
SYS_AUDIT_SESSION_JOIN = 429
|
|
||||||
SYS_FILEPORT_MAKEPORT = 430
|
|
||||||
SYS_FILEPORT_MAKEFD = 431
|
|
||||||
SYS_AUDIT_SESSION_PORT = 432
|
|
||||||
SYS_PID_SUSPEND = 433
|
|
||||||
SYS_PID_RESUME = 434
|
|
||||||
SYS_PID_HIBERNATE = 435
|
|
||||||
SYS_PID_SHUTDOWN_SOCKETS = 436
|
|
||||||
SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438
|
|
||||||
SYS_KAS_INFO = 439
|
|
||||||
SYS_MEMORYSTATUS_CONTROL = 440
|
|
||||||
SYS_GUARDED_OPEN_NP = 441
|
|
||||||
SYS_GUARDED_CLOSE_NP = 442
|
|
||||||
SYS_GUARDED_KQUEUE_NP = 443
|
|
||||||
SYS_CHANGE_FDGUARD_NP = 444
|
|
||||||
SYS_USRCTL = 445
|
|
||||||
SYS_PROC_RLIMIT_CONTROL = 446
|
|
||||||
SYS_CONNECTX = 447
|
|
||||||
SYS_DISCONNECTX = 448
|
|
||||||
SYS_PEELOFF = 449
|
|
||||||
SYS_SOCKET_DELEGATE = 450
|
|
||||||
SYS_TELEMETRY = 451
|
|
||||||
SYS_PROC_UUID_POLICY = 452
|
|
||||||
SYS_MEMORYSTATUS_GET_LEVEL = 453
|
|
||||||
SYS_SYSTEM_OVERRIDE = 454
|
|
||||||
SYS_VFS_PURGE = 455
|
|
||||||
SYS_SFI_CTL = 456
|
|
||||||
SYS_SFI_PIDCTL = 457
|
|
||||||
SYS_COALITION = 458
|
|
||||||
SYS_COALITION_INFO = 459
|
|
||||||
SYS_NECP_MATCH_POLICY = 460
|
|
||||||
SYS_GETATTRLISTBULK = 461
|
|
||||||
SYS_CLONEFILEAT = 462
|
|
||||||
SYS_OPENAT = 463
|
|
||||||
SYS_OPENAT_NOCANCEL = 464
|
|
||||||
SYS_RENAMEAT = 465
|
|
||||||
SYS_FACCESSAT = 466
|
|
||||||
SYS_FCHMODAT = 467
|
|
||||||
SYS_FCHOWNAT = 468
|
|
||||||
SYS_FSTATAT = 469
|
|
||||||
SYS_FSTATAT64 = 470
|
|
||||||
SYS_LINKAT = 471
|
|
||||||
SYS_UNLINKAT = 472
|
|
||||||
SYS_READLINKAT = 473
|
|
||||||
SYS_SYMLINKAT = 474
|
|
||||||
SYS_MKDIRAT = 475
|
|
||||||
SYS_GETATTRLISTAT = 476
|
|
||||||
SYS_PROC_TRACE_LOG = 477
|
|
||||||
SYS_BSDTHREAD_CTL = 478
|
|
||||||
SYS_OPENBYID_NP = 479
|
|
||||||
SYS_RECVMSG_X = 480
|
|
||||||
SYS_SENDMSG_X = 481
|
|
||||||
SYS_THREAD_SELFUSAGE = 482
|
|
||||||
SYS_CSRCTL = 483
|
|
||||||
SYS_GUARDED_OPEN_DPROTECTED_NP = 484
|
|
||||||
SYS_GUARDED_WRITE_NP = 485
|
|
||||||
SYS_GUARDED_PWRITE_NP = 486
|
|
||||||
SYS_GUARDED_WRITEV_NP = 487
|
|
||||||
SYS_RENAMEATX_NP = 488
|
|
||||||
SYS_MREMAP_ENCRYPTED = 489
|
|
||||||
SYS_NETAGENT_TRIGGER = 490
|
|
||||||
SYS_STACK_SNAPSHOT_WITH_CONFIG = 491
|
|
||||||
SYS_MICROSTACKSHOT = 492
|
|
||||||
SYS_GRAB_PGO_DATA = 493
|
|
||||||
SYS_PERSONA = 494
|
|
||||||
SYS_WORK_INTERVAL_CTL = 499
|
|
||||||
SYS_GETENTROPY = 500
|
|
||||||
SYS_NECP_OPEN = 501
|
|
||||||
SYS_NECP_CLIENT_ACTION = 502
|
|
||||||
SYS___NEXUS_OPEN = 503
|
|
||||||
SYS___NEXUS_REGISTER = 504
|
|
||||||
SYS___NEXUS_DEREGISTER = 505
|
|
||||||
SYS___NEXUS_CREATE = 506
|
|
||||||
SYS___NEXUS_DESTROY = 507
|
|
||||||
SYS___NEXUS_GET_OPT = 508
|
|
||||||
SYS___NEXUS_SET_OPT = 509
|
|
||||||
SYS___CHANNEL_OPEN = 510
|
|
||||||
SYS___CHANNEL_GET_INFO = 511
|
|
||||||
SYS___CHANNEL_SYNC = 512
|
|
||||||
SYS___CHANNEL_GET_OPT = 513
|
|
||||||
SYS___CHANNEL_SET_OPT = 514
|
|
||||||
SYS_ULOCK_WAIT = 515
|
|
||||||
SYS_ULOCK_WAKE = 516
|
|
||||||
SYS_FCLONEFILEAT = 517
|
|
||||||
SYS_FS_SNAPSHOT = 518
|
|
||||||
SYS_TERMINATE_WITH_PAYLOAD = 520
|
|
||||||
SYS_ABORT_WITH_PAYLOAD = 521
|
|
||||||
SYS_NECP_SESSION_OPEN = 522
|
|
||||||
SYS_NECP_SESSION_ACTION = 523
|
|
||||||
SYS_SETATTRLISTAT = 524
|
|
||||||
SYS_NET_QOS_GUIDELINE = 525
|
|
||||||
SYS_FMOUNT = 526
|
|
||||||
SYS_NTP_ADJTIME = 527
|
|
||||||
SYS_NTP_GETTIME = 528
|
|
||||||
SYS_OS_FAULT_WITH_PAYLOAD = 529
|
|
||||||
SYS_MAXSYSCALL = 530
|
|
||||||
SYS_INVALID = 63
|
|
||||||
)
|
|
Loading…
x
Reference in New Issue
Block a user