TUN-1734: Pin packages at exact versions

This commit is contained in:
Areg Harutyunyan 2019-04-17 12:15:55 -05:00
parent 2e2fa29637
commit bab7583a97
823 changed files with 108625 additions and 22044 deletions

182
Gopkg.lock generated
View File

@ -2,20 +2,20 @@
[[projects]] [[projects]]
digest = "1:b16fbfbcc20645cb419f78325bb2e85ec729b338e996a228124d68931a6f2a37" digest = "1:9f3b30d9f8e0d7040f729b82dcbc8f0dead820a133b3147ce355fc451f32d761"
name = "github.com/BurntSushi/toml" name = "github.com/BurntSushi/toml"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "b26d9c308763d68093482582cea63d69be07a0f0" revision = "3012a1dbe2e4bd1391d42b32f0577cb7bbc7f005"
version = "v0.3.0" version = "v0.3.1"
[[projects]] [[projects]]
branch = "master"
digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d" digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d"
name = "github.com/beorn7/perks" name = "github.com/beorn7/perks"
packages = ["quantile"] packages = ["quantile"]
pruneopts = "UT" pruneopts = "UT"
revision = "3a771d992973f24aa725d07868b467d1ddfceafb" revision = "4b2b341e8d7715fae06375aa633dbb6e91b3fb46"
version = "v1.0.0"
[[projects]] [[projects]]
digest = "1:fed1f537c2f1269fe475a8556c393fe466641682d73ef8fd0491cd3aa1e47bad" digest = "1:fed1f537c2f1269fe475a8556c393fe466641682d73ef8fd0491cd3aa1e47bad"
@ -26,7 +26,6 @@
version = "2018.01.18" version = "2018.01.18"
[[projects]] [[projects]]
branch = "master"
digest = "1:e5003c19d396d8b3cf1324ea0bf49b00f13e9466d0297d1268b641f1c617c3a2" digest = "1:e5003c19d396d8b3cf1324ea0bf49b00f13e9466d0297d1268b641f1c617c3a2"
name = "github.com/cloudflare/brotli-go" name = "github.com/cloudflare/brotli-go"
packages = ["."] packages = ["."]
@ -34,7 +33,6 @@
revision = "18c9f6c67e3dfc12e0ddaca748d2887f97a7ac28" revision = "18c9f6c67e3dfc12e0ddaca748d2887f97a7ac28"
[[projects]] [[projects]]
branch = "master"
digest = "1:6dbb2bbc7e6333e691c4d82fd86485f0695a35902fbb9b2df5f72e22ab0040f3" digest = "1:6dbb2bbc7e6333e691c4d82fd86485f0695a35902fbb9b2df5f72e22ab0040f3"
name = "github.com/cloudflare/golibs" name = "github.com/cloudflare/golibs"
packages = ["lrucache"] packages = ["lrucache"]
@ -42,8 +40,7 @@
revision = "333127dbecfcc23a8db7d9a4f52785d23aff44a1" revision = "333127dbecfcc23a8db7d9a4f52785d23aff44a1"
[[projects]] [[projects]]
branch = "master" digest = "1:3f9506ee991cdee1f05bf0cd3e34b5cd922dc00d6a950fb4beb4e07ab1c4d3d1"
digest = "1:af68c8bdac3ceaf46c67f0c43cc1ee5f10e705d8e04f8a63fa41231d0be6b0fb"
name = "github.com/coredns/coredns" name = "github.com/coredns/coredns"
packages = [ packages = [
"core/dnsserver", "core/dnsserver",
@ -72,10 +69,10 @@
"request", "request",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "992e7928c7c258628d2b13b769acc86781b9faea" revision = "2e322f6e8a54f18c6aef9c25a7c432c291a3d9f7"
version = "v1.2.0"
[[projects]] [[projects]]
branch = "master"
digest = "1:6a503e232df389d94ebb97dfb22d4ae463b6e2f351660613e11d9e42f57ab6df" digest = "1:6a503e232df389d94ebb97dfb22d4ae463b6e2f351660613e11d9e42f57ab6df"
name = "github.com/coreos/go-oidc" name = "github.com/coreos/go-oidc"
packages = [ packages = [
@ -93,8 +90,8 @@
name = "github.com/coreos/go-systemd" name = "github.com/coreos/go-systemd"
packages = ["daemon"] packages = ["daemon"]
pruneopts = "UT" pruneopts = "UT"
revision = "39ca1b05acc7ad1220e09f133283b8859a8b71ab" revision = "95778dfbb74eb7e4dbaf43bf7d71809650ef8076"
version = "v17" version = "v19"
[[projects]] [[projects]]
digest = "1:6fda0d7f5e52b081e075775b1ecebf1ea0c923e7be33604ed0225ae078e701b5" digest = "1:6fda0d7f5e52b081e075775b1ecebf1ea0c923e7be33604ed0225ae078e701b5"
@ -109,12 +106,12 @@
version = "v4" version = "v4"
[[projects]] [[projects]]
digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39" digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
name = "github.com/davecgh/go-spew" name = "github.com/davecgh/go-spew"
packages = ["spew"] packages = ["spew"]
pruneopts = "UT" pruneopts = "UT"
revision = "346938d642f2ec3594ed81d874461961cd0faa76" revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.0" version = "v1.1.1"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -125,8 +122,7 @@
revision = "027aa4915315a0b2825c0f025cea347829b974fa" revision = "027aa4915315a0b2825c0f025cea347829b974fa"
[[projects]] [[projects]]
branch = "master" digest = "1:d4268b2a09b1f736633577c4ac93f2a5356c73742fff5344e2451aeec60a7ad0"
digest = "1:15eadee5930d325154e5e1f3c4f4b28ab62f9c0aa949580e8d9edabaf0b64e85"
name = "github.com/equinox-io/equinox" name = "github.com/equinox-io/equinox"
packages = [ packages = [
".", ".",
@ -137,10 +133,10 @@
"proto", "proto",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "f24972fa72facf59d05c91c848b65eac38815915" revision = "5205c98a6c11dc72747ce12fff6cd620a99fde05"
version = "v1.2.0"
[[projects]] [[projects]]
branch = "master"
digest = "1:433763f10d88dba9b533a7ea2fe9f5ee11e57e00306eb97a1f6090fd978e8fa1" digest = "1:433763f10d88dba9b533a7ea2fe9f5ee11e57e00306eb97a1f6090fd978e8fa1"
name = "github.com/facebookgo/grace" name = "github.com/facebookgo/grace"
packages = ["gracenet"] packages = ["gracenet"]
@ -156,7 +152,6 @@
revision = "3f9db97f856818214da2e1057f8ad84803971cff" revision = "3f9db97f856818214da2e1057f8ad84803971cff"
[[projects]] [[projects]]
branch = "master"
digest = "1:d4623fc7bf7e281d9107367cc4a9e76ed3e86b1eec1a4e30630c870bef1fedd0" digest = "1:d4623fc7bf7e281d9107367cc4a9e76ed3e86b1eec1a4e30630c870bef1fedd0"
name = "github.com/getsentry/raven-go" name = "github.com/getsentry/raven-go"
packages = ["."] packages = ["."]
@ -172,7 +167,7 @@
revision = "604e922904d35e97f98a774db7881f049cd8d970" revision = "604e922904d35e97f98a774db7881f049cd8d970"
[[projects]] [[projects]]
digest = "1:17fe264ee908afc795734e8c4e63db2accabaf57326dbf21763a7d6b86096260" digest = "1:239c4c7fd2159585454003d9be7207167970194216193a8a210b8d29576f19c9"
name = "github.com/golang/protobuf" name = "github.com/golang/protobuf"
packages = [ packages = [
"proto", "proto",
@ -182,32 +177,24 @@
"ptypes/timestamp", "ptypes/timestamp",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" revision = "b5d812f8a3706043e23a9cd5babf2e5423744d30"
version = "v1.1.0" version = "v1.3.1"
[[projects]] [[projects]]
branch = "master"
digest = "1:582b704bebaa06b48c29b0cec224a6058a09c86883aaddabde889cd1a5f73e1b" digest = "1:582b704bebaa06b48c29b0cec224a6058a09c86883aaddabde889cd1a5f73e1b"
name = "github.com/google/uuid" name = "github.com/google/uuid"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "0cd6bf5da1e1c83f8b45653022c74f71af0538a4" revision = "0cd6bf5da1e1c83f8b45653022c74f71af0538a4"
[[projects]]
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
name = "github.com/gorilla/context"
packages = ["."]
pruneopts = "UT"
revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42"
version = "v1.1.1" version = "v1.1.1"
[[projects]] [[projects]]
digest = "1:e73f5b0152105f18bc131fba127d9949305c8693f8a762588a82a48f61756f5f" digest = "1:d5f97fc268267ec1b61c3453058c738246fc3e746f14b1ae25161513b7367b0c"
name = "github.com/gorilla/mux" name = "github.com/gorilla/mux"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "e3702bed27f0d39777b0b37b664b6280e8ef8fbf" revision = "c5c6c98bc25355028a63748a498942a6398ccd22"
version = "v1.6.2" version = "v1.7.1"
[[projects]] [[projects]]
digest = "1:43dd08a10854b2056e615d1b1d22ac94559d822e1f8b6fcc92c1a1057e85188e" digest = "1:43dd08a10854b2056e615d1b1d22ac94559d822e1f8b6fcc92c1a1057e85188e"
@ -234,31 +221,32 @@
version = "v0.1.0" version = "v0.1.0"
[[projects]] [[projects]]
branch = "master" digest = "1:bc1c0be40c67b6b4aee09d7508d5a2a52c1c116b1fa43806dad2b0d6b4d4003b"
digest = "1:37ce7d7d80531b227023331002c0d42b4b4b291a96798c82a049d03a54ba79e4"
name = "github.com/lib/pq" name = "github.com/lib/pq"
packages = [ packages = [
".", ".",
"oid", "oid",
"scram",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "90697d60dd844d5ef6ff15135d0203f65d2f53b8" revision = "51e2106eed1cea199c802d2a49e91e2491b02056"
version = "v1.1.0"
[[projects]] [[projects]]
digest = "1:c658e84ad3916da105a761660dcaeb01e63416c8ec7bc62256a9b411a05fcd67" digest = "1:2fa7b0155cd54479a755c629de26f888a918e13f8857a2c442205d825368e084"
name = "github.com/mattn/go-colorable" name = "github.com/mattn/go-colorable"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" revision = "3a70a971f94a22f2fa562ffcc7a0eb45f5daf045"
version = "v0.0.9" version = "v0.1.1"
[[projects]] [[projects]]
digest = "1:d4d17353dbd05cb52a2a52b7fe1771883b682806f68db442b436294926bbfafb" digest = "1:e150b5fafbd7607e2d638e4e5cf43aa4100124e5593385147b0a74e2733d8b0d"
name = "github.com/mattn/go-isatty" name = "github.com/mattn/go-isatty"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" revision = "c2a7a6ca930a4cd0bc33a3f298eb71960732a3a7"
version = "v0.0.3" version = "v0.0.7"
[[projects]] [[projects]]
digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc" digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc"
@ -269,7 +257,6 @@
version = "v1.0.1" version = "v1.0.1"
[[projects]] [[projects]]
branch = "master"
digest = "1:75fa16a231ef40da3e462d651c20b9df20bde0777bdc1ac0982242c79057ee71" digest = "1:75fa16a231ef40da3e462d651c20b9df20bde0777bdc1ac0982242c79057ee71"
name = "github.com/mholt/caddy" name = "github.com/mholt/caddy"
packages = [ packages = [
@ -281,25 +268,23 @@
revision = "d3b731e9255b72d4571a5aac125634cf1b6031dc" revision = "d3b731e9255b72d4571a5aac125634cf1b6031dc"
[[projects]] [[projects]]
digest = "1:73f788f2df39614dd7d9e75c8ca5fb8b4a68937b5e6d4a15e4c3a596f6f8c07b" digest = "1:2b4b4b2e5544c2a11a486c1b631357aa2ddf766e50c1b2483cf809da2c511234"
name = "github.com/miekg/dns" name = "github.com/miekg/dns"
packages = [ packages = ["."]
".",
"internal/socket",
]
pruneopts = "UT" pruneopts = "UT"
revision = "6da3249dfb57fbaa16efafcd8744cee8809d80cd" revision = "73601d4aed9d844322611759d7f3619110b7c88e"
version = "v1.1.8"
[[projects]] [[projects]]
branch = "master" digest = "1:5d231480e1c64a726869bc4142d270184c419749d34f167646baa21008eb0a79"
digest = "1:8eb17c2ec4df79193ae65b621cd1c0c4697db3bc317fe6afdc76d7f2746abd05"
name = "github.com/mitchellh/go-homedir" name = "github.com/mitchellh/go-homedir"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "3864e76763d94a6df2f9960b16a20a33da9f9a66" revision = "af06845cf3004701891bf4fdb884bfe4920b3727"
version = "v1.1.0"
[[projects]] [[projects]]
digest = "1:450b7623b185031f3a456801155c8320209f75d0d4c4e633c6b1e59d44d6e392" digest = "1:11e62d6050198055e6cd87ed57e5d8c669e84f839c16e16f192374d913d1a70d"
name = "github.com/opentracing/opentracing-go" name = "github.com/opentracing/opentracing-go"
packages = [ packages = [
".", ".",
@ -307,8 +292,8 @@
"log", "log",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "1949ddbfd147afd4d964a9f00b24eb291e0e7c38" revision = "659c90643e714681897ec2521c60567dd21da733"
version = "v1.0.2" version = "v1.1.0"
[[projects]] [[projects]]
digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747" digest = "1:40e195917a951a8bf867cd05de2a46aaf1806c50cf92eebf4c16f78cd196f747"
@ -339,15 +324,14 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:32d10bdfa8f09ecf13598324dba86ab891f11db3c538b6a34d1c3b5b99d7c36b" digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4"
name = "github.com/prometheus/client_model" name = "github.com/prometheus/client_model"
packages = ["go"] packages = ["go"]
pruneopts = "UT" pruneopts = "UT"
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c" revision = "fd36f4220a901265f90734c3183c5f0c91daa0b8"
[[projects]] [[projects]]
branch = "master" digest = "1:35cf6bdf68db765988baa9c4f10cc5d7dda1126a54bd62e252dbcd0b1fc8da90"
digest = "1:e469cd65badf7694aeb44874518606d93c1d59e7735d3754ad442782437d3cc3"
name = "github.com/prometheus/common" name = "github.com/prometheus/common"
packages = [ packages = [
"expfmt", "expfmt",
@ -355,48 +339,44 @@
"model", "model",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "7600349dcfe1abd18d72d3a1770870d9800a7801" revision = "a82f4c12f983cc2649298185f296632953e50d3e"
version = "v0.3.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:20d9bb50dbee172242f9bcd6ec24a917dd7a5bb17421bf16a79c33111dea7db1" digest = "1:49b09905e781d7775c086604cc00083e1832d0783f1f421b79f42657c457d029"
name = "github.com/prometheus/procfs" name = "github.com/prometheus/procfs"
packages = [ packages = ["."]
".",
"internal/util",
"nfs",
"xfs",
]
pruneopts = "UT" pruneopts = "UT"
revision = "ae68e2d4c00fed4943b5f6698d504a5fe083da8a" revision = "8368d24ba045f26503eb745b624d930cbe214c79"
[[projects]] [[projects]]
digest = "1:9a6f766efd8d5752adb7052aebb6e3d85255b31a8dff5e58ab4efa740ba9efa0" digest = "1:1a23fdd843129ef761ffe7651bc5fe7c5b09fbe933e92783ab06cc11c37b7b37"
name = "github.com/rifflock/lfshook" name = "github.com/rifflock/lfshook"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "bf539943797a1f34c1f502d07de419b5238ae6c6" revision = "b9218ef580f59a2e72dad1aa33d660150445d05a"
version = "v2.3" version = "v2.4"
[[projects]] [[projects]]
digest = "1:9e9193aa51197513b3abcb108970d831fbcf40ef96aa845c4f03276e1fa316d2" digest = "1:5f2aaa360f48d1711795bd88c7e45a38f86cf81e4bc01453d20983baa67e2d51"
name = "github.com/sirupsen/logrus" name = "github.com/sirupsen/logrus"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc" revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e"
version = "v1.0.5" version = "v1.0.3"
[[projects]] [[projects]]
digest = "1:18752d0b95816a1b777505a97f71c7467a8445b8ffb55631a7bf779f6ba4fa83" digest = "1:f85e109eda8f6080877185d1c39e98dd8795e1780c08beca28304b87fd855a1c"
name = "github.com/stretchr/testify" name = "github.com/stretchr/testify"
packages = ["assert"] packages = ["assert"]
pruneopts = "UT" pruneopts = "UT"
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686" revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
version = "v1.2.2" version = "v1.2.1"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:1182d12da264c8fe593504f150c3a479297767991fc1c06796cb67e4f61c4366" digest = "1:9afbc3e330bd691e0eb0e704d05cc182b5c62ea71c5691c99fa5e82f06b628b6"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = [ packages = [
"curve25519", "curve25519",
@ -410,27 +390,31 @@
"ssh/terminal", "ssh/terminal",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" revision = "f416ebab96af27ca70b6e5c23d6a0747530da626"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:9513f8a0f1f6918181b7d744225b1931ffacafeb57067a1c26893a51058afb80" digest = "1:52d140f7ab52e491cc1cbc93e6637aa5e9a7f3beae7545d675b02e52ca9d7290"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = [ packages = [
"bpf",
"context", "context",
"http/httpguts", "http/httpguts",
"http2", "http2",
"http2/hpack", "http2/hpack",
"idna", "idna",
"internal/iana",
"internal/socket",
"internal/timeseries", "internal/timeseries",
"ipv4",
"ipv6",
"trace", "trace",
"websocket", "websocket",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "32a936f46389aa10549d60bd7833e54b01685d09" revision = "1da14a5a36f220ea3f03470682b737b1dfd5de22"
[[projects]] [[projects]]
branch = "master"
digest = "1:39ebcc2b11457b703ae9ee2e8cca0f68df21969c6102cb3b705f76cca0ea0239" digest = "1:39ebcc2b11457b703ae9ee2e8cca0f68df21969c6102cb3b705f76cca0ea0239"
name = "golang.org/x/sync" name = "golang.org/x/sync"
packages = ["errgroup"] packages = ["errgroup"]
@ -439,9 +423,10 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:2e8e74aa73847379a370c2704ff08baf4a7303ae682766e70c23ded3fd9b3f37" digest = "1:77751d02e939d7078faedaeec10c09af575a09c528d84d18f2cb45a84bd1889a"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = [ packages = [
"cpu",
"unix", "unix",
"windows", "windows",
"windows/registry", "windows/registry",
@ -450,7 +435,7 @@
"windows/svc/mgr", "windows/svc/mgr",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "ce36f3865eeb42541ce3f87f32f8462c5687befa" revision = "12500544f89f9420afe9529ba8940bf72d294972"
[[projects]] [[projects]]
digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18" digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
@ -477,30 +462,38 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:601e63e7d4577f907118bec825902505291918859d223bce015539e79f1160e3" digest = "1:c3076e7defee87de1236f1814beb588f40a75544c60121e6eb38b3b3721783e2"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"] packages = ["googleapis/rpc/status"]
pruneopts = "UT" pruneopts = "UT"
revision = "ff3583edef7de132f219f0efc00e097cabcc0ec0" revision = "d1146b9035b912113a38af3b138eb2af567b2c67"
[[projects]] [[projects]]
digest = "1:2dab32a43451e320e49608ff4542fdfc653c95dcc35d0065ec9c6c3dd540ed74" digest = "1:31d87f39886fb38a2b6c097ff3b9f985d6960772170d64a68246f7790e955746"
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
packages = [ packages = [
".", ".",
"balancer", "balancer",
"balancer/base", "balancer/base",
"balancer/roundrobin", "balancer/roundrobin",
"binarylog/grpc_binarylog_v1",
"codes", "codes",
"connectivity", "connectivity",
"credentials", "credentials",
"credentials/internal",
"encoding", "encoding",
"encoding/proto", "encoding/proto",
"grpclog", "grpclog",
"internal", "internal",
"internal/backoff", "internal/backoff",
"internal/balancerload",
"internal/binarylog",
"internal/channelz", "internal/channelz",
"internal/envconfig",
"internal/grpcrand", "internal/grpcrand",
"internal/grpcsync",
"internal/syscall",
"internal/transport",
"keepalive", "keepalive",
"metadata", "metadata",
"naming", "naming",
@ -511,11 +504,10 @@
"stats", "stats",
"status", "status",
"tap", "tap",
"transport",
] ]
pruneopts = "UT" pruneopts = "UT"
revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8" revision = "236199dd5f8031d698fb64091194aecd1c3895b2"
version = "v1.13.0" version = "v1.20.0"
[[projects]] [[projects]]
branch = "altsrc-parse-durations" branch = "altsrc-parse-durations"
@ -530,12 +522,12 @@
source = "https://github.com/cbranch/cli" source = "https://github.com/cbranch/cli"
[[projects]] [[projects]]
digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96"
name = "gopkg.in/yaml.v2" name = "gopkg.in/yaml.v2"
packages = ["."] packages = ["."]
pruneopts = "UT" pruneopts = "UT"
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
version = "v2.2.1" version = "v2.2.2"
[[projects]] [[projects]]
digest = "1:8ffc3ddc31414c0a71220957bb723b16510d7fcb5b3880dc0da4cf6d39c31642" digest = "1:8ffc3ddc31414c0a71220957bb723b16510d7fcb5b3880dc0da4cf6d39c31642"

View File

@ -10,35 +10,35 @@
[[constraint]] [[constraint]]
name = "github.com/facebookgo/grace" name = "github.com/facebookgo/grace"
branch = "master" revision = "75cf19382434e82df4dd84953f566b8ad23d6e9e"
[[constraint]] [[constraint]]
name = "github.com/getsentry/raven-go" name = "github.com/getsentry/raven-go"
branch = "master" revision = "ed7bcb39ff10f39ab08e317ce16df282845852fa"
[[constraint]] [[constraint]]
name = "github.com/pkg/errors" name = "github.com/pkg/errors"
version = "0.8.0" version = "=0.8.0"
[[constraint]] [[constraint]]
name = "github.com/prometheus/client_golang" name = "github.com/prometheus/client_golang"
version = "0.9.0-pre1" version = "=0.9.0-pre1"
[[constraint]] [[constraint]]
name = "github.com/sirupsen/logrus" name = "github.com/sirupsen/logrus"
version = "1.0.3" version = "=1.0.3"
[[constraint]] [[constraint]]
name = "github.com/stretchr/testify" name = "github.com/stretchr/testify"
version = "1.2.1" version = "=1.2.1"
[[constraint]] [[constraint]]
name = "golang.org/x/net" name = "golang.org/x/net"
branch = "master" branch = "master" # master required by github.com/miekg/dns
[[constraint]] [[constraint]]
name = "golang.org/x/sync" name = "golang.org/x/sync"
branch = "master" revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
[[constraint]] [[constraint]]
name = "gopkg.in/urfave/cli.v2" name = "gopkg.in/urfave/cli.v2"
@ -48,40 +48,40 @@
[[constraint]] [[constraint]]
name = "zombiezen.com/go/capnproto2" name = "zombiezen.com/go/capnproto2"
source = "https://github.com/zombiezen/go-capnproto2" source = "https://github.com/zombiezen/go-capnproto2"
version = "2.17.1" version = "=2.17.1"
[[constraint]] [[constraint]]
name = "github.com/gorilla/websocket" name = "github.com/gorilla/websocket"
version = "1.2.0" version = "=1.2.0"
[[constraint]] [[constraint]]
name = "github.com/coredns/coredns" name = "github.com/coredns/coredns"
branch = "master" version = "=1.2.0"
[[constraint]] [[constraint]]
name = "github.com/miekg/dns" name = "github.com/miekg/dns"
revision = "6da3249dfb57fbaa16efafcd8744cee8809d80cd" version = "=1.1.8"
[[constraint]] [[constraint]]
name = "github.com/cloudflare/brotli-go" name = "github.com/cloudflare/brotli-go"
branch = "master" revision = "18c9f6c67e3dfc12e0ddaca748d2887f97a7ac28"
[[override]] [[override]]
name = "github.com/mholt/caddy" name = "github.com/mholt/caddy"
branch = "master" revision = "d3b731e9255b72d4571a5aac125634cf1b6031dc"
[[constraint]] [[constraint]]
branch = "master"
name = "github.com/coreos/go-oidc" name = "github.com/coreos/go-oidc"
revision = "a93f71fdfe73d2c0f5413c0565eea0af6523a6df"
[[constraint]] [[constraint]]
branch = "master"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
branch = "master" # master required by github.com/miekg/dns
[[constraint]] [[constraint]]
branch = "master"
name = "github.com/cloudflare/golibs" name = "github.com/cloudflare/golibs"
revision = "333127dbecfcc23a8db7d9a4f52785d23aff44a1"
[[constraint]] [[constraint]]
name = "github.com/google/uuid" name = "github.com/google/uuid"
version = "v1.1.1" version = "=1.1.1"

View File

@ -1,14 +1,21 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE The MIT License (MIT)
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> Copyright (c) 2013 TOML authors
Everyone is permitted to copy and distribute verbatim or modified Permission is hereby granted, free of charge, to any person obtaining a copy
copies of this license document, and changing it is allowed as long of this software and associated documentation files (the "Software"), to deal
as the name is changed. 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:
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE The above copyright notice and this permission notice shall be included in
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION all copies or substantial portions of the Software.
0. You just DO WHAT THE FUCK YOU WANT TO.
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.

View File

@ -1,14 +1,21 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE The MIT License (MIT)
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> Copyright (c) 2013 TOML authors
Everyone is permitted to copy and distribute verbatim or modified Permission is hereby granted, free of charge, to any person obtaining a copy
copies of this license document, and changing it is allowed as long of this software and associated documentation files (the "Software"), to deal
as the name is changed. 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:
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE The above copyright notice and this permission notice shall be included in
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION all copies or substantial portions of the Software.
0. You just DO WHAT THE FUCK YOU WANT TO.
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.

View File

@ -1,14 +1,21 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE The MIT License (MIT)
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> Copyright (c) 2013 TOML authors
Everyone is permitted to copy and distribute verbatim or modified Permission is hereby granted, free of charge, to any person obtaining a copy
copies of this license document, and changing it is allowed as long of this software and associated documentation files (the "Software"), to deal
as the name is changed. 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:
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE The above copyright notice and this permission notice shall be included in
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION all copies or substantial portions of the Software.
0. You just DO WHAT THE FUCK YOU WANT TO.
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.

View File

@ -1,14 +1,21 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE The MIT License (MIT)
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> Copyright (c) 2013 TOML authors
Everyone is permitted to copy and distribute verbatim or modified Permission is hereby granted, free of charge, to any person obtaining a copy
copies of this license document, and changing it is allowed as long of this software and associated documentation files (the "Software"), to deal
as the name is changed. 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:
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE The above copyright notice and this permission notice shall be included in
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION all copies or substantial portions of the Software.
0. You just DO WHAT THE FUCK YOU WANT TO.
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.

View File

@ -775,7 +775,7 @@ func lexDatetime(lx *lexer) stateFn {
return lexDatetime return lexDatetime
} }
switch r { switch r {
case '-', 'T', ':', '.', 'Z': case '-', 'T', ':', '.', 'Z', '+':
return lexDatetime return lexDatetime
} }

View File

@ -39,7 +39,6 @@ var Directives = []string{
"auto", "auto",
"secondary", "secondary",
"etcd", "etcd",
"loop",
"forward", "forward",
"proxy", "proxy",
"erratic", "erratic",

View File

@ -10,9 +10,7 @@ package log
import ( import (
"fmt" "fmt"
"io/ioutil"
golog "log" golog "log"
"os"
) )
// D controls whether we should output debug logs. If true, we do. // D controls whether we should output debug logs. If true, we do.
@ -63,21 +61,9 @@ func Error(v ...interface{}) { log(err, v...) }
// Errorf is equivalent to log.Printf, but prefixed with "[ERROR] ". // Errorf is equivalent to log.Printf, but prefixed with "[ERROR] ".
func Errorf(format string, v ...interface{}) { logf(err, format, v...) } func Errorf(format string, v ...interface{}) { logf(err, format, v...) }
// Fatal is equivalent to log.Print, but prefixed with "[FATAL] ", and calling
// os.Exit(1).
func Fatal(v ...interface{}) { log(fatal, v...); os.Exit(1) }
// Fatalf is equivalent to log.Printf, but prefixed with "[FATAL] ", and calling
// os.Exit(1)
func Fatalf(format string, v ...interface{}) { logf(fatal, format, v...); os.Exit(1) }
// Discard sets the log output to /dev/null.
func Discard() { golog.SetOutput(ioutil.Discard) }
const ( const (
debug = "[DEBUG] " debug = "[DEBUG] "
err = "[ERROR] " err = "[ERROR] "
fatal = "[FATAL] "
info = "[INFO] "
warning = "[WARNING] " warning = "[WARNING] "
info = "[INFO] "
) )

View File

@ -3,7 +3,6 @@ package log
import ( import (
"fmt" "fmt"
golog "log" golog "log"
"os"
) )
// P is a logger that includes the plugin doing the logging. // P is a logger that includes the plugin doing the logging.
@ -59,10 +58,4 @@ func (p P) Error(v ...interface{}) { p.log(err, v...) }
// Errorf logs as log.Errorf. // Errorf logs as log.Errorf.
func (p P) Errorf(format string, v ...interface{}) { p.logf(err, format, v...) } func (p P) Errorf(format string, v ...interface{}) { p.logf(err, format, v...) }
// Fatal logs as log.Fatal and calls os.Exit(1).
func (p P) Fatal(v ...interface{}) { p.log(fatal, v...); os.Exit(1) }
// Fatalf logs as log.Fatalf and calls os.Exit(1).
func (p P) Fatalf(format string, v ...interface{}) { p.logf(fatal, format, v...); os.Exit(1) }
func pFormat(s string) string { return "plugin/" + s + ": " } func pFormat(s string) string { return "plugin/" + s + ": " }

View File

@ -2,7 +2,7 @@ ISC License
Copyright (c) 2012-2016 Dave Collins <dave@davec.name> Copyright (c) 2012-2016 Dave Collins <dave@davec.name>
Permission to use, copy, modify, and distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies. copyright notice and this permission notice appear in all copies.

View File

@ -16,7 +16,9 @@
// when the code is not running on Google App Engine, compiled by GopherJS, and // when the code is not running on Google App Engine, compiled by GopherJS, and
// "-tags safe" is not added to the go build command line. The "disableunsafe" // "-tags safe" is not added to the go build command line. The "disableunsafe"
// tag is deprecated and thus should not be used. // tag is deprecated and thus should not be used.
// +build !js,!appengine,!safe,!disableunsafe // Go versions prior to 1.4 are disabled because they use a different layout
// for interfaces which make the implementation of unsafeReflectValue more complex.
// +build !js,!appengine,!safe,!disableunsafe,go1.4
package spew package spew
@ -34,80 +36,49 @@ const (
ptrSize = unsafe.Sizeof((*byte)(nil)) ptrSize = unsafe.Sizeof((*byte)(nil))
) )
var ( type flag uintptr
// offsetPtr, offsetScalar, and offsetFlag are the offsets for the
// internal reflect.Value fields. These values are valid before golang
// commit ecccf07e7f9d which changed the format. The are also valid
// after commit 82f48826c6c7 which changed the format again to mirror
// the original format. Code in the init function updates these offsets
// as necessary.
offsetPtr = uintptr(ptrSize)
offsetScalar = uintptr(0)
offsetFlag = uintptr(ptrSize * 2)
// flagKindWidth and flagKindShift indicate various bits that the var (
// reflect package uses internally to track kind information. // flagRO indicates whether the value field of a reflect.Value
// // is read-only.
// flagRO indicates whether or not the value field of a reflect.Value is flagRO flag
// read-only.
// // flagAddr indicates whether the address of the reflect.Value's
// flagIndir indicates whether the value field of a reflect.Value is // value may be taken.
// the actual data or a pointer to the data. flagAddr flag
//
// These values are valid before golang commit 90a7c3c86944 which
// changed their positions. Code in the init function updates these
// flags as necessary.
flagKindWidth = uintptr(5)
flagKindShift = uintptr(flagKindWidth - 1)
flagRO = uintptr(1 << 0)
flagIndir = uintptr(1 << 1)
) )
func init() { // flagKindMask holds the bits that make up the kind
// Older versions of reflect.Value stored small integers directly in the // part of the flags field. In all the supported versions,
// ptr field (which is named val in the older versions). Versions // it is in the lower 5 bits.
// between commits ecccf07e7f9d and 82f48826c6c7 added a new field named const flagKindMask = flag(0x1f)
// scalar for this purpose which unfortunately came before the flag
// field, so the offset of the flag field is different for those
// versions.
//
// This code constructs a new reflect.Value from a known small integer
// and checks if the size of the reflect.Value struct indicates it has
// the scalar field. When it does, the offsets are updated accordingly.
vv := reflect.ValueOf(0xf00)
if unsafe.Sizeof(vv) == (ptrSize * 4) {
offsetScalar = ptrSize * 2
offsetFlag = ptrSize * 3
}
// Commit 90a7c3c86944 changed the flag positions such that the low // Different versions of Go have used different
// order bits are the kind. This code extracts the kind from the flags // bit layouts for the flags type. This table
// field and ensures it's the correct type. When it's not, the flag // records the known combinations.
// order has been changed to the newer format, so the flags are updated var okFlags = []struct {
// accordingly. ro, addr flag
upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) }{{
upfv := *(*uintptr)(upf) // From Go 1.4 to 1.5
flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift) ro: 1 << 5,
if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) { addr: 1 << 7,
flagKindShift = 0 }, {
flagRO = 1 << 5 // Up to Go tip.
flagIndir = 1 << 6 ro: 1<<5 | 1<<6,
addr: 1 << 8,
}}
// Commit adf9b30e5594 modified the flags to separate the var flagValOffset = func() uintptr {
// flagRO flag into two bits which specifies whether or not the field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
// field is embedded. This causes flagIndir to move over a bit if !ok {
// and means that flagRO is the combination of either of the panic("reflect.Value has no flag field")
// original flagRO bit and the new bit.
//
// This code detects the change by extracting what used to be
// the indirect bit to ensure it's set. When it's not, the flag
// order has been changed to the newer format, so the flags are
// updated accordingly.
if upfv&flagIndir == 0 {
flagRO = 3 << 5
flagIndir = 1 << 7
}
} }
return field.Offset
}()
// flagField returns a pointer to the flag field of a reflect.Value.
func flagField(v *reflect.Value) *flag {
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
} }
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses // unsafeReflectValue converts the passed reflect.Value into a one that bypasses
@ -119,34 +90,56 @@ func init() {
// This allows us to check for implementations of the Stringer and error // This allows us to check for implementations of the Stringer and error
// interfaces to be used for pretty printing ordinarily unaddressable and // interfaces to be used for pretty printing ordinarily unaddressable and
// inaccessible values such as unexported struct fields. // inaccessible values such as unexported struct fields.
func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { func unsafeReflectValue(v reflect.Value) reflect.Value {
indirects := 1 if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
vt := v.Type() return v
upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) }
rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) flagFieldPtr := flagField(&v)
if rvf&flagIndir != 0 { *flagFieldPtr &^= flagRO
vt = reflect.PtrTo(v.Type()) *flagFieldPtr |= flagAddr
indirects++ return v
} else if offsetScalar != 0 { }
// The value is in the scalar field when it's not one of the
// reference types. // Sanity checks against future reflect package changes
switch vt.Kind() { // to the type or semantics of the Value.flag field.
case reflect.Uintptr: func init() {
case reflect.Chan: field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
case reflect.Func: if !ok {
case reflect.Map: panic("reflect.Value has no flag field")
case reflect.Ptr: }
case reflect.UnsafePointer: if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
default: panic("reflect.Value flag field has changed kind")
upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + }
offsetScalar) type t0 int
var t struct {
A t0
// t0 will have flagEmbedRO set.
t0
// a will have flagStickyRO set
a t0
}
vA := reflect.ValueOf(t).FieldByName("A")
va := reflect.ValueOf(t).FieldByName("a")
vt0 := reflect.ValueOf(t).FieldByName("t0")
// Infer flagRO from the difference between the flags
// for the (otherwise identical) fields in t.
flagPublic := *flagField(&vA)
flagWithRO := *flagField(&va) | *flagField(&vt0)
flagRO = flagPublic ^ flagWithRO
// Infer flagAddr from the difference between a value
// taken from a pointer and not.
vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
flagNoPtr := *flagField(&vA)
flagPtr := *flagField(&vPtrA)
flagAddr = flagNoPtr ^ flagPtr
// Check that the inferred flags tally with one of the known versions.
for _, f := range okFlags {
if flagRO == f.ro && flagAddr == f.addr {
return
} }
} }
panic("reflect.Value read-only flag has changed semantics")
pv := reflect.NewAt(vt, upv)
rv = pv
for i := 0; i < indirects; i++ {
rv = rv.Elem()
}
return rv
} }

View File

@ -16,7 +16,7 @@
// when the code is running on Google App Engine, compiled by GopherJS, or // when the code is running on Google App Engine, compiled by GopherJS, or
// "-tags safe" is added to the go build command line. The "disableunsafe" // "-tags safe" is added to the go build command line. The "disableunsafe"
// tag is deprecated and thus should not be used. // tag is deprecated and thus should not be used.
// +build js appengine safe disableunsafe // +build js appengine safe disableunsafe !go1.4
package spew package spew

View File

@ -180,7 +180,7 @@ func printComplex(w io.Writer, c complex128, floatPrecision int) {
w.Write(closeParenBytes) w.Write(closeParenBytes)
} }
// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' // printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
// prefix to Writer w. // prefix to Writer w.
func printHexPtr(w io.Writer, p uintptr) { func printHexPtr(w io.Writer, p uintptr) {
// Null pointer. // Null pointer.

View File

@ -35,16 +35,16 @@ var (
// cCharRE is a regular expression that matches a cgo char. // cCharRE is a regular expression that matches a cgo char.
// It is used to detect character arrays to hexdump them. // It is used to detect character arrays to hexdump them.
cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
// cUnsignedCharRE is a regular expression that matches a cgo unsigned // cUnsignedCharRE is a regular expression that matches a cgo unsigned
// char. It is used to detect unsigned character arrays to hexdump // char. It is used to detect unsigned character arrays to hexdump
// them. // them.
cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
// cUint8tCharRE is a regular expression that matches a cgo uint8_t. // cUint8tCharRE is a regular expression that matches a cgo uint8_t.
// It is used to detect uint8_t arrays to hexdump them. // It is used to detect uint8_t arrays to hexdump them.
cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
) )
// dumpState contains information about the state of a dump operation. // dumpState contains information about the state of a dump operation.
@ -143,10 +143,10 @@ func (d *dumpState) dumpPtr(v reflect.Value) {
// Display dereferenced value. // Display dereferenced value.
d.w.Write(openParenBytes) d.w.Write(openParenBytes)
switch { switch {
case nilFound == true: case nilFound:
d.w.Write(nilAngleBytes) d.w.Write(nilAngleBytes)
case cycleFound == true: case cycleFound:
d.w.Write(circularBytes) d.w.Write(circularBytes)
default: default:

View File

@ -182,10 +182,10 @@ func (f *formatState) formatPtr(v reflect.Value) {
// Display dereferenced value. // Display dereferenced value.
switch { switch {
case nilFound == true: case nilFound:
f.fs.Write(nilAngleBytes) f.fs.Write(nilAngleBytes)
case cycleFound == true: case cycleFound:
f.fs.Write(circularShortBytes) f.fs.Write(circularShortBytes)
default: default:

View File

@ -1,5 +1,13 @@
language: go language: go
go: go:
- 1.4 - "1.4"
- 1.5 - "1.5"
- "1.7"
- "1.9"
- "1.10"
- "1.11"
- "tip"
matrix:
allow_failures:
- go: tip
script: go test -v github.com/equinox-io/equinox github.com/equinox-io/equinox/proto script: go test -v github.com/equinox-io/equinox github.com/equinox-io/equinox/proto

1
vendor/github.com/equinox-io/equinox/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/equinox-io/equinox

View File

@ -131,8 +131,16 @@ func (o *Options) SetPublicKeyPEM(pembytes []byte) error {
// a successful check that found no update from other errors like a failed // a successful check that found no update from other errors like a failed
// network connection. // network connection.
func Check(appID string, opts Options) (Response, error) { func Check(appID string, opts Options) (Response, error) {
var r Response var req, err = checkRequest(appID, &opts)
if err != nil {
return Response{}, err
}
return doCheckRequest(opts, req)
}
func checkRequest(appID string, opts *Options) (*http.Request, error) {
if opts.Channel == "" { if opts.Channel == "" {
opts.Channel = "stable" opts.Channel = "stable"
} }
@ -140,7 +148,7 @@ func Check(appID string, opts Options) (Response, error) {
var err error var err error
opts.TargetPath, err = osext.Executable() opts.TargetPath, err = osext.Executable()
if err != nil { if err != nil {
return r, err return nil, err
} }
} }
if opts.OS == "" { if opts.OS == "" {
@ -172,11 +180,17 @@ func Check(appID string, opts Options) (Response, error) {
req, err := http.NewRequest("POST", opts.CheckURL, bytes.NewReader(payload)) req, err := http.NewRequest("POST", opts.CheckURL, bytes.NewReader(payload))
if err != nil { if err != nil {
return r, err return nil, err
} }
req.Header.Set("Accept", fmt.Sprintf("application/json; q=1; version=%s; charset=utf-8", protocolVersion)) req.Header.Set("Accept", fmt.Sprintf("application/json; q=1; version=%s; charset=utf-8", protocolVersion))
req.Header.Set("Content-Type", "application/json; charset=utf-8") req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.Close = true
return req, err
}
func doCheckRequest(opts Options, req *http.Request) (r Response, err error) {
resp, err := opts.HTTPClient.Do(req) resp, err := opts.HTTPClient.Do(req)
if err != nil { if err != nil {
return r, err return r, err
@ -236,6 +250,16 @@ func computeChecksum(path string) string {
// //
// Error is nil if and only if the entire update completes successfully. // Error is nil if and only if the entire update completes successfully.
func (r Response) Apply() error { func (r Response) Apply() error {
var req, opts, err = r.applyRequest()
if err != nil {
return err
}
return r.applyUpdate(req, opts)
}
func (r Response) applyRequest() (*http.Request, update.Options, error) {
opts := update.Options{ opts := update.Options{
TargetPath: r.opts.TargetPath, TargetPath: r.opts.TargetPath,
TargetMode: r.opts.TargetMode, TargetMode: r.opts.TargetMode,
@ -250,15 +274,16 @@ func (r Response) Apply() error {
} }
if err := opts.CheckPermissions(); err != nil { if err := opts.CheckPermissions(); err != nil {
return err return nil, opts, err
} }
req, err := http.NewRequest("GET", r.downloadURL, nil) req, err := http.NewRequest("GET", r.downloadURL, nil)
if err != nil { return req, opts, err
return err }
}
func (r Response) applyUpdate(req *http.Request, opts update.Options) error {
// fetch the update // fetch the update
req.Close = true
resp, err := r.opts.HTTPClient.Do(req) resp, err := r.opts.HTTPClient.Do(req)
if err != nil { if err != nil {
return err return err

29
vendor/github.com/equinox-io/equinox/sdk_ctx.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// +build go1.7
package equinox
import (
"context"
)
// CheckContext is like Check but includes a context.
func CheckContext(ctx context.Context, appID string, opts Options) (Response, error) {
var req, err = checkRequest(appID, &opts)
if err != nil {
return Response{}, err
}
return doCheckRequest(opts, req.WithContext(ctx))
}
// ApplyContext is like Apply but includes a context.
func (r Response) ApplyContext(ctx context.Context) error {
var req, opts, err = r.applyRequest()
if err != nil {
return err
}
return r.applyUpdate(req.WithContext(ctx), opts)
}

View File

@ -1,7 +1,4 @@
Go support for Protocol Buffers - Google's data interchange format
Copyright 2010 The Go Authors. All rights reserved. Copyright 2010 The Go Authors. All rights reserved.
https://github.com/golang/protobuf
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are

View File

@ -186,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
if b&0x80 == 0 { if b&0x80 == 0 {
goto done goto done
} }
// x -= 0x80 << 63 // Always zero.
return 0, errOverflow return 0, errOverflow

63
vendor/github.com/golang/protobuf/proto/deprecated.go generated vendored Normal file
View File

@ -0,0 +1,63 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2018 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 "errors"
// Deprecated: do not use.
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
// Deprecated: do not use.
func GetStats() Stats { return Stats{} }
// Deprecated: do not use.
func MarshalMessageSet(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSet([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSetJSON([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func RegisterMessageSetType(Message, int32, string) {}

View File

@ -37,27 +37,9 @@ package proto
import ( import (
"errors" "errors"
"fmt"
"reflect" "reflect"
) )
// RequiredNotSetError is the error returned if Marshal is called with
// a protocol buffer struct whose required fields have not
// all been initialized. It is also the error returned if Unmarshal is
// called with an encoded protocol buffer that does not include all the
// required fields.
//
// When printed, RequiredNotSetError reports the first unset required field in a
// message. If the field cannot be precisely determined, it is reported as
// "{Unknown}".
type RequiredNotSetError struct {
field string
}
func (e *RequiredNotSetError) Error() string {
return fmt.Sprintf("proto: required field %q not set", e.field)
}
var ( var (
// errRepeatedHasNil is the error returned if Marshal is called with // errRepeatedHasNil is the error returned if Marshal is called with
// a struct with a repeated field containing a nil element. // a struct with a repeated field containing a nil element.

View File

@ -246,7 +246,8 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
return false return false
} }
m1, m2 := e1.value, e2.value m1 := extensionAsLegacyType(e1.value)
m2 := extensionAsLegacyType(e2.value)
if m1 == nil && m2 == nil { if m1 == nil && m2 == nil {
// Both have only encoded form. // Both have only encoded form.

View File

@ -185,9 +185,25 @@ type Extension struct {
// extension will have only enc set. When such an extension is // extension will have only enc set. When such an extension is
// accessed using GetExtension (or GetExtensions) desc and value // accessed using GetExtension (or GetExtensions) desc and value
// will be set. // will be set.
desc *ExtensionDesc desc *ExtensionDesc
// value is a concrete value for the extension field. Let the type of
// desc.ExtensionType be the "API type" and the type of Extension.value
// be the "storage type". The API type and storage type are the same except:
// * For scalars (except []byte), the API type uses *T,
// while the storage type uses T.
// * For repeated fields, the API type uses []T, while the storage type
// uses *[]T.
//
// The reason for the divergence is so that the storage type more naturally
// matches what is expected of when retrieving the values through the
// protobuf reflection APIs.
//
// The value may only be populated if desc is also populated.
value interface{} value interface{}
enc []byte
// enc is the raw bytes for the extension field.
enc []byte
} }
// SetRawExtension is for testing only. // SetRawExtension is for testing only.
@ -334,7 +350,7 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// descriptors with the same field number. // descriptors with the same field number.
return nil, errors.New("proto: descriptor conflict") return nil, errors.New("proto: descriptor conflict")
} }
return e.value, nil return extensionAsLegacyType(e.value), nil
} }
if extension.ExtensionType == nil { if extension.ExtensionType == nil {
@ -349,11 +365,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// Remember the decoded version and drop the encoded version. // Remember the decoded version and drop the encoded version.
// That way it is safe to mutate what we return. // That way it is safe to mutate what we return.
e.value = v e.value = extensionAsStorageType(v)
e.desc = extension e.desc = extension
e.enc = nil e.enc = nil
emap[extension.Field] = e emap[extension.Field] = e
return e.value, nil return extensionAsLegacyType(e.value), nil
} }
// defaultExtensionValue returns the default value for extension. // defaultExtensionValue returns the default value for extension.
@ -488,7 +504,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
} }
typ := reflect.TypeOf(extension.ExtensionType) typ := reflect.TypeOf(extension.ExtensionType)
if typ != reflect.TypeOf(value) { if typ != reflect.TypeOf(value) {
return errors.New("proto: bad extension value type") return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
} }
// nil extension values need to be caught early, because the // nil extension values need to be caught early, because the
// encoder can't distinguish an ErrNil due to a nil extension // encoder can't distinguish an ErrNil due to a nil extension
@ -500,7 +516,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
} }
extmap := epb.extensionsWrite() extmap := epb.extensionsWrite()
extmap[extension.Field] = Extension{desc: extension, value: value} extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
return nil return nil
} }
@ -541,3 +557,51 @@ func RegisterExtension(desc *ExtensionDesc) {
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
return extensionMaps[reflect.TypeOf(pb).Elem()] return extensionMaps[reflect.TypeOf(pb).Elem()]
} }
// extensionAsLegacyType converts an value in the storage type as the API type.
// See Extension.value.
func extensionAsLegacyType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
// Represent primitive types as a pointer to the value.
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
case reflect.Ptr:
// Represent slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Slice:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
}
}
}
return v
}
// extensionAsStorageType converts an value in the API type as the storage type.
// See Extension.value.
func extensionAsStorageType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Ptr:
// Represent slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
}
}
case reflect.Slice:
// Represent slice types as a pointer to the value.
if rv.Type().Elem().Kind() != reflect.Uint8 {
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
}
}
return v
}

View File

@ -265,7 +265,6 @@ package proto
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"log" "log"
"reflect" "reflect"
@ -274,7 +273,66 @@ import (
"sync" "sync"
) )
var errInvalidUTF8 = errors.New("proto: invalid UTF-8 string") // 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. // Message is implemented by generated protocol buffer messages.
type Message interface { type Message interface {
@ -283,26 +341,6 @@ type Message interface {
ProtoMessage() ProtoMessage()
} }
// Stats records allocation details about the protocol buffer encoders
// and decoders. Useful for tuning the library itself.
type Stats struct {
Emalloc uint64 // mallocs in encode
Dmalloc uint64 // mallocs in decode
Encode uint64 // number of encodes
Decode uint64 // number of decodes
Chit uint64 // number of cache hits
Cmiss uint64 // number of cache misses
Size uint64 // number of sizes
}
// Set to true to enable stats collection.
const collectStats = false
var stats Stats
// GetStats returns a copy of the global Stats structure.
func GetStats() Stats { return stats }
// A Buffer is a buffer manager for marshaling and unmarshaling // A Buffer is a buffer manager for marshaling and unmarshaling
// protocol buffers. It may be reused between invocations to // protocol buffers. It may be reused between invocations to
// reduce memory usage. It is not necessary to use a Buffer; // reduce memory usage. It is not necessary to use a Buffer;
@ -902,13 +940,19 @@ func isProto3Zero(v reflect.Value) bool {
return false return false
} }
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files const (
// to assert that that code is compatible with this version of the proto package. // ProtoPackageIsVersion3 is referenced from generated protocol buffer files
const ProtoPackageIsVersion2 = true // to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion3 = true
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files // ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package. // to assert that that code is compatible with this version of the proto package.
const ProtoPackageIsVersion1 = true 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. // 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 intended to be used by non-generated code.

View File

@ -36,13 +36,7 @@ package proto
*/ */
import ( import (
"bytes"
"encoding/json"
"errors" "errors"
"fmt"
"reflect"
"sort"
"sync"
) )
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID. // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
@ -145,46 +139,9 @@ func skipVarint(buf []byte) []byte {
return buf[i+1:] return buf[i+1:]
} }
// MarshalMessageSet encodes the extension map represented by m in the message set wire format. // unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSet(exts interface{}) ([]byte, error) {
return marshalMessageSet(exts, false)
}
// marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) {
switch exts := exts.(type) {
case *XXX_InternalExtensions:
var u marshalInfo
siz := u.sizeMessageSet(exts)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, exts, deterministic)
case map[int32]Extension:
// This is an old-style extension map.
// Wrap it in a new-style XXX_InternalExtensions.
ie := XXX_InternalExtensions{
p: &struct {
mu sync.Mutex
extensionMap map[int32]Extension
}{
extensionMap: exts,
},
}
var u marshalInfo
siz := u.sizeMessageSet(&ie)
b := make([]byte, 0, siz)
return u.appendMessageSet(b, &ie, deterministic)
default:
return nil, errors.New("proto: not an extension map")
}
}
// 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. // It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
func UnmarshalMessageSet(buf []byte, exts interface{}) error { func unmarshalMessageSet(buf []byte, exts interface{}) error {
var m map[int32]Extension var m map[int32]Extension
switch exts := exts.(type) { switch exts := exts.(type) {
case *XXX_InternalExtensions: case *XXX_InternalExtensions:
@ -222,93 +179,3 @@ func UnmarshalMessageSet(buf []byte, exts interface{}) error {
} }
return nil return nil
} }
// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
var mu sync.Locker
m, mu = exts.extensionsRead()
if m != nil {
// Keep the extensions map locked until we're done marshaling to prevent
// races between marshaling and unmarshaling the lazily-{en,de}coded
// values.
mu.Lock()
defer mu.Unlock()
}
case map[int32]Extension:
m = exts
default:
return nil, errors.New("proto: not an extension map")
}
var b bytes.Buffer
b.WriteByte('{')
// Process the map in key order for deterministic output.
ids := make([]int32, 0, len(m))
for id := range m {
ids = append(ids, id)
}
sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
for i, id := range ids {
ext := m[id]
msd, ok := messageSetMap[id]
if !ok {
// Unknown type; we can't render it, so skip it.
continue
}
if i > 0 && b.Len() > 1 {
b.WriteByte(',')
}
fmt.Fprintf(&b, `"[%s]":`, msd.name)
x := ext.value
if x == nil {
x = reflect.New(msd.t.Elem()).Interface()
if err := Unmarshal(ext.enc, x.(Message)); err != nil {
return nil, err
}
}
d, err := json.Marshal(x)
if err != nil {
return nil, err
}
b.Write(d)
}
b.WriteByte('}')
return b.Bytes(), nil
}
// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
// Common-case fast path.
if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
return nil
}
// This is fairly tricky, and it's not clear that it is needed.
return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
}
// A global registry of types that can be used in a MessageSet.
var messageSetMap = make(map[int32]messageSetDesc)
type messageSetDesc struct {
t reflect.Type // pointer to struct
name string
}
// RegisterMessageSetType is called from the generated code.
func RegisterMessageSetType(m Message, fieldNum int32, name string) {
messageSetMap[fieldNum] = messageSetDesc{
t: reflect.TypeOf(m),
name: name,
}
}

View File

@ -79,10 +79,13 @@ func toPointer(i *Message) pointer {
// toAddrPointer converts an interface to a pointer that points to // toAddrPointer converts an interface to a pointer that points to
// the interface data. // the interface data.
func toAddrPointer(i *interface{}, isptr bool) pointer { func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
v := reflect.ValueOf(*i) v := reflect.ValueOf(*i)
u := reflect.New(v.Type()) u := reflect.New(v.Type())
u.Elem().Set(v) u.Elem().Set(v)
if deref {
u = u.Elem()
}
return pointer{v: u} return pointer{v: u}
} }

View File

@ -85,16 +85,21 @@ func toPointer(i *Message) pointer {
// toAddrPointer converts an interface to a pointer that points to // toAddrPointer converts an interface to a pointer that points to
// the interface data. // the interface data.
func toAddrPointer(i *interface{}, isptr bool) pointer { func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
// Super-tricky - read or get the address of data word of interface value. // Super-tricky - read or get the address of data word of interface value.
if isptr { if isptr {
// The interface is of pointer type, thus it is a direct interface. // The interface is of pointer type, thus it is a direct interface.
// The data word is the pointer data itself. We take its address. // The data word is the pointer data itself. We take its address.
return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} 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]}
} }
// The interface is not of pointer type. The data word is the pointer if deref {
// to the data. p.p = *(*unsafe.Pointer)(p.p)
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} }
return p
} }
// valToPointer converts v to a pointer. v must be of pointer type. // valToPointer converts v to a pointer. v must be of pointer type.

View File

@ -139,7 +139,7 @@ type Properties struct {
Repeated bool Repeated bool
Packed bool // relevant for repeated primitives only Packed bool // relevant for repeated primitives only
Enum string // set for enum types only Enum string // set for enum types only
proto3 bool // whether this is known to be a proto3 field; set for []byte only proto3 bool // whether this is known to be a proto3 field
oneof bool // whether this is a oneof field oneof bool // whether this is a oneof field
Default string // default value Default string // default value
@ -148,9 +148,9 @@ type Properties struct {
stype reflect.Type // set for struct types only stype reflect.Type // set for struct types only
sprop *StructProperties // set for struct types only sprop *StructProperties // set for struct types only
mtype reflect.Type // set for map types only mtype reflect.Type // set for map types only
mkeyprop *Properties // set for map types only MapKeyProp *Properties // set for map types only
mvalprop *Properties // set for map types only MapValProp *Properties // set for map types only
} }
// String formats the properties in the protobuf struct field tag style. // String formats the properties in the protobuf struct field tag style.
@ -275,16 +275,16 @@ func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, loc
case reflect.Map: case reflect.Map:
p.mtype = t1 p.mtype = t1
p.mkeyprop = &Properties{} p.MapKeyProp = &Properties{}
p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp) p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
p.mvalprop = &Properties{} p.MapValProp = &Properties{}
vtype := p.mtype.Elem() vtype := p.mtype.Elem()
if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice { if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
// The value type is not a message (*T) or bytes ([]byte), // The value type is not a message (*T) or bytes ([]byte),
// so we need encoders for the pointer to this type. // so we need encoders for the pointer to this type.
vtype = reflect.PtrTo(vtype) vtype = reflect.PtrTo(vtype)
} }
p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp) p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
} }
if p.stype != nil { if p.stype != nil {
@ -334,9 +334,6 @@ func GetProperties(t reflect.Type) *StructProperties {
sprop, ok := propertiesMap[t] sprop, ok := propertiesMap[t]
propertiesMu.RUnlock() propertiesMu.RUnlock()
if ok { if ok {
if collectStats {
stats.Chit++
}
return sprop return sprop
} }
@ -346,17 +343,20 @@ func GetProperties(t reflect.Type) *StructProperties {
return sprop return sprop
} }
type (
oneofFuncsIface interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
oneofWrappersIface interface {
XXX_OneofWrappers() []interface{}
}
)
// getPropertiesLocked requires that propertiesMu is held. // getPropertiesLocked requires that propertiesMu is held.
func getPropertiesLocked(t reflect.Type) *StructProperties { func getPropertiesLocked(t reflect.Type) *StructProperties {
if prop, ok := propertiesMap[t]; ok { if prop, ok := propertiesMap[t]; ok {
if collectStats {
stats.Chit++
}
return prop return prop
} }
if collectStats {
stats.Cmiss++
}
prop := new(StructProperties) prop := new(StructProperties)
// in case of recursive protos, fill this in now. // in case of recursive protos, fill this in now.
@ -391,13 +391,14 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
// Re-order prop.order. // Re-order prop.order.
sort.Sort(prop) sort.Sort(prop)
type oneofMessage interface { var oots []interface{}
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oots = m.XXX_OneofFuncs()
case oneofWrappersIface:
oots = m.XXX_OneofWrappers()
} }
if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { if len(oots) > 0 {
var oots []interface{}
_, _, _, oots = om.XXX_OneofFuncs()
// Interpret oneof metadata. // Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties) prop.OneofTypes = make(map[string]*OneofProperties)
for _, oot := range oots { for _, oot := range oots {

View File

@ -87,6 +87,7 @@ type marshalElemInfo struct {
sizer sizer sizer sizer
marshaler marshaler marshaler marshaler
isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only) isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
deref bool // dereference the pointer before operating on it; implies isptr
} }
var ( var (
@ -231,7 +232,7 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
return b, err return b, err
} }
var err, errreq error var err, errLater error
// The old marshaler encodes extensions at beginning. // The old marshaler encodes extensions at beginning.
if u.extensions.IsValid() { if u.extensions.IsValid() {
e := ptr.offset(u.extensions).toExtensions() e := ptr.offset(u.extensions).toExtensions()
@ -252,11 +253,13 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
} }
} }
for _, f := range u.fields { for _, f := range u.fields {
if f.required && errreq == nil { if f.required {
if ptr.offset(f.field).getPointer().isNil() { if ptr.offset(f.field).getPointer().isNil() {
// Required field is not set. // Required field is not set.
// We record the error but keep going, to give a complete marshaling. // We record the error but keep going, to give a complete marshaling.
errreq = &RequiredNotSetError{f.name} if errLater == nil {
errLater = &RequiredNotSetError{f.name}
}
continue continue
} }
} }
@ -269,14 +272,21 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
if err1, ok := err.(*RequiredNotSetError); ok { if err1, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set. // Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling. // We record the error but keep going, to give a complete marshaling.
if errreq == nil { if errLater == nil {
errreq = &RequiredNotSetError{f.name + "." + err1.field} errLater = &RequiredNotSetError{f.name + "." + err1.field}
} }
continue continue
} }
if err == errRepeatedHasNil { if err == errRepeatedHasNil {
err = errors.New("proto: repeated field " + f.name + " has nil element") err = errors.New("proto: repeated field " + f.name + " has nil element")
} }
if err == errInvalidUTF8 {
if errLater == nil {
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
errLater = &invalidUTF8Error{fullName}
}
continue
}
return b, err return b, err
} }
} }
@ -284,7 +294,7 @@ func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte
s := *ptr.offset(u.unrecognized).toBytes() s := *ptr.offset(u.unrecognized).toBytes()
b = append(b, s...) b = append(b, s...)
} }
return b, errreq return b, errLater
} }
// computeMarshalInfo initializes the marshal info. // computeMarshalInfo initializes the marshal info.
@ -311,8 +321,11 @@ func (u *marshalInfo) computeMarshalInfo() {
// get oneof implementers // get oneof implementers
var oneofImplementers []interface{} var oneofImplementers []interface{}
if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oneofImplementers = m.XXX_OneofFuncs() _, _, _, oneofImplementers = m.XXX_OneofFuncs()
case oneofWrappersIface:
oneofImplementers = m.XXX_OneofWrappers()
} }
n := t.NumField() n := t.NumField()
@ -398,13 +411,22 @@ func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
panic("tag is not an integer") panic("tag is not an integer")
} }
wt := wiretype(tags[0]) wt := wiretype(tags[0])
if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct {
t = t.Elem()
}
sizer, marshaler := typeMarshaler(t, tags, false, false) sizer, marshaler := typeMarshaler(t, tags, false, false)
var deref bool
if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
t = reflect.PtrTo(t)
deref = true
}
e = &marshalElemInfo{ e = &marshalElemInfo{
wiretag: uint64(tag)<<3 | wt, wiretag: uint64(tag)<<3 | wt,
tagsize: SizeVarint(uint64(tag) << 3), tagsize: SizeVarint(uint64(tag) << 3),
sizer: sizer, sizer: sizer,
marshaler: marshaler, marshaler: marshaler,
isptr: t.Kind() == reflect.Ptr, isptr: t.Kind() == reflect.Ptr,
deref: deref,
} }
// update cache // update cache
@ -439,7 +461,7 @@ func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) { func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
fi.field = toField(f) fi.field = toField(f)
fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire. fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
fi.isPointer = true fi.isPointer = true
fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f) fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
fi.oneofElems = make(map[reflect.Type]*marshalElemInfo) fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
@ -467,10 +489,6 @@ func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofI
} }
} }
type oneofMessage interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
// wiretype returns the wire encoding of the type. // wiretype returns the wire encoding of the type.
func wiretype(encoding string) uint64 { func wiretype(encoding string) uint64 {
switch encoding { switch encoding {
@ -530,6 +548,7 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
packed := false packed := false
proto3 := false proto3 := false
validateUTF8 := true
for i := 2; i < len(tags); i++ { for i := 2; i < len(tags); i++ {
if tags[i] == "packed" { if tags[i] == "packed" {
packed = true packed = true
@ -538,6 +557,7 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
proto3 = true proto3 = true
} }
} }
validateUTF8 = validateUTF8 && proto3
switch t.Kind() { switch t.Kind() {
case reflect.Bool: case reflect.Bool:
@ -735,6 +755,18 @@ func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, ma
} }
return sizeFloat64Value, appendFloat64Value return sizeFloat64Value, appendFloat64Value
case reflect.String: case reflect.String:
if validateUTF8 {
if pointer {
return sizeStringPtr, appendUTF8StringPtr
}
if slice {
return sizeStringSlice, appendUTF8StringSlice
}
if nozero {
return sizeStringValueNoZero, appendUTF8StringValueNoZero
}
return sizeStringValue, appendUTF8StringValue
}
if pointer { if pointer {
return sizeStringPtr, appendStringPtr return sizeStringPtr, appendStringPtr
} }
@ -1984,9 +2016,6 @@ func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byt
} }
func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
v := *ptr.toString() v := *ptr.toString()
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag) b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v))) b = appendVarint(b, uint64(len(v)))
b = append(b, v...) b = append(b, v...)
@ -1997,9 +2026,6 @@ func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]b
if v == "" { if v == "" {
return b, nil return b, nil
} }
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag) b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v))) b = appendVarint(b, uint64(len(v)))
b = append(b, v...) b = append(b, v...)
@ -2011,24 +2037,83 @@ func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, err
return b, nil return b, nil
} }
v := *p v := *p
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
b = appendVarint(b, wiretag) b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v))) b = appendVarint(b, uint64(len(v)))
b = append(b, v...) b = append(b, v...)
return b, nil return b, nil
} }
func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
s := *ptr.toStringSlice()
for _, v := range s {
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
}
return b, nil
}
func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
v := *ptr.toString()
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
v := *ptr.toString()
if v == "" {
return b, nil
}
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
p := *ptr.toStringPtr()
if p == nil {
return b, nil
}
v := *p
if !utf8.ValidString(v) {
invalidUTF8 = true
}
b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v)))
b = append(b, v...)
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil
}
func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
var invalidUTF8 bool
s := *ptr.toStringSlice() s := *ptr.toStringSlice()
for _, v := range s { for _, v := range s {
if !utf8.ValidString(v) { if !utf8.ValidString(v) {
return nil, errInvalidUTF8 invalidUTF8 = true
} }
b = appendVarint(b, wiretag) b = appendVarint(b, wiretag)
b = appendVarint(b, uint64(len(v))) b = appendVarint(b, uint64(len(v)))
b = append(b, v...) b = append(b, v...)
} }
if invalidUTF8 {
return b, errInvalidUTF8
}
return b, nil return b, nil
} }
func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) { func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
@ -2107,7 +2192,8 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
}, },
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getPointerSlice() s := ptr.getPointerSlice()
var err, errreq error var err error
var nerr nonFatal
for _, v := range s { for _, v := range s {
if v.isNil() { if v.isNil() {
return b, errRepeatedHasNil return b, errRepeatedHasNil
@ -2115,22 +2201,14 @@ func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
b = appendVarint(b, wiretag) // start group b = appendVarint(b, wiretag) // start group
b, err = u.marshal(b, v, deterministic) b, err = u.marshal(b, v, deterministic)
b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
if err != nil { if !nerr.Merge(err) {
if _, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling.
if errreq == nil {
errreq = err
}
continue
}
if err == ErrNil { if err == ErrNil {
err = errRepeatedHasNil err = errRepeatedHasNil
} }
return b, err return b, err
} }
} }
return b, errreq return b, nerr.E
} }
} }
@ -2174,7 +2252,8 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
}, },
func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) { func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
s := ptr.getPointerSlice() s := ptr.getPointerSlice()
var err, errreq error var err error
var nerr nonFatal
for _, v := range s { for _, v := range s {
if v.isNil() { if v.isNil() {
return b, errRepeatedHasNil return b, errRepeatedHasNil
@ -2184,22 +2263,14 @@ func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
b = appendVarint(b, uint64(siz)) b = appendVarint(b, uint64(siz))
b, err = u.marshal(b, v, deterministic) b, err = u.marshal(b, v, deterministic)
if err != nil { if !nerr.Merge(err) {
if _, ok := err.(*RequiredNotSetError); ok {
// Required field in submessage is not set.
// We record the error but keep going, to give a complete marshaling.
if errreq == nil {
errreq = err
}
continue
}
if err == ErrNil { if err == ErrNil {
err = errRepeatedHasNil err = errRepeatedHasNil
} }
return b, err return b, err
} }
} }
return b, errreq return b, nerr.E
} }
} }
@ -2223,14 +2294,33 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
// value. // value.
// Key cannot be pointer-typed. // Key cannot be pointer-typed.
valIsPtr := valType.Kind() == reflect.Ptr valIsPtr := valType.Kind() == reflect.Ptr
// If value is a message with nested maps, calling
// valSizer in marshal may be quadratic. We should use
// cached version in marshal (but not in size).
// If value is not message type, we don't have size cache,
// but it cannot be nested either. Just use valSizer.
valCachedSizer := valSizer
if valIsPtr && valType.Elem().Kind() == reflect.Struct {
u := getMarshalInfo(valType.Elem())
valCachedSizer = func(ptr pointer, tagsize int) int {
// Same as message sizer, but use cache.
p := ptr.getPointer()
if p.isNil() {
return 0
}
siz := u.cachedsize(p)
return siz + SizeVarint(uint64(siz)) + tagsize
}
}
return func(ptr pointer, tagsize int) int { return func(ptr pointer, tagsize int) int {
m := ptr.asPointerTo(t).Elem() // the map m := ptr.asPointerTo(t).Elem() // the map
n := 0 n := 0
for _, k := range m.MapKeys() { for _, k := range m.MapKeys() {
ki := k.Interface() ki := k.Interface()
vi := m.MapIndex(k).Interface() vi := m.MapIndex(k).Interface()
kaddr := toAddrPointer(&ki, false) // pointer to key kaddr := toAddrPointer(&ki, false, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
n += siz + SizeVarint(uint64(siz)) + tagsize n += siz + SizeVarint(uint64(siz)) + tagsize
} }
@ -2243,24 +2333,26 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
if len(keys) > 1 && deterministic { if len(keys) > 1 && deterministic {
sort.Sort(mapKeys(keys)) sort.Sort(mapKeys(keys))
} }
var nerr nonFatal
for _, k := range keys { for _, k := range keys {
ki := k.Interface() ki := k.Interface()
vi := m.MapIndex(k).Interface() vi := m.MapIndex(k).Interface()
kaddr := toAddrPointer(&ki, false) // pointer to key kaddr := toAddrPointer(&ki, false, false) // pointer to key
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
b = appendVarint(b, tag) b = appendVarint(b, tag)
siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1) siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
b = appendVarint(b, uint64(siz)) b = appendVarint(b, uint64(siz))
b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic) b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
b, err = valMarshaler(b, vaddr, valWireTag, deterministic) b, err = valMarshaler(b, vaddr, valWireTag, deterministic)
if err != nil && err != ErrNil { // allow nil value in map if err != ErrNil && !nerr.Merge(err) { // allow nil value in map
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
} }
@ -2316,7 +2408,7 @@ func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
// the last time this function was called. // the last time this function was called.
ei := u.getExtElemInfo(e.desc) ei := u.getExtElemInfo(e.desc)
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr, ei.deref)
n += ei.sizer(p, ei.tagsize) n += ei.sizer(p, ei.tagsize)
} }
mu.Unlock() mu.Unlock()
@ -2333,6 +2425,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
defer mu.Unlock() defer mu.Unlock()
var err error var err error
var nerr nonFatal
// Fast-path for common cases: zero or one extensions. // Fast-path for common cases: zero or one extensions.
// Don't bother sorting the keys. // Don't bother sorting the keys.
@ -2350,13 +2443,13 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc) ei := u.getExtElemInfo(e.desc)
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic) b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
// Sort the keys to provide a deterministic encoding. // Sort the keys to provide a deterministic encoding.
@ -2381,13 +2474,13 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc) ei := u.getExtElemInfo(e.desc)
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic) b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
// message set format is: // message set format is:
@ -2426,7 +2519,7 @@ func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
ei := u.getExtElemInfo(e.desc) ei := u.getExtElemInfo(e.desc)
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr, ei.deref)
n += ei.sizer(p, 1) // message, tag = 3 (size=1) n += ei.sizer(p, 1) // message, tag = 3 (size=1)
} }
mu.Unlock() mu.Unlock()
@ -2444,6 +2537,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
defer mu.Unlock() defer mu.Unlock()
var err error var err error
var nerr nonFatal
// Fast-path for common cases: zero or one extensions. // Fast-path for common cases: zero or one extensions.
// Don't bother sorting the keys. // Don't bother sorting the keys.
@ -2468,14 +2562,14 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc) ei := u.getExtElemInfo(e.desc)
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
b = append(b, 1<<3|WireEndGroup) b = append(b, 1<<3|WireEndGroup)
} }
return b, nil return b, nerr.E
} }
// Sort the keys to provide a deterministic encoding. // Sort the keys to provide a deterministic encoding.
@ -2506,14 +2600,14 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
ei := u.getExtElemInfo(e.desc) ei := u.getExtElemInfo(e.desc)
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
b = append(b, 1<<3|WireEndGroup) b = append(b, 1<<3|WireEndGroup)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
// sizeV1Extensions computes the size of encoded data for a V1-API extension field. // sizeV1Extensions computes the size of encoded data for a V1-API extension field.
@ -2536,7 +2630,7 @@ func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
ei := u.getExtElemInfo(e.desc) ei := u.getExtElemInfo(e.desc)
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr, ei.deref)
n += ei.sizer(p, ei.tagsize) n += ei.sizer(p, ei.tagsize)
} }
return n return n
@ -2556,6 +2650,7 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
sort.Ints(keys) sort.Ints(keys)
var err error var err error
var nerr nonFatal
for _, k := range keys { for _, k := range keys {
e := m[int32(k)] e := m[int32(k)]
if e.value == nil || e.desc == nil { if e.value == nil || e.desc == nil {
@ -2570,13 +2665,13 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
ei := u.getExtElemInfo(e.desc) ei := u.getExtElemInfo(e.desc)
v := e.value v := e.value
p := toAddrPointer(&v, ei.isptr) p := toAddrPointer(&v, ei.isptr, ei.deref)
b, err = ei.marshaler(b, p, ei.wiretag, deterministic) b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
if err != nil { if !nerr.Merge(err) {
return b, err return b, err
} }
} }
return b, nil return b, nerr.E
} }
// newMarshaler is the interface representing objects that can marshal themselves. // newMarshaler is the interface representing objects that can marshal themselves.

View File

@ -97,6 +97,8 @@ type unmarshalFieldInfo struct {
// if a required field, contains a single set bit at this field's index in the required field list. // if a required field, contains a single set bit at this field's index in the required field list.
reqMask uint64 reqMask uint64
name string // name of the field, for error reporting
} }
var ( var (
@ -134,10 +136,10 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
u.computeUnmarshalInfo() u.computeUnmarshalInfo()
} }
if u.isMessageSet { if u.isMessageSet {
return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions()) return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
} }
var reqMask uint64 // bitmask of required fields we've seen. var reqMask uint64 // bitmask of required fields we've seen.
var rnse *RequiredNotSetError // an instance of a RequiredNotSetError returned by a submessage. var errLater error
for len(b) > 0 { for len(b) > 0 {
// Read tag and wire type. // Read tag and wire type.
// Special case 1 and 2 byte varints. // Special case 1 and 2 byte varints.
@ -176,11 +178,20 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
if r, ok := err.(*RequiredNotSetError); ok { if r, ok := err.(*RequiredNotSetError); ok {
// Remember this error, but keep parsing. We need to produce // Remember this error, but keep parsing. We need to produce
// a full parse even if a required field is missing. // a full parse even if a required field is missing.
rnse = r if errLater == nil {
errLater = r
}
reqMask |= f.reqMask reqMask |= f.reqMask
continue continue
} }
if err != errInternalBadWireType { if err != errInternalBadWireType {
if err == errInvalidUTF8 {
if errLater == nil {
fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
errLater = &invalidUTF8Error{fullName}
}
continue
}
return err return err
} }
// Fragments with bad wire type are treated as unknown fields. // Fragments with bad wire type are treated as unknown fields.
@ -239,20 +250,16 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
emap[int32(tag)] = e emap[int32(tag)] = e
} }
} }
if rnse != nil { if reqMask != u.reqMask && errLater == nil {
// A required field of a submessage/group is missing. Return that error.
return rnse
}
if reqMask != u.reqMask {
// A required field of this message is missing. // A required field of this message is missing.
for _, n := range u.reqFields { for _, n := range u.reqFields {
if reqMask&1 == 0 { if reqMask&1 == 0 {
return &RequiredNotSetError{n} errLater = &RequiredNotSetError{n}
} }
reqMask >>= 1 reqMask >>= 1
} }
} }
return nil return errLater
} }
// computeUnmarshalInfo fills in u with information for use // computeUnmarshalInfo fills in u with information for use
@ -351,43 +358,52 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
} }
// Store the info in the correct slot in the message. // Store the info in the correct slot in the message.
u.setTag(tag, toField(&f), unmarshal, reqMask) u.setTag(tag, toField(&f), unmarshal, reqMask, name)
} }
// Find any types associated with oneof fields. // Find any types associated with oneof fields.
// TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it? var oneofImplementers []interface{}
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs") switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
if fn.IsValid() { case oneofFuncsIface:
res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{} _, _, _, oneofImplementers = m.XXX_OneofFuncs()
for i := res.Len() - 1; i >= 0; i-- { case oneofWrappersIface:
v := res.Index(i) // interface{} oneofImplementers = m.XXX_OneofWrappers()
tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X }
typ := tptr.Elem() // Msg_X for _, v := range oneofImplementers {
tptr := reflect.TypeOf(v) // *Msg_X
typ := tptr.Elem() // Msg_X
f := typ.Field(0) // oneof implementers have one field f := typ.Field(0) // oneof implementers have one field
baseUnmarshal := fieldUnmarshaler(&f) baseUnmarshal := fieldUnmarshaler(&f)
tagstr := strings.Split(f.Tag.Get("protobuf"), ",")[1] tags := strings.Split(f.Tag.Get("protobuf"), ",")
tag, err := strconv.Atoi(tagstr) fieldNum, err := strconv.Atoi(tags[1])
if err != nil { if err != nil {
panic("protobuf tag field not an integer: " + tagstr) panic("protobuf tag field not an integer: " + tags[1])
} }
var name string
// Find the oneof field that this struct implements. for _, tag := range tags {
// Might take O(n^2) to process all of the oneofs, but who cares. if strings.HasPrefix(tag, "name=") {
for _, of := range oneofFields { name = strings.TrimPrefix(tag, "name=")
if tptr.Implements(of.ityp) { break
// We have found the corresponding interface for this struct.
// That lets us know where this struct should be stored
// when we encounter it during unmarshaling.
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
u.setTag(tag, of.field, unmarshal, 0)
}
} }
} }
// Find the oneof field that this struct implements.
// Might take O(n^2) to process all of the oneofs, but who cares.
for _, of := range oneofFields {
if tptr.Implements(of.ityp) {
// We have found the corresponding interface for this struct.
// That lets us know where this struct should be stored
// when we encounter it during unmarshaling.
unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
u.setTag(fieldNum, of.field, unmarshal, 0, name)
}
}
} }
// Get extension ranges, if any. // Get extension ranges, if any.
fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
if fn.IsValid() { if fn.IsValid() {
if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { if !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
panic("a message with extensions, but no extensions field in " + t.Name()) panic("a message with extensions, but no extensions field in " + t.Name())
@ -401,7 +417,7 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
// [0 0] is [tag=0/wiretype=varint varint-encoded-0]. // [0 0] is [tag=0/wiretype=varint varint-encoded-0].
u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) { u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) {
return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w) return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w)
}, 0) }, 0, "")
// Set mask for required field check. // Set mask for required field check.
u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1 u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1
@ -413,8 +429,9 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
// tag = tag # for field // tag = tag # for field
// field/unmarshal = unmarshal info for that field. // field/unmarshal = unmarshal info for that field.
// reqMask = if required, bitmask for field position in required field list. 0 otherwise. // reqMask = if required, bitmask for field position in required field list. 0 otherwise.
func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64) { // name = short name of the field.
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask} func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64, name string) {
i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask, name: name}
n := u.typ.NumField() n := u.typ.NumField()
if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here? if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here?
for len(u.dense) <= tag { for len(u.dense) <= tag {
@ -442,11 +459,17 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
tagArray := strings.Split(tags, ",") tagArray := strings.Split(tags, ",")
encoding := tagArray[0] encoding := tagArray[0]
name := "unknown" name := "unknown"
proto3 := false
validateUTF8 := true
for _, tag := range tagArray[3:] { for _, tag := range tagArray[3:] {
if strings.HasPrefix(tag, "name=") { if strings.HasPrefix(tag, "name=") {
name = tag[5:] name = tag[5:]
} }
if tag == "proto3" {
proto3 = true
}
} }
validateUTF8 = validateUTF8 && proto3
// Figure out packaging (pointer, slice, or both) // Figure out packaging (pointer, slice, or both)
slice := false slice := false
@ -594,6 +617,15 @@ func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
} }
return unmarshalBytesValue return unmarshalBytesValue
case reflect.String: case reflect.String:
if validateUTF8 {
if pointer {
return unmarshalUTF8StringPtr
}
if slice {
return unmarshalUTF8StringSlice
}
return unmarshalUTF8StringValue
}
if pointer { if pointer {
return unmarshalStringPtr return unmarshalStringPtr
} }
@ -1448,9 +1480,6 @@ func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF return nil, io.ErrUnexpectedEOF
} }
v := string(b[:x]) v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
*f.toString() = v *f.toString() = v
return b[x:], nil return b[x:], nil
} }
@ -1468,9 +1497,6 @@ func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF return nil, io.ErrUnexpectedEOF
} }
v := string(b[:x]) v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
*f.toStringPtr() = &v *f.toStringPtr() = &v
return b[x:], nil return b[x:], nil
} }
@ -1488,14 +1514,72 @@ func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) {
return nil, io.ErrUnexpectedEOF return nil, io.ErrUnexpectedEOF
} }
v := string(b[:x]) v := string(b[:x])
if !utf8.ValidString(v) {
return nil, errInvalidUTF8
}
s := f.toStringSlice() s := f.toStringSlice()
*s = append(*s, v) *s = append(*s, v)
return b[x:], nil return b[x:], nil
} }
func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
*f.toString() = v
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
*f.toStringPtr() = &v
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) {
if w != WireBytes {
return b, errInternalBadWireType
}
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
if x > uint64(len(b)) {
return nil, io.ErrUnexpectedEOF
}
v := string(b[:x])
s := f.toStringSlice()
*s = append(*s, v)
if !utf8.ValidString(v) {
return b[x:], errInvalidUTF8
}
return b[x:], nil
}
var emptyBuf [0]byte var emptyBuf [0]byte
func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) { func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) {
@ -1674,6 +1758,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
// Maps will be somewhat slow. Oh well. // Maps will be somewhat slow. Oh well.
// Read key and value from data. // Read key and value from data.
var nerr nonFatal
k := reflect.New(kt) k := reflect.New(kt)
v := reflect.New(vt) v := reflect.New(vt)
for len(b) > 0 { for len(b) > 0 {
@ -1694,7 +1779,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
err = errInternalBadWireType // skip unknown tag err = errInternalBadWireType // skip unknown tag
} }
if err == nil { if nerr.Merge(err) {
continue continue
} }
if err != errInternalBadWireType { if err != errInternalBadWireType {
@ -1717,7 +1802,7 @@ func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
// Insert into map. // Insert into map.
m.SetMapIndex(k.Elem(), v.Elem()) m.SetMapIndex(k.Elem(), v.Elem())
return r, nil return r, nerr.E
} }
} }
@ -1743,15 +1828,16 @@ func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshal
// Unmarshal data into holder. // Unmarshal data into holder.
// We unmarshal into the first field of the holder object. // We unmarshal into the first field of the holder object.
var err error var err error
var nerr nonFatal
b, err = unmarshal(b, valToPointer(v).offset(field0), w) b, err = unmarshal(b, valToPointer(v).offset(field0), w)
if err != nil { if !nerr.Merge(err) {
return nil, err return nil, err
} }
// Write pointer to holder into target field. // Write pointer to holder into target field.
f.asPointerTo(ityp).Elem().Set(v) f.asPointerTo(ityp).Elem().Set(v)
return b, nil return b, nerr.E
} }
} }
@ -1864,7 +1950,7 @@ func encodeVarint(b []byte, x uint64) []byte {
// If there is an error, it returns 0,0. // If there is an error, it returns 0,0.
func decodeVarint(b []byte) (uint64, int) { func decodeVarint(b []byte) (uint64, int) {
var x, y uint64 var x, y uint64
if len(b) <= 0 { if len(b) == 0 {
goto bad goto bad
} }
x = uint64(b[0]) x = uint64(b[0])

View File

@ -353,7 +353,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err return err
} }
} }
if err := tm.writeAny(w, key, props.mkeyprop); err != nil { if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
return err return err
} }
if err := w.WriteByte('\n'); err != nil { if err := w.WriteByte('\n'); err != nil {
@ -370,7 +370,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err return err
} }
} }
if err := tm.writeAny(w, val, props.mvalprop); err != nil { if err := tm.writeAny(w, val, props.MapValProp); err != nil {
return err return err
} }
if err := w.WriteByte('\n'); err != nil { if err := w.WriteByte('\n'); err != nil {

View File

@ -630,17 +630,17 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
if err := p.consumeToken(":"); err != nil { if err := p.consumeToken(":"); err != nil {
return err return err
} }
if err := p.readAny(key, props.mkeyprop); err != nil { if err := p.readAny(key, props.MapKeyProp); err != nil {
return err return err
} }
if err := p.consumeOptionalSeparator(); err != nil { if err := p.consumeOptionalSeparator(); err != nil {
return err return err
} }
case "value": case "value":
if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
return err return err
} }
if err := p.readAny(val, props.mvalprop); err != nil { if err := p.readAny(val, props.MapValProp); err != nil {
return err return err
} }
if err := p.consumeOptionalSeparator(); err != nil { if err := p.consumeOptionalSeparator(); err != nil {

View File

@ -130,10 +130,12 @@ func UnmarshalAny(any *any.Any, pb proto.Message) error {
// Is returns true if any value contains a given message type. // Is returns true if any value contains a given message type.
func Is(any *any.Any, pb proto.Message) bool { func Is(any *any.Any, pb proto.Message) bool {
aname, err := AnyMessageName(any) // The following is equivalent to AnyMessageName(any) == proto.MessageName(pb),
if err != nil { // but it avoids scanning TypeUrl for the slash.
if any == nil {
return false return false
} }
name := proto.MessageName(pb)
return aname == proto.MessageName(pb) prefix := len(any.TypeUrl) - len(name)
return prefix >= 1 && any.TypeUrl[prefix-1] == '/' && any.TypeUrl[prefix:] == name
} }

View File

@ -1,11 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/protobuf/any.proto // source: google/protobuf/any.proto
package any // import "github.com/golang/protobuf/ptypes/any" package any
import proto "github.com/golang/protobuf/proto" import (
import fmt "fmt" fmt "fmt"
import math "math" proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
@ -16,7 +18,7 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against. // is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the // A compilation error at this line likely means your copy of the
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// `Any` contains an arbitrary serialized protocol buffer message along with a // `Any` contains an arbitrary serialized protocol buffer message along with a
// URL that describes the type of the serialized message. // URL that describes the type of the serialized message.
@ -99,17 +101,18 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// } // }
// //
type Any struct { type Any struct {
// A URL/resource name whose content describes the type of the // A URL/resource name that uniquely identifies the type of the serialized
// serialized protocol buffer message. // protocol buffer message. 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).
// //
// For URLs which use the scheme `http`, `https`, or no scheme, the // In practice, teams usually precompile into the binary all types that they
// following restrictions and interpretations apply: // 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. // * If no scheme is provided, `https` is assumed.
// * 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).
// * An HTTP GET on the URL must yield a [google.protobuf.Type][] // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
// value in binary format, or produce an error. // value in binary format, or produce an error.
// * Applications are allowed to cache lookup results based on the // * Applications are allowed to cache lookup results based on the
@ -118,10 +121,14 @@ type Any struct {
// on changes to types. (Use versioned type names to manage // on changes to types. (Use versioned type names to manage
// breaking changes.) // 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 // Schemes other than `http`, `https` (or the empty scheme) might be
// used with implementation specific semantics. // used with implementation specific semantics.
// //
TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl" json:"type_url,omitempty"` TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`
// Must be a valid serialized protocol buffer of the above specified type. // Must be a valid serialized protocol buffer of the above specified type.
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
@ -133,17 +140,19 @@ func (m *Any) Reset() { *m = Any{} }
func (m *Any) String() string { return proto.CompactTextString(m) } func (m *Any) String() string { return proto.CompactTextString(m) }
func (*Any) ProtoMessage() {} func (*Any) ProtoMessage() {}
func (*Any) Descriptor() ([]byte, []int) { func (*Any) Descriptor() ([]byte, []int) {
return fileDescriptor_any_744b9ca530f228db, []int{0} return fileDescriptor_b53526c13ae22eb4, []int{0}
} }
func (*Any) XXX_WellKnownType() string { return "Any" } func (*Any) XXX_WellKnownType() string { return "Any" }
func (m *Any) XXX_Unmarshal(b []byte) error { func (m *Any) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Any.Unmarshal(m, b) return xxx_messageInfo_Any.Unmarshal(m, b)
} }
func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Any.Marshal(b, m, deterministic) return xxx_messageInfo_Any.Marshal(b, m, deterministic)
} }
func (dst *Any) XXX_Merge(src proto.Message) { func (m *Any) XXX_Merge(src proto.Message) {
xxx_messageInfo_Any.Merge(dst, src) xxx_messageInfo_Any.Merge(m, src)
} }
func (m *Any) XXX_Size() int { func (m *Any) XXX_Size() int {
return xxx_messageInfo_Any.Size(m) return xxx_messageInfo_Any.Size(m)
@ -172,9 +181,9 @@ func init() {
proto.RegisterType((*Any)(nil), "google.protobuf.Any") proto.RegisterType((*Any)(nil), "google.protobuf.Any")
} }
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_any_744b9ca530f228db) } func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) }
var fileDescriptor_any_744b9ca530f228db = []byte{ var fileDescriptor_b53526c13ae22eb4 = []byte{
// 185 bytes of a gzipped FileDescriptorProto // 185 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4, 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,

View File

@ -120,17 +120,18 @@ option objc_class_prefix = "GPB";
// } // }
// //
message Any { message Any {
// A URL/resource name whose content describes the type of the // A URL/resource name that uniquely identifies the type of the serialized
// serialized protocol buffer message. // protocol buffer message. 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).
// //
// For URLs which use the scheme `http`, `https`, or no scheme, the // In practice, teams usually precompile into the binary all types that they
// following restrictions and interpretations apply: // 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. // * If no scheme is provided, `https` is assumed.
// * 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).
// * An HTTP GET on the URL must yield a [google.protobuf.Type][] // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
// value in binary format, or produce an error. // value in binary format, or produce an error.
// * Applications are allowed to cache lookup results based on the // * Applications are allowed to cache lookup results based on the
@ -139,6 +140,10 @@ message Any {
// on changes to types. (Use versioned type names to manage // on changes to types. (Use versioned type names to manage
// breaking changes.) // 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 // Schemes other than `http`, `https` (or the empty scheme) might be
// used with implementation specific semantics. // used with implementation specific semantics.
// //

View File

@ -82,7 +82,7 @@ func Duration(p *durpb.Duration) (time.Duration, error) {
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
} }
if p.Nanos != 0 { if p.Nanos != 0 {
d += time.Duration(p.Nanos) d += time.Duration(p.Nanos) * time.Nanosecond
if (d < 0) != (p.Nanos < 0) { if (d < 0) != (p.Nanos < 0) {
return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
} }

View File

@ -1,11 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/protobuf/duration.proto // source: google/protobuf/duration.proto
package duration // import "github.com/golang/protobuf/ptypes/duration" package duration
import proto "github.com/golang/protobuf/proto" import (
import fmt "fmt" fmt "fmt"
import math "math" proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
@ -16,7 +18,7 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against. // is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the // A compilation error at this line likely means your copy of the
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// A Duration represents a signed, fixed-length span of time represented // A Duration represents a signed, fixed-length span of time represented
// as a count of seconds and fractions of seconds at nanosecond // as a count of seconds and fractions of seconds at nanosecond
@ -82,14 +84,14 @@ type Duration struct {
// Signed seconds of the span of time. Must be from -315,576,000,000 // 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: // 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 // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
// Signed fractions of a second at nanosecond resolution of the span // Signed fractions of a second at nanosecond resolution of the span
// of time. Durations less than one second are represented with a 0 // of time. Durations less than one second are represented with a 0
// `seconds` field and a positive or negative `nanos` field. For durations // `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 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 // of the same sign as the `seconds` field. Must be from -999,999,999
// to +999,999,999 inclusive. // to +999,999,999 inclusive.
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -99,17 +101,19 @@ func (m *Duration) Reset() { *m = Duration{} }
func (m *Duration) String() string { return proto.CompactTextString(m) } func (m *Duration) String() string { return proto.CompactTextString(m) }
func (*Duration) ProtoMessage() {} func (*Duration) ProtoMessage() {}
func (*Duration) Descriptor() ([]byte, []int) { func (*Duration) Descriptor() ([]byte, []int) {
return fileDescriptor_duration_e7d612259e3f0613, []int{0} return fileDescriptor_23597b2ebd7ac6c5, []int{0}
} }
func (*Duration) XXX_WellKnownType() string { return "Duration" } func (*Duration) XXX_WellKnownType() string { return "Duration" }
func (m *Duration) XXX_Unmarshal(b []byte) error { func (m *Duration) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Duration.Unmarshal(m, b) return xxx_messageInfo_Duration.Unmarshal(m, b)
} }
func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Duration.Marshal(b, m, deterministic) return xxx_messageInfo_Duration.Marshal(b, m, deterministic)
} }
func (dst *Duration) XXX_Merge(src proto.Message) { func (m *Duration) XXX_Merge(src proto.Message) {
xxx_messageInfo_Duration.Merge(dst, src) xxx_messageInfo_Duration.Merge(m, src)
} }
func (m *Duration) XXX_Size() int { func (m *Duration) XXX_Size() int {
return xxx_messageInfo_Duration.Size(m) return xxx_messageInfo_Duration.Size(m)
@ -138,11 +142,9 @@ func init() {
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
} }
func init() { func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5) }
proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_duration_e7d612259e3f0613)
}
var fileDescriptor_duration_e7d612259e3f0613 = []byte{ var fileDescriptor_23597b2ebd7ac6c5 = []byte{
// 190 bytes of a gzipped FileDescriptorProto // 190 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a, 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,

View File

@ -111,11 +111,9 @@ func TimestampNow() *tspb.Timestamp {
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
// It returns an error if the resulting Timestamp is invalid. // It returns an error if the resulting Timestamp is invalid.
func TimestampProto(t time.Time) (*tspb.Timestamp, error) { func TimestampProto(t time.Time) (*tspb.Timestamp, error) {
seconds := t.Unix()
nanos := int32(t.Sub(time.Unix(seconds, 0)))
ts := &tspb.Timestamp{ ts := &tspb.Timestamp{
Seconds: seconds, Seconds: t.Unix(),
Nanos: nanos, Nanos: int32(t.Nanosecond()),
} }
if err := validateTimestamp(ts); err != nil { if err := validateTimestamp(ts); err != nil {
return nil, err return nil, err

View File

@ -1,11 +1,13 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/protobuf/timestamp.proto // source: google/protobuf/timestamp.proto
package timestamp // import "github.com/golang/protobuf/ptypes/timestamp" package timestamp
import proto "github.com/golang/protobuf/proto" import (
import fmt "fmt" fmt "fmt"
import math "math" proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
@ -16,7 +18,7 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against. // is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the // A compilation error at this line likely means your copy of the
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// A Timestamp represents a point in time independent of any time zone // A Timestamp represents a point in time independent of any time zone
// or calendar, represented as seconds and fractions of seconds at // or calendar, represented as seconds and fractions of seconds at
@ -81,7 +83,9 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional // {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), // 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 // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
// is required, though only UTC (as indicated by "Z") is presently supported. // 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 // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
// 01:30 UTC on January 15, 2017. // 01:30 UTC on January 15, 2017.
@ -92,20 +96,20 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) // 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 // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( // can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--) // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
// to obtain a formatter capable of generating timestamps in this format. // ) to obtain a formatter capable of generating timestamps in this format.
// //
// //
type Timestamp struct { type Timestamp struct {
// Represents seconds of UTC time since Unix epoch // Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive. // 9999-12-31T23:59:59Z inclusive.
Seconds int64 `protobuf:"varint,1,opt,name=seconds" json:"seconds,omitempty"` Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
// Non-negative fractions of a second at nanosecond resolution. Negative // Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values // second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999 // that count forward in time. Must be from 0 to 999,999,999
// inclusive. // inclusive.
Nanos int32 `protobuf:"varint,2,opt,name=nanos" json:"nanos,omitempty"` Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -115,17 +119,19 @@ func (m *Timestamp) Reset() { *m = Timestamp{} }
func (m *Timestamp) String() string { return proto.CompactTextString(m) } func (m *Timestamp) String() string { return proto.CompactTextString(m) }
func (*Timestamp) ProtoMessage() {} func (*Timestamp) ProtoMessage() {}
func (*Timestamp) Descriptor() ([]byte, []int) { func (*Timestamp) Descriptor() ([]byte, []int) {
return fileDescriptor_timestamp_b826e8e5fba671a8, []int{0} return fileDescriptor_292007bbfe81227e, []int{0}
} }
func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
func (m *Timestamp) XXX_Unmarshal(b []byte) error { func (m *Timestamp) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Timestamp.Unmarshal(m, b) return xxx_messageInfo_Timestamp.Unmarshal(m, b)
} }
func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic) return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic)
} }
func (dst *Timestamp) XXX_Merge(src proto.Message) { func (m *Timestamp) XXX_Merge(src proto.Message) {
xxx_messageInfo_Timestamp.Merge(dst, src) xxx_messageInfo_Timestamp.Merge(m, src)
} }
func (m *Timestamp) XXX_Size() int { func (m *Timestamp) XXX_Size() int {
return xxx_messageInfo_Timestamp.Size(m) return xxx_messageInfo_Timestamp.Size(m)
@ -154,11 +160,9 @@ func init() {
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
} }
func init() { func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e) }
proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_timestamp_b826e8e5fba671a8)
}
var fileDescriptor_timestamp_b826e8e5fba671a8 = []byte{ var fileDescriptor_292007bbfe81227e = []byte{
// 191 bytes of a gzipped FileDescriptorProto // 191 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d, 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,

View File

@ -103,7 +103,9 @@ option objc_class_prefix = "GPB";
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional // {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), // 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 // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
// is required, though only UTC (as indicated by "Z") is presently supported. // 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 // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
// 01:30 UTC on January 15, 2017. // 01:30 UTC on January 15, 2017.
@ -114,8 +116,8 @@ option objc_class_prefix = "GPB";
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) // 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 // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( // can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--) // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
// to obtain a formatter capable of generating timestamps in this format. // ) to obtain a formatter capable of generating timestamps in this format.
// //
// //
message Timestamp { message Timestamp {

View File

@ -1,19 +0,0 @@
language: go
sudo: false
matrix:
include:
- go: 1.3
- go: 1.4
- go: 1.5
- go: 1.6
- go: 1.7
- go: tip
allow_failures:
- go: tip
script:
- go get -t -v ./...
- diff -u <(echo -n) <(gofmt -d .)
- go vet $(go list ./... | grep -v /vendor/)
- go test -v -race ./...

View File

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

View File

@ -1,10 +0,0 @@
context
=======
[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context)
gorilla/context is a general purpose registry for global request variables.
> Note: gorilla/context, having been born well before `context.Context` existed, does not play well
> with the shallow copying of the request that [`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext) (added to net/http Go 1.7 onwards) performs. You should either use *just* gorilla/context, or moving forward, the new `http.Request.Context()`.
Read the full documentation here: http://www.gorillatoolkit.org/pkg/context

View File

@ -1,143 +0,0 @@
// Copyright 2012 The Gorilla 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 context
import (
"net/http"
"sync"
"time"
)
var (
mutex sync.RWMutex
data = make(map[*http.Request]map[interface{}]interface{})
datat = make(map[*http.Request]int64)
)
// Set stores a value for a given key in a given request.
func Set(r *http.Request, key, val interface{}) {
mutex.Lock()
if data[r] == nil {
data[r] = make(map[interface{}]interface{})
datat[r] = time.Now().Unix()
}
data[r][key] = val
mutex.Unlock()
}
// Get returns a value stored for a given key in a given request.
func Get(r *http.Request, key interface{}) interface{} {
mutex.RLock()
if ctx := data[r]; ctx != nil {
value := ctx[key]
mutex.RUnlock()
return value
}
mutex.RUnlock()
return nil
}
// GetOk returns stored value and presence state like multi-value return of map access.
func GetOk(r *http.Request, key interface{}) (interface{}, bool) {
mutex.RLock()
if _, ok := data[r]; ok {
value, ok := data[r][key]
mutex.RUnlock()
return value, ok
}
mutex.RUnlock()
return nil, false
}
// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests.
func GetAll(r *http.Request) map[interface{}]interface{} {
mutex.RLock()
if context, ok := data[r]; ok {
result := make(map[interface{}]interface{}, len(context))
for k, v := range context {
result[k] = v
}
mutex.RUnlock()
return result
}
mutex.RUnlock()
return nil
}
// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if
// the request was registered.
func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) {
mutex.RLock()
context, ok := data[r]
result := make(map[interface{}]interface{}, len(context))
for k, v := range context {
result[k] = v
}
mutex.RUnlock()
return result, ok
}
// Delete removes a value stored for a given key in a given request.
func Delete(r *http.Request, key interface{}) {
mutex.Lock()
if data[r] != nil {
delete(data[r], key)
}
mutex.Unlock()
}
// Clear removes all values stored for a given request.
//
// This is usually called by a handler wrapper to clean up request
// variables at the end of a request lifetime. See ClearHandler().
func Clear(r *http.Request) {
mutex.Lock()
clear(r)
mutex.Unlock()
}
// clear is Clear without the lock.
func clear(r *http.Request) {
delete(data, r)
delete(datat, r)
}
// Purge removes request data stored for longer than maxAge, in seconds.
// It returns the amount of requests removed.
//
// If maxAge <= 0, all request data is removed.
//
// This is only used for sanity check: in case context cleaning was not
// properly set some request data can be kept forever, consuming an increasing
// amount of memory. In case this is detected, Purge() must be called
// periodically until the problem is fixed.
func Purge(maxAge int) int {
mutex.Lock()
count := 0
if maxAge <= 0 {
count = len(data)
data = make(map[*http.Request]map[interface{}]interface{})
datat = make(map[*http.Request]int64)
} else {
min := time.Now().Unix() - int64(maxAge)
for r := range data {
if datat[r] < min {
clear(r)
count++
}
}
}
mutex.Unlock()
return count
}
// ClearHandler wraps an http.Handler and clears request values at the end
// of a request lifetime.
func ClearHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer Clear(r)
h.ServeHTTP(w, r)
})
}

View File

@ -1,88 +0,0 @@
// Copyright 2012 The Gorilla 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 context stores values shared during a request lifetime.
Note: gorilla/context, having been born well before `context.Context` existed,
does not play well > with the shallow copying of the request that
[`http.Request.WithContext`](https://golang.org/pkg/net/http/#Request.WithContext)
(added to net/http Go 1.7 onwards) performs. You should either use *just*
gorilla/context, or moving forward, the new `http.Request.Context()`.
For example, a router can set variables extracted from the URL and later
application handlers can access those values, or it can be used to store
sessions values to be saved at the end of a request. There are several
others common uses.
The idea was posted by Brad Fitzpatrick to the go-nuts mailing list:
http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53
Here's the basic usage: first define the keys that you will need. The key
type is interface{} so a key can be of any type that supports equality.
Here we define a key using a custom int type to avoid name collisions:
package foo
import (
"github.com/gorilla/context"
)
type key int
const MyKey key = 0
Then set a variable. Variables are bound to an http.Request object, so you
need a request instance to set a value:
context.Set(r, MyKey, "bar")
The application can later access the variable using the same key you provided:
func MyHandler(w http.ResponseWriter, r *http.Request) {
// val is "bar".
val := context.Get(r, foo.MyKey)
// returns ("bar", true)
val, ok := context.GetOk(r, foo.MyKey)
// ...
}
And that's all about the basic usage. We discuss some other ideas below.
Any type can be stored in the context. To enforce a given type, make the key
private and wrap Get() and Set() to accept and return values of a specific
type:
type key int
const mykey key = 0
// GetMyKey returns a value for this package from the request values.
func GetMyKey(r *http.Request) SomeType {
if rv := context.Get(r, mykey); rv != nil {
return rv.(SomeType)
}
return nil
}
// SetMyKey sets a value for this package in the request values.
func SetMyKey(r *http.Request, val SomeType) {
context.Set(r, mykey, val)
}
Variables must be cleared at the end of a request, to remove all values
that were stored. This can be done in an http.Handler, after a request was
served. Just call Clear() passing the request:
context.Clear(r)
...or use ClearHandler(), which conveniently wraps an http.Handler to clear
variables at the end of a request lifetime.
The Routers from the packages gorilla/mux and gorilla/pat call Clear()
so if you are using either of them you don't need to clear the context manually.
*/
package context

View File

@ -1,14 +1,15 @@
language: go language: go
sudo: false
matrix: matrix:
include: include:
- go: 1.5.x
- go: 1.6.x
- go: 1.7.x - go: 1.7.x
- go: 1.8.x - go: 1.8.x
- go: 1.9.x - go: 1.9.x
- go: 1.10.x - go: 1.10.x
- go: 1.11.x
- go: 1.x
env: LATEST=true
- go: tip - go: tip
allow_failures: allow_failures:
- go: tip - go: tip
@ -19,5 +20,5 @@ install:
script: script:
- go get -t -v ./... - go get -t -v ./...
- diff -u <(echo -n) <(gofmt -d .) - diff -u <(echo -n) <(gofmt -d .)
- go tool vet . - if [[ "$LATEST" = true ]]; then go vet .; fi
- go test -v -race ./... - go test -v -race ./...

8
vendor/github.com/gorilla/mux/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,8 @@
# This is the official list of gorilla/mux authors for copyright purposes.
#
# Please keep the list sorted.
Google LLC (https://opensource.google.com/)
Kamil Kisielk <kamil@kamilkisiel.net>
Matt Silverlock <matt@eatsleeprepeat.net>
Rodrigo Moraes (https://github.com/moraes)

View File

@ -1,4 +1,4 @@
Copyright (c) 2012 Rodrigo Moraes. All rights reserved. Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are modification, are permitted provided that the following conditions are

View File

@ -6,7 +6,7 @@
![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png) ![Gorilla Logo](http://www.gorillatoolkit.org/static/images/gorilla-icon-64.png)
http://www.gorillatoolkit.org/pkg/mux https://www.gorillatoolkit.org/pkg/mux
Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to Package `gorilla/mux` implements a request router and dispatcher for matching incoming requests to
their respective handler. their respective handler.
@ -88,7 +88,7 @@ r := mux.NewRouter()
// Only matches if domain is "www.example.com". // Only matches if domain is "www.example.com".
r.Host("www.example.com") r.Host("www.example.com")
// Matches a dynamic subdomain. // Matches a dynamic subdomain.
r.Host("{subdomain:[a-z]+}.domain.com") r.Host("{subdomain:[a-z]+}.example.com")
``` ```
There are several other matchers that can be added. To match path prefixes: There are several other matchers that can be added. To match path prefixes:
@ -238,13 +238,13 @@ This also works for host and query value variables:
```go ```go
r := mux.NewRouter() r := mux.NewRouter()
r.Host("{subdomain}.domain.com"). r.Host("{subdomain}.example.com").
Path("/articles/{category}/{id:[0-9]+}"). Path("/articles/{category}/{id:[0-9]+}").
Queries("filter", "{filter}"). Queries("filter", "{filter}").
HandlerFunc(ArticleHandler). HandlerFunc(ArticleHandler).
Name("article") Name("article")
// url.String() will be "http://news.domain.com/articles/technology/42?filter=gorilla" // url.String() will be "http://news.example.com/articles/technology/42?filter=gorilla"
url, err := r.Get("article").URL("subdomain", "news", url, err := r.Get("article").URL("subdomain", "news",
"category", "technology", "category", "technology",
"id", "42", "id", "42",
@ -264,7 +264,7 @@ r.HeadersRegexp("Content-Type", "application/(text|json)")
There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do: There's also a way to build only the URL host or path for a route: use the methods `URLHost()` or `URLPath()` instead. For the previous route, we would do:
```go ```go
// "http://news.domain.com/" // "http://news.example.com/"
host, err := r.Get("article").URLHost("subdomain", "news") host, err := r.Get("article").URLHost("subdomain", "news")
// "/articles/technology/42" // "/articles/technology/42"
@ -275,12 +275,12 @@ And if you use subrouters, host and path defined separately can be built as well
```go ```go
r := mux.NewRouter() r := mux.NewRouter()
s := r.Host("{subdomain}.domain.com").Subrouter() s := r.Host("{subdomain}.example.com").Subrouter()
s.Path("/articles/{category}/{id:[0-9]+}"). s.Path("/articles/{category}/{id:[0-9]+}").
HandlerFunc(ArticleHandler). HandlerFunc(ArticleHandler).
Name("article") Name("article")
// "http://news.domain.com/articles/technology/42" // "http://news.example.com/articles/technology/42"
url, err := r.Get("article").URL("subdomain", "news", url, err := r.Get("article").URL("subdomain", "news",
"category", "technology", "category", "technology",
"id", "42") "id", "42")
@ -503,8 +503,8 @@ package main
func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
// A very simple health check. // A very simple health check.
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
// In the future we could report back on the status of our DB, or our cache // In the future we could report back on the status of our DB, or our cache
// (e.g. Redis) by performing a simple PING, and include them in the response. // (e.g. Redis) by performing a simple PING, and include them in the response.

View File

@ -1,5 +1,3 @@
// +build go1.7
package mux package mux
import ( import (
@ -18,7 +16,3 @@ func contextSet(r *http.Request, key, val interface{}) *http.Request {
return r.WithContext(context.WithValue(r.Context(), key, val)) return r.WithContext(context.WithValue(r.Context(), key, val))
} }
func contextClear(r *http.Request) {
return
}

View File

@ -1,26 +0,0 @@
// +build !go1.7
package mux
import (
"net/http"
"github.com/gorilla/context"
)
func contextGet(r *http.Request, key interface{}) interface{} {
return context.Get(r, key)
}
func contextSet(r *http.Request, key, val interface{}) *http.Request {
if val == nil {
return r
}
context.Set(r, key, val)
return r
}
func contextClear(r *http.Request) {
context.Clear(r)
}

1
vendor/github.com/gorilla/mux/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/gorilla/mux

129
vendor/github.com/gorilla/mux/mux.go generated vendored
View File

@ -22,7 +22,7 @@ var (
// NewRouter returns a new router instance. // NewRouter returns a new router instance.
func NewRouter() *Router { func NewRouter() *Router {
return &Router{namedRoutes: make(map[string]*Route), KeepContext: false} return &Router{namedRoutes: make(map[string]*Route)}
} }
// Router registers routes to be matched and dispatches a handler. // Router registers routes to be matched and dispatches a handler.
@ -50,24 +50,78 @@ type Router struct {
// Configurable Handler to be used when the request method does not match the route. // Configurable Handler to be used when the request method does not match the route.
MethodNotAllowedHandler http.Handler MethodNotAllowedHandler http.Handler
// Parent route, if this is a subrouter.
parent parentRoute
// Routes to be matched, in order. // Routes to be matched, in order.
routes []*Route routes []*Route
// Routes by name for URL building. // Routes by name for URL building.
namedRoutes map[string]*Route namedRoutes map[string]*Route
// See Router.StrictSlash(). This defines the flag for new routes.
strictSlash bool
// See Router.SkipClean(). This defines the flag for new routes.
skipClean bool
// If true, do not clear the request context after handling the request. // If true, do not clear the request context after handling the request.
// This has no effect when go1.7+ is used, since the context is stored //
// Deprecated: No effect when go1.7+ is used, since the context is stored
// on the request itself. // on the request itself.
KeepContext bool KeepContext bool
// see Router.UseEncodedPath(). This defines a flag for all routes.
useEncodedPath bool
// Slice of middlewares to be called after a match is found // Slice of middlewares to be called after a match is found
middlewares []middleware middlewares []middleware
// configuration shared with `Route`
routeConf
}
// common route configuration shared between `Router` and `Route`
type routeConf struct {
// If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to"
useEncodedPath bool
// If true, when the path pattern is "/path/", accessing "/path" will
// redirect to the former and vice versa.
strictSlash bool
// If true, when the path pattern is "/path//to", accessing "/path//to"
// will not redirect
skipClean bool
// Manager for the variables from host and path.
regexp routeRegexpGroup
// List of matchers.
matchers []matcher
// The scheme used when building URLs.
buildScheme string
buildVarsFunc BuildVarsFunc
}
// returns an effective deep copy of `routeConf`
func copyRouteConf(r routeConf) routeConf {
c := r
if r.regexp.path != nil {
c.regexp.path = copyRouteRegexp(r.regexp.path)
}
if r.regexp.host != nil {
c.regexp.host = copyRouteRegexp(r.regexp.host)
}
c.regexp.queries = make([]*routeRegexp, 0, len(r.regexp.queries))
for _, q := range r.regexp.queries {
c.regexp.queries = append(c.regexp.queries, copyRouteRegexp(q))
}
c.matchers = make([]matcher, 0, len(r.matchers))
for _, m := range r.matchers {
c.matchers = append(c.matchers, m)
}
return c
}
func copyRouteRegexp(r *routeRegexp) *routeRegexp {
c := *r
return &c
} }
// Match attempts to match the given request against the router's registered routes. // Match attempts to match the given request against the router's registered routes.
@ -155,22 +209,18 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
handler = http.NotFoundHandler() handler = http.NotFoundHandler()
} }
if !r.KeepContext {
defer contextClear(req)
}
handler.ServeHTTP(w, req) handler.ServeHTTP(w, req)
} }
// Get returns a route registered with the given name. // Get returns a route registered with the given name.
func (r *Router) Get(name string) *Route { func (r *Router) Get(name string) *Route {
return r.getNamedRoutes()[name] return r.namedRoutes[name]
} }
// GetRoute returns a route registered with the given name. This method // GetRoute returns a route registered with the given name. This method
// was renamed to Get() and remains here for backwards compatibility. // was renamed to Get() and remains here for backwards compatibility.
func (r *Router) GetRoute(name string) *Route { func (r *Router) GetRoute(name string) *Route {
return r.getNamedRoutes()[name] return r.namedRoutes[name]
} }
// StrictSlash defines the trailing slash behavior for new routes. The initial // StrictSlash defines the trailing slash behavior for new routes. The initial
@ -221,55 +271,24 @@ func (r *Router) UseEncodedPath() *Router {
return r return r
} }
// ----------------------------------------------------------------------------
// parentRoute
// ----------------------------------------------------------------------------
func (r *Router) getBuildScheme() string {
if r.parent != nil {
return r.parent.getBuildScheme()
}
return ""
}
// getNamedRoutes returns the map where named routes are registered.
func (r *Router) getNamedRoutes() map[string]*Route {
if r.namedRoutes == nil {
if r.parent != nil {
r.namedRoutes = r.parent.getNamedRoutes()
} else {
r.namedRoutes = make(map[string]*Route)
}
}
return r.namedRoutes
}
// getRegexpGroup returns regexp definitions from the parent route, if any.
func (r *Router) getRegexpGroup() *routeRegexpGroup {
if r.parent != nil {
return r.parent.getRegexpGroup()
}
return nil
}
func (r *Router) buildVars(m map[string]string) map[string]string {
if r.parent != nil {
m = r.parent.buildVars(m)
}
return m
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Route factories // Route factories
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// NewRoute registers an empty route. // NewRoute registers an empty route.
func (r *Router) NewRoute() *Route { func (r *Router) NewRoute() *Route {
route := &Route{parent: r, strictSlash: r.strictSlash, skipClean: r.skipClean, useEncodedPath: r.useEncodedPath} // initialize a route with a copy of the parent router's configuration
route := &Route{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes}
r.routes = append(r.routes, route) r.routes = append(r.routes, route)
return route return route
} }
// Name registers a new route with a name.
// See Route.Name().
func (r *Router) Name(name string) *Route {
return r.NewRoute().Name(name)
}
// Handle registers a new route with a matcher for the URL path. // Handle registers a new route with a matcher for the URL path.
// See Route.Path() and Route.Handler(). // See Route.Path() and Route.Handler().
func (r *Router) Handle(path string, handler http.Handler) *Route { func (r *Router) Handle(path string, handler http.Handler) *Route {

View File

@ -267,7 +267,7 @@ type routeRegexpGroup struct {
} }
// setMatch extracts the variables from the URL once a route matches. // setMatch extracts the variables from the URL once a route matches.
func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { func (v routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) {
// Store host variables. // Store host variables.
if v.host != nil { if v.host != nil {
host := getHost(req) host := getHost(req)
@ -296,7 +296,7 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route)
} else { } else {
u.Path += "/" u.Path += "/"
} }
m.Handler = http.RedirectHandler(u.String(), 301) m.Handler = http.RedirectHandler(u.String(), http.StatusMovedPermanently)
} }
} }
} }
@ -312,17 +312,13 @@ func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route)
} }
// getHost tries its best to return the request host. // getHost tries its best to return the request host.
// According to section 14.23 of RFC 2616 the Host header
// can include the port number if the default value of 80 is not used.
func getHost(r *http.Request) string { func getHost(r *http.Request) string {
if r.URL.IsAbs() { if r.URL.IsAbs() {
return r.URL.Host return r.URL.Host
} }
host := r.Host return r.Host
// Slice off any port information.
if i := strings.Index(host, ":"); i != -1 {
host = host[:i]
}
return host
} }
func extractVars(input string, matches []int, names []string, output map[string]string) { func extractVars(input string, matches []int, names []string, output map[string]string) {

View File

@ -15,24 +15,8 @@ import (
// Route stores information to match a request and build URLs. // Route stores information to match a request and build URLs.
type Route struct { type Route struct {
// Parent where the route was registered (a Router).
parent parentRoute
// Request handler for the route. // Request handler for the route.
handler http.Handler handler http.Handler
// List of matchers.
matchers []matcher
// Manager for the variables from host and path.
regexp *routeRegexpGroup
// If true, when the path pattern is "/path/", accessing "/path" will
// redirect to the former and vice versa.
strictSlash bool
// If true, when the path pattern is "/path//to", accessing "/path//to"
// will not redirect
skipClean bool
// If true, "/path/foo%2Fbar/to" will match the path "/path/{var}/to"
useEncodedPath bool
// The scheme used when building URLs.
buildScheme string
// If true, this route never matches: it is only used to build URLs. // If true, this route never matches: it is only used to build URLs.
buildOnly bool buildOnly bool
// The name used to build URLs. // The name used to build URLs.
@ -40,7 +24,11 @@ type Route struct {
// Error resulted from building a route. // Error resulted from building a route.
err error err error
buildVarsFunc BuildVarsFunc // "global" reference to all named routes
namedRoutes map[string]*Route
// config possibly passed in from `Router`
routeConf
} }
// SkipClean reports whether path cleaning is enabled for this route via // SkipClean reports whether path cleaning is enabled for this route via
@ -64,6 +52,18 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
matchErr = ErrMethodMismatch matchErr = ErrMethodMismatch
continue continue
} }
// Ignore ErrNotFound errors. These errors arise from match call
// to Subrouters.
//
// This prevents subsequent matching subrouters from failing to
// run middleware. If not ignored, the middleware would see a
// non-nil MatchErr and be skipped, even when there was a
// matching route.
if match.MatchErr == ErrNotFound {
match.MatchErr = nil
}
matchErr = nil matchErr = nil
return false return false
} }
@ -93,9 +93,7 @@ func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
} }
// Set variables. // Set variables.
if r.regexp != nil { r.regexp.setMatch(req, match, r)
r.regexp.setMatch(req, match, r)
}
return true return true
} }
@ -137,7 +135,7 @@ func (r *Route) GetHandler() http.Handler {
// Name ----------------------------------------------------------------------- // Name -----------------------------------------------------------------------
// Name sets the name for the route, used to build URLs. // Name sets the name for the route, used to build URLs.
// If the name was registered already it will be overwritten. // It is an error to call Name more than once on a route.
func (r *Route) Name(name string) *Route { func (r *Route) Name(name string) *Route {
if r.name != "" { if r.name != "" {
r.err = fmt.Errorf("mux: route already has name %q, can't set %q", r.err = fmt.Errorf("mux: route already has name %q, can't set %q",
@ -145,7 +143,7 @@ func (r *Route) Name(name string) *Route {
} }
if r.err == nil { if r.err == nil {
r.name = name r.name = name
r.getNamedRoutes()[name] = r r.namedRoutes[name] = r
} }
return r return r
} }
@ -177,7 +175,6 @@ func (r *Route) addRegexpMatcher(tpl string, typ regexpType) error {
if r.err != nil { if r.err != nil {
return r.err return r.err
} }
r.regexp = r.getRegexpGroup()
if typ == regexpTypePath || typ == regexpTypePrefix { if typ == regexpTypePath || typ == regexpTypePrefix {
if len(tpl) > 0 && tpl[0] != '/' { if len(tpl) > 0 && tpl[0] != '/' {
return fmt.Errorf("mux: path must start with a slash, got %q", tpl) return fmt.Errorf("mux: path must start with a slash, got %q", tpl)
@ -386,7 +383,7 @@ func (r *Route) PathPrefix(tpl string) *Route {
// The above route will only match if the URL contains the defined queries // The above route will only match if the URL contains the defined queries
// values, e.g.: ?foo=bar&id=42. // values, e.g.: ?foo=bar&id=42.
// //
// It the value is an empty string, it will match any value if the key is set. // If the value is an empty string, it will match any value if the key is set.
// //
// Variables can define an optional regexp pattern to be matched: // Variables can define an optional regexp pattern to be matched:
// //
@ -424,7 +421,7 @@ func (r *Route) Schemes(schemes ...string) *Route {
for k, v := range schemes { for k, v := range schemes {
schemes[k] = strings.ToLower(v) schemes[k] = strings.ToLower(v)
} }
if r.buildScheme == "" && len(schemes) > 0 { if len(schemes) > 0 {
r.buildScheme = schemes[0] r.buildScheme = schemes[0]
} }
return r.addMatcher(schemeMatcher(schemes)) return r.addMatcher(schemeMatcher(schemes))
@ -439,7 +436,15 @@ type BuildVarsFunc func(map[string]string) map[string]string
// BuildVarsFunc adds a custom function to be used to modify build variables // BuildVarsFunc adds a custom function to be used to modify build variables
// before a route's URL is built. // before a route's URL is built.
func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route { func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
r.buildVarsFunc = f if r.buildVarsFunc != nil {
// compose the old and new functions
old := r.buildVarsFunc
r.buildVarsFunc = func(m map[string]string) map[string]string {
return f(old(m))
}
} else {
r.buildVarsFunc = f
}
return r return r
} }
@ -458,7 +463,8 @@ func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
// Here, the routes registered in the subrouter won't be tested if the host // Here, the routes registered in the subrouter won't be tested if the host
// doesn't match. // doesn't match.
func (r *Route) Subrouter() *Router { func (r *Route) Subrouter() *Router {
router := &Router{parent: r, strictSlash: r.strictSlash} // initialize a subrouter with a copy of the parent route's configuration
router := &Router{routeConf: copyRouteConf(r.routeConf), namedRoutes: r.namedRoutes}
r.addMatcher(router) r.addMatcher(router)
return router return router
} }
@ -502,9 +508,6 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) {
if r.err != nil { if r.err != nil {
return nil, r.err return nil, r.err
} }
if r.regexp == nil {
return nil, errors.New("mux: route doesn't have a host or path")
}
values, err := r.prepareVars(pairs...) values, err := r.prepareVars(pairs...)
if err != nil { if err != nil {
return nil, err return nil, err
@ -516,8 +519,8 @@ func (r *Route) URL(pairs ...string) (*url.URL, error) {
return nil, err return nil, err
} }
scheme = "http" scheme = "http"
if s := r.getBuildScheme(); s != "" { if r.buildScheme != "" {
scheme = s scheme = r.buildScheme
} }
} }
if r.regexp.path != nil { if r.regexp.path != nil {
@ -547,7 +550,7 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
if r.err != nil { if r.err != nil {
return nil, r.err return nil, r.err
} }
if r.regexp == nil || r.regexp.host == nil { if r.regexp.host == nil {
return nil, errors.New("mux: route doesn't have a host") return nil, errors.New("mux: route doesn't have a host")
} }
values, err := r.prepareVars(pairs...) values, err := r.prepareVars(pairs...)
@ -562,8 +565,8 @@ func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
Scheme: "http", Scheme: "http",
Host: host, Host: host,
} }
if s := r.getBuildScheme(); s != "" { if r.buildScheme != "" {
u.Scheme = s u.Scheme = r.buildScheme
} }
return u, nil return u, nil
} }
@ -575,7 +578,7 @@ func (r *Route) URLPath(pairs ...string) (*url.URL, error) {
if r.err != nil { if r.err != nil {
return nil, r.err return nil, r.err
} }
if r.regexp == nil || r.regexp.path == nil { if r.regexp.path == nil {
return nil, errors.New("mux: route doesn't have a path") return nil, errors.New("mux: route doesn't have a path")
} }
values, err := r.prepareVars(pairs...) values, err := r.prepareVars(pairs...)
@ -600,7 +603,7 @@ func (r *Route) GetPathTemplate() (string, error) {
if r.err != nil { if r.err != nil {
return "", r.err return "", r.err
} }
if r.regexp == nil || r.regexp.path == nil { if r.regexp.path == nil {
return "", errors.New("mux: route doesn't have a path") return "", errors.New("mux: route doesn't have a path")
} }
return r.regexp.path.template, nil return r.regexp.path.template, nil
@ -614,7 +617,7 @@ func (r *Route) GetPathRegexp() (string, error) {
if r.err != nil { if r.err != nil {
return "", r.err return "", r.err
} }
if r.regexp == nil || r.regexp.path == nil { if r.regexp.path == nil {
return "", errors.New("mux: route does not have a path") return "", errors.New("mux: route does not have a path")
} }
return r.regexp.path.regexp.String(), nil return r.regexp.path.regexp.String(), nil
@ -629,7 +632,7 @@ func (r *Route) GetQueriesRegexp() ([]string, error) {
if r.err != nil { if r.err != nil {
return nil, r.err return nil, r.err
} }
if r.regexp == nil || r.regexp.queries == nil { if r.regexp.queries == nil {
return nil, errors.New("mux: route doesn't have queries") return nil, errors.New("mux: route doesn't have queries")
} }
var queries []string var queries []string
@ -648,7 +651,7 @@ func (r *Route) GetQueriesTemplates() ([]string, error) {
if r.err != nil { if r.err != nil {
return nil, r.err return nil, r.err
} }
if r.regexp == nil || r.regexp.queries == nil { if r.regexp.queries == nil {
return nil, errors.New("mux: route doesn't have queries") return nil, errors.New("mux: route doesn't have queries")
} }
var queries []string var queries []string
@ -683,7 +686,7 @@ func (r *Route) GetHostTemplate() (string, error) {
if r.err != nil { if r.err != nil {
return "", r.err return "", r.err
} }
if r.regexp == nil || r.regexp.host == nil { if r.regexp.host == nil {
return "", errors.New("mux: route doesn't have a host") return "", errors.New("mux: route doesn't have a host")
} }
return r.regexp.host.template, nil return r.regexp.host.template, nil
@ -700,64 +703,8 @@ func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {
} }
func (r *Route) buildVars(m map[string]string) map[string]string { func (r *Route) buildVars(m map[string]string) map[string]string {
if r.parent != nil {
m = r.parent.buildVars(m)
}
if r.buildVarsFunc != nil { if r.buildVarsFunc != nil {
m = r.buildVarsFunc(m) m = r.buildVarsFunc(m)
} }
return m return m
} }
// ----------------------------------------------------------------------------
// parentRoute
// ----------------------------------------------------------------------------
// parentRoute allows routes to know about parent host and path definitions.
type parentRoute interface {
getBuildScheme() string
getNamedRoutes() map[string]*Route
getRegexpGroup() *routeRegexpGroup
buildVars(map[string]string) map[string]string
}
func (r *Route) getBuildScheme() string {
if r.buildScheme != "" {
return r.buildScheme
}
if r.parent != nil {
return r.parent.getBuildScheme()
}
return ""
}
// getNamedRoutes returns the map where named routes are registered.
func (r *Route) getNamedRoutes() map[string]*Route {
if r.parent == nil {
// During tests router is not always set.
r.parent = NewRouter()
}
return r.parent.getNamedRoutes()
}
// getRegexpGroup returns regexp definitions from this route.
func (r *Route) getRegexpGroup() *routeRegexpGroup {
if r.regexp == nil {
if r.parent == nil {
// During tests router is not always set.
r.parent = NewRouter()
}
regexp := r.parent.getRegexpGroup()
if regexp == nil {
r.regexp = new(routeRegexpGroup)
} else {
// Copy.
r.regexp = &routeRegexpGroup{
host: regexp.host,
path: regexp.path,
queries: regexp.queries,
}
}
}
return r.regexp
}

View File

@ -80,7 +80,7 @@ megacheck_install() {
} }
golint_install() { golint_install() {
go get github.com/golang/lint/golint go get golang.org/x/lint/golint
} }
$1 $1

View File

@ -1,9 +1,9 @@
language: go language: go
go: go:
- 1.8.x
- 1.9.x - 1.9.x
- 1.10.x - 1.10.x
- 1.11.x
- master - master
sudo: true sudo: true
@ -44,7 +44,7 @@ script:
- > - >
goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }' goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 0 : 1 }'
- go vet ./... - go vet ./...
- megacheck -go 1.8 ./... - megacheck -go 1.9 ./...
- golint ./... - golint ./...
- PQTEST_BINARY_PARAMETERS=no go test -race -v ./... - PQTEST_BINARY_PARAMETERS=no go test -race -v ./...
- PQTEST_BINARY_PARAMETERS=yes go test -race -v ./... - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./...

2
vendor/github.com/lib/pq/README.md generated vendored
View File

@ -10,7 +10,7 @@
## Docs ## Docs
For detailed documentation and basic usage examples, please see the package For detailed documentation and basic usage examples, please see the package
documentation at <http://godoc.org/github.com/lib/pq>. documentation at <https://godoc.org/github.com/lib/pq>.
## Tests ## Tests

259
vendor/github.com/lib/pq/conn.go generated vendored
View File

@ -2,7 +2,9 @@ package pq
import ( import (
"bufio" "bufio"
"context"
"crypto/md5" "crypto/md5"
"crypto/sha256"
"database/sql" "database/sql"
"database/sql/driver" "database/sql/driver"
"encoding/binary" "encoding/binary"
@ -20,6 +22,7 @@ import (
"unicode" "unicode"
"github.com/lib/pq/oid" "github.com/lib/pq/oid"
"github.com/lib/pq/scram"
) )
// Common error types // Common error types
@ -89,13 +92,24 @@ type Dialer interface {
DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error)
} }
type defaultDialer struct{} type DialerContext interface {
DialContext(ctx context.Context, network, address string) (net.Conn, error)
func (d defaultDialer) Dial(ntw, addr string) (net.Conn, error) {
return net.Dial(ntw, addr)
} }
func (d defaultDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout(ntw, addr, timeout) type defaultDialer struct {
d net.Dialer
}
func (d defaultDialer) Dial(network, address string) (net.Conn, error) {
return d.d.Dial(network, address)
}
func (d defaultDialer) DialTimeout(network, address string, timeout time.Duration) (net.Conn, error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
return d.DialContext(ctx, network, address)
}
func (d defaultDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
return d.d.DialContext(ctx, network, address)
} }
type conn struct { type conn struct {
@ -244,90 +258,35 @@ func (cn *conn) writeBuf(b byte) *writeBuf {
} }
} }
// Open opens a new connection to the database. name is a connection string. // Open opens a new connection to the database. dsn is a connection string.
// Most users should only use it through database/sql package from the standard // Most users should only use it through database/sql package from the standard
// library. // library.
func Open(name string) (_ driver.Conn, err error) { func Open(dsn string) (_ driver.Conn, err error) {
return DialOpen(defaultDialer{}, name) return DialOpen(defaultDialer{}, dsn)
} }
// DialOpen opens a new connection to the database using a dialer. // DialOpen opens a new connection to the database using a dialer.
func DialOpen(d Dialer, name string) (_ driver.Conn, err error) { func DialOpen(d Dialer, dsn string) (_ driver.Conn, err error) {
c, err := NewConnector(dsn)
if err != nil {
return nil, err
}
c.dialer = d
return c.open(context.Background())
}
func (c *Connector) open(ctx context.Context) (cn *conn, err error) {
// Handle any panics during connection initialization. Note that we // Handle any panics during connection initialization. Note that we
// specifically do *not* want to use errRecover(), as that would turn any // specifically do *not* want to use errRecover(), as that would turn any
// connection errors into ErrBadConns, hiding the real error message from // connection errors into ErrBadConns, hiding the real error message from
// the user. // the user.
defer errRecoverNoErrBadConn(&err) defer errRecoverNoErrBadConn(&err)
o := make(values) o := c.opts
// A number of defaults are applied here, in this order: cn = &conn{
//
// * Very low precedence defaults applied in every situation
// * Environment variables
// * Explicitly passed connection information
o["host"] = "localhost"
o["port"] = "5432"
// N.B.: Extra float digits should be set to 3, but that breaks
// Postgres 8.4 and older, where the max is 2.
o["extra_float_digits"] = "2"
for k, v := range parseEnviron(os.Environ()) {
o[k] = v
}
if strings.HasPrefix(name, "postgres://") || strings.HasPrefix(name, "postgresql://") {
name, err = ParseURL(name)
if err != nil {
return nil, err
}
}
if err := parseOpts(name, o); err != nil {
return nil, err
}
// Use the "fallback" application name if necessary
if fallback, ok := o["fallback_application_name"]; ok {
if _, ok := o["application_name"]; !ok {
o["application_name"] = fallback
}
}
// We can't work with any client_encoding other than UTF-8 currently.
// However, we have historically allowed the user to set it to UTF-8
// explicitly, and there's no reason to break such programs, so allow that.
// Note that the "options" setting could also set client_encoding, but
// parsing its value is not worth it. Instead, we always explicitly send
// client_encoding as a separate run-time parameter, which should override
// anything set in options.
if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) {
return nil, errors.New("client_encoding must be absent or 'UTF8'")
}
o["client_encoding"] = "UTF8"
// DateStyle needs a similar treatment.
if datestyle, ok := o["datestyle"]; ok {
if datestyle != "ISO, MDY" {
panic(fmt.Sprintf("setting datestyle must be absent or %v; got %v",
"ISO, MDY", datestyle))
}
} else {
o["datestyle"] = "ISO, MDY"
}
// If a user is not provided by any other means, the last
// resort is to use the current operating system provided user
// name.
if _, ok := o["user"]; !ok {
u, err := userCurrent()
if err != nil {
return nil, err
}
o["user"] = u
}
cn := &conn{
opts: o, opts: o,
dialer: d, dialer: c.dialer,
} }
err = cn.handleDriverSettings(o) err = cn.handleDriverSettings(o)
if err != nil { if err != nil {
@ -335,7 +294,7 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
} }
cn.handlePgpass(o) cn.handlePgpass(o)
cn.c, err = dial(d, o) cn.c, err = dial(ctx, c.dialer, o)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -364,10 +323,10 @@ func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
return cn, err return cn, err
} }
func dial(d Dialer, o values) (net.Conn, error) { func dial(ctx context.Context, d Dialer, o values) (net.Conn, error) {
ntw, addr := network(o) network, address := network(o)
// SSL is not necessary or supported over UNIX domain sockets // SSL is not necessary or supported over UNIX domain sockets
if ntw == "unix" { if network == "unix" {
o["sslmode"] = "disable" o["sslmode"] = "disable"
} }
@ -378,19 +337,30 @@ func dial(d Dialer, o values) (net.Conn, error) {
return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err) return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err)
} }
duration := time.Duration(seconds) * time.Second duration := time.Duration(seconds) * time.Second
// connect_timeout should apply to the entire connection establishment // connect_timeout should apply to the entire connection establishment
// procedure, so we both use a timeout for the TCP connection // procedure, so we both use a timeout for the TCP connection
// establishment and set a deadline for doing the initial handshake. // establishment and set a deadline for doing the initial handshake.
// The deadline is then reset after startup() is done. // The deadline is then reset after startup() is done.
deadline := time.Now().Add(duration) deadline := time.Now().Add(duration)
conn, err := d.DialTimeout(ntw, addr, duration) var conn net.Conn
if dctx, ok := d.(DialerContext); ok {
ctx, cancel := context.WithTimeout(ctx, duration)
defer cancel()
conn, err = dctx.DialContext(ctx, network, address)
} else {
conn, err = d.DialTimeout(network, address, duration)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = conn.SetDeadline(deadline) err = conn.SetDeadline(deadline)
return conn, err return conn, err
} }
return d.Dial(ntw, addr) if dctx, ok := d.(DialerContext); ok {
return dctx.DialContext(ctx, network, address)
}
return d.Dial(network, address)
} }
func network(o values) (string, string) { func network(o values) (string, string) {
@ -704,7 +674,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
// res might be non-nil here if we received a previous // res might be non-nil here if we received a previous
// CommandComplete, but that's fine; just overwrite it // CommandComplete, but that's fine; just overwrite it
res = &rows{cn: cn} res = &rows{cn: cn}
res.colNames, res.colFmts, res.colTyps = parsePortalRowDescribe(r) res.rowsHeader = parsePortalRowDescribe(r)
// To work around a bug in QueryRow in Go 1.2 and earlier, wait // To work around a bug in QueryRow in Go 1.2 and earlier, wait
// until the first DataRow has been received. // until the first DataRow has been received.
@ -861,17 +831,15 @@ func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) {
cn.readParseResponse() cn.readParseResponse()
cn.readBindResponse() cn.readBindResponse()
rows := &rows{cn: cn} rows := &rows{cn: cn}
rows.colNames, rows.colFmts, rows.colTyps = cn.readPortalDescribeResponse() rows.rowsHeader = cn.readPortalDescribeResponse()
cn.postExecuteWorkaround() cn.postExecuteWorkaround()
return rows, nil return rows, nil
} }
st := cn.prepareTo(query, "") st := cn.prepareTo(query, "")
st.exec(args) st.exec(args)
return &rows{ return &rows{
cn: cn, cn: cn,
colNames: st.colNames, rowsHeader: st.rowsHeader,
colTyps: st.colTyps,
colFmts: st.colFmts,
}, nil }, nil
} }
@ -992,7 +960,6 @@ func (cn *conn) recv() (t byte, r *readBuf) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
switch t { switch t {
case 'E': case 'E':
panic(parseError(r)) panic(parseError(r))
@ -1163,6 +1130,55 @@ func (cn *conn) auth(r *readBuf, o values) {
if r.int32() != 0 { if r.int32() != 0 {
errorf("unexpected authentication response: %q", t) errorf("unexpected authentication response: %q", t)
} }
case 10:
sc := scram.NewClient(sha256.New, o["user"], o["password"])
sc.Step(nil)
if sc.Err() != nil {
errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
}
scOut := sc.Out()
w := cn.writeBuf('p')
w.string("SCRAM-SHA-256")
w.int32(len(scOut))
w.bytes(scOut)
cn.send(w)
t, r := cn.recv()
if t != 'R' {
errorf("unexpected password response: %q", t)
}
if r.int32() != 11 {
errorf("unexpected authentication response: %q", t)
}
nextStep := r.next(len(*r))
sc.Step(nextStep)
if sc.Err() != nil {
errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
}
scOut = sc.Out()
w = cn.writeBuf('p')
w.bytes(scOut)
cn.send(w)
t, r = cn.recv()
if t != 'R' {
errorf("unexpected password response: %q", t)
}
if r.int32() != 12 {
errorf("unexpected authentication response: %q", t)
}
nextStep = r.next(len(*r))
sc.Step(nextStep)
if sc.Err() != nil {
errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
}
default: default:
errorf("unknown authentication response: %d", code) errorf("unknown authentication response: %d", code)
} }
@ -1180,12 +1196,10 @@ var colFmtDataAllBinary = []byte{0, 1, 0, 1}
var colFmtDataAllText = []byte{0, 0} var colFmtDataAllText = []byte{0, 0}
type stmt struct { type stmt struct {
cn *conn cn *conn
name string name string
colNames []string rowsHeader
colFmts []format
colFmtData []byte colFmtData []byte
colTyps []fieldDesc
paramTyps []oid.Oid paramTyps []oid.Oid
closed bool closed bool
} }
@ -1231,10 +1245,8 @@ func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) {
st.exec(v) st.exec(v)
return &rows{ return &rows{
cn: st.cn, cn: st.cn,
colNames: st.colNames, rowsHeader: st.rowsHeader,
colTyps: st.colTyps,
colFmts: st.colFmts,
}, nil }, nil
} }
@ -1344,16 +1356,22 @@ func (cn *conn) parseComplete(commandTag string) (driver.Result, string) {
return driver.RowsAffected(n), commandTag return driver.RowsAffected(n), commandTag
} }
type rows struct { type rowsHeader struct {
cn *conn
finish func()
colNames []string colNames []string
colTyps []fieldDesc colTyps []fieldDesc
colFmts []format colFmts []format
done bool }
rb readBuf
result driver.Result type rows struct {
tag string cn *conn
finish func()
rowsHeader
done bool
rb readBuf
result driver.Result
tag string
next *rowsHeader
} }
func (rs *rows) Close() error { func (rs *rows) Close() error {
@ -1440,7 +1458,8 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
} }
return return
case 'T': case 'T':
rs.colNames, rs.colFmts, rs.colTyps = parsePortalRowDescribe(&rs.rb) next := parsePortalRowDescribe(&rs.rb)
rs.next = &next
return io.EOF return io.EOF
default: default:
errorf("unexpected message after execute: %q", t) errorf("unexpected message after execute: %q", t)
@ -1449,10 +1468,16 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
} }
func (rs *rows) HasNextResultSet() bool { func (rs *rows) HasNextResultSet() bool {
return !rs.done hasNext := rs.next != nil && !rs.done
return hasNext
} }
func (rs *rows) NextResultSet() error { func (rs *rows) NextResultSet() error {
if rs.next == nil {
return io.EOF
}
rs.rowsHeader = *rs.next
rs.next = nil
return nil return nil
} }
@ -1630,13 +1655,13 @@ func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames [
} }
} }
func (cn *conn) readPortalDescribeResponse() (colNames []string, colFmts []format, colTyps []fieldDesc) { func (cn *conn) readPortalDescribeResponse() rowsHeader {
t, r := cn.recv1() t, r := cn.recv1()
switch t { switch t {
case 'T': case 'T':
return parsePortalRowDescribe(r) return parsePortalRowDescribe(r)
case 'n': case 'n':
return nil, nil, nil return rowsHeader{}
case 'E': case 'E':
err := parseError(r) err := parseError(r)
cn.readReadyForQuery() cn.readReadyForQuery()
@ -1742,11 +1767,11 @@ func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []fieldDe
return return
} }
func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, colTyps []fieldDesc) { func parsePortalRowDescribe(r *readBuf) rowsHeader {
n := r.int16() n := r.int16()
colNames = make([]string, n) colNames := make([]string, n)
colFmts = make([]format, n) colFmts := make([]format, n)
colTyps = make([]fieldDesc, n) colTyps := make([]fieldDesc, n)
for i := range colNames { for i := range colNames {
colNames[i] = r.string() colNames[i] = r.string()
r.next(6) r.next(6)
@ -1755,7 +1780,11 @@ func parsePortalRowDescribe(r *readBuf) (colNames []string, colFmts []format, co
colTyps[i].Mod = r.int32() colTyps[i].Mod = r.int32()
colFmts[i] = format(r.int16()) colFmts[i] = format(r.int16())
} }
return return rowsHeader{
colNames: colNames,
colFmts: colFmts,
colTyps: colTyps,
}
} }
// parseEnviron tries to mimic some of libpq's environment handling // parseEnviron tries to mimic some of libpq's environment handling

View File

@ -1,5 +1,3 @@
// +build go1.8
package pq package pq
import ( import (
@ -9,6 +7,7 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"time"
) )
// Implement the "QueryerContext" interface // Implement the "QueryerContext" interface
@ -76,13 +75,32 @@ func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx,
return tx, nil return tx, nil
} }
func (cn *conn) Ping(ctx context.Context) error {
if finish := cn.watchCancel(ctx); finish != nil {
defer finish()
}
rows, err := cn.simpleQuery("SELECT 'lib/pq ping test';")
if err != nil {
return driver.ErrBadConn // https://golang.org/pkg/database/sql/driver/#Pinger
}
rows.Close()
return nil
}
func (cn *conn) watchCancel(ctx context.Context) func() { func (cn *conn) watchCancel(ctx context.Context) func() {
if done := ctx.Done(); done != nil { if done := ctx.Done(); done != nil {
finished := make(chan struct{}) finished := make(chan struct{})
go func() { go func() {
select { select {
case <-done: case <-done:
_ = cn.cancel() // At this point the function level context is canceled,
// so it must not be used for the additional network
// request to cancel the query.
// Create a new context to pass into the dial.
ctxCancel, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
_ = cn.cancel(ctxCancel)
finished <- struct{}{} finished <- struct{}{}
case <-finished: case <-finished:
} }
@ -97,8 +115,8 @@ func (cn *conn) watchCancel(ctx context.Context) func() {
return nil return nil
} }
func (cn *conn) cancel() error { func (cn *conn) cancel(ctx context.Context) error {
c, err := dial(cn.dialer, cn.opts) c, err := dial(ctx, cn.dialer, cn.opts)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,10 +1,12 @@
// +build go1.10
package pq package pq
import ( import (
"context" "context"
"database/sql/driver" "database/sql/driver"
"errors"
"fmt"
"os"
"strings"
) )
// Connector represents a fixed configuration for the pq driver with a given // Connector represents a fixed configuration for the pq driver with a given
@ -14,30 +16,95 @@ import (
// //
// See https://golang.org/pkg/database/sql/driver/#Connector. // See https://golang.org/pkg/database/sql/driver/#Connector.
// See https://golang.org/pkg/database/sql/#OpenDB. // See https://golang.org/pkg/database/sql/#OpenDB.
type connector struct { type Connector struct {
name string opts values
dialer Dialer
} }
// Connect returns a connection to the database using the fixed configuration // Connect returns a connection to the database using the fixed configuration
// of this Connector. Context is not used. // of this Connector. Context is not used.
func (c *connector) Connect(_ context.Context) (driver.Conn, error) { func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) {
return (&Driver{}).Open(c.name) return c.open(ctx)
} }
// Driver returnst the underlying driver of this Connector. // Driver returnst the underlying driver of this Connector.
func (c *connector) Driver() driver.Driver { func (c *Connector) Driver() driver.Driver {
return &Driver{} return &Driver{}
} }
var _ driver.Connector = &connector{}
// NewConnector returns a connector for the pq driver in a fixed configuration // NewConnector returns a connector for the pq driver in a fixed configuration
// with the given name. The returned connector can be used to create any number // with the given dsn. The returned connector can be used to create any number
// of equivalent Conn's. The returned connector is intended to be used with // of equivalent Conn's. The returned connector is intended to be used with
// database/sql.OpenDB. // database/sql.OpenDB.
// //
// See https://golang.org/pkg/database/sql/driver/#Connector. // See https://golang.org/pkg/database/sql/driver/#Connector.
// See https://golang.org/pkg/database/sql/#OpenDB. // See https://golang.org/pkg/database/sql/#OpenDB.
func NewConnector(name string) (driver.Connector, error) { func NewConnector(dsn string) (*Connector, error) {
return &connector{name: name}, nil var err error
o := make(values)
// A number of defaults are applied here, in this order:
//
// * Very low precedence defaults applied in every situation
// * Environment variables
// * Explicitly passed connection information
o["host"] = "localhost"
o["port"] = "5432"
// N.B.: Extra float digits should be set to 3, but that breaks
// Postgres 8.4 and older, where the max is 2.
o["extra_float_digits"] = "2"
for k, v := range parseEnviron(os.Environ()) {
o[k] = v
}
if strings.HasPrefix(dsn, "postgres://") || strings.HasPrefix(dsn, "postgresql://") {
dsn, err = ParseURL(dsn)
if err != nil {
return nil, err
}
}
if err := parseOpts(dsn, o); err != nil {
return nil, err
}
// Use the "fallback" application name if necessary
if fallback, ok := o["fallback_application_name"]; ok {
if _, ok := o["application_name"]; !ok {
o["application_name"] = fallback
}
}
// We can't work with any client_encoding other than UTF-8 currently.
// However, we have historically allowed the user to set it to UTF-8
// explicitly, and there's no reason to break such programs, so allow that.
// Note that the "options" setting could also set client_encoding, but
// parsing its value is not worth it. Instead, we always explicitly send
// client_encoding as a separate run-time parameter, which should override
// anything set in options.
if enc, ok := o["client_encoding"]; ok && !isUTF8(enc) {
return nil, errors.New("client_encoding must be absent or 'UTF8'")
}
o["client_encoding"] = "UTF8"
// DateStyle needs a similar treatment.
if datestyle, ok := o["datestyle"]; ok {
if datestyle != "ISO, MDY" {
return nil, fmt.Errorf("setting datestyle must be absent or %v; got %v", "ISO, MDY", datestyle)
}
} else {
o["datestyle"] = "ISO, MDY"
}
// If a user is not provided by any other means, the last
// resort is to use the current operating system provided user
// name.
if _, ok := o["user"]; !ok {
u, err := userCurrent()
if err != nil {
return nil, err
}
o["user"] = u
}
return &Connector{opts: o, dialer: defaultDialer{}}, nil
} }

2
vendor/github.com/lib/pq/doc.go generated vendored
View File

@ -239,7 +239,7 @@ for more information). Note that the channel name will be truncated to 63
bytes by the PostgreSQL server. bytes by the PostgreSQL server.
You can find a complete, working example of Listener usage at You can find a complete, working example of Listener usage at
http://godoc.org/github.com/lib/pq/example/listen. https://godoc.org/github.com/lib/pq/example/listen.
*/ */
package pq package pq

1
vendor/github.com/lib/pq/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/lib/pq

3
vendor/github.com/lib/pq/notify.go generated vendored
View File

@ -725,6 +725,9 @@ func (l *Listener) Close() error {
} }
l.isClosed = true l.isClosed = true
// Unblock calls to Listen()
l.reconnectCond.Broadcast()
return nil return nil
} }

264
vendor/github.com/lib/pq/scram/scram.go generated vendored Normal file
View File

@ -0,0 +1,264 @@
// Copyright (c) 2014 - Gustavo Niemeyer <gustavo@niemeyer.net>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. 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.
//
// 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.
// Pacakage scram implements a SCRAM-{SHA-1,etc} client per RFC5802.
//
// http://tools.ietf.org/html/rfc5802
//
package scram
import (
"bytes"
"crypto/hmac"
"crypto/rand"
"encoding/base64"
"fmt"
"hash"
"strconv"
"strings"
)
// Client implements a SCRAM-* client (SCRAM-SHA-1, SCRAM-SHA-256, etc).
//
// A Client may be used within a SASL conversation with logic resembling:
//
// var in []byte
// var client = scram.NewClient(sha1.New, user, pass)
// for client.Step(in) {
// out := client.Out()
// // send out to server
// in := serverOut
// }
// if client.Err() != nil {
// // auth failed
// }
//
type Client struct {
newHash func() hash.Hash
user string
pass string
step int
out bytes.Buffer
err error
clientNonce []byte
serverNonce []byte
saltedPass []byte
authMsg bytes.Buffer
}
// NewClient returns a new SCRAM-* client with the provided hash algorithm.
//
// For SCRAM-SHA-256, for example, use:
//
// client := scram.NewClient(sha256.New, user, pass)
//
func NewClient(newHash func() hash.Hash, user, pass string) *Client {
c := &Client{
newHash: newHash,
user: user,
pass: pass,
}
c.out.Grow(256)
c.authMsg.Grow(256)
return c
}
// Out returns the data to be sent to the server in the current step.
func (c *Client) Out() []byte {
if c.out.Len() == 0 {
return nil
}
return c.out.Bytes()
}
// Err returns the error that ocurred, or nil if there were no errors.
func (c *Client) Err() error {
return c.err
}
// SetNonce sets the client nonce to the provided value.
// If not set, the nonce is generated automatically out of crypto/rand on the first step.
func (c *Client) SetNonce(nonce []byte) {
c.clientNonce = nonce
}
var escaper = strings.NewReplacer("=", "=3D", ",", "=2C")
// Step processes the incoming data from the server and makes the
// next round of data for the server available via Client.Out.
// Step returns false if there are no errors and more data is
// still expected.
func (c *Client) Step(in []byte) bool {
c.out.Reset()
if c.step > 2 || c.err != nil {
return false
}
c.step++
switch c.step {
case 1:
c.err = c.step1(in)
case 2:
c.err = c.step2(in)
case 3:
c.err = c.step3(in)
}
return c.step > 2 || c.err != nil
}
func (c *Client) step1(in []byte) error {
if len(c.clientNonce) == 0 {
const nonceLen = 16
buf := make([]byte, nonceLen+b64.EncodedLen(nonceLen))
if _, err := rand.Read(buf[:nonceLen]); err != nil {
return fmt.Errorf("cannot read random SCRAM-SHA-256 nonce from operating system: %v", err)
}
c.clientNonce = buf[nonceLen:]
b64.Encode(c.clientNonce, buf[:nonceLen])
}
c.authMsg.WriteString("n=")
escaper.WriteString(&c.authMsg, c.user)
c.authMsg.WriteString(",r=")
c.authMsg.Write(c.clientNonce)
c.out.WriteString("n,,")
c.out.Write(c.authMsg.Bytes())
return nil
}
var b64 = base64.StdEncoding
func (c *Client) step2(in []byte) error {
c.authMsg.WriteByte(',')
c.authMsg.Write(in)
fields := bytes.Split(in, []byte(","))
if len(fields) != 3 {
return fmt.Errorf("expected 3 fields in first SCRAM-SHA-256 server message, got %d: %q", len(fields), in)
}
if !bytes.HasPrefix(fields[0], []byte("r=")) || len(fields[0]) < 2 {
return fmt.Errorf("server sent an invalid SCRAM-SHA-256 nonce: %q", fields[0])
}
if !bytes.HasPrefix(fields[1], []byte("s=")) || len(fields[1]) < 6 {
return fmt.Errorf("server sent an invalid SCRAM-SHA-256 salt: %q", fields[1])
}
if !bytes.HasPrefix(fields[2], []byte("i=")) || len(fields[2]) < 6 {
return fmt.Errorf("server sent an invalid SCRAM-SHA-256 iteration count: %q", fields[2])
}
c.serverNonce = fields[0][2:]
if !bytes.HasPrefix(c.serverNonce, c.clientNonce) {
return fmt.Errorf("server SCRAM-SHA-256 nonce is not prefixed by client nonce: got %q, want %q+\"...\"", c.serverNonce, c.clientNonce)
}
salt := make([]byte, b64.DecodedLen(len(fields[1][2:])))
n, err := b64.Decode(salt, fields[1][2:])
if err != nil {
return fmt.Errorf("cannot decode SCRAM-SHA-256 salt sent by server: %q", fields[1])
}
salt = salt[:n]
iterCount, err := strconv.Atoi(string(fields[2][2:]))
if err != nil {
return fmt.Errorf("server sent an invalid SCRAM-SHA-256 iteration count: %q", fields[2])
}
c.saltPassword(salt, iterCount)
c.authMsg.WriteString(",c=biws,r=")
c.authMsg.Write(c.serverNonce)
c.out.WriteString("c=biws,r=")
c.out.Write(c.serverNonce)
c.out.WriteString(",p=")
c.out.Write(c.clientProof())
return nil
}
func (c *Client) step3(in []byte) error {
var isv, ise bool
var fields = bytes.Split(in, []byte(","))
if len(fields) == 1 {
isv = bytes.HasPrefix(fields[0], []byte("v="))
ise = bytes.HasPrefix(fields[0], []byte("e="))
}
if ise {
return fmt.Errorf("SCRAM-SHA-256 authentication error: %s", fields[0][2:])
} else if !isv {
return fmt.Errorf("unsupported SCRAM-SHA-256 final message from server: %q", in)
}
if !bytes.Equal(c.serverSignature(), fields[0][2:]) {
return fmt.Errorf("cannot authenticate SCRAM-SHA-256 server signature: %q", fields[0][2:])
}
return nil
}
func (c *Client) saltPassword(salt []byte, iterCount int) {
mac := hmac.New(c.newHash, []byte(c.pass))
mac.Write(salt)
mac.Write([]byte{0, 0, 0, 1})
ui := mac.Sum(nil)
hi := make([]byte, len(ui))
copy(hi, ui)
for i := 1; i < iterCount; i++ {
mac.Reset()
mac.Write(ui)
mac.Sum(ui[:0])
for j, b := range ui {
hi[j] ^= b
}
}
c.saltedPass = hi
}
func (c *Client) clientProof() []byte {
mac := hmac.New(c.newHash, c.saltedPass)
mac.Write([]byte("Client Key"))
clientKey := mac.Sum(nil)
hash := c.newHash()
hash.Write(clientKey)
storedKey := hash.Sum(nil)
mac = hmac.New(c.newHash, storedKey)
mac.Write(c.authMsg.Bytes())
clientProof := mac.Sum(nil)
for i, b := range clientKey {
clientProof[i] ^= b
}
clientProof64 := make([]byte, b64.EncodedLen(len(clientProof)))
b64.Encode(clientProof64, clientProof)
return clientProof64
}
func (c *Client) serverSignature() []byte {
mac := hmac.New(c.newHash, c.saltedPass)
mac.Write([]byte("Server Key"))
serverKey := mac.Sum(nil)
mac = hmac.New(c.newHash, serverKey)
mac.Write(c.authMsg.Bytes())
serverSignature := mac.Sum(nil)
encoded := make([]byte, b64.EncodedLen(len(serverSignature)))
b64.Encode(encoded, serverSignature)
return encoded
}

8
vendor/github.com/lib/pq/ssl.go generated vendored
View File

@ -58,7 +58,13 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
sslRenegotiation(&tlsConf)
// Accept renegotiation requests initiated by the backend.
//
// Renegotiation was deprecated then removed from PostgreSQL 9.5, but
// the default configuration of older versions has it enabled. Redshift
// also initiates renegotiations and cannot be reconfigured.
tlsConf.Renegotiation = tls.RenegotiateFreelyAsClient
return func(conn net.Conn) (net.Conn, error) { return func(conn net.Conn) (net.Conn, error) {
client := tls.Client(conn, &tlsConf) client := tls.Client(conn, &tlsConf)

View File

@ -1,14 +0,0 @@
// +build go1.7
package pq
import "crypto/tls"
// Accept renegotiation requests initiated by the backend.
//
// Renegotiation was deprecated then removed from PostgreSQL 9.5, but
// the default configuration of older versions has it enabled. Redshift
// also initiates renegotiations and cannot be reconfigured.
func sslRenegotiation(conf *tls.Config) {
conf.Renegotiation = tls.RenegotiateFreelyAsClient
}

View File

@ -1,8 +0,0 @@
// +build !go1.7
package pq
import "crypto/tls"
// Renegotiation is not supported by crypto/tls until Go 1.7.
func sslRenegotiation(*tls.Config) {}

View File

@ -29,6 +29,15 @@ const (
backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity)
) )
const (
genericRead = 0x80000000
genericWrite = 0x40000000
)
const (
consoleTextmodeBuffer = 0x1
)
type wchar uint16 type wchar uint16
type short int16 type short int16
type dword uint32 type dword uint32
@ -69,14 +78,17 @@ var (
procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo") procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo")
procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo") procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo")
procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW") procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW")
procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer")
) )
// Writer provide colorable Writer to the console // Writer provide colorable Writer to the console
type Writer struct { type Writer struct {
out io.Writer out io.Writer
handle syscall.Handle handle syscall.Handle
oldattr word althandle syscall.Handle
oldpos coord oldattr word
oldpos coord
rest bytes.Buffer
} }
// NewColorable return new instance of Writer which handle escape sequence from File. // NewColorable return new instance of Writer which handle escape sequence from File.
@ -407,7 +419,18 @@ func (w *Writer) Write(data []byte) (n int, err error) {
var csbi consoleScreenBufferInfo var csbi consoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
er := bytes.NewReader(data) handle := w.handle
var er *bytes.Reader
if w.rest.Len() > 0 {
var rest bytes.Buffer
w.rest.WriteTo(&rest)
w.rest.Reset()
rest.Write(data)
er = bytes.NewReader(rest.Bytes())
} else {
er = bytes.NewReader(data)
}
var bw [1]byte var bw [1]byte
loop: loop:
for { for {
@ -425,29 +448,55 @@ loop:
break loop break loop
} }
if c2 == ']' { switch c2 {
if err := doTitleSequence(er); err != nil { case '>':
continue
case ']':
w.rest.WriteByte(c1)
w.rest.WriteByte(c2)
er.WriteTo(&w.rest)
if bytes.IndexByte(w.rest.Bytes(), 0x07) == -1 {
break loop break loop
} }
continue er = bytes.NewReader(w.rest.Bytes()[2:])
} err := doTitleSequence(er)
if c2 != 0x5b {
continue
}
var buf bytes.Buffer
var m byte
for {
c, err := er.ReadByte()
if err != nil { if err != nil {
break loop break loop
} }
w.rest.Reset()
continue
// https://github.com/mattn/go-colorable/issues/27
case '7':
procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
w.oldpos = csbi.cursorPosition
continue
case '8':
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
continue
case 0x5b:
// execute part after switch
default:
continue
}
w.rest.WriteByte(c1)
w.rest.WriteByte(c2)
er.WriteTo(&w.rest)
var buf bytes.Buffer
var m byte
for i, c := range w.rest.Bytes()[2:] {
if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
m = c m = c
er = bytes.NewReader(w.rest.Bytes()[2+i+1:])
w.rest.Reset()
break break
} }
buf.Write([]byte(string(c))) buf.Write([]byte(string(c)))
} }
if m == 0 {
break loop
}
switch m { switch m {
case 'A': case 'A':
@ -455,61 +504,64 @@ loop:
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.y -= short(n) csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'B': case 'B':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.y += short(n) csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'C': case 'C':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x += short(n) csbi.cursorPosition.x += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'D': case 'D':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x -= short(n) csbi.cursorPosition.x -= short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) if csbi.cursorPosition.x < 0 {
csbi.cursorPosition.x = 0
}
procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'E': case 'E':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = 0 csbi.cursorPosition.x = 0
csbi.cursorPosition.y += short(n) csbi.cursorPosition.y += short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'F': case 'F':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = 0 csbi.cursorPosition.x = 0
csbi.cursorPosition.y -= short(n) csbi.cursorPosition.y -= short(n)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'G': case 'G':
n, err = strconv.Atoi(buf.String()) n, err = strconv.Atoi(buf.String())
if err != nil { if err != nil {
continue continue
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
csbi.cursorPosition.x = short(n - 1) csbi.cursorPosition.x = short(n - 1)
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'H', 'f': case 'H', 'f':
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
if buf.Len() > 0 { if buf.Len() > 0 {
token := strings.Split(buf.String(), ";") token := strings.Split(buf.String(), ";")
switch len(token) { switch len(token) {
@ -534,7 +586,7 @@ loop:
} else { } else {
csbi.cursorPosition.y = 0 csbi.cursorPosition.y = 0
} }
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&csbi.cursorPosition)))
case 'J': case 'J':
n := 0 n := 0
if buf.Len() > 0 { if buf.Len() > 0 {
@ -545,20 +597,20 @@ loop:
} }
var count, written dword var count, written dword
var cursor coord var cursor coord
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
switch n { switch n {
case 0: case 0:
cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y} cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x) count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
case 1: case 1:
cursor = coord{x: csbi.window.left, y: csbi.window.top} cursor = coord{x: csbi.window.left, y: csbi.window.top}
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.window.top-csbi.cursorPosition.y)*csbi.size.x) count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.window.top-csbi.cursorPosition.y)*dword(csbi.size.x)
case 2: case 2:
cursor = coord{x: csbi.window.left, y: csbi.window.top} cursor = coord{x: csbi.window.left, y: csbi.window.top}
count = dword(csbi.size.x - csbi.cursorPosition.x + (csbi.size.y-csbi.cursorPosition.y)*csbi.size.x) count = dword(csbi.size.x) - dword(csbi.cursorPosition.x) + dword(csbi.size.y-csbi.cursorPosition.y)*dword(csbi.size.x)
} }
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'K': case 'K':
n := 0 n := 0
if buf.Len() > 0 { if buf.Len() > 0 {
@ -567,28 +619,28 @@ loop:
continue continue
} }
} }
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
var cursor coord var cursor coord
var count, written dword var count, written dword
switch n { switch n {
case 0: case 0:
cursor = coord{x: csbi.cursorPosition.x + 1, y: csbi.cursorPosition.y} cursor = coord{x: csbi.cursorPosition.x, y: csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x - 1) count = dword(csbi.size.x - csbi.cursorPosition.x)
case 1: case 1:
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y} cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
count = dword(csbi.size.x - csbi.cursorPosition.x) count = dword(csbi.size.x - csbi.cursorPosition.x)
case 2: case 2:
cursor = coord{x: csbi.window.left, y: csbi.window.top + csbi.cursorPosition.y} cursor = coord{x: csbi.window.left, y: csbi.cursorPosition.y}
count = dword(csbi.size.x) count = dword(csbi.size.x)
} }
procFillConsoleOutputCharacter.Call(uintptr(w.handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) procFillConsoleOutputCharacter.Call(uintptr(handle), uintptr(' '), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
procFillConsoleOutputAttribute.Call(uintptr(w.handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written))) procFillConsoleOutputAttribute.Call(uintptr(handle), uintptr(csbi.attributes), uintptr(count), *(*uintptr)(unsafe.Pointer(&cursor)), uintptr(unsafe.Pointer(&written)))
case 'm': case 'm':
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
attr := csbi.attributes attr := csbi.attributes
cs := buf.String() cs := buf.String()
if cs == "" { if cs == "" {
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(w.oldattr)) procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(w.oldattr))
continue continue
} }
token := strings.Split(cs, ";") token := strings.Split(cs, ";")
@ -627,6 +679,21 @@ loop:
attr |= n256foreAttr[n256] attr |= n256foreAttr[n256]
i += 2 i += 2
} }
} else if len(token) == 5 && token[i+1] == "2" {
var r, g, b int
r, _ = strconv.Atoi(token[i+2])
g, _ = strconv.Atoi(token[i+3])
b, _ = strconv.Atoi(token[i+4])
i += 4
if r > 127 {
attr |= foregroundRed
}
if g > 127 {
attr |= foregroundGreen
}
if b > 127 {
attr |= foregroundBlue
}
} else { } else {
attr = attr & (w.oldattr & backgroundMask) attr = attr & (w.oldattr & backgroundMask)
} }
@ -654,6 +721,21 @@ loop:
attr |= n256backAttr[n256] attr |= n256backAttr[n256]
i += 2 i += 2
} }
} else if len(token) == 5 && token[i+1] == "2" {
var r, g, b int
r, _ = strconv.Atoi(token[i+2])
g, _ = strconv.Atoi(token[i+3])
b, _ = strconv.Atoi(token[i+4])
i += 4
if r > 127 {
attr |= backgroundRed
}
if g > 127 {
attr |= backgroundGreen
}
if b > 127 {
attr |= backgroundBlue
}
} else { } else {
attr = attr & (w.oldattr & foregroundMask) attr = attr & (w.oldattr & foregroundMask)
} }
@ -685,38 +767,52 @@ loop:
attr |= backgroundBlue attr |= backgroundBlue
} }
} }
procSetConsoleTextAttribute.Call(uintptr(w.handle), uintptr(attr)) procSetConsoleTextAttribute.Call(uintptr(handle), uintptr(attr))
} }
} }
case 'h': case 'h':
var ci consoleCursorInfo var ci consoleCursorInfo
cs := buf.String() cs := buf.String()
if cs == "5>" { if cs == "5>" {
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 0 ci.visible = 0
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?25" { } else if cs == "?25" {
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 1 ci.visible = 1
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?1049" {
if w.althandle == 0 {
h, _, _ := procCreateConsoleScreenBuffer.Call(uintptr(genericRead|genericWrite), 0, 0, uintptr(consoleTextmodeBuffer), 0, 0)
w.althandle = syscall.Handle(h)
if w.althandle != 0 {
handle = w.althandle
}
}
} }
case 'l': case 'l':
var ci consoleCursorInfo var ci consoleCursorInfo
cs := buf.String() cs := buf.String()
if cs == "5>" { if cs == "5>" {
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 1 ci.visible = 1
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?25" { } else if cs == "?25" {
procGetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procGetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
ci.visible = 0 ci.visible = 0
procSetConsoleCursorInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&ci))) procSetConsoleCursorInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&ci)))
} else if cs == "?1049" {
if w.althandle != 0 {
syscall.CloseHandle(w.althandle)
w.althandle = 0
handle = w.handle
}
} }
case 's': case 's':
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi)))
w.oldpos = csbi.cursorPosition w.oldpos = csbi.cursorPosition
case 'u': case 'u':
procSetConsoleCursorPosition.Call(uintptr(w.handle), *(*uintptr)(unsafe.Pointer(&w.oldpos))) procSetConsoleCursorPosition.Call(uintptr(handle), *(*uintptr)(unsafe.Pointer(&w.oldpos)))
} }
} }

3
vendor/github.com/mattn/go-colorable/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/mattn/go-colorable
require github.com/mattn/go-isatty v0.0.5

4
vendor/github.com/mattn/go-colorable/go.sum generated vendored Normal file
View File

@ -0,0 +1,4 @@
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View File

@ -2,6 +2,10 @@ language: go
go: go:
- tip - tip
os:
- linux
- osx
before_install: before_install:
- go get github.com/mattn/goveralls - go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover - go get golang.org/x/tools/cmd/cover

3
vendor/github.com/mattn/go-isatty/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/mattn/go-isatty
require golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223

2
vendor/github.com/mattn/go-isatty/go.sum generated vendored Normal file
View File

@ -0,0 +1,2 @@
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View File

@ -1,12 +1,10 @@
// +build linux // +build android
// +build ppc64 ppc64le
package isatty package isatty
import ( import (
"syscall"
"unsafe" "unsafe"
syscall "golang.org/x/sys/unix"
) )
const ioctlReadTermios = syscall.TCGETS const ioctlReadTermios = syscall.TCGETS
@ -17,3 +15,9 @@ func IsTerminal(fd uintptr) bool {
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0 return err == 0
} }
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View File

@ -1,15 +0,0 @@
// +build appengine
package isatty
// IsTerminal returns true if the file descriptor is terminal which
// is always false on on appengine classic which is a sandboxed PaaS.
func IsTerminal(fd uintptr) bool {
return false
}
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View File

@ -16,3 +16,9 @@ func IsTerminal(fd uintptr) bool {
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
return err == 0 return err == 0
} }
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

View File

@ -1,18 +1,19 @@
// +build linux // +build linux
// +build !appengine,!ppc64,!ppc64le // +build !appengine
// +build !android
package isatty package isatty
import ( import "golang.org/x/sys/unix"
"syscall"
"unsafe"
)
const ioctlReadTermios = syscall.TCGETS
// IsTerminal return true if the file descriptor is terminal. // IsTerminal return true if the file descriptor is terminal.
func IsTerminal(fd uintptr) bool { func IsTerminal(fd uintptr) bool {
var termios syscall.Termios _, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) return err == nil
return err == 0 }
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
} }

View File

@ -1,8 +1,13 @@
// +build !windows // +build appengine js
// +build !appengine
package isatty package isatty
// IsTerminal returns true if the file descriptor is terminal which
// is always false on js and appengine classic which is a sandboxed PaaS.
func IsTerminal(fd uintptr) bool {
return false
}
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2 // IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment. // terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool { func IsCygwinTerminal(fd uintptr) bool {

View File

@ -14,3 +14,9 @@ func IsTerminal(fd uintptr) bool {
err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
return err == nil return err == nil
} }
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
// terminal. This is also always false on this environment.
func IsCygwinTerminal(fd uintptr) bool {
return false
}

8
vendor/github.com/miekg/dns/.codecov.yml generated vendored Normal file
View File

@ -0,0 +1,8 @@
coverage:
status:
project:
default:
target: 40%
threshold: null
patch: false
changes: false

View File

@ -1,12 +1,11 @@
language: go language: go
sudo: false sudo: false
go:
- 1.9.x
- tip
env: go:
- TESTS="-race -v -bench=. -coverprofile=coverage.txt -covermode=atomic" - 1.10.x
- TESTS="-race -v ./..." - 1.11.x
- 1.12.x
- tip
before_install: before_install:
# don't use the miekg/dns when testing forks # don't use the miekg/dns when testing forks
@ -14,7 +13,7 @@ before_install:
- ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true - ln -s $TRAVIS_BUILD_DIR $GOPATH/src/github.com/miekg/ || true
script: script:
- go test $TESTS - go test -race -v -bench=. -coverprofile=coverage.txt -covermode=atomic ./...
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) - bash <(curl -s https://codecov.io/bash)

View File

@ -3,13 +3,55 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:6914c49eed986dfb8dffb33516fa129c49929d4d873f41e073c83c11c372b870"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = ["ed25519","ed25519/internal/edwards25519"] packages = [
revision = "b080dc9a8c480b08e698fb1219160d598526310f" "ed25519",
"ed25519/internal/edwards25519",
]
pruneopts = ""
revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
[[projects]]
branch = "master"
digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685"
name = "golang.org/x/net"
packages = [
"bpf",
"context",
"internal/iana",
"internal/socket",
"ipv4",
"ipv6",
]
pruneopts = ""
revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de"
[[projects]]
branch = "master"
digest = "1:b2ea75de0ccb2db2ac79356407f8a4cd8f798fe15d41b381c00abf3ae8e55ed1"
name = "golang.org/x/sync"
packages = ["errgroup"]
pruneopts = ""
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
[[projects]]
branch = "master"
digest = "1:149a432fabebb8221a80f77731b1cd63597197ded4f14af606ebe3a0959004ec"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = ""
revision = "e4b3c5e9061176387e7cea65e4dc5853801f3fb7"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "5046e265393bd5e54f570ce29ae8bc6fa3f30ef5110e922996540400f287c64a" input-imports = [
"golang.org/x/crypto/ed25519",
"golang.org/x/net/ipv4",
"golang.org/x/net/ipv6",
"golang.org/x/sync/errgroup",
"golang.org/x/sys/unix",
]
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

View File

@ -24,3 +24,15 @@
[[constraint]] [[constraint]]
branch = "master" branch = "master"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
[[constraint]]
branch = "master"
name = "golang.org/x/net"
[[constraint]]
branch = "master"
name = "golang.org/x/sys"
[[constraint]]
branch = "master"
name = "golang.org/x/sync"

52
vendor/github.com/miekg/dns/Makefile.release generated vendored Normal file
View File

@ -0,0 +1,52 @@
# Makefile for releasing.
#
# The release is controlled from version.go. The version found there is
# used to tag the git repo, we're not building any artifects so there is nothing
# to upload to github.
#
# * Up the version in version.go
# * Run: make -f Makefile.release release
# * will *commit* your change with 'Release $VERSION'
# * push to github
#
define GO
//+build ignore
package main
import (
"fmt"
"github.com/miekg/dns"
)
func main() {
fmt.Println(dns.Version.String())
}
endef
$(file > version_release.go,$(GO))
VERSION:=$(shell go run version_release.go)
TAG="v$(VERSION)"
all:
@echo Use the \'release\' target to start a release $(VERSION)
rm -f version_release.go
.PHONY: release
release: commit push
@echo Released $(VERSION)
rm -f version_release.go
.PHONY: commit
commit:
@echo Committing release $(VERSION)
git commit -am"Release $(VERSION)"
git tag $(TAG)
.PHONY: push
push:
@echo Pushing release $(VERSION) to master
git push --tags
git push

View File

@ -7,10 +7,10 @@
> Less is more. > Less is more.
Complete and usable DNS library. All widely used Resource Records are supported, including the Complete and usable DNS library. All Resource Records are supported, including the DNSSEC types.
DNSSEC types. It follows a lean and mean philosophy. If there is stuff you should know as a DNS It follows a lean and mean philosophy. If there is stuff you should know as a DNS programmer there
programmer there isn't a convenience function for it. Server side and client side programming is isn't a convenience function for it. Server side and client side programming is supported, i.e. you
supported, i.e. you can build servers and resolvers with it. can build servers and resolvers with it.
We try to keep the "master" branch as sane as possible and at the bleeding edge of standards, We try to keep the "master" branch as sane as possible and at the bleeding edge of standards,
avoiding breaking changes wherever reasonable. We support the last two versions of Go. avoiding breaking changes wherever reasonable. We support the last two versions of Go.
@ -42,10 +42,9 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/tianon/rawdns * https://github.com/tianon/rawdns
* https://mesosphere.github.io/mesos-dns/ * https://mesosphere.github.io/mesos-dns/
* https://pulse.turbobytes.com/ * https://pulse.turbobytes.com/
* https://play.google.com/store/apps/details?id=com.turbobytes.dig
* https://github.com/fcambus/statzone * https://github.com/fcambus/statzone
* https://github.com/benschw/dns-clb-go * https://github.com/benschw/dns-clb-go
* https://github.com/corny/dnscheck for http://public-dns.info/ * https://github.com/corny/dnscheck for <http://public-dns.info/>
* https://namesmith.io * https://namesmith.io
* https://github.com/miekg/unbound * https://github.com/miekg/unbound
* https://github.com/miekg/exdns * https://github.com/miekg/exdns
@ -56,35 +55,41 @@ A not-so-up-to-date-list-that-may-be-actually-current:
* https://github.com/bamarni/dockness * https://github.com/bamarni/dockness
* https://github.com/fffaraz/microdns * https://github.com/fffaraz/microdns
* http://kelda.io * http://kelda.io
* https://github.com/ipdcode/hades (JD.COM) * https://github.com/ipdcode/hades <https://jd.com>
* https://github.com/StackExchange/dnscontrol/ * https://github.com/StackExchange/dnscontrol/
* https://www.dnsperf.com/ * https://www.dnsperf.com/
* https://dnssectest.net/ * https://dnssectest.net/
* https://dns.apebits.com * https://dns.apebits.com
* https://github.com/oif/apex * https://github.com/oif/apex
* https://github.com/jedisct1/dnscrypt-proxy
* https://github.com/jedisct1/rpdns
* https://github.com/xor-gate/sshfp
* https://github.com/rs/dnstrace
* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
* https://github.com/semihalev/sdns
* https://render.com
* https://github.com/peterzen/goresolver
Send pull request if you want to be listed here. Send pull request if you want to be listed here.
# Features # Features
* UDP/TCP queries, IPv4 and IPv6; * UDP/TCP queries, IPv4 and IPv6
* RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported; * RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported
* Fast: * Fast
* Reply speed around ~ 80K qps (faster hardware results in more qps); * Server side programming (mimicking the net/http package)
* Parsing RRs ~ 100K RR/s, that's 5M records in about 50 seconds; * Client side programming
* Server side programming (mimicking the net/http package); * DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519
* Client side programming; * EDNS0, NSID, Cookies
* DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519; * AXFR/IXFR
* EDNS0, NSID, Cookies; * TSIG, SIG(0)
* AXFR/IXFR; * DNS over TLS (DoT): encrypted connection between client and server over TCP
* TSIG, SIG(0); * DNS name compression
* DNS over TLS: optional encrypted connection between client and server;
* DNS name compression;
* Depends only on the standard library.
Have fun! Have fun!
Miek Gieben - 2010-2012 - <miek@miek.nl> Miek Gieben - 2010-2012 - <miek@miek.nl>
DNS Authors 2012-
# Building # Building
@ -96,8 +101,8 @@ work:
## Examples ## Examples
A short "how to use the API" is at the beginning of doc.go (this also will show A short "how to use the API" is at the beginning of doc.go (this also will show when you call `godoc
when you call `godoc github.com/miekg/dns`). github.com/miekg/dns`).
Example programs can be found in the `github.com/miekg/exdns` repository. Example programs can be found in the `github.com/miekg/exdns` repository.
@ -155,12 +160,13 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 7553 - URI record * 7553 - URI record
* 7858 - DNS over TLS: Initiation and Performance Considerations * 7858 - DNS over TLS: Initiation and Performance Considerations
* 7871 - EDNS0 Client Subnet * 7871 - EDNS0 Client Subnet
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies) * 7873 - Domain Name System (DNS) Cookies
* 8080 - EdDSA for DNSSEC * 8080 - EdDSA for DNSSEC
* 8499 - DNS Terminology
## Loosely based upon ## Loosely Based Upon
* `ldns` * ldns - <https://nlnetlabs.nl/projects/ldns/about/>
* `NSD` * NSD - <https://nlnetlabs.nl/projects/nsd/about/>
* `Net::DNS` * Net::DNS - <http://www.net-dns.org/>
* `GRONG` * GRONG - <https://github.com/bortzmeyer/grong>

56
vendor/github.com/miekg/dns/acceptfunc.go generated vendored Normal file
View File

@ -0,0 +1,56 @@
package dns
// MsgAcceptFunc is used early in the server code to accept or reject a message with RcodeFormatError.
// It returns a MsgAcceptAction to indicate what should happen with the message.
type MsgAcceptFunc func(dh Header) MsgAcceptAction
// DefaultMsgAcceptFunc checks the request and will reject if:
//
// * isn't a request (don't respond in that case).
// * opcode isn't OpcodeQuery or OpcodeNotify
// * Zero bit isn't zero
// * has more than 1 question in the question section
// * has more than 1 RR in the Answer section
// * has more than 0 RRs in the Authority section
// * has more than 2 RRs in the Additional section
var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc
// MsgAcceptAction represents the action to be taken.
type MsgAcceptAction int
const (
MsgAccept MsgAcceptAction = iota // Accept the message
MsgReject // Reject the message with a RcodeFormatError
MsgIgnore // Ignore the error and send nothing back.
)
func defaultMsgAcceptFunc(dh Header) MsgAcceptAction {
if isResponse := dh.Bits&_QR != 0; isResponse {
return MsgIgnore
}
// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs.
opcode := int(dh.Bits>>11) & 0xF
if opcode != OpcodeQuery && opcode != OpcodeNotify {
return MsgReject
}
if isZero := dh.Bits&_Z != 0; isZero {
return MsgReject
}
if dh.Qdcount != 1 {
return MsgReject
}
// NOTIFY requests can have a SOA in the ANSWER section. See RFC 1996 Section 3.7 and 3.11.
if dh.Ancount > 1 {
return MsgReject
}
// IXFR request could have one SOA RR in the NS section. See RFC 1995, section 3.
if dh.Nscount > 1 {
return MsgReject
}
if dh.Arcount > 2 {
return MsgReject
}
return MsgAccept
}

202
vendor/github.com/miekg/dns/client.go generated vendored
View File

@ -3,7 +3,6 @@ package dns
// A client implementation. // A client implementation.
import ( import (
"bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/binary" "encoding/binary"
@ -13,16 +12,16 @@ import (
"time" "time"
) )
const dnsTimeout time.Duration = 2 * time.Second const (
const tcpIdleTimeout time.Duration = 8 * time.Second dnsTimeout time.Duration = 2 * time.Second
tcpIdleTimeout time.Duration = 8 * time.Second
)
// A Conn represents a connection to a DNS server. // A Conn represents a connection to a DNS server.
type Conn struct { type Conn struct {
net.Conn // a net.Conn holding the connection net.Conn // a net.Conn holding the connection
UDPSize uint16 // minimum receive buffer for UDP messages UDPSize uint16 // minimum receive buffer for UDP messages
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
rtt time.Duration
t time.Time
tsigRequestMAC string tsigRequestMAC string
} }
@ -83,33 +82,22 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
// create a new dialer with the appropriate timeout // create a new dialer with the appropriate timeout
var d net.Dialer var d net.Dialer
if c.Dialer == nil { if c.Dialer == nil {
d = net.Dialer{} d = net.Dialer{Timeout: c.getTimeoutForRequest(c.dialTimeout())}
} else { } else {
d = net.Dialer(*c.Dialer) d = *c.Dialer
} }
d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
network := "udp" network := c.Net
useTLS := false if network == "" {
network = "udp"
switch c.Net {
case "tcp-tls":
network = "tcp"
useTLS = true
case "tcp4-tls":
network = "tcp4"
useTLS = true
case "tcp6-tls":
network = "tcp6"
useTLS = true
default:
if c.Net != "" {
network = c.Net
}
} }
useTLS := strings.HasPrefix(network, "tcp") && strings.HasSuffix(network, "-tls")
conn = new(Conn) conn = new(Conn)
if useTLS { if useTLS {
network = strings.TrimSuffix(network, "-tls")
conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig) conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig)
} else { } else {
conn.Conn, err = d.Dial(network, address) conn.Conn, err = d.Dial(network, address)
@ -117,6 +105,7 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return conn, nil return conn, nil
} }
@ -177,8 +166,9 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
} }
co.TsigSecret = c.TsigSecret co.TsigSecret = c.TsigSecret
t := time.Now()
// write with the appropriate write timeout // write with the appropriate write timeout
co.SetWriteDeadline(time.Now().Add(c.getTimeoutForRequest(c.writeTimeout()))) co.SetWriteDeadline(t.Add(c.getTimeoutForRequest(c.writeTimeout())))
if err = co.WriteMsg(m); err != nil { if err = co.WriteMsg(m); err != nil {
return nil, 0, err return nil, 0, err
} }
@ -188,12 +178,15 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
if err == nil && r.Id != m.Id { if err == nil && r.Id != m.Id {
err = ErrId err = ErrId
} }
return r, co.rtt, err rtt = time.Since(t)
return r, rtt, err
} }
// ReadMsg reads a message from the connection co. // ReadMsg reads a message from the connection co.
// If the received message contains a TSIG record the transaction // If the received message contains a TSIG record the transaction signature
// signature is verified. // is verified. This method always tries to return the message, however if an
// error is returned there are no guarantees that the returned message is a
// valid representation of the packet read.
func (co *Conn) ReadMsg() (*Msg, error) { func (co *Conn) ReadMsg() (*Msg, error) {
p, err := co.ReadMsgHeader(nil) p, err := co.ReadMsgHeader(nil)
if err != nil { if err != nil {
@ -202,13 +195,10 @@ func (co *Conn) ReadMsg() (*Msg, error) {
m := new(Msg) m := new(Msg)
if err := m.Unpack(p); err != nil { if err := m.Unpack(p); err != nil {
// If ErrTruncated was returned, we still want to allow the user to use // If an error was returned, we still want to allow the user to use
// the message, but naively they can just check err if they don't want // the message, but naively they can just check err if they don't want
// to use a truncated message // to use an erroneous message
if err == ErrTruncated { return m, err
return m, err
}
return nil, err
} }
if t := m.IsTsig(); t != nil { if t := m.IsTsig(); t != nil {
if _, ok := co.TsigSecret[t.Hdr.Name]; !ok { if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
@ -229,19 +219,15 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
n int n int
err error err error
) )
switch co.Conn.(type) {
switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn: case *net.TCPConn, *tls.Conn:
r := t.(io.Reader) var length uint16
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
// First two bytes specify the length of the entire message.
l, err := tcpMsgLen(r)
if err != nil {
return nil, err return nil, err
} }
p = make([]byte, l)
n, err = tcpRead(r, p) p = make([]byte, length)
co.rtt = time.Since(co.t) n, err = io.ReadFull(co.Conn, p)
default: default:
if co.UDPSize > MinMsgSize { if co.UDPSize > MinMsgSize {
p = make([]byte, co.UDPSize) p = make([]byte, co.UDPSize)
@ -249,7 +235,6 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
p = make([]byte, MinMsgSize) p = make([]byte, MinMsgSize)
} }
n, err = co.Read(p) n, err = co.Read(p)
co.rtt = time.Since(co.t)
} }
if err != nil { if err != nil {
@ -269,78 +254,27 @@ func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
return p, err return p, err
} }
// tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
func tcpMsgLen(t io.Reader) (int, error) {
p := []byte{0, 0}
n, err := t.Read(p)
if err != nil {
return 0, err
}
// As seen with my local router/switch, returns 1 byte on the above read,
// resulting a a ShortRead. Just write it out (instead of loop) and read the
// other byte.
if n == 1 {
n1, err := t.Read(p[1:])
if err != nil {
return 0, err
}
n += n1
}
if n != 2 {
return 0, ErrShortRead
}
l := binary.BigEndian.Uint16(p)
if l == 0 {
return 0, ErrShortRead
}
return int(l), nil
}
// tcpRead calls TCPConn.Read enough times to fill allocated buffer.
func tcpRead(t io.Reader, p []byte) (int, error) {
n, err := t.Read(p)
if err != nil {
return n, err
}
for n < len(p) {
j, err := t.Read(p[n:])
if err != nil {
return n, err
}
n += j
}
return n, err
}
// Read implements the net.Conn read method. // Read implements the net.Conn read method.
func (co *Conn) Read(p []byte) (n int, err error) { func (co *Conn) Read(p []byte) (n int, err error) {
if co.Conn == nil { if co.Conn == nil {
return 0, ErrConnEmpty return 0, ErrConnEmpty
} }
if len(p) < 2 {
return 0, io.ErrShortBuffer
}
switch t := co.Conn.(type) {
case *net.TCPConn, *tls.Conn:
r := t.(io.Reader)
l, err := tcpMsgLen(r) switch co.Conn.(type) {
if err != nil { case *net.TCPConn, *tls.Conn:
var length uint16
if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil {
return 0, err return 0, err
} }
if l > len(p) { if int(length) > len(p) {
return int(l), io.ErrShortBuffer return 0, io.ErrShortBuffer
} }
return tcpRead(r, p[:l])
return io.ReadFull(co.Conn, p[:length])
} }
// UDP connection // UDP connection
n, err = co.Conn.Read(p) return co.Conn.Read(p)
if err != nil {
return n, err
}
return n, err
} }
// WriteMsg sends a message through the connection co. // WriteMsg sends a message through the connection co.
@ -362,34 +296,26 @@ func (co *Conn) WriteMsg(m *Msg) (err error) {
if err != nil { if err != nil {
return err return err
} }
co.t = time.Now() _, err = co.Write(out)
if _, err = co.Write(out); err != nil { return err
return err
}
return nil
} }
// Write implements the net.Conn Write method. // Write implements the net.Conn Write method.
func (co *Conn) Write(p []byte) (n int, err error) { func (co *Conn) Write(p []byte) (n int, err error) {
switch t := co.Conn.(type) { switch co.Conn.(type) {
case *net.TCPConn, *tls.Conn: case *net.TCPConn, *tls.Conn:
w := t.(io.Writer) if len(p) > MaxMsgSize {
lp := len(p)
if lp < 2 {
return 0, io.ErrShortBuffer
}
if lp > MaxMsgSize {
return 0, &Error{err: "message too large"} return 0, &Error{err: "message too large"}
} }
l := make([]byte, 2, lp+2)
binary.BigEndian.PutUint16(l, uint16(lp)) l := make([]byte, 2)
p = append(l, p...) binary.BigEndian.PutUint16(l, uint16(len(p)))
n, err := io.Copy(w, bytes.NewReader(p))
n, err := (&net.Buffers{l, p}).WriteTo(co.Conn)
return int(n), err return int(n), err
} }
n, err = co.Conn.Write(p)
return n, err return co.Conn.Write(p)
} }
// Return the appropriate timeout for a specific request // Return the appropriate timeout for a specific request
@ -432,7 +358,7 @@ func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error)
// ExchangeConn performs a synchronous query. It sends the message m via the connection // ExchangeConn performs a synchronous query. It sends the message m via the connection
// c and waits for a reply. The connection c is not closed by ExchangeConn. // c and waits for a reply. The connection c is not closed by ExchangeConn.
// This function is going away, but can easily be mimicked: // Deprecated: This function is going away, but can easily be mimicked:
// //
// co := &dns.Conn{Conn: c} // c is your net.Conn // co := &dns.Conn{Conn: c} // c is your net.Conn
// co.WriteMsg(m) // co.WriteMsg(m)
@ -456,11 +382,7 @@ func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
// DialTimeout acts like Dial but takes a timeout. // DialTimeout acts like Dial but takes a timeout.
func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) { func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}} client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}}
conn, err = client.Dial(address) return client.Dial(address)
if err != nil {
return nil, err
}
return conn, nil
} }
// DialWithTLS connects to the address on the named network with TLS. // DialWithTLS connects to the address on the named network with TLS.
@ -469,12 +391,7 @@ func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, er
network += "-tls" network += "-tls"
} }
client := Client{Net: network, TLSConfig: tlsConfig} client := Client{Net: network, TLSConfig: tlsConfig}
conn, err = client.Dial(address) return client.Dial(address)
if err != nil {
return nil, err
}
return conn, nil
} }
// DialTimeoutWithTLS acts like DialWithTLS but takes a timeout. // DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
@ -483,11 +400,7 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout
network += "-tls" network += "-tls"
} }
client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig} client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig}
conn, err = client.Dial(address) return client.Dial(address)
if err != nil {
return nil, err
}
return conn, nil
} }
// ExchangeContext acts like Exchange, but honors the deadline on the provided // ExchangeContext acts like Exchange, but honors the deadline on the provided
@ -498,10 +411,11 @@ func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg,
if deadline, ok := ctx.Deadline(); !ok { if deadline, ok := ctx.Deadline(); !ok {
timeout = 0 timeout = 0
} else { } else {
timeout = deadline.Sub(time.Now()) timeout = time.Until(deadline)
} }
// not passing the context to the underlying calls, as the API does not support // not passing the context to the underlying calls, as the API does not support
// context. For timeouts you should set up Client.Dialer and call Client.Exchange. // context. For timeouts you should set up Client.Dialer and call Client.Exchange.
// TODO(tmthrgd,miekg): this is a race condition.
c.Dialer = &net.Dialer{Timeout: timeout} c.Dialer = &net.Dialer{Timeout: timeout}
return c.Exchange(m, a) return c.Exchange(m, a)
} }

View File

@ -68,14 +68,10 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
} }
case "search": // set search path to given servers case "search": // set search path to given servers
c.Search = make([]string, len(f)-1) c.Search = append([]string(nil), f[1:]...)
for i := 0; i < len(c.Search); i++ {
c.Search[i] = f[i+1]
}
case "options": // magic options case "options": // magic options
for i := 1; i < len(f); i++ { for _, s := range f[1:] {
s := f[i]
switch { switch {
case len(s) >= 6 && s[:6] == "ndots:": case len(s) >= 6 && s[:6] == "ndots:":
n, _ := strconv.Atoi(s[6:]) n, _ := strconv.Atoi(s[6:])
@ -91,7 +87,7 @@ func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) {
n = 1 n = 1
} }
c.Timeout = n c.Timeout = n
case len(s) >= 8 && s[:9] == "attempts:": case len(s) >= 9 && s[:9] == "attempts:":
n, _ := strconv.Atoi(s[9:]) n, _ := strconv.Atoi(s[9:])
if n < 1 { if n < 1 {
n = 1 n = 1

View File

@ -1,189 +0,0 @@
//+build ignore
// compression_generate.go is meant to run with go generate. It will use
// go/{importer,types} to track down all the RR struct types. Then for each type
// it will look to see if there are (compressible) names, if so it will add that
// type to compressionLenHelperType and comressionLenSearchType which "fake" the
// compression so that Len() is fast.
package main
import (
"bytes"
"fmt"
"go/format"
"go/importer"
"go/types"
"log"
"os"
)
var packageHdr = `
// *** DO NOT MODIFY ***
// AUTOGENERATED BY go generate from compress_generate.go
package dns
`
// getTypeStruct will take a type and the package scope, and return the
// (innermost) struct if the type is considered a RR type (currently defined as
// those structs beginning with a RR_Header, could be redefined as implementing
// the RR interface). The bool return value indicates if embedded structs were
// resolved.
func getTypeStruct(t types.Type, scope *types.Scope) (*types.Struct, bool) {
st, ok := t.Underlying().(*types.Struct)
if !ok {
return nil, false
}
if st.Field(0).Type() == scope.Lookup("RR_Header").Type() {
return st, false
}
if st.Field(0).Anonymous() {
st, _ := getTypeStruct(st.Field(0).Type(), scope)
return st, true
}
return nil, false
}
func main() {
// Import and type-check the package
pkg, err := importer.Default().Import("github.com/miekg/dns")
fatalIfErr(err)
scope := pkg.Scope()
var domainTypes []string // Types that have a domain name in them (either compressible or not).
var cdomainTypes []string // Types that have a compressible domain name in them (subset of domainType)
Names:
for _, name := range scope.Names() {
o := scope.Lookup(name)
if o == nil || !o.Exported() {
continue
}
st, _ := getTypeStruct(o.Type(), scope)
if st == nil {
continue
}
if name == "PrivateRR" {
continue
}
if scope.Lookup("Type"+o.Name()) == nil && o.Name() != "RFC3597" {
log.Fatalf("Constant Type%s does not exist.", o.Name())
}
for i := 1; i < st.NumFields(); i++ {
if _, ok := st.Field(i).Type().(*types.Slice); ok {
if st.Tag(i) == `dns:"domain-name"` {
domainTypes = append(domainTypes, o.Name())
continue Names
}
if st.Tag(i) == `dns:"cdomain-name"` {
cdomainTypes = append(cdomainTypes, o.Name())
domainTypes = append(domainTypes, o.Name())
continue Names
}
continue
}
switch {
case st.Tag(i) == `dns:"domain-name"`:
domainTypes = append(domainTypes, o.Name())
continue Names
case st.Tag(i) == `dns:"cdomain-name"`:
cdomainTypes = append(cdomainTypes, o.Name())
domainTypes = append(domainTypes, o.Name())
continue Names
}
}
}
b := &bytes.Buffer{}
b.WriteString(packageHdr)
// compressionLenHelperType - all types that have domain-name/cdomain-name can be used for compressing names
fmt.Fprint(b, "func compressionLenHelperType(c map[string]int, r RR) {\n")
fmt.Fprint(b, "switch x := r.(type) {\n")
for _, name := range domainTypes {
o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope)
fmt.Fprintf(b, "case *%s:\n", name)
for i := 1; i < st.NumFields(); i++ {
out := func(s string) { fmt.Fprintf(b, "compressionLenHelper(c, x.%s)\n", st.Field(i).Name()) }
if _, ok := st.Field(i).Type().(*types.Slice); ok {
switch st.Tag(i) {
case `dns:"domain-name"`:
fallthrough
case `dns:"cdomain-name"`:
// For HIP we need to slice over the elements in this slice.
fmt.Fprintf(b, `for i := range x.%s {
compressionLenHelper(c, x.%s[i])
}
`, st.Field(i).Name(), st.Field(i).Name())
}
continue
}
switch {
case st.Tag(i) == `dns:"cdomain-name"`:
fallthrough
case st.Tag(i) == `dns:"domain-name"`:
out(st.Field(i).Name())
}
}
}
fmt.Fprintln(b, "}\n}\n\n")
// compressionLenSearchType - search cdomain-tags types for compressible names.
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool) {\n")
fmt.Fprint(b, "switch x := r.(type) {\n")
for _, name := range cdomainTypes {
o := scope.Lookup(name)
st, _ := getTypeStruct(o.Type(), scope)
fmt.Fprintf(b, "case *%s:\n", name)
j := 1
for i := 1; i < st.NumFields(); i++ {
out := func(s string, j int) {
fmt.Fprintf(b, "k%d, ok%d := compressionLenSearch(c, x.%s)\n", j, j, st.Field(i).Name())
}
// There are no slice types with names that can be compressed.
switch {
case st.Tag(i) == `dns:"cdomain-name"`:
out(st.Field(i).Name(), j)
j++
}
}
k := "k1"
ok := "ok1"
for i := 2; i < j; i++ {
k += fmt.Sprintf(" + k%d", i)
ok += fmt.Sprintf(" && ok%d", i)
}
fmt.Fprintf(b, "return %s, %s\n", k, ok)
}
fmt.Fprintln(b, "}\nreturn 0, false\n}\n\n")
// gofmt
res, err := format.Source(b.Bytes())
if err != nil {
b.WriteTo(os.Stderr)
log.Fatal(err)
}
f, err := os.Create("zcompress.go")
fatalIfErr(err)
defer f.Close()
f.Write(res)
}
func fatalIfErr(err error) {
if err != nil {
log.Fatal(err)
}
}

View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"net" "net"
"strconv" "strconv"
"strings"
) )
const hexDigit = "0123456789abcdef" const hexDigit = "0123456789abcdef"
@ -145,10 +146,9 @@ func (dns *Msg) IsTsig() *TSIG {
// record in the additional section will do. It returns the OPT record // record in the additional section will do. It returns the OPT record
// found or nil. // found or nil.
func (dns *Msg) IsEdns0() *OPT { func (dns *Msg) IsEdns0() *OPT {
// EDNS0 is at the end of the additional section, start there. // RFC 6891, Section 6.1.1 allows the OPT record to appear
// We might want to change this to *only* look at the last two // anywhere in the additional record section, but it's usually at
// records. So we see TSIG and/or OPT - this a slightly bigger // the end so start there.
// change though.
for i := len(dns.Extra) - 1; i >= 0; i-- { for i := len(dns.Extra) - 1; i >= 0; i-- {
if dns.Extra[i].Header().Rrtype == TypeOPT { if dns.Extra[i].Header().Rrtype == TypeOPT {
return dns.Extra[i].(*OPT) return dns.Extra[i].(*OPT)
@ -157,17 +157,93 @@ func (dns *Msg) IsEdns0() *OPT {
return nil return nil
} }
// popEdns0 is like IsEdns0, but it removes the record from the message.
func (dns *Msg) popEdns0() *OPT {
// RFC 6891, Section 6.1.1 allows the OPT record to appear
// anywhere in the additional record section, but it's usually at
// the end so start there.
for i := len(dns.Extra) - 1; i >= 0; i-- {
if dns.Extra[i].Header().Rrtype == TypeOPT {
opt := dns.Extra[i].(*OPT)
dns.Extra = append(dns.Extra[:i], dns.Extra[i+1:]...)
return opt
}
}
return nil
}
// IsDomainName checks if s is a valid domain name, it returns the number of // IsDomainName checks if s is a valid domain name, it returns the number of
// labels and true, when a domain name is valid. Note that non fully qualified // labels and true, when a domain name is valid. Note that non fully qualified
// domain name is considered valid, in this case the last label is counted in // domain name is considered valid, in this case the last label is counted in
// the number of labels. When false is returned the number of labels is not // the number of labels. When false is returned the number of labels is not
// defined. Also note that this function is extremely liberal; almost any // defined. Also note that this function is extremely liberal; almost any
// string is a valid domain name as the DNS is 8 bit protocol. It checks if each // string is a valid domain name as the DNS is 8 bit protocol. It checks if each
// label fits in 63 characters, but there is no length check for the entire // label fits in 63 characters and that the entire name will fit into the 255
// string s. I.e. a domain name longer than 255 characters is considered valid. // octet wire format limit.
func IsDomainName(s string) (labels int, ok bool) { func IsDomainName(s string) (labels int, ok bool) {
_, labels, err := packDomainName(s, nil, 0, nil, false) // XXX: The logic in this function was copied from packDomainName and
return labels, err == nil // should be kept in sync with that function.
const lenmsg = 256
if len(s) == 0 { // Ok, for instance when dealing with update RR without any rdata.
return 0, false
}
s = Fqdn(s)
// Each dot ends a segment of the name. Except for escaped dots (\.), which
// are normal dots.
var (
off int
begin int
wasDot bool
)
for i := 0; i < len(s); i++ {
switch s[i] {
case '\\':
if off+1 > lenmsg {
return labels, false
}
// check for \DDD
if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
i += 3
begin += 3
} else {
i++
begin++
}
wasDot = false
case '.':
if wasDot {
// two dots back to back is not legal
return labels, false
}
wasDot = true
labelLen := i - begin
if labelLen >= 1<<6 { // top two bits of length must be clear
return labels, false
}
// off can already (we're in a loop) be bigger than lenmsg
// this happens when a name isn't fully qualified
off += 1 + labelLen
if off > lenmsg {
return labels, false
}
labels++
begin = i + 1
default:
wasDot = false
}
}
return labels, true
} }
// IsSubDomain checks if child is indeed a child of the parent. If child and parent // IsSubDomain checks if child is indeed a child of the parent. If child and parent
@ -181,7 +257,7 @@ func IsSubDomain(parent, child string) bool {
// The checking is performed on the binary payload. // The checking is performed on the binary payload.
func IsMsg(buf []byte) error { func IsMsg(buf []byte) error {
// Header // Header
if len(buf) < 12 { if len(buf) < headerSize {
return errors.New("dns: bad message header") return errors.New("dns: bad message header")
} }
// Header: Opcode // Header: Opcode
@ -191,11 +267,18 @@ func IsMsg(buf []byte) error {
// IsFqdn checks if a domain name is fully qualified. // IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool { func IsFqdn(s string) bool {
l := len(s) s2 := strings.TrimSuffix(s, ".")
if l == 0 { if s == s2 {
return false return false
} }
return s[l-1] == '.'
i := strings.LastIndexFunc(s2, func(r rune) bool {
return r != '\\'
})
// Test whether we have an even number of escape sequences before
// the dot or none.
return (len(s2)-i)%2 != 0
} }
// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181. // IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.
@ -244,12 +327,19 @@ func ReverseAddr(addr string) (arpa string, err error) {
if ip == nil { if ip == nil {
return "", &Error{err: "unrecognized address: " + addr} return "", &Error{err: "unrecognized address: " + addr}
} }
if ip.To4() != nil { if v4 := ip.To4(); v4 != nil {
return strconv.Itoa(int(ip[15])) + "." + strconv.Itoa(int(ip[14])) + "." + strconv.Itoa(int(ip[13])) + "." + buf := make([]byte, 0, net.IPv4len*4+len("in-addr.arpa."))
strconv.Itoa(int(ip[12])) + ".in-addr.arpa.", nil // Add it, in reverse, to the buffer
for i := len(v4) - 1; i >= 0; i-- {
buf = strconv.AppendInt(buf, int64(v4[i]), 10)
buf = append(buf, '.')
}
// Append "in-addr.arpa." and return (buf already has the final .)
buf = append(buf, "in-addr.arpa."...)
return string(buf), nil
} }
// Must be IPv6 // Must be IPv6
buf := make([]byte, 0, len(ip)*4+len("ip6.arpa.")) buf := make([]byte, 0, net.IPv6len*4+len("ip6.arpa."))
// Add it, in reverse, to the buffer // Add it, in reverse, to the buffer
for i := len(ip) - 1; i >= 0; i-- { for i := len(ip) - 1; i >= 0; i-- {
v := ip[i] v := ip[i]
@ -273,8 +363,11 @@ func (t Type) String() string {
// String returns the string representation for the class c. // String returns the string representation for the class c.
func (c Class) String() string { func (c Class) String() string {
if c1, ok := ClassToString[uint16(c)]; ok { if s, ok := ClassToString[uint16(c)]; ok {
return c1 // Only emit mnemonics when they are unambiguous, specically ANY is in both.
if _, ok := StringToType[s]; !ok {
return s
}
} }
return "CLASS" + strconv.Itoa(int(c)) return "CLASS" + strconv.Itoa(int(c))
} }

71
vendor/github.com/miekg/dns/dns.go generated vendored
View File

@ -34,10 +34,30 @@ type RR interface {
// copy returns a copy of the RR // copy returns a copy of the RR
copy() RR copy() RR
// len returns the length (in octets) of the uncompressed RR in wire format.
len() int // len returns the length (in octets) of the compressed or uncompressed RR in wire format.
// pack packs an RR into wire format. //
pack([]byte, int, map[string]int, bool) (int, error) // If compression is nil, the uncompressed size will be returned, otherwise the compressed
// size will be returned and domain names will be added to the map for future compression.
len(off int, compression map[string]struct{}) int
// pack packs the records RDATA into wire format. The header will
// already have been packed into msg.
pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error)
// unpack unpacks an RR from wire format.
//
// This will only be called on a new and empty RR type with only the header populated. It
// will only be called if the record's RDATA is non-empty.
unpack(msg []byte, off int) (off1 int, err error)
// parse parses an RR from zone file format.
//
// This will only be called on a new and empty RR type with only the header populated.
parse(c *zlexer, origin, file string) *ParseError
// isDuplicate returns whether the two RRs are duplicates.
isDuplicate(r2 RR) bool
} }
// RR_Header is the header all DNS resource records share. // RR_Header is the header all DNS resource records share.
@ -55,16 +75,6 @@ func (h *RR_Header) Header() *RR_Header { return h }
// Just to implement the RR interface. // Just to implement the RR interface.
func (h *RR_Header) copy() RR { return nil } func (h *RR_Header) copy() RR { return nil }
func (h *RR_Header) copyHeader() *RR_Header {
r := new(RR_Header)
r.Name = h.Name
r.Rrtype = h.Rrtype
r.Class = h.Class
r.Ttl = h.Ttl
r.Rdlength = h.Rdlength
return r
}
func (h *RR_Header) String() string { func (h *RR_Header) String() string {
var s string var s string
@ -80,28 +90,45 @@ func (h *RR_Header) String() string {
return s return s
} }
func (h *RR_Header) len() int { func (h *RR_Header) len(off int, compression map[string]struct{}) int {
l := len(h.Name) + 1 l := domainNameLen(h.Name, off, compression, true)
l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2) l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2)
return l return l
} }
func (h *RR_Header) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) {
// RR_Header has no RDATA to pack.
return off, nil
}
func (h *RR_Header) unpack(msg []byte, off int) (int, error) {
panic("dns: internal error: unpack should never be called on RR_Header")
}
func (h *RR_Header) parse(c *zlexer, origin, file string) *ParseError {
panic("dns: internal error: parse should never be called on RR_Header")
}
// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597. // ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597.
func (rr *RFC3597) ToRFC3597(r RR) error { func (rr *RFC3597) ToRFC3597(r RR) error {
buf := make([]byte, r.len()*2) buf := make([]byte, Len(r)*2)
off, err := PackRR(r, buf, 0, nil, false) headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false)
if err != nil { if err != nil {
return err return err
} }
buf = buf[:off] buf = buf[:off]
if int(r.Header().Rdlength) > off {
return ErrBuf *rr = RFC3597{Hdr: *r.Header()}
rr.Hdr.Rdlength = uint16(off - headerEnd)
if noRdata(rr.Hdr) {
return nil
} }
rfc3597, _, err := unpackRFC3597(*r.Header(), buf, off-int(r.Header().Rdlength)) _, err = rr.unpack(buf, headerEnd)
if err != nil { if err != nil {
return err return err
} }
*rr = *rfc3597.(*RFC3597)
return nil return nil
} }

107
vendor/github.com/miekg/dns/dnssec.go generated vendored
View File

@ -67,12 +67,10 @@ var AlgorithmToString = map[uint8]string{
PRIVATEOID: "PRIVATEOID", PRIVATEOID: "PRIVATEOID",
} }
// StringToAlgorithm is the reverse of AlgorithmToString.
var StringToAlgorithm = reverseInt8(AlgorithmToString)
// AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's. // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's.
var AlgorithmToHash = map[uint8]crypto.Hash{ var AlgorithmToHash = map[uint8]crypto.Hash{
RSAMD5: crypto.MD5, // Deprecated in RFC 6725 RSAMD5: crypto.MD5, // Deprecated in RFC 6725
DSA: crypto.SHA1,
RSASHA1: crypto.SHA1, RSASHA1: crypto.SHA1,
RSASHA1NSEC3SHA1: crypto.SHA1, RSASHA1NSEC3SHA1: crypto.SHA1,
RSASHA256: crypto.SHA256, RSASHA256: crypto.SHA256,
@ -101,9 +99,6 @@ var HashToString = map[uint8]string{
SHA512: "SHA512", SHA512: "SHA512",
} }
// StringToHash is a map of names to hash IDs.
var StringToHash = reverseInt8(HashToString)
// DNSKEY flag values. // DNSKEY flag values.
const ( const (
SEP = 1 SEP = 1
@ -172,7 +167,7 @@ func (k *DNSKEY) KeyTag() uint16 {
keytag += int(v) << 8 keytag += int(v) << 8
} }
} }
keytag += (keytag >> 16) & 0xFFFF keytag += keytag >> 16 & 0xFFFF
keytag &= 0xFFFF keytag &= 0xFFFF
} }
return uint16(keytag) return uint16(keytag)
@ -239,7 +234,7 @@ func (k *DNSKEY) ToDS(h uint8) *DS {
// ToCDNSKEY converts a DNSKEY record to a CDNSKEY record. // ToCDNSKEY converts a DNSKEY record to a CDNSKEY record.
func (k *DNSKEY) ToCDNSKEY() *CDNSKEY { func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
c := &CDNSKEY{DNSKEY: *k} c := &CDNSKEY{DNSKEY: *k}
c.Hdr = *k.Hdr.copyHeader() c.Hdr = k.Hdr
c.Hdr.Rrtype = TypeCDNSKEY c.Hdr.Rrtype = TypeCDNSKEY
return c return c
} }
@ -247,7 +242,7 @@ func (k *DNSKEY) ToCDNSKEY() *CDNSKEY {
// ToCDS converts a DS record to a CDS record. // ToCDS converts a DS record to a CDS record.
func (d *DS) ToCDS() *CDS { func (d *DS) ToCDS() *CDS {
c := &CDS{DS: *d} c := &CDS{DS: *d}
c.Hdr = *d.Hdr.copyHeader() c.Hdr = d.Hdr
c.Hdr.Rrtype = TypeCDS c.Hdr.Rrtype = TypeCDS
return c return c
} }
@ -267,16 +262,17 @@ func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error {
return ErrKey return ErrKey
} }
h0 := rrset[0].Header()
rr.Hdr.Rrtype = TypeRRSIG rr.Hdr.Rrtype = TypeRRSIG
rr.Hdr.Name = rrset[0].Header().Name rr.Hdr.Name = h0.Name
rr.Hdr.Class = rrset[0].Header().Class rr.Hdr.Class = h0.Class
if rr.OrigTtl == 0 { // If set don't override if rr.OrigTtl == 0 { // If set don't override
rr.OrigTtl = rrset[0].Header().Ttl rr.OrigTtl = h0.Ttl
} }
rr.TypeCovered = rrset[0].Header().Rrtype rr.TypeCovered = h0.Rrtype
rr.Labels = uint8(CountLabel(rrset[0].Header().Name)) rr.Labels = uint8(CountLabel(h0.Name))
if strings.HasPrefix(rrset[0].Header().Name, "*") { if strings.HasPrefix(h0.Name, "*") {
rr.Labels-- // wildcard, remove from label count rr.Labels-- // wildcard, remove from label count
} }
@ -400,7 +396,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
if rr.Algorithm != k.Algorithm { if rr.Algorithm != k.Algorithm {
return ErrKey return ErrKey
} }
if strings.ToLower(rr.SignerName) != strings.ToLower(k.Hdr.Name) { if !strings.EqualFold(rr.SignerName, k.Hdr.Name) {
return ErrKey return ErrKey
} }
if k.Protocol != 3 { if k.Protocol != 3 {
@ -410,10 +406,7 @@ func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error {
// IsRRset checked that we have at least one RR and that the RRs in // IsRRset checked that we have at least one RR and that the RRs in
// the set have consistent type, class, and name. Also check that type and // the set have consistent type, class, and name. Also check that type and
// class matches the RRSIG record. // class matches the RRSIG record.
if rrset[0].Header().Class != rr.Hdr.Class { if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered {
return ErrRRset
}
if rrset[0].Header().Rrtype != rr.TypeCovered {
return ErrRRset return ErrRRset
} }
@ -511,8 +504,8 @@ func (rr *RRSIG) ValidityPeriod(t time.Time) bool {
} }
modi := (int64(rr.Inception) - utc) / year68 modi := (int64(rr.Inception) - utc) / year68
mode := (int64(rr.Expiration) - utc) / year68 mode := (int64(rr.Expiration) - utc) / year68
ti := int64(rr.Inception) + (modi * year68) ti := int64(rr.Inception) + modi*year68
te := int64(rr.Expiration) + (mode * year68) te := int64(rr.Expiration) + mode*year68
return ti <= utc && utc <= te return ti <= utc && utc <= te
} }
@ -532,6 +525,11 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
return nil return nil
} }
if len(keybuf) < 1+1+64 {
// Exponent must be at least 1 byte and modulus at least 64
return nil
}
// RFC 2537/3110, section 2. RSA Public KEY Resource Records // RFC 2537/3110, section 2. RSA Public KEY Resource Records
// Length is in the 0th byte, unless its zero, then it // Length is in the 0th byte, unless its zero, then it
// it in bytes 1 and 2 and its a 16 bit number // it in bytes 1 and 2 and its a 16 bit number
@ -541,25 +539,35 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
explen = uint16(keybuf[1])<<8 | uint16(keybuf[2]) explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
keyoff = 3 keyoff = 3
} }
pubkey := new(rsa.PublicKey)
pubkey.N = big.NewInt(0) if explen > 4 || explen == 0 || keybuf[keyoff] == 0 {
shift := uint64((explen - 1) * 8) // Exponent larger than supported by the crypto package,
expo := uint64(0) // empty, or contains prohibited leading zero.
for i := int(explen - 1); i > 0; i-- {
expo += uint64(keybuf[keyoff+i]) << shift
shift -= 8
}
// Remainder
expo += uint64(keybuf[keyoff])
if expo > (2<<31)+1 {
// Larger expo than supported.
// println("dns: F5 primes (or larger) are not supported")
return nil return nil
} }
pubkey.E = int(expo)
pubkey.N.SetBytes(keybuf[keyoff+int(explen):]) modoff := keyoff + int(explen)
modlen := len(keybuf) - modoff
if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 {
// Modulus is too small, large, or contains prohibited leading zero.
return nil
}
pubkey := new(rsa.PublicKey)
var expo uint64
// The exponent of length explen is between keyoff and modoff.
for _, v := range keybuf[keyoff:modoff] {
expo <<= 8
expo |= uint64(v)
}
if expo > 1<<31-1 {
// Larger exponent than supported by the crypto package.
return nil
}
pubkey.E = int(expo)
pubkey.N = new(big.Int).SetBytes(keybuf[modoff:])
return pubkey return pubkey
} }
@ -584,10 +592,8 @@ func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey {
return nil return nil
} }
} }
pubkey.X = big.NewInt(0) pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2])
pubkey.X.SetBytes(keybuf[:len(keybuf)/2]) pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:])
pubkey.Y = big.NewInt(0)
pubkey.Y.SetBytes(keybuf[len(keybuf)/2:])
return pubkey return pubkey
} }
@ -608,10 +614,10 @@ func (k *DNSKEY) publicKeyDSA() *dsa.PublicKey {
p, keybuf := keybuf[:size], keybuf[size:] p, keybuf := keybuf[:size], keybuf[size:]
g, y := keybuf[:size], keybuf[size:] g, y := keybuf[:size], keybuf[size:]
pubkey := new(dsa.PublicKey) pubkey := new(dsa.PublicKey)
pubkey.Parameters.Q = big.NewInt(0).SetBytes(q) pubkey.Parameters.Q = new(big.Int).SetBytes(q)
pubkey.Parameters.P = big.NewInt(0).SetBytes(p) pubkey.Parameters.P = new(big.Int).SetBytes(p)
pubkey.Parameters.G = big.NewInt(0).SetBytes(g) pubkey.Parameters.G = new(big.Int).SetBytes(g)
pubkey.Y = big.NewInt(0).SetBytes(y) pubkey.Y = new(big.Int).SetBytes(y)
return pubkey return pubkey
} }
@ -641,15 +647,16 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
wires := make(wireSlice, len(rrset)) wires := make(wireSlice, len(rrset))
for i, r := range rrset { for i, r := range rrset {
r1 := r.copy() r1 := r.copy()
r1.Header().Ttl = s.OrigTtl h := r1.Header()
labels := SplitDomainName(r1.Header().Name) h.Ttl = s.OrigTtl
labels := SplitDomainName(h.Name)
// 6.2. Canonical RR Form. (4) - wildcards // 6.2. Canonical RR Form. (4) - wildcards
if len(labels) > int(s.Labels) { if len(labels) > int(s.Labels) {
// Wildcard // Wildcard
r1.Header().Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "." h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "."
} }
// RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase // RFC 4034: 6.2. Canonical RR Form. (2) - domain name to lowercase
r1.Header().Name = strings.ToLower(r1.Header().Name) h.Name = strings.ToLower(h.Name)
// 6.2. Canonical RR Form. (3) - domain rdata to lowercase. // 6.2. Canonical RR Form. (3) - domain rdata to lowercase.
// NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR, // NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
// HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, // HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
@ -707,7 +714,7 @@ func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) {
x.Target = strings.ToLower(x.Target) x.Target = strings.ToLower(x.Target)
} }
// 6.2. Canonical RR Form. (5) - origTTL // 6.2. Canonical RR Form. (5) - origTTL
wire := make([]byte, r1.len()+1) // +1 to be safe(r) wire := make([]byte, Len(r1)+1) // +1 to be safe(r)
off, err1 := PackRR(r1, wire, 0, nil, false) off, err1 := PackRR(r1, wire, 0, nil, false)
if err1 != nil { if err1 != nil {
return nil, err1 return nil, err1

View File

@ -1,7 +1,7 @@
package dns package dns
import ( import (
"bytes" "bufio"
"crypto" "crypto"
"crypto/dsa" "crypto/dsa"
"crypto/ecdsa" "crypto/ecdsa"
@ -109,21 +109,16 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
} }
switch k { switch k {
case "modulus": case "modulus":
p.PublicKey.N = big.NewInt(0) p.PublicKey.N = new(big.Int).SetBytes(v1)
p.PublicKey.N.SetBytes(v1)
case "publicexponent": case "publicexponent":
i := big.NewInt(0) i := new(big.Int).SetBytes(v1)
i.SetBytes(v1)
p.PublicKey.E = int(i.Int64()) // int64 should be large enough p.PublicKey.E = int(i.Int64()) // int64 should be large enough
case "privateexponent": case "privateexponent":
p.D = big.NewInt(0) p.D = new(big.Int).SetBytes(v1)
p.D.SetBytes(v1)
case "prime1": case "prime1":
p.Primes[0] = big.NewInt(0) p.Primes[0] = new(big.Int).SetBytes(v1)
p.Primes[0].SetBytes(v1)
case "prime2": case "prime2":
p.Primes[1] = big.NewInt(0) p.Primes[1] = new(big.Int).SetBytes(v1)
p.Primes[1].SetBytes(v1)
} }
case "exponent1", "exponent2", "coefficient": case "exponent1", "exponent2", "coefficient":
// not used in Go (yet) // not used in Go (yet)
@ -136,7 +131,7 @@ func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) {
func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) { func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
p := new(dsa.PrivateKey) p := new(dsa.PrivateKey)
p.X = big.NewInt(0) p.X = new(big.Int)
for k, v := range m { for k, v := range m {
switch k { switch k {
case "private_value(x)": case "private_value(x)":
@ -154,7 +149,7 @@ func readPrivateKeyDSA(m map[string]string) (*dsa.PrivateKey, error) {
func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) { func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) {
p := new(ecdsa.PrivateKey) p := new(ecdsa.PrivateKey)
p.D = big.NewInt(0) p.D = new(big.Int)
// TODO: validate that the required flags are present // TODO: validate that the required flags are present
for k, v := range m { for k, v := range m {
switch k { switch k {
@ -181,22 +176,10 @@ func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if len(p1) != 32 { if len(p1) != ed25519.SeedSize {
return nil, ErrPrivKey return nil, ErrPrivKey
} }
// RFC 8080 and Golang's x/crypto/ed25519 differ as to how the p = ed25519.NewKeyFromSeed(p1)
// private keys are represented. RFC 8080 specifies that private
// keys be stored solely as the seed value (p1 above) while the
// ed25519 package represents them as the seed value concatenated
// to the public key, which is derived from the seed value.
//
// ed25519.GenerateKey reads exactly 32 bytes from the passed in
// io.Reader and uses them as the seed. It also derives the
// public key and produces a compatible private key.
_, p, err = ed25519.GenerateKey(bytes.NewReader(p1))
if err != nil {
return nil, err
}
case "created", "publish", "activate": case "created", "publish", "activate":
/* not used in Go (yet) */ /* not used in Go (yet) */
} }
@ -207,23 +190,12 @@ func readPrivateKeyED25519(m map[string]string) (ed25519.PrivateKey, error) {
// parseKey reads a private key from r. It returns a map[string]string, // parseKey reads a private key from r. It returns a map[string]string,
// with the key-value pairs, or an error when the file is not correct. // with the key-value pairs, or an error when the file is not correct.
func parseKey(r io.Reader, file string) (map[string]string, error) { func parseKey(r io.Reader, file string) (map[string]string, error) {
s, cancel := scanInit(r)
m := make(map[string]string) m := make(map[string]string)
c := make(chan lex) var k string
k := ""
defer func() { c := newKLexer(r)
cancel()
// zlexer can send up to two tokens, the next one and possibly 1 remainders. for l, ok := c.Next(); ok; l, ok = c.Next() {
// Do a non-blocking read.
_, ok := <-c
_, ok = <-c
if !ok {
// too bad
}
}()
// Start the lexer
go klexer(s, c)
for l := range c {
// It should alternate // It should alternate
switch l.value { switch l.value {
case zKey: case zKey:
@ -232,41 +204,111 @@ func parseKey(r io.Reader, file string) (map[string]string, error) {
if k == "" { if k == "" {
return nil, &ParseError{file, "no private key seen", l} return nil, &ParseError{file, "no private key seen", l}
} }
//println("Setting", strings.ToLower(k), "to", l.token, "b")
m[strings.ToLower(k)] = l.token m[strings.ToLower(k)] = l.token
k = "" k = ""
} }
} }
// Surface any read errors from r.
if err := c.Err(); err != nil {
return nil, &ParseError{file: file, err: err.Error()}
}
return m, nil return m, nil
} }
// klexer scans the sourcefile and returns tokens on the channel c. type klexer struct {
func klexer(s *scan, c chan lex) { br io.ByteReader
var l lex
str := "" // Hold the current read text readErr error
commt := false
key := true line int
x, err := s.tokenText() column int
defer close(c)
for err == nil { key bool
l.column = s.position.Column
l.line = s.position.Line eol bool // end-of-line
}
func newKLexer(r io.Reader) *klexer {
br, ok := r.(io.ByteReader)
if !ok {
br = bufio.NewReaderSize(r, 1024)
}
return &klexer{
br: br,
line: 1,
key: true,
}
}
func (kl *klexer) Err() error {
if kl.readErr == io.EOF {
return nil
}
return kl.readErr
}
// readByte returns the next byte from the input
func (kl *klexer) readByte() (byte, bool) {
if kl.readErr != nil {
return 0, false
}
c, err := kl.br.ReadByte()
if err != nil {
kl.readErr = err
return 0, false
}
// delay the newline handling until the next token is delivered,
// fixes off-by-one errors when reporting a parse error.
if kl.eol {
kl.line++
kl.column = 0
kl.eol = false
}
if c == '\n' {
kl.eol = true
} else {
kl.column++
}
return c, true
}
func (kl *klexer) Next() (lex, bool) {
var (
l lex
str strings.Builder
commt bool
)
for x, ok := kl.readByte(); ok; x, ok = kl.readByte() {
l.line, l.column = kl.line, kl.column
switch x { switch x {
case ':': case ':':
if commt { if commt || !kl.key {
break break
} }
l.token = str
if key { kl.key = false
l.value = zKey
c <- l // Next token is a space, eat it
// Next token is a space, eat it kl.readByte()
s.tokenText()
key = false l.value = zKey
str = "" l.token = str.String()
} else { return l, true
l.value = zValue
}
case ';': case ';':
commt = true commt = true
case '\n': case '\n':
@ -274,24 +316,37 @@ func klexer(s *scan, c chan lex) {
// Reset a comment // Reset a comment
commt = false commt = false
} }
if kl.key && str.Len() == 0 {
// ignore empty lines
break
}
kl.key = true
l.value = zValue l.value = zValue
l.token = str l.token = str.String()
c <- l return l, true
str = ""
commt = false
key = true
default: default:
if commt { if commt {
break break
} }
str += string(x)
str.WriteByte(x)
} }
x, err = s.tokenText()
} }
if len(str) > 0 {
if kl.readErr != nil && kl.readErr != io.EOF {
// Don't return any tokens after a read error occurs.
return lex{value: zEOF}, false
}
if str.Len() > 0 {
// Send remainder // Send remainder
l.token = str
l.value = zValue l.value = zValue
c <- l l.token = str.String()
return l, true
} }
return lex{value: zEOF}, false
} }

View File

@ -13,6 +13,8 @@ import (
const format = "Private-key-format: v1.3\n" const format = "Private-key-format: v1.3\n"
var bigIntOne = big.NewInt(1)
// PrivateKeyString converts a PrivateKey to a string. This string has the same // PrivateKeyString converts a PrivateKey to a string. This string has the same
// format as the private-key-file of BIND9 (Private-key-format: v1.3). // format as the private-key-file of BIND9 (Private-key-format: v1.3).
// It needs some info from the key (the algorithm), so its a method of the DNSKEY // It needs some info from the key (the algorithm), so its a method of the DNSKEY
@ -31,12 +33,11 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
prime2 := toBase64(p.Primes[1].Bytes()) prime2 := toBase64(p.Primes[1].Bytes())
// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm // Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm
// and from: http://code.google.com/p/go/issues/detail?id=987 // and from: http://code.google.com/p/go/issues/detail?id=987
one := big.NewInt(1) p1 := new(big.Int).Sub(p.Primes[0], bigIntOne)
p1 := big.NewInt(0).Sub(p.Primes[0], one) q1 := new(big.Int).Sub(p.Primes[1], bigIntOne)
q1 := big.NewInt(0).Sub(p.Primes[1], one) exp1 := new(big.Int).Mod(p.D, p1)
exp1 := big.NewInt(0).Mod(p.D, p1) exp2 := new(big.Int).Mod(p.D, q1)
exp2 := big.NewInt(0).Mod(p.D, q1) coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0])
coeff := big.NewInt(0).ModInverse(p.Primes[1], p.Primes[0])
exponent1 := toBase64(exp1.Bytes()) exponent1 := toBase64(exp1.Bytes())
exponent2 := toBase64(exp2.Bytes()) exponent2 := toBase64(exp2.Bytes())
@ -82,7 +83,7 @@ func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string {
"Public_value(y): " + pub + "\n" "Public_value(y): " + pub + "\n"
case ed25519.PrivateKey: case ed25519.PrivateKey:
private := toBase64(p[:32]) private := toBase64(p.Seed())
return format + return format +
"Algorithm: " + algorithm + "\n" + "Algorithm: " + algorithm + "\n" +
"PrivateKey: " + private + "\n" "PrivateKey: " + private + "\n"

111
vendor/github.com/miekg/dns/doc.go generated vendored
View File

@ -1,20 +1,20 @@
/* /*
Package dns implements a full featured interface to the Domain Name System. Package dns implements a full featured interface to the Domain Name System.
Server- and client-side programming is supported. Both server- and client-side programming is supported. The package allows
The package allows complete control over what is sent out to the DNS. The package complete control over what is sent out to the DNS. The API follows the
API follows the less-is-more principle, by presenting a small, clean interface. less-is-more principle, by presenting a small, clean interface.
The package dns supports (asynchronous) querying/replying, incoming/outgoing zone transfers, It supports (asynchronous) querying/replying, incoming/outgoing zone transfers,
TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing. TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing.
Note that domain names MUST be fully qualified, before sending them, unqualified
Note that domain names MUST be fully qualified before sending them, unqualified
names in a message will result in a packing failure. names in a message will result in a packing failure.
Resource records are native types. They are not stored in wire format. Resource records are native types. They are not stored in wire format. Basic
Basic usage pattern for creating a new resource record: usage pattern for creating a new resource record:
r := new(dns.MX) r := new(dns.MX)
r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600}
Class: dns.ClassINET, Ttl: 3600}
r.Preference = 10 r.Preference = 10
r.Mx = "mx.miek.nl." r.Mx = "mx.miek.nl."
@ -30,8 +30,8 @@ Or even:
mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek") mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek")
In the DNS messages are exchanged, these messages contain resource In the DNS messages are exchanged, these messages contain resource records
records (sets). Use pattern for creating a message: (sets). Use pattern for creating a message:
m := new(dns.Msg) m := new(dns.Msg)
m.SetQuestion("miek.nl.", dns.TypeMX) m.SetQuestion("miek.nl.", dns.TypeMX)
@ -40,8 +40,8 @@ Or when not certain if the domain name is fully qualified:
m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX) m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX)
The message m is now a message with the question section set to ask The message m is now a message with the question section set to ask the MX
the MX records for the miek.nl. zone. records for the miek.nl. zone.
The following is slightly more verbose, but more flexible: The following is slightly more verbose, but more flexible:
@ -51,9 +51,8 @@ The following is slightly more verbose, but more flexible:
m1.Question = make([]dns.Question, 1) m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET} m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET}
After creating a message it can be sent. After creating a message it can be sent. Basic use pattern for synchronous
Basic use pattern for synchronous querying the DNS at a querying the DNS at a server configured on 127.0.0.1 and port 53:
server configured on 127.0.0.1 and port 53:
c := new(dns.Client) c := new(dns.Client)
in, rtt, err := c.Exchange(m1, "127.0.0.1:53") in, rtt, err := c.Exchange(m1, "127.0.0.1:53")
@ -73,11 +72,11 @@ and port to use for the connection:
Port: 12345, Port: 12345,
Zone: "", Zone: "",
} }
d := net.Dialer{ c.Dialer := &net.Dialer{
Timeout: 200 * time.Millisecond, Timeout: 200 * time.Millisecond,
LocalAddr: &laddr, LocalAddr: &laddr,
} }
in, rtt, err := c.ExchangeWithDialer(&d, m1, "8.8.8.8:53") in, rtt, err := c.Exchange(m1, "8.8.8.8:53")
If these "advanced" features are not needed, a simple UDP query can be sent, If these "advanced" features are not needed, a simple UDP query can be sent,
with: with:
@ -99,25 +98,24 @@ the Answer section:
Domain Name and TXT Character String Representations Domain Name and TXT Character String Representations
Both domain names and TXT character strings are converted to presentation Both domain names and TXT character strings are converted to presentation form
form both when unpacked and when converted to strings. both when unpacked and when converted to strings.
For TXT character strings, tabs, carriage returns and line feeds will be For TXT character strings, tabs, carriage returns and line feeds will be
converted to \t, \r and \n respectively. Back slashes and quotations marks converted to \t, \r and \n respectively. Back slashes and quotations marks will
will be escaped. Bytes below 32 and above 127 will be converted to \DDD be escaped. Bytes below 32 and above 127 will be converted to \DDD form.
form.
For domain names, in addition to the above rules brackets, periods, For domain names, in addition to the above rules brackets, periods, spaces,
spaces, semicolons and the at symbol are escaped. semicolons and the at symbol are escaped.
DNSSEC DNSSEC
DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses
uses public key cryptography to sign resource records. The public key cryptography to sign resource records. The public keys are stored in
public keys are stored in DNSKEY records and the signatures in RRSIG records. DNSKEY records and the signatures in RRSIG records.
Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) bit Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK)
to a request. bit to a request.
m := new(dns.Msg) m := new(dns.Msg)
m.SetEdns0(4096, true) m.SetEdns0(4096, true)
@ -126,9 +124,9 @@ Signature generation, signature verification and key generation are all supporte
DYNAMIC UPDATES DYNAMIC UPDATES
Dynamic updates reuses the DNS message format, but renames three of Dynamic updates reuses the DNS message format, but renames three of the
the sections. Question is Zone, Answer is Prerequisite, Authority is sections. Question is Zone, Answer is Prerequisite, Authority is Update, only
Update, only the Additional is not renamed. See RFC 2136 for the gory details. the Additional is not renamed. See RFC 2136 for the gory details.
You can set a rather complex set of rules for the existence of absence of You can set a rather complex set of rules for the existence of absence of
certain resource records or names in a zone to specify if resource records certain resource records or names in a zone to specify if resource records
@ -145,10 +143,9 @@ DNS function shows which functions exist to specify the prerequisites.
NONE rrset empty RRset does not exist dns.RRsetNotUsed NONE rrset empty RRset does not exist dns.RRsetNotUsed
zone rrset rr RRset exists (value dep) dns.Used zone rrset rr RRset exists (value dep) dns.Used
The prerequisite section can also be left empty. The prerequisite section can also be left empty. If you have decided on the
If you have decided on the prerequisites you can tell what RRs should prerequisites you can tell what RRs should be added or deleted. The next table
be added or deleted. The next table shows the options you have and shows the options you have and what functions to call.
what functions to call.
3.4.2.6 - Table Of Metavalues Used In Update Section 3.4.2.6 - Table Of Metavalues Used In Update Section
@ -181,10 +178,10 @@ changes to the RRset after calling SetTsig() the signature will be incorrect.
... ...
// When sending the TSIG RR is calculated and filled in before sending // When sending the TSIG RR is calculated and filled in before sending
When requesting an zone transfer (almost all TSIG usage is when requesting zone transfers), with When requesting an zone transfer (almost all TSIG usage is when requesting zone
TSIG, this is the basic use pattern. In this example we request an AXFR for transfers), with TSIG, this is the basic use pattern. In this example we
miek.nl. with TSIG key named "axfr." and secret "so6ZGir4GPAqINNh9U5c3A==" request an AXFR for miek.nl. with TSIG key named "axfr." and secret
and using the server 176.58.119.54: "so6ZGir4GPAqINNh9U5c3A==" and using the server 176.58.119.54:
t := new(dns.Transfer) t := new(dns.Transfer)
m := new(dns.Msg) m := new(dns.Msg)
@ -194,8 +191,8 @@ and using the server 176.58.119.54:
c, err := t.In(m, "176.58.119.54:53") c, err := t.In(m, "176.58.119.54:53")
for r := range c { ... } for r := range c { ... }
You can now read the records from the transfer as they come in. Each envelope is checked with TSIG. You can now read the records from the transfer as they come in. Each envelope
If something is not correct an error is returned. is checked with TSIG. If something is not correct an error is returned.
Basic use pattern validating and replying to a message that has TSIG set. Basic use pattern validating and replying to a message that has TSIG set.
@ -220,29 +217,30 @@ Basic use pattern validating and replying to a message that has TSIG set.
PRIVATE RRS PRIVATE RRS
RFC 6895 sets aside a range of type codes for private use. This range RFC 6895 sets aside a range of type codes for private use. This range is 65,280
is 65,280 - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these
can be used, before requesting an official type code from IANA. can be used, before requesting an official type code from IANA.
see http://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more See https://miek.nl/2014/September/21/idn-and-private-rr-in-go-dns/ for more
information. information.
EDNS0 EDNS0
EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by
by RFC 6891. It defines an new RR type, the OPT RR, which is then completely RFC 6891. It defines an new RR type, the OPT RR, which is then completely
abused. abused.
Basic use pattern for creating an (empty) OPT RR: Basic use pattern for creating an (empty) OPT RR:
o := new(dns.OPT) o := new(dns.OPT)
o.Hdr.Name = "." // MUST be the root zone, per definition. o.Hdr.Name = "." // MUST be the root zone, per definition.
o.Hdr.Rrtype = dns.TypeOPT o.Hdr.Rrtype = dns.TypeOPT
The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces.
interfaces. Currently only a few have been standardized: EDNS0_NSID Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and
(RFC 5001) and EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note EDNS0_SUBNET (draft-vandergaast-edns-client-subnet-02). Note that these options
that these options may be combined in an OPT RR. may be combined in an OPT RR. Basic use pattern for a server to check if (and
Basic use pattern for a server to check if (and which) options are set: which) options are set:
// o is a dns.OPT // o is a dns.OPT
for _, s := range o.Option { for _, s := range o.Option {
@ -262,10 +260,9 @@ From RFC 2931:
... protection for glue records, DNS requests, protection for message headers ... protection for glue records, DNS requests, protection for message headers
on requests and responses, and protection of the overall integrity of a response. on requests and responses, and protection of the overall integrity of a response.
It works like TSIG, except that SIG(0) uses public key cryptography, instead of the shared It works like TSIG, except that SIG(0) uses public key cryptography, instead of
secret approach in TSIG. the shared secret approach in TSIG. Supported algorithms: DSA, ECDSAP256SHA256,
Supported algorithms: DSA, ECDSAP256SHA256, ECDSAP384SHA384, RSASHA1, RSASHA256 and ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512.
RSASHA512.
Signing subsequent messages in multi-message sessions is not implemented. Signing subsequent messages in multi-message sessions is not implemented.
*/ */

38
vendor/github.com/miekg/dns/duplicate.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
package dns
//go:generate go run duplicate_generate.go
// IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL.
// So this means the header data is equal *and* the RDATA is the same. Return true
// is so, otherwise false.
// It's is a protocol violation to have identical RRs in a message.
func IsDuplicate(r1, r2 RR) bool {
// Check whether the record header is identical.
if !r1.Header().isDuplicate(r2.Header()) {
return false
}
// Check whether the RDATA is identical.
return r1.isDuplicate(r2)
}
func (r1 *RR_Header) isDuplicate(_r2 RR) bool {
r2, ok := _r2.(*RR_Header)
if !ok {
return false
}
if r1.Class != r2.Class {
return false
}
if r1.Rrtype != r2.Rrtype {
return false
}
if !isDuplicateName(r1.Name, r2.Name) {
return false
}
// ignore TTL
return true
}
// isDuplicateName checks if the domain names s1 and s2 are equal.
func isDuplicateName(s1, s2 string) bool { return equal(s1, s2) }

Some files were not shown because too many files have changed in this diff Show More