Updating dependencies.
Этот коммит содержится в:
169
Gopkg.lock
сгенерированный
169
Gopkg.lock
сгенерированный
@@ -42,12 +42,12 @@
|
|||||||
version = "v3.5.1"
|
version = "v3.5.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
digest = "1:86909a5b1e4522ad763f86327cfa65e51d7eb838d4adb3d6f68069fede181122"
|
||||||
digest = "1:cc439e1d9d8cff3d575642f5401033b00f2b8d0cd9f859db45604701c990879a"
|
|
||||||
name = "github.com/corpix/uarand"
|
name = "github.com/corpix/uarand"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "2b8494104d86337cdd41d0a49cbed8e4583c0ab4"
|
revision = "37c9140f52f6bf4998ff7617c456d554d6a2dc2f"
|
||||||
|
version = "v0.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
|
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
|
||||||
@@ -74,12 +74,12 @@
|
|||||||
version = "v1.5.0"
|
version = "v1.5.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
|
||||||
digest = "1:6f9339c912bbdda81302633ad7e99a28dfa5a639c864061f1929510a9a64aa74"
|
digest = "1:6f9339c912bbdda81302633ad7e99a28dfa5a639c864061f1929510a9a64aa74"
|
||||||
name = "github.com/dustin/go-humanize"
|
name = "github.com/dustin/go-humanize"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "9f541cc9db5d55bce703bd99987c9d5cb8eea45e"
|
revision = "9f541cc9db5d55bce703bd99987c9d5cb8eea45e"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -98,23 +98,23 @@
|
|||||||
version = "v1.4.7"
|
version = "v1.4.7"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:5abd6a22805b1919f6a6bca0ae58b13cef1f3412812f38569978f43ef02743d4"
|
digest = "1:6295a00553abd595aa3c647d36b58eae91410f107ad554873aaaf7c71ca55855"
|
||||||
name = "github.com/go-ini/ini"
|
name = "github.com/go-ini/ini"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "5cf292cae48347c2490ac1a58fe36735fb78df7e"
|
revision = "ffaaebdac6e54ce73b4e196b8406920921304ec9"
|
||||||
version = "v1.38.2"
|
version = "v1.39.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:93aaeb913621a3a53aaa78592c00f46d63e3bb0ea76e2d9b07327b50959a5778"
|
digest = "1:0b246ee52301dd5ff243a5511c07c5a3d9a44eaa682c2a5554be4206b1881b1f"
|
||||||
name = "github.com/go-ldap/ldap"
|
name = "github.com/go-ldap/ldap"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "bb7a9ca6e4fbc2129e3db588a34bc970ffe811a9"
|
revision = "5c2c0f997205c29de14cb6c35996370c2c5dfab1"
|
||||||
version = "v2.5.1"
|
version = "v3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:7c2fd446293ff7799cc496d3446e674ee67902d119f244de645caf95dff1bb98"
|
digest = "1:34a9a60fade37f8009ed4a19e02924198aba3eabfcc120ee5c6002b7de17212d"
|
||||||
name = "github.com/go-redis/redis"
|
name = "github.com/go-redis/redis"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@@ -127,16 +127,16 @@
|
|||||||
"internal/util",
|
"internal/util",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "f3bba01df2026fc865f7782948845db9cf44cf23"
|
revision = "b3d9bf10f6666b2ee5100a6f3f84f4caf3b4e37d"
|
||||||
version = "v6.14.1"
|
version = "v6.14.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:adea5a94903eb4384abef30f3d878dc9ff6b6b5b0722da25b82e5169216dfb61"
|
digest = "1:ec6f9bf5e274c833c911923c9193867f3f18788c461f76f05f62bb1510e0ae65"
|
||||||
name = "github.com/go-sql-driver/mysql"
|
name = "github.com/go-sql-driver/mysql"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
revision = "72cd26f257d44c1114970e19afddcd812016007e"
|
||||||
version = "v1.4.0"
|
version = "v1.4.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -165,12 +165,12 @@
|
|||||||
version = "v1.2.0"
|
version = "v1.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:3a26588bc48b96825977c1b3df964f8fd842cd6860cc26370588d3563433cf11"
|
digest = "1:236d7e1bdb50d8f68559af37dbcf9d142d56b431c9b2176d41e2a009b664cda8"
|
||||||
name = "github.com/google/uuid"
|
name = "github.com/google/uuid"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494"
|
revision = "9b3b1e0f5f99ae461456d768e7d301a7acdaa2d8"
|
||||||
version = "v1.0.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
|
digest = "1:c79fb010be38a59d657c48c6ba1d003a8aa651fa56b579d959d74573b7dff8e1"
|
||||||
@@ -260,11 +260,11 @@
|
|||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:20f78c1cf1b6fe6c55ba1407350d6fc7dc77d1591f8106ba693c28014a1a1b37"
|
digest = "1:12fd3b73c54592003bf5214e9efff0092abaa173eedfc5390ed17431ed5dde1e"
|
||||||
name = "github.com/hashicorp/go-plugin"
|
name = "github.com/hashicorp/go-plugin"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "a4620f9913d19f03a6bf19b2f304daaaf83ea130"
|
revision = "54b6ff97d8180dbbd93d2010dd4a92c86f604bb8"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -306,11 +306,11 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:70e2df69879bd481a620b103b21940a09c61dc7727c9193423509c0507b052d0"
|
digest = "1:627c9500c0e9631be1aa484dee9b76607fed8edaa6ce4f57f04d3d63960575a8"
|
||||||
name = "github.com/hashicorp/memberlist"
|
name = "github.com/hashicorp/memberlist"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "b195c8e4fcc6284fff1583fd6ab09e68ca207551"
|
revision = "2072f3a3ff4b7b3d830be77678d5d4b978362bc4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -318,7 +318,7 @@
|
|||||||
name = "github.com/hashicorp/yamux"
|
name = "github.com/hashicorp/yamux"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "7221087c3d281fda5f794e28c2ea4c6e4d5c4558"
|
revision = "2f1d1f20f75d5404f53b9edf6b53ed5505508675"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -353,12 +353,12 @@
|
|||||||
revision = "1d33003b386959af197ba96475f198c114627b5e"
|
revision = "1d33003b386959af197ba96475f198c114627b5e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
digest = "1:0a69a1c0db3591fcefb47f115b224592c8dfa4368b7ba9fae509d5e16cdc95c8"
|
||||||
digest = "1:f44d34fda864bed6d6c71514cd40b2ee097e6e67f745d5d014113e1faa5af8b7"
|
|
||||||
name = "github.com/konsorten/go-windows-terminal-sequences"
|
name = "github.com/konsorten/go-windows-terminal-sequences"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "b729f2633dfe35f4d1d8a32385f6685610ce1cb5"
|
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
|
||||||
|
version = "v1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:8ef506fc2bb9ced9b151dafa592d4046063d744c646c1bbe801982ce87e4bc24"
|
digest = "1:8ef506fc2bb9ced9b151dafa592d4046063d744c646c1bbe801982ce87e4bc24"
|
||||||
@@ -414,11 +414,11 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "mattermost"
|
branch = "mattermost"
|
||||||
digest = "1:184692ed2b6b7d604bfe9d0d43a95cd0e0d9872b3dc49a6cb3c11a231bd9788d"
|
digest = "1:c6cbc44e897fdfaae297ca38aab2d6d62867761bdf811af0225bfb8b9d95e0f2"
|
||||||
name = "github.com/mattermost/viper"
|
name = "github.com/mattermost/viper"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "362ff1e71044349d56d37d8b75cd317bff8369b9"
|
revision = "f99c30686b8675673ed42548816de2b0ff751c01"
|
||||||
source = "https://github.com/mattermost/viper"
|
source = "https://github.com/mattermost/viper"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
@@ -430,12 +430,12 @@
|
|||||||
version = "v0.0.3"
|
version = "v0.0.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:3cafc6a5a1b8269605d9df4c6956d43d8011fc57f266ca6b9d04da6c09dee548"
|
digest = "1:4a49346ca45376a2bba679ca0e83bec949d780d4e927931317904bad482943ec"
|
||||||
name = "github.com/mattn/go-sqlite3"
|
name = "github.com/mattn/go-sqlite3"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "25ecb14adfc7543176f7d85291ec7dba82c6f7e4"
|
revision = "c7c4067b79cc51e6dfdcef5c702e74b1e0fa7c75"
|
||||||
version = "v1.9.0"
|
version = "v1.10.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc"
|
digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc"
|
||||||
@@ -446,15 +446,15 @@
|
|||||||
version = "v1.0.1"
|
version = "v1.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:b39aee4261f1ae13fdd21a0db189e0bba0f96c0f2eba77ab278428e2d3b00052"
|
digest = "1:702ff5d8a0196ccb0627f35996efd1081be00c8ae1719402adbffc6e0f8f59ac"
|
||||||
name = "github.com/miekg/dns"
|
name = "github.com/miekg/dns"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "f4db2ca6edc3af0ee51bf332099cc480bcf3ef9d"
|
revision = "7586a3cbe8ccfc63f82de3ab2ceeb08c9939af72"
|
||||||
version = "v1.0.10"
|
version = "v1.1.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:66917113d25f811af092599123662fe8e1b9eebdc4057a2eedf9b9f1ca00d76a"
|
digest = "1:ce1c41ebdf4761c8c1336e967b822568534342bf836ad56fee476b102653cec3"
|
||||||
name = "github.com/minio/minio-go"
|
name = "github.com/minio/minio-go"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@@ -465,8 +465,8 @@
|
|||||||
"pkg/set",
|
"pkg/set",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "e8c97c88468e122f161683409cde02dc89a2961c"
|
revision = "39381cf62425050629c7264228fc2f9e0c6616f6"
|
||||||
version = "v6.0.7"
|
version = "v6.0.11"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:78bbb1ba5b7c3f2ed0ea1eab57bdd3859aec7e177811563edc41198a760b06af"
|
digest = "1:78bbb1ba5b7c3f2ed0ea1eab57bdd3859aec7e177811563edc41198a760b06af"
|
||||||
@@ -485,12 +485,12 @@
|
|||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:645110e089152bd0f4a011a2648fbb0e4df5977be73ca605781157ac297f50c4"
|
digest = "1:53bc4cd4914cd7cd52139990d5170d6dc99067ae31c56530621b18b35fc30318"
|
||||||
name = "github.com/mitchellh/mapstructure"
|
name = "github.com/mitchellh/mapstructure"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "fa473d140ef3c6adf42d6b391fe76707f1f243c8"
|
revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe"
|
||||||
version = "v1.0.0"
|
version = "v1.1.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:07140002dbf37da92090f731b46fa47be4820b82fe5c14a035203b0e813d0ec2"
|
digest = "1:07140002dbf37da92090f731b46fa47be4820b82fe5c14a035203b0e813d0ec2"
|
||||||
@@ -514,12 +514,12 @@
|
|||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
digest = "1:abcdbf03ca6ca13d3697e2186edc1f33863bbdac2b3a44dfa39015e8903f7409"
|
||||||
digest = "1:f611266e3ac01ab4adb6f1d67f6c1be82998d02f452faff450596658712d860b"
|
|
||||||
name = "github.com/olekukonko/tablewriter"
|
name = "github.com/olekukonko/tablewriter"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "be2c049b30ccd4d3fd795d6bf7dce74e42eeedaa"
|
revision = "e6d60cf7ba1f42d86d54cdf5508611c4aafb3970"
|
||||||
|
version = "v0.0.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:e5d0bd87abc2781d14e274807a470acd180f0499f8bf5bb18606e9ec22ad9de9"
|
digest = "1:e5d0bd87abc2781d14e274807a470acd180f0499f8bf5bb18606e9ec22ad9de9"
|
||||||
@@ -554,15 +554,16 @@
|
|||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb"
|
digest = "1:26663fafdea73a38075b07e8e9d82fc0056379d2be8bb4e13899e8fda7c7dd23"
|
||||||
name = "github.com/prometheus/client_golang"
|
name = "github.com/prometheus/client_golang"
|
||||||
packages = [
|
packages = [
|
||||||
"prometheus",
|
"prometheus",
|
||||||
|
"prometheus/internal",
|
||||||
"prometheus/promhttp",
|
"prometheus/promhttp",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "c5b7fccd204277076155f10851dad72b76a49317"
|
revision = "abad2d1bd44235a26707c172eab6bca5bf2dbad3"
|
||||||
version = "v0.8.0"
|
version = "v0.9.1"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -574,7 +575,7 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5"
|
digest = "1:db712fde5d12d6cdbdf14b777f0c230f4ff5ab0be8e35b239fc319953ed577a4"
|
||||||
name = "github.com/prometheus/common"
|
name = "github.com/prometheus/common"
|
||||||
packages = [
|
packages = [
|
||||||
"expfmt",
|
"expfmt",
|
||||||
@@ -582,11 +583,11 @@
|
|||||||
"model",
|
"model",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "c7de2306084e37d54b8be01f3541a8464345e9a5"
|
revision = "4724e9255275ce38f7179b2478abeae4e28c904f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:ef1dd9945e58ee9b635273d28c0ef3fa3742a7dedc038ebe207fd63e6ce000ef"
|
digest = "1:9ea97158ea06d60b1f324aa384f6a4cbd596a81b3cae994e17108b195f398d01"
|
||||||
name = "github.com/prometheus/procfs"
|
name = "github.com/prometheus/procfs"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@@ -595,15 +596,15 @@
|
|||||||
"xfs",
|
"xfs",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "418d78d0b9a7b7de3a6bbc8a23def624cc977bb2"
|
revision = "aa55a523dc0a8297edf51bb75e8eec13eb3be45d"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:0b8dd7447e420afff0260179dc892711e837edd1d446bc78dab924624a3c3c81"
|
digest = "1:b0c25f00bad20d783d259af2af8666969e2fc343fa0dc9efe52936bbd67fb758"
|
||||||
name = "github.com/rs/cors"
|
name = "github.com/rs/cors"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "3fb1b69b103a84de38a19c3c6ec073dd6caa4d3f"
|
revision = "9a47f48565a795472d43519dd49aac781f3034fb"
|
||||||
version = "v1.5.0"
|
version = "v1.6.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "go1"
|
branch = "go1"
|
||||||
@@ -660,12 +661,12 @@
|
|||||||
version = "v1.1.2"
|
version = "v1.1.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f"
|
digest = "1:08d65904057412fc0270fc4812a1c90c594186819243160dc779a402d4b6d0bc"
|
||||||
name = "github.com/spf13/cast"
|
name = "github.com/spf13/cast"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "8965335b8c7107321228e3e3702cab9832751bac"
|
revision = "8c9545af88b134710ab1cd196795e7f2388358d7"
|
||||||
version = "v1.2.0"
|
version = "v1.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939"
|
digest = "1:645cabccbb4fa8aab25a956cbcbdf6a6845ca736b2c64e197ca7cbb9d210b939"
|
||||||
@@ -684,12 +685,12 @@
|
|||||||
version = "v1.0.0"
|
version = "v1.0.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9"
|
digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2"
|
||||||
name = "github.com/spf13/pflag"
|
name = "github.com/spf13/pflag"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
|
revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
|
||||||
version = "v1.0.2"
|
version = "v1.0.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -721,15 +722,15 @@
|
|||||||
version = "v1.2.2"
|
version = "v1.2.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:61887463fa9092425462901371114c3d1fbea3272c74e421d4502294a89556e3"
|
digest = "1:dcc5f8e4cd517d4cceca662dd7ce0f15ba27daf43468307b6fbbfdf1130f3845"
|
||||||
name = "github.com/throttled/throttled"
|
name = "github.com/throttled/throttled"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
"store/memstore",
|
"store/memstore",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "aeea1c7338e6dd1e1b309afe07fb7bbcfa83c2fa"
|
revision = "def5708c45a0d2b2b9a3604521f3164e227d2c83"
|
||||||
version = "v2.2.1"
|
version = "v2.2.4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:43b8a34f6390d8fbdcfd300ed52103064e9eaaecc7e50b7e3518fe246ebe8403"
|
digest = "1:43b8a34f6390d8fbdcfd300ed52103064e9eaaecc7e50b7e3518fe246ebe8403"
|
||||||
@@ -780,7 +781,7 @@
|
|||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:097fe1a8acb060fbbd78abc62c2e2d2a1ec0d24ec620b6a919bd11e75cbf425b"
|
digest = "1:50d4ea522a5de5b13c947d022364ee3139e66406f91db7d6b2f7a15f4b94191a"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = [
|
packages = [
|
||||||
"acme",
|
"acme",
|
||||||
@@ -794,11 +795,11 @@
|
|||||||
"ssh/terminal",
|
"ssh/terminal",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "5295e8364332db77d75fce11f1d19c053919a9c9"
|
revision = "505ab145d0a99da450461ae2c1a9f6cd10d1f447"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:759e3d3f934e59167dcae65e5270630d0ae1c51d97d3080725dee05146502fa3"
|
digest = "1:8aabc191fd00a92f1880d1ee3383ee57b44df6e55d6e682d0a8f994309f58e36"
|
||||||
name = "golang.org/x/image"
|
name = "golang.org/x/image"
|
||||||
packages = [
|
packages = [
|
||||||
"bmp",
|
"bmp",
|
||||||
@@ -808,11 +809,11 @@
|
|||||||
"tiff/lzw",
|
"tiff/lzw",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "991ec62608f3c0da01d400756917825d1e2fd528"
|
revision = "cd38e8056d9b27bb2f265effa37fb0ea6b8a7f0f"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:8d7414cba5388e70dc334e2c938c66d276e7bd56c19c1f914d2e9a3f17db81f7"
|
digest = "1:dcbcbc31f39124af75fbe3354eee26697bd0af2ed05ccd76492e0c54457ac12c"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = [
|
packages = [
|
||||||
"bpf",
|
"bpf",
|
||||||
@@ -832,11 +833,11 @@
|
|||||||
"trace",
|
"trace",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "4dfa2610cdf3b287375bbba5b8f2a14d3b01d8de"
|
revision = "351d144fa1fc0bd934e2408202be0c29f25e35a0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:c90c6c71771006dd4c843a1af66f29af3fd7afb4937d2c70097f13f7c2a4a464"
|
digest = "1:401fc17cbc8a7c6ac25639d63c110385b2a04fab2911d9bad13366771b6e4df6"
|
||||||
name = "golang.org/x/sys"
|
name = "golang.org/x/sys"
|
||||||
packages = [
|
packages = [
|
||||||
"cpu",
|
"cpu",
|
||||||
@@ -844,7 +845,7 @@
|
|||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "e4b3c5e9061176387e7cea65e4dc5853801f3fb7"
|
revision = "4ed8d59d0b35e1e29334a206d1b3f38b1e5dfb31"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:436b24586f8fee329e0dd65fd67c817681420cda1d7f934345c13fe78c212a73"
|
digest = "1:436b24586f8fee329e0dd65fd67c817681420cda1d7f934345c13fe78c212a73"
|
||||||
@@ -886,19 +887,19 @@
|
|||||||
name = "google.golang.org/appengine"
|
name = "google.golang.org/appengine"
|
||||||
packages = ["cloudsql"]
|
packages = ["cloudsql"]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "ae0ab99deb4dc413a2b4bd6c8bdd0eb67f1e4d06"
|
revision = "4a4468ece617fc8205e99368fa2200e9d1fad421"
|
||||||
version = "v1.2.0"
|
version = "v1.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
digest = "1:56b0bca90b7e5d1facf5fbdacba23e4e0ce069d25381b8e2f70ef1e7ebfb9c1a"
|
digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c"
|
||||||
name = "google.golang.org/genproto"
|
name = "google.golang.org/genproto"
|
||||||
packages = ["googleapis/rpc/status"]
|
packages = ["googleapis/rpc/status"]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "0e822944c569bf5c9afd034adaa56208bd2906ac"
|
revision = "bd91e49a0898e27abb88c339b432fa53d7497ac0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:1b6d2676ea895d33cbd1999c75dfc8e25b103c754ccfc66dc06ae845ce3a47bc"
|
digest = "1:95550b4aa2a79019c2a832c1a7d6a5446b046e3ee8cce12a042778ac0ac47baf"
|
||||||
name = "google.golang.org/grpc"
|
name = "google.golang.org/grpc"
|
||||||
packages = [
|
packages = [
|
||||||
".",
|
".",
|
||||||
@@ -931,8 +932,8 @@
|
|||||||
"tap",
|
"tap",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1"
|
revision = "2e463a05d100327ca47ac218281906921038fd95"
|
||||||
version = "v1.15.0"
|
version = "v1.16.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "v3"
|
branch = "v3"
|
||||||
@@ -943,12 +944,12 @@
|
|||||||
revision = "2caba252f4dc53eaf6b553000885530023f54623"
|
revision = "2caba252f4dc53eaf6b553000885530023f54623"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:81e1c5cee195fca5de06e2540cb63eea727a850b7e5c213548e7f81521c97a57"
|
digest = "1:af07c44dc04418be522bfd4e21ca9130d58169ea084e3a883e23772003a381c4"
|
||||||
name = "gopkg.in/asn1-ber.v1"
|
name = "gopkg.in/asn1-ber.v1"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "379148ca0225df7a432012b8df0355c2a2063ac0"
|
revision = "f715ec2f112d1e4195b827ad68cf44017a3ef2b1"
|
||||||
version = "v1.2"
|
version = "v1.3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:eebd52aee67d9f1e0af1859a584e14b1817581dd5f90d4585418c27b6a93c966"
|
digest = "1:eebd52aee67d9f1e0af1859a584e14b1817581dd5f90d4585418c27b6a93c966"
|
||||||
@@ -979,12 +980,12 @@
|
|||||||
version = "v5.0.76"
|
version = "v5.0.76"
|
||||||
|
|
||||||
[[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"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
|
|||||||
10
Gopkg.toml
10
Gopkg.toml
@@ -52,16 +52,8 @@
|
|||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/hashicorp/go-plugin"
|
name = "github.com/hashicorp/go-plugin"
|
||||||
revision = "a4620f9913d19f03a6bf19b2f304daaaf83ea130"
|
revision = "54b6ff97d8180dbbd93d2010dd4a92c86f604bb8"
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/blang/semver"
|
|
||||||
version = "~3.5.0"
|
|
||||||
|
|
||||||
[prune]
|
[prune]
|
||||||
go-tests = true
|
go-tests = true
|
||||||
unused-packages = true
|
unused-packages = true
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
name = "github.com/sirupsen/logrus"
|
|
||||||
version = "1.2.0"
|
|
||||||
|
|||||||
12
vendor/github.com/corpix/uarand/uarand.go
сгенерированный
поставляемый
12
vendor/github.com/corpix/uarand/uarand.go
сгенерированный
поставляемый
@@ -23,11 +23,12 @@ type Randomizer interface {
|
|||||||
// UARand describes the user agent randomizer settings.
|
// UARand describes the user agent randomizer settings.
|
||||||
type UARand struct {
|
type UARand struct {
|
||||||
Randomizer
|
Randomizer
|
||||||
|
UserAgents []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRandom returns a random user agent from UserAgents slice.
|
// GetRandom returns a random user agent from UserAgents slice.
|
||||||
func (u *UARand) GetRandom() string {
|
func (u *UARand) GetRandom() string {
|
||||||
return UserAgents[u.Intn(len(UserAgents))]
|
return u.UserAgents[u.Intn(len(u.UserAgents))]
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRandom returns a random user agent from UserAgents slice.
|
// GetRandom returns a random user agent from UserAgents slice.
|
||||||
@@ -36,6 +37,13 @@ func GetRandom() string {
|
|||||||
return Default.GetRandom()
|
return Default.GetRandom()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New return UserAgent randomizer settings with default user-agents list
|
||||||
func New(r Randomizer) *UARand {
|
func New(r Randomizer) *UARand {
|
||||||
return &UARand{r}
|
return &UARand{r, UserAgents}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWithCustomList return UserAgent randomizer settings with custom user-agents list
|
||||||
|
func NewWithCustomList(userAgents []string) *UARand {
|
||||||
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
return &UARand{r, userAgents}
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/go-ini/ini/.travis.yml
сгенерированный
поставляемый
1
vendor/github.com/go-ini/ini/.travis.yml
сгенерированный
поставляемый
@@ -6,6 +6,7 @@ go:
|
|||||||
- 1.8.x
|
- 1.8.x
|
||||||
- 1.9.x
|
- 1.9.x
|
||||||
- 1.10.x
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- go get golang.org/x/tools/cmd/cover
|
- go get golang.org/x/tools/cmd/cover
|
||||||
|
|||||||
2
vendor/github.com/go-ini/ini/README.md
сгенерированный
поставляемый
2
vendor/github.com/go-ini/ini/README.md
сгенерированный
поставляемый
@@ -20,6 +20,8 @@ Package ini provides INI file read and write functionality in Go.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
The minimum requirement of Go is **1.6**.
|
||||||
|
|
||||||
To use a tagged revision:
|
To use a tagged revision:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
10
vendor/github.com/go-ini/ini/file.go
сгенерированный
поставляемый
10
vendor/github.com/go-ini/ini/file.go
сгенерированный
поставляемый
@@ -45,6 +45,9 @@ type File struct {
|
|||||||
|
|
||||||
// newFile initializes File object with given data sources.
|
// newFile initializes File object with given data sources.
|
||||||
func newFile(dataSources []dataSource, opts LoadOptions) *File {
|
func newFile(dataSources []dataSource, opts LoadOptions) *File {
|
||||||
|
if len(opts.KeyValueDelimiters) == 0 {
|
||||||
|
opts.KeyValueDelimiters = "=:"
|
||||||
|
}
|
||||||
return &File{
|
return &File{
|
||||||
BlockMode: true,
|
BlockMode: true,
|
||||||
dataSources: dataSources,
|
dataSources: dataSources,
|
||||||
@@ -227,7 +230,8 @@ func (f *File) Append(source interface{}, others ...interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
||||||
equalSign := "="
|
equalSign := DefaultFormatLeft + "=" + DefaultFormatRight
|
||||||
|
|
||||||
if PrettyFormat || PrettyEqual {
|
if PrettyFormat || PrettyEqual {
|
||||||
equalSign = " = "
|
equalSign = " = "
|
||||||
}
|
}
|
||||||
@@ -285,7 +289,7 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
|||||||
for _, kname := range sec.keyList {
|
for _, kname := range sec.keyList {
|
||||||
keyLength := len(kname)
|
keyLength := len(kname)
|
||||||
// First case will surround key by ` and second by """
|
// First case will surround key by ` and second by """
|
||||||
if strings.ContainsAny(kname, "\"=:") {
|
if strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters) {
|
||||||
keyLength += 2
|
keyLength += 2
|
||||||
} else if strings.Contains(kname, "`") {
|
} else if strings.Contains(kname, "`") {
|
||||||
keyLength += 6
|
keyLength += 6
|
||||||
@@ -328,7 +332,7 @@ func (f *File) writeToBuffer(indent string) (*bytes.Buffer, error) {
|
|||||||
switch {
|
switch {
|
||||||
case key.isAutoIncrement:
|
case key.isAutoIncrement:
|
||||||
kname = "-"
|
kname = "-"
|
||||||
case strings.ContainsAny(kname, "\"=:"):
|
case strings.Contains(kname, "\"") || strings.ContainsAny(kname, f.options.KeyValueDelimiters):
|
||||||
kname = "`" + kname + "`"
|
kname = "`" + kname + "`"
|
||||||
case strings.Contains(kname, "`"):
|
case strings.Contains(kname, "`"):
|
||||||
kname = `"""` + kname + `"""`
|
kname = `"""` + kname + `"""`
|
||||||
|
|||||||
8
vendor/github.com/go-ini/ini/ini.go
сгенерированный
поставляемый
8
vendor/github.com/go-ini/ini/ini.go
сгенерированный
поставляемый
@@ -34,7 +34,7 @@ const (
|
|||||||
|
|
||||||
// Maximum allowed depth when recursively substituing variable names.
|
// Maximum allowed depth when recursively substituing variable names.
|
||||||
_DEPTH_VALUES = 99
|
_DEPTH_VALUES = 99
|
||||||
_VERSION = "1.38.2"
|
_VERSION = "1.39.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version returns current package version literal.
|
// Version returns current package version literal.
|
||||||
@@ -48,6 +48,10 @@ var (
|
|||||||
// at package init time.
|
// at package init time.
|
||||||
LineBreak = "\n"
|
LineBreak = "\n"
|
||||||
|
|
||||||
|
// Place custom spaces when PrettyFormat and PrettyEqual are both disabled
|
||||||
|
DefaultFormatLeft = ""
|
||||||
|
DefaultFormatRight = ""
|
||||||
|
|
||||||
// Variable regexp pattern: %(variable)s
|
// Variable regexp pattern: %(variable)s
|
||||||
varPattern = regexp.MustCompile(`%\(([^\)]+)\)s`)
|
varPattern = regexp.MustCompile(`%\(([^\)]+)\)s`)
|
||||||
|
|
||||||
@@ -164,6 +168,8 @@ type LoadOptions struct {
|
|||||||
// UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise
|
// UnparseableSections stores a list of blocks that are allowed with raw content which do not otherwise
|
||||||
// conform to key/value pairs. Specify the names of those blocks here.
|
// conform to key/value pairs. Specify the names of those blocks here.
|
||||||
UnparseableSections []string
|
UnparseableSections []string
|
||||||
|
// KeyValueDelimiters is the sequence of delimiters that are used to separate key and value. By default, it is "=:".
|
||||||
|
KeyValueDelimiters string
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
|
func LoadSources(opts LoadOptions, source interface{}, others ...interface{}) (_ *File, err error) {
|
||||||
|
|||||||
20
vendor/github.com/go-ini/ini/parser.go
сгенерированный
поставляемый
20
vendor/github.com/go-ini/ini/parser.go
сгенерированный
поставляемый
@@ -100,7 +100,7 @@ func cleanComment(in []byte) ([]byte, bool) {
|
|||||||
return in[i:], true
|
return in[i:], true
|
||||||
}
|
}
|
||||||
|
|
||||||
func readKeyName(in []byte) (string, int, error) {
|
func readKeyName(delimiters string, in []byte) (string, int, error) {
|
||||||
line := string(in)
|
line := string(in)
|
||||||
|
|
||||||
// Check if key name surrounded by quotes.
|
// Check if key name surrounded by quotes.
|
||||||
@@ -127,7 +127,7 @@ func readKeyName(in []byte) (string, int, error) {
|
|||||||
pos += startIdx
|
pos += startIdx
|
||||||
|
|
||||||
// Find key-value delimiter
|
// Find key-value delimiter
|
||||||
i := strings.IndexAny(line[pos+startIdx:], "=:")
|
i := strings.IndexAny(line[pos+startIdx:], delimiters)
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
return "", -1, ErrDelimiterNotFound{line}
|
return "", -1, ErrDelimiterNotFound{line}
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ func readKeyName(in []byte) (string, int, error) {
|
|||||||
return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
|
return strings.TrimSpace(line[startIdx:pos]), endIdx + startIdx + 1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
endIdx = strings.IndexAny(line, "=:")
|
endIdx = strings.IndexAny(line, delimiters)
|
||||||
if endIdx < 0 {
|
if endIdx < 0 {
|
||||||
return "", -1, ErrDelimiterNotFound{line}
|
return "", -1, ErrDelimiterNotFound{line}
|
||||||
}
|
}
|
||||||
@@ -273,7 +273,6 @@ func (p *parser) readValue(in []byte,
|
|||||||
parserBufferPeekResult, _ := p.buf.Peek(parserBufferSize)
|
parserBufferPeekResult, _ := p.buf.Peek(parserBufferSize)
|
||||||
peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
|
peekBuffer := bytes.NewBuffer(parserBufferPeekResult)
|
||||||
|
|
||||||
identSize := -1
|
|
||||||
val := line
|
val := line
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -290,12 +289,11 @@ func (p *parser) readValue(in []byte,
|
|||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
currentIdentSize := len(peekMatches[1])
|
|
||||||
// NOTE: Return if not a python-ini multi-line value.
|
// NOTE: Return if not a python-ini multi-line value.
|
||||||
if currentIdentSize < 0 {
|
currentIdentSize := len(peekMatches[1])
|
||||||
|
if currentIdentSize <= 0 {
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
identSize = currentIdentSize
|
|
||||||
|
|
||||||
// NOTE: Just advance the parser reader (buffer) in-sync with the peek buffer.
|
// NOTE: Just advance the parser reader (buffer) in-sync with the peek buffer.
|
||||||
_, err := p.readUntil('\n')
|
_, err := p.readUntil('\n')
|
||||||
@@ -305,12 +303,6 @@ func (p *parser) readValue(in []byte,
|
|||||||
|
|
||||||
val += fmt.Sprintf("\n%s", peekMatches[2])
|
val += fmt.Sprintf("\n%s", peekMatches[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: If it was a Python multi-line value,
|
|
||||||
// return the appended value.
|
|
||||||
if identSize > 0 {
|
|
||||||
return val, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return line, nil
|
return line, nil
|
||||||
@@ -428,7 +420,7 @@ func (f *File) parse(reader io.Reader) (err error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
kname, offset, err := readKeyName(line)
|
kname, offset, err := readKeyName(f.options.KeyValueDelimiters, line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Treat as boolean key when desired, and whole line is key name.
|
// Treat as boolean key when desired, and whole line is key name.
|
||||||
if IsErrDelimiterNotFound(err) {
|
if IsErrDelimiterNotFound(err) {
|
||||||
|
|||||||
34
vendor/github.com/go-ldap/ldap/.travis.yml
сгенерированный
поставляемый
34
vendor/github.com/go-ldap/ldap/.travis.yml
сгенерированный
поставляемый
@@ -1,31 +1,31 @@
|
|||||||
|
sudo: false
|
||||||
language: go
|
language: go
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- VET_VERSIONS="1.6 1.7 1.8 1.9 tip"
|
|
||||||
- LINT_VERSIONS="1.6 1.7 1.8 1.9 tip"
|
|
||||||
go:
|
go:
|
||||||
- 1.2
|
- "1.4.x"
|
||||||
- 1.3
|
- "1.5.x"
|
||||||
- 1.4
|
- "1.6.x"
|
||||||
- 1.5
|
- "1.7.x"
|
||||||
- 1.6
|
- "1.8.x"
|
||||||
- 1.7
|
- "1.9.x"
|
||||||
- 1.8
|
- "1.10.x"
|
||||||
- 1.9
|
- "1.11.x"
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
|
git:
|
||||||
|
depth: 1
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- go: tip
|
- go: tip
|
||||||
go_import_path: gopkg.in/ldap.v2
|
go_import_path: gopkg.in/ldap.v3
|
||||||
install:
|
install:
|
||||||
- go get gopkg.in/asn1-ber.v1
|
- go get gopkg.in/asn1-ber.v1
|
||||||
- go get gopkg.in/ldap.v2
|
|
||||||
- go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
|
- go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
|
||||||
- go get github.com/golang/lint/golint || true
|
- go get github.com/golang/lint/golint || go get golang.org/x/lint/golint || true
|
||||||
- go build -v ./...
|
- go build -v ./...
|
||||||
script:
|
script:
|
||||||
- make test
|
- make test
|
||||||
- make fmt
|
- make fmt
|
||||||
- if [[ "$VET_VERSIONS" == *"$TRAVIS_GO_VERSION"* ]]; then make vet; fi
|
- make vet
|
||||||
- if [[ "$LINT_VERSIONS" == *"$TRAVIS_GO_VERSION"* ]]; then make lint; fi
|
- make lint
|
||||||
|
|||||||
12
vendor/github.com/go-ldap/ldap/CONTRIBUTING.md
сгенерированный
поставляемый
Обычный файл
12
vendor/github.com/go-ldap/ldap/CONTRIBUTING.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,12 @@
|
|||||||
|
# Contribution Guidelines
|
||||||
|
|
||||||
|
We welcome contribution and improvements.
|
||||||
|
|
||||||
|
## Guiding Principles
|
||||||
|
|
||||||
|
To begin with here is a draft from an email exchange:
|
||||||
|
|
||||||
|
* take compatibility seriously (our semvers, compatibility with older go versions, etc)
|
||||||
|
* don't tag untested code for release
|
||||||
|
* beware of baking in implicit behavior based on other libraries/tools choices
|
||||||
|
* be as high-fidelity as possible in plumbing through LDAP data (don't mask errors or reduce power of someone using the library)
|
||||||
20
vendor/github.com/go-ldap/ldap/Makefile
сгенерированный
поставляемый
20
vendor/github.com/go-ldap/ldap/Makefile
сгенерированный
поставляемый
@@ -36,7 +36,23 @@ fmt:
|
|||||||
|
|
||||||
# Only run on go1.5+
|
# Only run on go1.5+
|
||||||
vet:
|
vet:
|
||||||
go tool vet -atomic -bool -copylocks -nilfunc -printf -shadow -rangeloops -unreachable -unsafeptr -unusedresult .
|
@go tool -n vet >/dev/null 2>&1; \
|
||||||
|
if [ $$? -eq 0 ]; then \
|
||||||
|
echo "go vet" ; \
|
||||||
|
go tool vet \
|
||||||
|
-atomic \
|
||||||
|
-bool \
|
||||||
|
-copylocks \
|
||||||
|
-nilfunc \
|
||||||
|
-printf \
|
||||||
|
-shadow \
|
||||||
|
-rangeloops \
|
||||||
|
-unreachable \
|
||||||
|
-unsafeptr \
|
||||||
|
-unusedresult \
|
||||||
|
. ; \
|
||||||
|
fi ;
|
||||||
|
|
||||||
|
|
||||||
# https://github.com/golang/lint
|
# https://github.com/golang/lint
|
||||||
# go get github.com/golang/lint/golint
|
# go get github.com/golang/lint/golint
|
||||||
@@ -44,7 +60,7 @@ vet:
|
|||||||
# Only run on go1.5+
|
# Only run on go1.5+
|
||||||
lint:
|
lint:
|
||||||
@echo golint ./...
|
@echo golint ./...
|
||||||
@OUTPUT=`golint ./... 2>&1`; \
|
@OUTPUT=`command -v golint >/dev/null 2>&1 && golint ./... 2>&1`; \
|
||||||
if [ "$$OUTPUT" ]; then \
|
if [ "$$OUTPUT" ]; then \
|
||||||
echo "golint errors:"; \
|
echo "golint errors:"; \
|
||||||
echo "$$OUTPUT"; \
|
echo "$$OUTPUT"; \
|
||||||
|
|||||||
7
vendor/github.com/go-ldap/ldap/README.md
сгенерированный
поставляемый
7
vendor/github.com/go-ldap/ldap/README.md
сгенерированный
поставляемый
@@ -1,4 +1,4 @@
|
|||||||
[](https://godoc.org/gopkg.in/ldap.v2)
|
[](https://godoc.org/gopkg.in/ldap.v3)
|
||||||
[](https://travis-ci.org/go-ldap/ldap)
|
[](https://travis-ci.org/go-ldap/ldap)
|
||||||
|
|
||||||
# Basic LDAP v3 functionality for the GO programming language.
|
# Basic LDAP v3 functionality for the GO programming language.
|
||||||
@@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
For the latest version use:
|
For the latest version use:
|
||||||
|
|
||||||
go get gopkg.in/ldap.v2
|
go get gopkg.in/ldap.v3
|
||||||
|
|
||||||
Import the latest version with:
|
Import the latest version with:
|
||||||
|
|
||||||
import "gopkg.in/ldap.v2"
|
import "gopkg.in/ldap.v3"
|
||||||
|
|
||||||
## Required Libraries:
|
## Required Libraries:
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ Import the latest version with:
|
|||||||
- Modify Requests / Responses
|
- Modify Requests / Responses
|
||||||
- Add Requests / Responses
|
- Add Requests / Responses
|
||||||
- Delete Requests / Responses
|
- Delete Requests / Responses
|
||||||
|
- Modify DN Requests / Responses
|
||||||
|
|
||||||
## Examples:
|
## Examples:
|
||||||
|
|
||||||
|
|||||||
16
vendor/github.com/go-ldap/ldap/add.go
сгенерированный
поставляемый
16
vendor/github.com/go-ldap/ldap/add.go
сгенерированный
поставляемый
@@ -41,6 +41,8 @@ type AddRequest struct {
|
|||||||
DN string
|
DN string
|
||||||
// Attributes list the attributes of the new entry
|
// Attributes list the attributes of the new entry
|
||||||
Attributes []Attribute
|
Attributes []Attribute
|
||||||
|
// Controls hold optional controls to send with the request
|
||||||
|
Controls []Control
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AddRequest) encode() *ber.Packet {
|
func (a AddRequest) encode() *ber.Packet {
|
||||||
@@ -60,9 +62,10 @@ func (a *AddRequest) Attribute(attrType string, attrVals []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewAddRequest returns an AddRequest for the given DN, with no attributes
|
// NewAddRequest returns an AddRequest for the given DN, with no attributes
|
||||||
func NewAddRequest(dn string) *AddRequest {
|
func NewAddRequest(dn string, controls []Control) *AddRequest {
|
||||||
return &AddRequest{
|
return &AddRequest{
|
||||||
DN: dn,
|
DN: dn,
|
||||||
|
Controls: controls,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -72,6 +75,9 @@ func (l *Conn) Add(addRequest *AddRequest) error {
|
|||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
||||||
packet.AppendChild(addRequest.encode())
|
packet.AppendChild(addRequest.encode())
|
||||||
|
if len(addRequest.Controls) > 0 {
|
||||||
|
packet.AppendChild(encodeControls(addRequest.Controls))
|
||||||
|
}
|
||||||
|
|
||||||
l.Debug.PrintPacket(packet)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
@@ -100,9 +106,9 @@ func (l *Conn) Add(addRequest *AddRequest) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if packet.Children[1].Tag == ApplicationAddResponse {
|
if packet.Children[1].Tag == ApplicationAddResponse {
|
||||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
err := GetLDAPError(packet)
|
||||||
if resultCode != 0 {
|
if err != nil {
|
||||||
return NewError(resultCode, errors.New(resultDescription))
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
|
|||||||
13
vendor/github.com/go-ldap/ldap/atomic_value.go
сгенерированный
поставляемый
13
vendor/github.com/go-ldap/ldap/atomic_value.go
сгенерированный
поставляемый
@@ -1,13 +0,0 @@
|
|||||||
// +build go1.4
|
|
||||||
|
|
||||||
package ldap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// For compilers that support it, we just use the underlying sync/atomic.Value
|
|
||||||
// type.
|
|
||||||
type atomicValue struct {
|
|
||||||
atomic.Value
|
|
||||||
}
|
|
||||||
28
vendor/github.com/go-ldap/ldap/atomic_value_go13.go
сгенерированный
поставляемый
28
vendor/github.com/go-ldap/ldap/atomic_value_go13.go
сгенерированный
поставляемый
@@ -1,28 +0,0 @@
|
|||||||
// +build !go1.4
|
|
||||||
|
|
||||||
package ldap
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a helper type that emulates the use of the "sync/atomic.Value"
|
|
||||||
// struct that's available in Go 1.4 and up.
|
|
||||||
type atomicValue struct {
|
|
||||||
value interface{}
|
|
||||||
lock sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (av *atomicValue) Store(val interface{}) {
|
|
||||||
av.lock.Lock()
|
|
||||||
av.value = val
|
|
||||||
av.lock.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (av *atomicValue) Load() interface{} {
|
|
||||||
av.lock.RLock()
|
|
||||||
ret := av.value
|
|
||||||
av.lock.RUnlock()
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
108
vendor/github.com/go-ldap/ldap/bind.go
сгенерированный
поставляемый
108
vendor/github.com/go-ldap/ldap/bind.go
сгенерированный
поставляемый
@@ -1,11 +1,8 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
@@ -18,6 +15,9 @@ type SimpleBindRequest struct {
|
|||||||
Password string
|
Password string
|
||||||
// Controls are optional controls to send with the bind request
|
// Controls are optional controls to send with the bind request
|
||||||
Controls []Control
|
Controls []Control
|
||||||
|
// AllowEmptyPassword sets whether the client allows binding with an empty password
|
||||||
|
// (normally used for unauthenticated bind).
|
||||||
|
AllowEmptyPassword bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimpleBindResult contains the response from the server
|
// SimpleBindResult contains the response from the server
|
||||||
@@ -28,9 +28,10 @@ type SimpleBindResult struct {
|
|||||||
// NewSimpleBindRequest returns a bind request
|
// NewSimpleBindRequest returns a bind request
|
||||||
func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
|
func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
|
||||||
return &SimpleBindRequest{
|
return &SimpleBindRequest{
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: password,
|
Password: password,
|
||||||
Controls: controls,
|
Controls: controls,
|
||||||
|
AllowEmptyPassword: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,17 +41,22 @@ func (bindRequest *SimpleBindRequest) encode() *ber.Packet {
|
|||||||
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, bindRequest.Username, "User Name"))
|
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, bindRequest.Username, "User Name"))
|
||||||
request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, bindRequest.Password, "Password"))
|
request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, bindRequest.Password, "Password"))
|
||||||
|
|
||||||
request.AppendChild(encodeControls(bindRequest.Controls))
|
|
||||||
|
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
// SimpleBind performs the simple bind operation defined in the given request
|
// SimpleBind performs the simple bind operation defined in the given request
|
||||||
func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
|
func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
|
||||||
|
if simpleBindRequest.Password == "" && !simpleBindRequest.AllowEmptyPassword {
|
||||||
|
return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client"))
|
||||||
|
}
|
||||||
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
||||||
encodedBindRequest := simpleBindRequest.encode()
|
encodedBindRequest := simpleBindRequest.encode()
|
||||||
packet.AppendChild(encodedBindRequest)
|
packet.AppendChild(encodedBindRequest)
|
||||||
|
if len(simpleBindRequest.Controls) > 0 {
|
||||||
|
packet.AppendChild(encodeControls(simpleBindRequest.Controls))
|
||||||
|
}
|
||||||
|
|
||||||
if l.Debug {
|
if l.Debug {
|
||||||
ber.PrintPacket(packet)
|
ber.PrintPacket(packet)
|
||||||
@@ -73,7 +79,7 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if l.Debug {
|
if l.Debug {
|
||||||
if err := addLDAPDescriptions(packet); err != nil {
|
if err = addLDAPDescriptions(packet); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ber.PrintPacket(packet)
|
ber.PrintPacket(packet)
|
||||||
@@ -85,59 +91,45 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
|
|||||||
|
|
||||||
if len(packet.Children) == 3 {
|
if len(packet.Children) == 3 {
|
||||||
for _, child := range packet.Children[2].Children {
|
for _, child := range packet.Children[2].Children {
|
||||||
result.Controls = append(result.Controls, DecodeControl(child))
|
decodedChild, decodeErr := DecodeControl(child)
|
||||||
|
if decodeErr != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode child control: %s", decodeErr)
|
||||||
|
}
|
||||||
|
result.Controls = append(result.Controls, decodedChild)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
err = GetLDAPError(packet)
|
||||||
if resultCode != 0 {
|
return result, err
|
||||||
return result, NewError(resultCode, errors.New(resultDescription))
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind performs a bind with the given username and password
|
// Bind performs a bind with the given username and password.
|
||||||
|
//
|
||||||
|
// It does not allow unauthenticated bind (i.e. empty password). Use the UnauthenticatedBind method
|
||||||
|
// for that.
|
||||||
func (l *Conn) Bind(username, password string) error {
|
func (l *Conn) Bind(username, password string) error {
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
req := &SimpleBindRequest{
|
||||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
Username: username,
|
||||||
bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
|
Password: password,
|
||||||
bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
|
AllowEmptyPassword: false,
|
||||||
bindRequest.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, username, "User Name"))
|
|
||||||
bindRequest.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, password, "Password"))
|
|
||||||
packet.AppendChild(bindRequest)
|
|
||||||
|
|
||||||
if l.Debug {
|
|
||||||
ber.PrintPacket(packet)
|
|
||||||
}
|
}
|
||||||
|
_, err := l.SimpleBind(req)
|
||||||
msgCtx, err := l.sendMessage(packet)
|
return err
|
||||||
if err != nil {
|
}
|
||||||
return err
|
|
||||||
}
|
// UnauthenticatedBind performs an unauthenticated bind.
|
||||||
defer l.finishMessage(msgCtx)
|
//
|
||||||
|
// A username may be provided for trace (e.g. logging) purpose only, but it is normally not
|
||||||
packetResponse, ok := <-msgCtx.responses
|
// authenticated or otherwise validated by the LDAP server.
|
||||||
if !ok {
|
//
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
|
// See https://tools.ietf.org/html/rfc4513#section-5.1.2 .
|
||||||
}
|
// See https://tools.ietf.org/html/rfc4513#section-6.3.1 .
|
||||||
packet, err = packetResponse.ReadPacket()
|
func (l *Conn) UnauthenticatedBind(username string) error {
|
||||||
l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
|
req := &SimpleBindRequest{
|
||||||
if err != nil {
|
Username: username,
|
||||||
return err
|
Password: "",
|
||||||
}
|
AllowEmptyPassword: true,
|
||||||
|
}
|
||||||
if l.Debug {
|
_, err := l.SimpleBind(req)
|
||||||
if err := addLDAPDescriptions(packet); err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
ber.PrintPacket(packet)
|
|
||||||
}
|
|
||||||
|
|
||||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
|
||||||
if resultCode != 0 {
|
|
||||||
return NewError(resultCode, errors.New(resultDescription))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
1
vendor/github.com/go-ldap/ldap/client.go
сгенерированный
поставляемый
1
vendor/github.com/go-ldap/ldap/client.go
сгенерированный
поставляемый
@@ -18,6 +18,7 @@ type Client interface {
|
|||||||
Add(addRequest *AddRequest) error
|
Add(addRequest *AddRequest) error
|
||||||
Del(delRequest *DelRequest) error
|
Del(delRequest *DelRequest) error
|
||||||
Modify(modifyRequest *ModifyRequest) error
|
Modify(modifyRequest *ModifyRequest) error
|
||||||
|
ModifyDN(modifyDNRequest *ModifyDNRequest) error
|
||||||
|
|
||||||
Compare(dn, attribute, value string) (bool, error)
|
Compare(dn, attribute, value string) (bool, error)
|
||||||
PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error)
|
PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error)
|
||||||
|
|||||||
20
vendor/github.com/go-ldap/ldap/compare.go
сгенерированный
поставляемый
20
vendor/github.com/go-ldap/ldap/compare.go
сгенерированный
поставляемый
@@ -1,7 +1,3 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
//
|
|
||||||
// File contains Compare functionality
|
// File contains Compare functionality
|
||||||
//
|
//
|
||||||
// https://tools.ietf.org/html/rfc4511
|
// https://tools.ietf.org/html/rfc4511
|
||||||
@@ -41,7 +37,7 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
|
|||||||
|
|
||||||
ava := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeValueAssertion")
|
ava := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeValueAssertion")
|
||||||
ava.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "AttributeDesc"))
|
ava.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "AttributeDesc"))
|
||||||
ava.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagOctetString, value, "AssertionValue"))
|
ava.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "AssertionValue"))
|
||||||
request.AppendChild(ava)
|
request.AppendChild(ava)
|
||||||
packet.AppendChild(request)
|
packet.AppendChild(request)
|
||||||
|
|
||||||
@@ -72,14 +68,16 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if packet.Children[1].Tag == ApplicationCompareResponse {
|
if packet.Children[1].Tag == ApplicationCompareResponse {
|
||||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
err := GetLDAPError(packet)
|
||||||
if resultCode == LDAPResultCompareTrue {
|
|
||||||
|
switch {
|
||||||
|
case IsErrorWithCode(err, LDAPResultCompareTrue):
|
||||||
return true, nil
|
return true, nil
|
||||||
} else if resultCode == LDAPResultCompareFalse {
|
case IsErrorWithCode(err, LDAPResultCompareFalse):
|
||||||
return false, nil
|
return false, nil
|
||||||
} else {
|
default:
|
||||||
return false, NewError(resultCode, errors.New(resultDescription))
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, fmt.Errorf("Unexpected Response: %d", packet.Children[1].Tag)
|
return false, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag)
|
||||||
}
|
}
|
||||||
|
|||||||
67
vendor/github.com/go-ldap/ldap/conn.go
сгенерированный
поставляемый
67
vendor/github.com/go-ldap/ldap/conn.go
сгенерированный
поставляемый
@@ -1,7 +1,3 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -10,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
@@ -30,6 +27,13 @@ const (
|
|||||||
MessageTimeout = 4
|
MessageTimeout = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultLdapPort default ldap port for pure TCP connection
|
||||||
|
DefaultLdapPort = "389"
|
||||||
|
// DefaultLdapsPort default ldap port for SSL connection
|
||||||
|
DefaultLdapsPort = "636"
|
||||||
|
)
|
||||||
|
|
||||||
// PacketResponse contains the packet or error encountered reading a response
|
// PacketResponse contains the packet or error encountered reading a response
|
||||||
type PacketResponse struct {
|
type PacketResponse struct {
|
||||||
// Packet is the packet read from the server
|
// Packet is the packet read from the server
|
||||||
@@ -84,7 +88,7 @@ type Conn struct {
|
|||||||
conn net.Conn
|
conn net.Conn
|
||||||
isTLS bool
|
isTLS bool
|
||||||
closing uint32
|
closing uint32
|
||||||
closeErr atomicValue
|
closeErr atomic.Value
|
||||||
isStartingTLS bool
|
isStartingTLS bool
|
||||||
Debug debugging
|
Debug debugging
|
||||||
chanConfirm chan struct{}
|
chanConfirm chan struct{}
|
||||||
@@ -121,22 +125,51 @@ func Dial(network, addr string) (*Conn, error) {
|
|||||||
// DialTLS connects to the given address on the given network using tls.Dial
|
// DialTLS connects to the given address on the given network using tls.Dial
|
||||||
// and then returns a new Conn for the connection.
|
// and then returns a new Conn for the connection.
|
||||||
func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
|
func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
|
||||||
dc, err := net.DialTimeout(network, addr, DefaultTimeout)
|
c, err := tls.DialWithDialer(&net.Dialer{Timeout: DefaultTimeout}, network, addr, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, NewError(ErrorNetwork, err)
|
return nil, NewError(ErrorNetwork, err)
|
||||||
}
|
}
|
||||||
c := tls.Client(dc, config)
|
|
||||||
err = c.Handshake()
|
|
||||||
if err != nil {
|
|
||||||
// Handshake error, close the established connection before we return an error
|
|
||||||
dc.Close()
|
|
||||||
return nil, NewError(ErrorNetwork, err)
|
|
||||||
}
|
|
||||||
conn := NewConn(c, true)
|
conn := NewConn(c, true)
|
||||||
conn.Start()
|
conn.Start()
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DialURL connects to the given ldap URL vie TCP using tls.Dial or net.Dial if ldaps://
|
||||||
|
// or ldap:// specified as protocol. On success a new Conn for the connection
|
||||||
|
// is returned.
|
||||||
|
func DialURL(addr string) (*Conn, error) {
|
||||||
|
|
||||||
|
lurl, err := url.Parse(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, NewError(ErrorNetwork, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
host, port, err := net.SplitHostPort(lurl.Host)
|
||||||
|
if err != nil {
|
||||||
|
// we asume that error is due to missing port
|
||||||
|
host = lurl.Host
|
||||||
|
port = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
switch lurl.Scheme {
|
||||||
|
case "ldap":
|
||||||
|
if port == "" {
|
||||||
|
port = DefaultLdapPort
|
||||||
|
}
|
||||||
|
return Dial("tcp", net.JoinHostPort(host, port))
|
||||||
|
case "ldaps":
|
||||||
|
if port == "" {
|
||||||
|
port = DefaultLdapsPort
|
||||||
|
}
|
||||||
|
tlsConf := &tls.Config{
|
||||||
|
ServerName: host,
|
||||||
|
}
|
||||||
|
return DialTLS("tcp", net.JoinHostPort(host, port), tlsConf)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, NewError(ErrorNetwork, fmt.Errorf("Unknown scheme '%s'", lurl.Scheme))
|
||||||
|
}
|
||||||
|
|
||||||
// NewConn returns a new Conn using conn for network I/O.
|
// NewConn returns a new Conn using conn for network I/O.
|
||||||
func NewConn(conn net.Conn, isTLS bool) *Conn {
|
func NewConn(conn net.Conn, isTLS bool) *Conn {
|
||||||
return &Conn{
|
return &Conn{
|
||||||
@@ -242,18 +275,18 @@ func (l *Conn) StartTLS(config *tls.Config) error {
|
|||||||
ber.PrintPacket(packet)
|
ber.PrintPacket(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
if resultCode, message := getLDAPResultCode(packet); resultCode == LDAPResultSuccess {
|
if err := GetLDAPError(packet); err == nil {
|
||||||
conn := tls.Client(l.conn, config)
|
conn := tls.Client(l.conn, config)
|
||||||
|
|
||||||
if err := conn.Handshake(); err != nil {
|
if connErr := conn.Handshake(); connErr != nil {
|
||||||
l.Close()
|
l.Close()
|
||||||
return NewError(ErrorNetwork, fmt.Errorf("TLS handshake failed (%v)", err))
|
return NewError(ErrorNetwork, fmt.Errorf("TLS handshake failed (%v)", connErr))
|
||||||
}
|
}
|
||||||
|
|
||||||
l.isTLS = true
|
l.isTLS = true
|
||||||
l.conn = conn
|
l.conn = conn
|
||||||
} else {
|
} else {
|
||||||
return NewError(resultCode, fmt.Errorf("ldap: cannot StartTLS (%s)", message))
|
return err
|
||||||
}
|
}
|
||||||
go l.reader()
|
go l.reader()
|
||||||
|
|
||||||
|
|||||||
119
vendor/github.com/go-ldap/ldap/control.go
сгенерированный
поставляемый
119
vendor/github.com/go-ldap/ldap/control.go
сгенерированный
поставляемый
@@ -1,7 +1,3 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -22,13 +18,20 @@ const (
|
|||||||
ControlTypeVChuPasswordWarning = "2.16.840.1.113730.3.4.5"
|
ControlTypeVChuPasswordWarning = "2.16.840.1.113730.3.4.5"
|
||||||
// ControlTypeManageDsaIT - https://tools.ietf.org/html/rfc3296
|
// ControlTypeManageDsaIT - https://tools.ietf.org/html/rfc3296
|
||||||
ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
|
ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
|
||||||
|
|
||||||
|
// ControlTypeMicrosoftNotification - https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx
|
||||||
|
ControlTypeMicrosoftNotification = "1.2.840.113556.1.4.528"
|
||||||
|
// ControlTypeMicrosoftShowDeleted - https://msdn.microsoft.com/en-us/library/aa366989(v=vs.85).aspx
|
||||||
|
ControlTypeMicrosoftShowDeleted = "1.2.840.113556.1.4.417"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ControlTypeMap maps controls to text descriptions
|
// ControlTypeMap maps controls to text descriptions
|
||||||
var ControlTypeMap = map[string]string{
|
var ControlTypeMap = map[string]string{
|
||||||
ControlTypePaging: "Paging",
|
ControlTypePaging: "Paging",
|
||||||
ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
|
ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
|
||||||
ControlTypeManageDsaIT: "Manage DSA IT",
|
ControlTypeManageDsaIT: "Manage DSA IT",
|
||||||
|
ControlTypeMicrosoftNotification: "Change Notification - Microsoft",
|
||||||
|
ControlTypeMicrosoftShowDeleted: "Show Deleted Objects - Microsoft",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Control defines an interface controls provide to encode and describe themselves
|
// Control defines an interface controls provide to encode and describe themselves
|
||||||
@@ -242,6 +245,64 @@ func NewControlManageDsaIT(Criticality bool) *ControlManageDsaIT {
|
|||||||
return &ControlManageDsaIT{Criticality: Criticality}
|
return &ControlManageDsaIT{Criticality: Criticality}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlMicrosoftNotification implements the control described in https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx
|
||||||
|
type ControlMicrosoftNotification struct{}
|
||||||
|
|
||||||
|
// GetControlType returns the OID
|
||||||
|
func (c *ControlMicrosoftNotification) GetControlType() string {
|
||||||
|
return ControlTypeMicrosoftNotification
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode returns the ber packet representation
|
||||||
|
func (c *ControlMicrosoftNotification) Encode() *ber.Packet {
|
||||||
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
||||||
|
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeMicrosoftNotification, "Control Type ("+ControlTypeMap[ControlTypeMicrosoftNotification]+")"))
|
||||||
|
|
||||||
|
return packet
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable description
|
||||||
|
func (c *ControlMicrosoftNotification) String() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Control Type: %s (%q)",
|
||||||
|
ControlTypeMap[ControlTypeMicrosoftNotification],
|
||||||
|
ControlTypeMicrosoftNotification)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewControlMicrosoftNotification returns a ControlMicrosoftNotification control
|
||||||
|
func NewControlMicrosoftNotification() *ControlMicrosoftNotification {
|
||||||
|
return &ControlMicrosoftNotification{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ControlMicrosoftShowDeleted implements the control described in https://msdn.microsoft.com/en-us/library/aa366989(v=vs.85).aspx
|
||||||
|
type ControlMicrosoftShowDeleted struct{}
|
||||||
|
|
||||||
|
// GetControlType returns the OID
|
||||||
|
func (c *ControlMicrosoftShowDeleted) GetControlType() string {
|
||||||
|
return ControlTypeMicrosoftShowDeleted
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode returns the ber packet representation
|
||||||
|
func (c *ControlMicrosoftShowDeleted) Encode() *ber.Packet {
|
||||||
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
||||||
|
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeMicrosoftShowDeleted, "Control Type ("+ControlTypeMap[ControlTypeMicrosoftShowDeleted]+")"))
|
||||||
|
|
||||||
|
return packet
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable description
|
||||||
|
func (c *ControlMicrosoftShowDeleted) String() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Control Type: %s (%q)",
|
||||||
|
ControlTypeMap[ControlTypeMicrosoftShowDeleted],
|
||||||
|
ControlTypeMicrosoftShowDeleted)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewControlMicrosoftShowDeleted returns a ControlMicrosoftShowDeleted control
|
||||||
|
func NewControlMicrosoftShowDeleted() *ControlMicrosoftShowDeleted {
|
||||||
|
return &ControlMicrosoftShowDeleted{}
|
||||||
|
}
|
||||||
|
|
||||||
// FindControl returns the first control of the given type in the list, or nil
|
// FindControl returns the first control of the given type in the list, or nil
|
||||||
func FindControl(controls []Control, controlType string) Control {
|
func FindControl(controls []Control, controlType string) Control {
|
||||||
for _, c := range controls {
|
for _, c := range controls {
|
||||||
@@ -253,7 +314,7 @@ func FindControl(controls []Control, controlType string) Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DecodeControl returns a control read from the given packet, or nil if no recognized control can be made
|
// DecodeControl returns a control read from the given packet, or nil if no recognized control can be made
|
||||||
func DecodeControl(packet *ber.Packet) Control {
|
func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||||
var (
|
var (
|
||||||
ControlType = ""
|
ControlType = ""
|
||||||
Criticality = false
|
Criticality = false
|
||||||
@@ -263,7 +324,7 @@ func DecodeControl(packet *ber.Packet) Control {
|
|||||||
switch len(packet.Children) {
|
switch len(packet.Children) {
|
||||||
case 0:
|
case 0:
|
||||||
// at least one child is required for control type
|
// at least one child is required for control type
|
||||||
return nil
|
return nil, fmt.Errorf("at least one child is required for control type")
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
// just type, no criticality or value
|
// just type, no criticality or value
|
||||||
@@ -296,17 +357,20 @@ func DecodeControl(packet *ber.Packet) Control {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
// more than 3 children is invalid
|
// more than 3 children is invalid
|
||||||
return nil
|
return nil, fmt.Errorf("more than 3 children is invalid for controls")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ControlType {
|
switch ControlType {
|
||||||
case ControlTypeManageDsaIT:
|
case ControlTypeManageDsaIT:
|
||||||
return NewControlManageDsaIT(Criticality)
|
return NewControlManageDsaIT(Criticality), nil
|
||||||
case ControlTypePaging:
|
case ControlTypePaging:
|
||||||
value.Description += " (Paging)"
|
value.Description += " (Paging)"
|
||||||
c := new(ControlPaging)
|
c := new(ControlPaging)
|
||||||
if value.Value != nil {
|
if value.Value != nil {
|
||||||
valueChildren := ber.DecodePacket(value.Data.Bytes())
|
valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
|
}
|
||||||
value.Data.Truncate(0)
|
value.Data.Truncate(0)
|
||||||
value.Value = nil
|
value.Value = nil
|
||||||
value.AppendChild(valueChildren)
|
value.AppendChild(valueChildren)
|
||||||
@@ -318,12 +382,15 @@ func DecodeControl(packet *ber.Packet) Control {
|
|||||||
c.PagingSize = uint32(value.Children[0].Value.(int64))
|
c.PagingSize = uint32(value.Children[0].Value.(int64))
|
||||||
c.Cookie = value.Children[1].Data.Bytes()
|
c.Cookie = value.Children[1].Data.Bytes()
|
||||||
value.Children[1].Value = c.Cookie
|
value.Children[1].Value = c.Cookie
|
||||||
return c
|
return c, nil
|
||||||
case ControlTypeBeheraPasswordPolicy:
|
case ControlTypeBeheraPasswordPolicy:
|
||||||
value.Description += " (Password Policy - Behera)"
|
value.Description += " (Password Policy - Behera)"
|
||||||
c := NewControlBeheraPasswordPolicy()
|
c := NewControlBeheraPasswordPolicy()
|
||||||
if value.Value != nil {
|
if value.Value != nil {
|
||||||
valueChildren := ber.DecodePacket(value.Data.Bytes())
|
valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
|
}
|
||||||
value.Data.Truncate(0)
|
value.Data.Truncate(0)
|
||||||
value.Value = nil
|
value.Value = nil
|
||||||
value.AppendChild(valueChildren)
|
value.AppendChild(valueChildren)
|
||||||
@@ -335,7 +402,10 @@ func DecodeControl(packet *ber.Packet) Control {
|
|||||||
if child.Tag == 0 {
|
if child.Tag == 0 {
|
||||||
//Warning
|
//Warning
|
||||||
warningPacket := child.Children[0]
|
warningPacket := child.Children[0]
|
||||||
packet := ber.DecodePacket(warningPacket.Data.Bytes())
|
packet, err := ber.DecodePacketErr(warningPacket.Data.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
|
}
|
||||||
val, ok := packet.Value.(int64)
|
val, ok := packet.Value.(int64)
|
||||||
if ok {
|
if ok {
|
||||||
if warningPacket.Tag == 0 {
|
if warningPacket.Tag == 0 {
|
||||||
@@ -350,7 +420,10 @@ func DecodeControl(packet *ber.Packet) Control {
|
|||||||
}
|
}
|
||||||
} else if child.Tag == 1 {
|
} else if child.Tag == 1 {
|
||||||
// Error
|
// Error
|
||||||
packet := ber.DecodePacket(child.Data.Bytes())
|
packet, err := ber.DecodePacketErr(child.Data.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
|
}
|
||||||
val, ok := packet.Value.(int8)
|
val, ok := packet.Value.(int8)
|
||||||
if !ok {
|
if !ok {
|
||||||
// what to do?
|
// what to do?
|
||||||
@@ -361,22 +434,26 @@ func DecodeControl(packet *ber.Packet) Control {
|
|||||||
c.ErrorString = BeheraPasswordPolicyErrorMap[c.Error]
|
c.ErrorString = BeheraPasswordPolicyErrorMap[c.Error]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c
|
return c, nil
|
||||||
case ControlTypeVChuPasswordMustChange:
|
case ControlTypeVChuPasswordMustChange:
|
||||||
c := &ControlVChuPasswordMustChange{MustChange: true}
|
c := &ControlVChuPasswordMustChange{MustChange: true}
|
||||||
return c
|
return c, nil
|
||||||
case ControlTypeVChuPasswordWarning:
|
case ControlTypeVChuPasswordWarning:
|
||||||
c := &ControlVChuPasswordWarning{Expire: -1}
|
c := &ControlVChuPasswordWarning{Expire: -1}
|
||||||
expireStr := ber.DecodeString(value.Data.Bytes())
|
expireStr := ber.DecodeString(value.Data.Bytes())
|
||||||
|
|
||||||
expire, err := strconv.ParseInt(expireStr, 10, 64)
|
expire, err := strconv.ParseInt(expireStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil, fmt.Errorf("failed to parse value as int: %s", err)
|
||||||
}
|
}
|
||||||
c.Expire = expire
|
c.Expire = expire
|
||||||
value.Value = c.Expire
|
value.Value = c.Expire
|
||||||
|
|
||||||
return c
|
return c, nil
|
||||||
|
case ControlTypeMicrosoftNotification:
|
||||||
|
return NewControlMicrosoftNotification(), nil
|
||||||
|
case ControlTypeMicrosoftShowDeleted:
|
||||||
|
return NewControlMicrosoftShowDeleted(), nil
|
||||||
default:
|
default:
|
||||||
c := new(ControlString)
|
c := new(ControlString)
|
||||||
c.ControlType = ControlType
|
c.ControlType = ControlType
|
||||||
@@ -384,7 +461,7 @@ func DecodeControl(packet *ber.Packet) Control {
|
|||||||
if value != nil {
|
if value != nil {
|
||||||
c.ControlValue = value.Value.(string)
|
c.ControlValue = value.Value.(string)
|
||||||
}
|
}
|
||||||
return c
|
return c, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
vendor/github.com/go-ldap/ldap/del.go
сгенерированный
поставляемый
8
vendor/github.com/go-ldap/ldap/del.go
сгенерированный
поставляемый
@@ -40,7 +40,7 @@ func (l *Conn) Del(delRequest *DelRequest) error {
|
|||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
||||||
packet.AppendChild(delRequest.encode())
|
packet.AppendChild(delRequest.encode())
|
||||||
if delRequest.Controls != nil {
|
if len(delRequest.Controls) > 0 {
|
||||||
packet.AppendChild(encodeControls(delRequest.Controls))
|
packet.AppendChild(encodeControls(delRequest.Controls))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,9 +71,9 @@ func (l *Conn) Del(delRequest *DelRequest) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if packet.Children[1].Tag == ApplicationDelResponse {
|
if packet.Children[1].Tag == ApplicationDelResponse {
|
||||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
err := GetLDAPError(packet)
|
||||||
if resultCode != 0 {
|
if err != nil {
|
||||||
return NewError(resultCode, errors.New(resultDescription))
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
|
|||||||
30
vendor/github.com/go-ldap/ldap/dn.go
сгенерированный
поставляемый
30
vendor/github.com/go-ldap/ldap/dn.go
сгенерированный
поставляемый
@@ -1,7 +1,3 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
//
|
|
||||||
// File contains DN parsing functionality
|
// File contains DN parsing functionality
|
||||||
//
|
//
|
||||||
// https://tools.ietf.org/html/rfc4514
|
// https://tools.ietf.org/html/rfc4514
|
||||||
@@ -94,7 +90,8 @@ func ParseDN(str string) (*DN, error) {
|
|||||||
|
|
||||||
for i := 0; i < len(str); i++ {
|
for i := 0; i < len(str); i++ {
|
||||||
char := str[i]
|
char := str[i]
|
||||||
if escaping {
|
switch {
|
||||||
|
case escaping:
|
||||||
unescapedTrailingSpaces = 0
|
unescapedTrailingSpaces = 0
|
||||||
escaping = false
|
escaping = false
|
||||||
switch char {
|
switch char {
|
||||||
@@ -104,22 +101,22 @@ func ParseDN(str string) (*DN, error) {
|
|||||||
}
|
}
|
||||||
// Not a special character, assume hex encoded octet
|
// Not a special character, assume hex encoded octet
|
||||||
if len(str) == i+1 {
|
if len(str) == i+1 {
|
||||||
return nil, errors.New("Got corrupted escaped character")
|
return nil, errors.New("got corrupted escaped character")
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := []byte{0}
|
dst := []byte{0}
|
||||||
n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
|
n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to decode escaped character: %s", err)
|
return nil, fmt.Errorf("failed to decode escaped character: %s", err)
|
||||||
} else if n != 1 {
|
} else if n != 1 {
|
||||||
return nil, fmt.Errorf("Expected 1 byte when un-escaping, got %d", n)
|
return nil, fmt.Errorf("expected 1 byte when un-escaping, got %d", n)
|
||||||
}
|
}
|
||||||
buffer.WriteByte(dst[0])
|
buffer.WriteByte(dst[0])
|
||||||
i++
|
i++
|
||||||
} else if char == '\\' {
|
case char == '\\':
|
||||||
unescapedTrailingSpaces = 0
|
unescapedTrailingSpaces = 0
|
||||||
escaping = true
|
escaping = true
|
||||||
} else if char == '=' {
|
case char == '=':
|
||||||
attribute.Type = stringFromBuffer()
|
attribute.Type = stringFromBuffer()
|
||||||
// Special case: If the first character in the value is # the
|
// Special case: If the first character in the value is # the
|
||||||
// following data is BER encoded so we can just fast forward
|
// following data is BER encoded so we can just fast forward
|
||||||
@@ -135,13 +132,16 @@ func ParseDN(str string) (*DN, error) {
|
|||||||
}
|
}
|
||||||
rawBER, err := enchex.DecodeString(data)
|
rawBER, err := enchex.DecodeString(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to decode BER encoding: %s", err)
|
return nil, fmt.Errorf("failed to decode BER encoding: %s", err)
|
||||||
|
}
|
||||||
|
packet, err := ber.DecodePacketErr(rawBER)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode BER packet: %s", err)
|
||||||
}
|
}
|
||||||
packet := ber.DecodePacket(rawBER)
|
|
||||||
buffer.WriteString(packet.Data.String())
|
buffer.WriteString(packet.Data.String())
|
||||||
i += len(data) - 1
|
i += len(data) - 1
|
||||||
}
|
}
|
||||||
} else if char == ',' || char == '+' {
|
case char == ',' || char == '+':
|
||||||
// We're done with this RDN or value, push it
|
// We're done with this RDN or value, push it
|
||||||
if len(attribute.Type) == 0 {
|
if len(attribute.Type) == 0 {
|
||||||
return nil, errors.New("incomplete type, value pair")
|
return nil, errors.New("incomplete type, value pair")
|
||||||
@@ -154,10 +154,10 @@ func ParseDN(str string) (*DN, error) {
|
|||||||
rdn = new(RelativeDN)
|
rdn = new(RelativeDN)
|
||||||
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
|
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
|
||||||
}
|
}
|
||||||
} else if char == ' ' && buffer.Len() == 0 {
|
case char == ' ' && buffer.Len() == 0:
|
||||||
// ignore unescaped leading spaces
|
// ignore unescaped leading spaces
|
||||||
continue
|
continue
|
||||||
} else {
|
default:
|
||||||
if char == ' ' {
|
if char == ' ' {
|
||||||
// Track unescaped spaces in case they are trailing and we need to remove them
|
// Track unescaped spaces in case they are trailing and we need to remove them
|
||||||
unescapedTrailingSpaces++
|
unescapedTrailingSpaces++
|
||||||
|
|||||||
277
vendor/github.com/go-ldap/ldap/error.go
сгенерированный
поставляемый
277
vendor/github.com/go-ldap/ldap/error.go
сгенерированный
поставляемый
@@ -8,45 +8,79 @@ import (
|
|||||||
|
|
||||||
// LDAP Result Codes
|
// LDAP Result Codes
|
||||||
const (
|
const (
|
||||||
LDAPResultSuccess = 0
|
LDAPResultSuccess = 0
|
||||||
LDAPResultOperationsError = 1
|
LDAPResultOperationsError = 1
|
||||||
LDAPResultProtocolError = 2
|
LDAPResultProtocolError = 2
|
||||||
LDAPResultTimeLimitExceeded = 3
|
LDAPResultTimeLimitExceeded = 3
|
||||||
LDAPResultSizeLimitExceeded = 4
|
LDAPResultSizeLimitExceeded = 4
|
||||||
LDAPResultCompareFalse = 5
|
LDAPResultCompareFalse = 5
|
||||||
LDAPResultCompareTrue = 6
|
LDAPResultCompareTrue = 6
|
||||||
LDAPResultAuthMethodNotSupported = 7
|
LDAPResultAuthMethodNotSupported = 7
|
||||||
LDAPResultStrongAuthRequired = 8
|
LDAPResultStrongAuthRequired = 8
|
||||||
LDAPResultReferral = 10
|
LDAPResultReferral = 10
|
||||||
LDAPResultAdminLimitExceeded = 11
|
LDAPResultAdminLimitExceeded = 11
|
||||||
LDAPResultUnavailableCriticalExtension = 12
|
LDAPResultUnavailableCriticalExtension = 12
|
||||||
LDAPResultConfidentialityRequired = 13
|
LDAPResultConfidentialityRequired = 13
|
||||||
LDAPResultSaslBindInProgress = 14
|
LDAPResultSaslBindInProgress = 14
|
||||||
LDAPResultNoSuchAttribute = 16
|
LDAPResultNoSuchAttribute = 16
|
||||||
LDAPResultUndefinedAttributeType = 17
|
LDAPResultUndefinedAttributeType = 17
|
||||||
LDAPResultInappropriateMatching = 18
|
LDAPResultInappropriateMatching = 18
|
||||||
LDAPResultConstraintViolation = 19
|
LDAPResultConstraintViolation = 19
|
||||||
LDAPResultAttributeOrValueExists = 20
|
LDAPResultAttributeOrValueExists = 20
|
||||||
LDAPResultInvalidAttributeSyntax = 21
|
LDAPResultInvalidAttributeSyntax = 21
|
||||||
LDAPResultNoSuchObject = 32
|
LDAPResultNoSuchObject = 32
|
||||||
LDAPResultAliasProblem = 33
|
LDAPResultAliasProblem = 33
|
||||||
LDAPResultInvalidDNSyntax = 34
|
LDAPResultInvalidDNSyntax = 34
|
||||||
LDAPResultAliasDereferencingProblem = 36
|
LDAPResultIsLeaf = 35
|
||||||
LDAPResultInappropriateAuthentication = 48
|
LDAPResultAliasDereferencingProblem = 36
|
||||||
LDAPResultInvalidCredentials = 49
|
LDAPResultInappropriateAuthentication = 48
|
||||||
LDAPResultInsufficientAccessRights = 50
|
LDAPResultInvalidCredentials = 49
|
||||||
LDAPResultBusy = 51
|
LDAPResultInsufficientAccessRights = 50
|
||||||
LDAPResultUnavailable = 52
|
LDAPResultBusy = 51
|
||||||
LDAPResultUnwillingToPerform = 53
|
LDAPResultUnavailable = 52
|
||||||
LDAPResultLoopDetect = 54
|
LDAPResultUnwillingToPerform = 53
|
||||||
LDAPResultNamingViolation = 64
|
LDAPResultLoopDetect = 54
|
||||||
LDAPResultObjectClassViolation = 65
|
LDAPResultSortControlMissing = 60
|
||||||
LDAPResultNotAllowedOnNonLeaf = 66
|
LDAPResultOffsetRangeError = 61
|
||||||
LDAPResultNotAllowedOnRDN = 67
|
LDAPResultNamingViolation = 64
|
||||||
LDAPResultEntryAlreadyExists = 68
|
LDAPResultObjectClassViolation = 65
|
||||||
LDAPResultObjectClassModsProhibited = 69
|
LDAPResultNotAllowedOnNonLeaf = 66
|
||||||
LDAPResultAffectsMultipleDSAs = 71
|
LDAPResultNotAllowedOnRDN = 67
|
||||||
LDAPResultOther = 80
|
LDAPResultEntryAlreadyExists = 68
|
||||||
|
LDAPResultObjectClassModsProhibited = 69
|
||||||
|
LDAPResultResultsTooLarge = 70
|
||||||
|
LDAPResultAffectsMultipleDSAs = 71
|
||||||
|
LDAPResultVirtualListViewErrorOrControlError = 76
|
||||||
|
LDAPResultOther = 80
|
||||||
|
LDAPResultServerDown = 81
|
||||||
|
LDAPResultLocalError = 82
|
||||||
|
LDAPResultEncodingError = 83
|
||||||
|
LDAPResultDecodingError = 84
|
||||||
|
LDAPResultTimeout = 85
|
||||||
|
LDAPResultAuthUnknown = 86
|
||||||
|
LDAPResultFilterError = 87
|
||||||
|
LDAPResultUserCanceled = 88
|
||||||
|
LDAPResultParamError = 89
|
||||||
|
LDAPResultNoMemory = 90
|
||||||
|
LDAPResultConnectError = 91
|
||||||
|
LDAPResultNotSupported = 92
|
||||||
|
LDAPResultControlNotFound = 93
|
||||||
|
LDAPResultNoResultsReturned = 94
|
||||||
|
LDAPResultMoreResultsToReturn = 95
|
||||||
|
LDAPResultClientLoop = 96
|
||||||
|
LDAPResultReferralLimitExceeded = 97
|
||||||
|
LDAPResultInvalidResponse = 100
|
||||||
|
LDAPResultAmbiguousResponse = 101
|
||||||
|
LDAPResultTLSNotSupported = 112
|
||||||
|
LDAPResultIntermediateResponse = 113
|
||||||
|
LDAPResultUnknownType = 114
|
||||||
|
LDAPResultCanceled = 118
|
||||||
|
LDAPResultNoSuchOperation = 119
|
||||||
|
LDAPResultTooLate = 120
|
||||||
|
LDAPResultCannotCancel = 121
|
||||||
|
LDAPResultAssertionFailed = 122
|
||||||
|
LDAPResultAuthorizationDenied = 123
|
||||||
|
LDAPResultSyncRefreshRequired = 4096
|
||||||
|
|
||||||
ErrorNetwork = 200
|
ErrorNetwork = 200
|
||||||
ErrorFilterCompile = 201
|
ErrorFilterCompile = 201
|
||||||
@@ -54,49 +88,84 @@ const (
|
|||||||
ErrorDebugging = 203
|
ErrorDebugging = 203
|
||||||
ErrorUnexpectedMessage = 204
|
ErrorUnexpectedMessage = 204
|
||||||
ErrorUnexpectedResponse = 205
|
ErrorUnexpectedResponse = 205
|
||||||
|
ErrorEmptyPassword = 206
|
||||||
)
|
)
|
||||||
|
|
||||||
// LDAPResultCodeMap contains string descriptions for LDAP error codes
|
// LDAPResultCodeMap contains string descriptions for LDAP error codes
|
||||||
var LDAPResultCodeMap = map[uint8]string{
|
var LDAPResultCodeMap = map[uint16]string{
|
||||||
LDAPResultSuccess: "Success",
|
LDAPResultSuccess: "Success",
|
||||||
LDAPResultOperationsError: "Operations Error",
|
LDAPResultOperationsError: "Operations Error",
|
||||||
LDAPResultProtocolError: "Protocol Error",
|
LDAPResultProtocolError: "Protocol Error",
|
||||||
LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
|
LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
|
||||||
LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
|
LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
|
||||||
LDAPResultCompareFalse: "Compare False",
|
LDAPResultCompareFalse: "Compare False",
|
||||||
LDAPResultCompareTrue: "Compare True",
|
LDAPResultCompareTrue: "Compare True",
|
||||||
LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
|
LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
|
||||||
LDAPResultStrongAuthRequired: "Strong Auth Required",
|
LDAPResultStrongAuthRequired: "Strong Auth Required",
|
||||||
LDAPResultReferral: "Referral",
|
LDAPResultReferral: "Referral",
|
||||||
LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
|
LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
|
||||||
LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
|
LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
|
||||||
LDAPResultConfidentialityRequired: "Confidentiality Required",
|
LDAPResultConfidentialityRequired: "Confidentiality Required",
|
||||||
LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
|
LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
|
||||||
LDAPResultNoSuchAttribute: "No Such Attribute",
|
LDAPResultNoSuchAttribute: "No Such Attribute",
|
||||||
LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
|
LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
|
||||||
LDAPResultInappropriateMatching: "Inappropriate Matching",
|
LDAPResultInappropriateMatching: "Inappropriate Matching",
|
||||||
LDAPResultConstraintViolation: "Constraint Violation",
|
LDAPResultConstraintViolation: "Constraint Violation",
|
||||||
LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
|
LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
|
||||||
LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
|
LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
|
||||||
LDAPResultNoSuchObject: "No Such Object",
|
LDAPResultNoSuchObject: "No Such Object",
|
||||||
LDAPResultAliasProblem: "Alias Problem",
|
LDAPResultAliasProblem: "Alias Problem",
|
||||||
LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
|
LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
|
||||||
LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
|
LDAPResultIsLeaf: "Is Leaf",
|
||||||
LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
|
LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
|
||||||
LDAPResultInvalidCredentials: "Invalid Credentials",
|
LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
|
||||||
LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
|
LDAPResultInvalidCredentials: "Invalid Credentials",
|
||||||
LDAPResultBusy: "Busy",
|
LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
|
||||||
LDAPResultUnavailable: "Unavailable",
|
LDAPResultBusy: "Busy",
|
||||||
LDAPResultUnwillingToPerform: "Unwilling To Perform",
|
LDAPResultUnavailable: "Unavailable",
|
||||||
LDAPResultLoopDetect: "Loop Detect",
|
LDAPResultUnwillingToPerform: "Unwilling To Perform",
|
||||||
LDAPResultNamingViolation: "Naming Violation",
|
LDAPResultLoopDetect: "Loop Detect",
|
||||||
LDAPResultObjectClassViolation: "Object Class Violation",
|
LDAPResultSortControlMissing: "Sort Control Missing",
|
||||||
LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
|
LDAPResultOffsetRangeError: "Result Offset Range Error",
|
||||||
LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
|
LDAPResultNamingViolation: "Naming Violation",
|
||||||
LDAPResultEntryAlreadyExists: "Entry Already Exists",
|
LDAPResultObjectClassViolation: "Object Class Violation",
|
||||||
LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
|
LDAPResultResultsTooLarge: "Results Too Large",
|
||||||
LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
|
LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
|
||||||
LDAPResultOther: "Other",
|
LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
|
||||||
|
LDAPResultEntryAlreadyExists: "Entry Already Exists",
|
||||||
|
LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
|
||||||
|
LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
|
||||||
|
LDAPResultVirtualListViewErrorOrControlError: "Failed because of a problem related to the virtual list view",
|
||||||
|
LDAPResultOther: "Other",
|
||||||
|
LDAPResultServerDown: "Cannot establish a connection",
|
||||||
|
LDAPResultLocalError: "An error occurred",
|
||||||
|
LDAPResultEncodingError: "LDAP encountered an error while encoding",
|
||||||
|
LDAPResultDecodingError: "LDAP encountered an error while decoding",
|
||||||
|
LDAPResultTimeout: "LDAP timeout while waiting for a response from the server",
|
||||||
|
LDAPResultAuthUnknown: "The auth method requested in a bind request is unknown",
|
||||||
|
LDAPResultFilterError: "An error occurred while encoding the given search filter",
|
||||||
|
LDAPResultUserCanceled: "The user canceled the operation",
|
||||||
|
LDAPResultParamError: "An invalid parameter was specified",
|
||||||
|
LDAPResultNoMemory: "Out of memory error",
|
||||||
|
LDAPResultConnectError: "A connection to the server could not be established",
|
||||||
|
LDAPResultNotSupported: "An attempt has been made to use a feature not supported LDAP",
|
||||||
|
LDAPResultControlNotFound: "The controls required to perform the requested operation were not found",
|
||||||
|
LDAPResultNoResultsReturned: "No results were returned from the server",
|
||||||
|
LDAPResultMoreResultsToReturn: "There are more results in the chain of results",
|
||||||
|
LDAPResultClientLoop: "A loop has been detected. For example when following referrals",
|
||||||
|
LDAPResultReferralLimitExceeded: "The referral hop limit has been exceeded",
|
||||||
|
LDAPResultCanceled: "Operation was canceled",
|
||||||
|
LDAPResultNoSuchOperation: "Server has no knowledge of the operation requested for cancellation",
|
||||||
|
LDAPResultTooLate: "Too late to cancel the outstanding operation",
|
||||||
|
LDAPResultCannotCancel: "The identified operation does not support cancellation or the cancel operation cannot be performed",
|
||||||
|
LDAPResultAssertionFailed: "An assertion control given in the LDAP operation evaluated to false causing the operation to not be performed",
|
||||||
|
LDAPResultSyncRefreshRequired: "Refresh Required",
|
||||||
|
LDAPResultInvalidResponse: "Invalid Response",
|
||||||
|
LDAPResultAmbiguousResponse: "Ambiguous Response",
|
||||||
|
LDAPResultTLSNotSupported: "Tls Not Supported",
|
||||||
|
LDAPResultIntermediateResponse: "Intermediate Response",
|
||||||
|
LDAPResultUnknownType: "Unknown Type",
|
||||||
|
LDAPResultAuthorizationDenied: "Authorization Denied",
|
||||||
|
|
||||||
ErrorNetwork: "Network Error",
|
ErrorNetwork: "Network Error",
|
||||||
ErrorFilterCompile: "Filter Compile Error",
|
ErrorFilterCompile: "Filter Compile Error",
|
||||||
@@ -104,23 +173,7 @@ var LDAPResultCodeMap = map[uint8]string{
|
|||||||
ErrorDebugging: "Debugging Error",
|
ErrorDebugging: "Debugging Error",
|
||||||
ErrorUnexpectedMessage: "Unexpected Message",
|
ErrorUnexpectedMessage: "Unexpected Message",
|
||||||
ErrorUnexpectedResponse: "Unexpected Response",
|
ErrorUnexpectedResponse: "Unexpected Response",
|
||||||
}
|
ErrorEmptyPassword: "Empty password not allowed by the client",
|
||||||
|
|
||||||
func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
|
|
||||||
if packet == nil {
|
|
||||||
return ErrorUnexpectedResponse, "Empty packet"
|
|
||||||
} else if len(packet.Children) >= 2 {
|
|
||||||
response := packet.Children[1]
|
|
||||||
if response == nil {
|
|
||||||
return ErrorUnexpectedResponse, "Empty response in packet"
|
|
||||||
}
|
|
||||||
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
|
|
||||||
// Children[1].Children[2] is the diagnosticMessage which is guaranteed to exist as seen here: https://tools.ietf.org/html/rfc4511#section-4.1.9
|
|
||||||
return uint8(response.Children[0].Value.(int64)), response.Children[2].Value.(string)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrorNetwork, "Invalid packet format"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error holds LDAP error information
|
// Error holds LDAP error information
|
||||||
@@ -128,20 +181,46 @@ type Error struct {
|
|||||||
// Err is the underlying error
|
// Err is the underlying error
|
||||||
Err error
|
Err error
|
||||||
// ResultCode is the LDAP error code
|
// ResultCode is the LDAP error code
|
||||||
ResultCode uint8
|
ResultCode uint16
|
||||||
|
// MatchedDN is the matchedDN returned if any
|
||||||
|
MatchedDN string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Error) Error() string {
|
func (e *Error) Error() string {
|
||||||
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
|
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLDAPError creates an Error out of a BER packet representing a LDAPResult
|
||||||
|
// The return is an error object. It can be casted to a Error structure.
|
||||||
|
// This function returns nil if resultCode in the LDAPResult sequence is success(0).
|
||||||
|
func GetLDAPError(packet *ber.Packet) error {
|
||||||
|
if packet == nil {
|
||||||
|
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty packet")}
|
||||||
|
} else if len(packet.Children) >= 2 {
|
||||||
|
response := packet.Children[1]
|
||||||
|
if response == nil {
|
||||||
|
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet")}
|
||||||
|
}
|
||||||
|
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
|
||||||
|
resultCode := uint16(response.Children[0].Value.(int64))
|
||||||
|
if resultCode == 0 { // No error
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &Error{ResultCode: resultCode, MatchedDN: response.Children[1].Value.(string),
|
||||||
|
Err: fmt.Errorf(response.Children[2].Value.(string))}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")}
|
||||||
|
}
|
||||||
|
|
||||||
// NewError creates an LDAP error with the given code and underlying error
|
// NewError creates an LDAP error with the given code and underlying error
|
||||||
func NewError(resultCode uint8, err error) error {
|
func NewError(resultCode uint16, err error) error {
|
||||||
return &Error{ResultCode: resultCode, Err: err}
|
return &Error{ResultCode: resultCode, Err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
|
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
|
||||||
func IsErrorWithCode(err error, desiredResultCode uint8) bool {
|
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
4
vendor/github.com/go-ldap/ldap/filter.go
сгенерированный
поставляемый
4
vendor/github.com/go-ldap/ldap/filter.go
сгенерированный
поставляемый
@@ -1,7 +1,3 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
86
vendor/github.com/go-ldap/ldap/ldap.go
сгенерированный
поставляемый
86
vendor/github.com/go-ldap/ldap/ldap.go
сгенерированный
поставляемый
@@ -1,11 +1,8 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@@ -101,13 +98,13 @@ func addLDAPDescriptions(packet *ber.Packet) (err error) {
|
|||||||
|
|
||||||
switch application {
|
switch application {
|
||||||
case ApplicationBindRequest:
|
case ApplicationBindRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationBindResponse:
|
case ApplicationBindResponse:
|
||||||
addDefaultLDAPResponseDescriptions(packet)
|
err = addDefaultLDAPResponseDescriptions(packet)
|
||||||
case ApplicationUnbindRequest:
|
case ApplicationUnbindRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationSearchRequest:
|
case ApplicationSearchRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationSearchResultEntry:
|
case ApplicationSearchResultEntry:
|
||||||
packet.Children[1].Children[0].Description = "Object Name"
|
packet.Children[1].Children[0].Description = "Object Name"
|
||||||
packet.Children[1].Children[1].Description = "Attributes"
|
packet.Children[1].Children[1].Description = "Attributes"
|
||||||
@@ -120,37 +117,37 @@ func addLDAPDescriptions(packet *ber.Packet) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(packet.Children) == 3 {
|
if len(packet.Children) == 3 {
|
||||||
addControlDescriptions(packet.Children[2])
|
err = addControlDescriptions(packet.Children[2])
|
||||||
}
|
}
|
||||||
case ApplicationSearchResultDone:
|
case ApplicationSearchResultDone:
|
||||||
addDefaultLDAPResponseDescriptions(packet)
|
err = addDefaultLDAPResponseDescriptions(packet)
|
||||||
case ApplicationModifyRequest:
|
case ApplicationModifyRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationModifyResponse:
|
case ApplicationModifyResponse:
|
||||||
case ApplicationAddRequest:
|
case ApplicationAddRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationAddResponse:
|
case ApplicationAddResponse:
|
||||||
case ApplicationDelRequest:
|
case ApplicationDelRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationDelResponse:
|
case ApplicationDelResponse:
|
||||||
case ApplicationModifyDNRequest:
|
case ApplicationModifyDNRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationModifyDNResponse:
|
case ApplicationModifyDNResponse:
|
||||||
case ApplicationCompareRequest:
|
case ApplicationCompareRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationCompareResponse:
|
case ApplicationCompareResponse:
|
||||||
case ApplicationAbandonRequest:
|
case ApplicationAbandonRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationSearchResultReference:
|
case ApplicationSearchResultReference:
|
||||||
case ApplicationExtendedRequest:
|
case ApplicationExtendedRequest:
|
||||||
addRequestDescriptions(packet)
|
err = addRequestDescriptions(packet)
|
||||||
case ApplicationExtendedResponse:
|
case ApplicationExtendedResponse:
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func addControlDescriptions(packet *ber.Packet) {
|
func addControlDescriptions(packet *ber.Packet) error {
|
||||||
packet.Description = "Controls"
|
packet.Description = "Controls"
|
||||||
for _, child := range packet.Children {
|
for _, child := range packet.Children {
|
||||||
var value *ber.Packet
|
var value *ber.Packet
|
||||||
@@ -159,7 +156,7 @@ func addControlDescriptions(packet *ber.Packet) {
|
|||||||
switch len(child.Children) {
|
switch len(child.Children) {
|
||||||
case 0:
|
case 0:
|
||||||
// at least one child is required for control type
|
// at least one child is required for control type
|
||||||
continue
|
return fmt.Errorf("at least one child is required for control type")
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
// just type, no criticality or value
|
// just type, no criticality or value
|
||||||
@@ -188,8 +185,9 @@ func addControlDescriptions(packet *ber.Packet) {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
// more than 3 children is invalid
|
// more than 3 children is invalid
|
||||||
continue
|
return fmt.Errorf("more than 3 children for control packet found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -197,7 +195,10 @@ func addControlDescriptions(packet *ber.Packet) {
|
|||||||
case ControlTypePaging:
|
case ControlTypePaging:
|
||||||
value.Description += " (Paging)"
|
value.Description += " (Paging)"
|
||||||
if value.Value != nil {
|
if value.Value != nil {
|
||||||
valueChildren := ber.DecodePacket(value.Data.Bytes())
|
valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
|
}
|
||||||
value.Data.Truncate(0)
|
value.Data.Truncate(0)
|
||||||
value.Value = nil
|
value.Value = nil
|
||||||
valueChildren.Children[1].Value = valueChildren.Children[1].Data.Bytes()
|
valueChildren.Children[1].Value = valueChildren.Children[1].Data.Bytes()
|
||||||
@@ -210,7 +211,10 @@ func addControlDescriptions(packet *ber.Packet) {
|
|||||||
case ControlTypeBeheraPasswordPolicy:
|
case ControlTypeBeheraPasswordPolicy:
|
||||||
value.Description += " (Password Policy - Behera Draft)"
|
value.Description += " (Password Policy - Behera Draft)"
|
||||||
if value.Value != nil {
|
if value.Value != nil {
|
||||||
valueChildren := ber.DecodePacket(value.Data.Bytes())
|
valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
|
}
|
||||||
value.Data.Truncate(0)
|
value.Data.Truncate(0)
|
||||||
value.Value = nil
|
value.Value = nil
|
||||||
value.AppendChild(valueChildren)
|
value.AppendChild(valueChildren)
|
||||||
@@ -220,7 +224,10 @@ func addControlDescriptions(packet *ber.Packet) {
|
|||||||
if child.Tag == 0 {
|
if child.Tag == 0 {
|
||||||
//Warning
|
//Warning
|
||||||
warningPacket := child.Children[0]
|
warningPacket := child.Children[0]
|
||||||
packet := ber.DecodePacket(warningPacket.Data.Bytes())
|
packet, err := ber.DecodePacketErr(warningPacket.Data.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
|
}
|
||||||
val, ok := packet.Value.(int64)
|
val, ok := packet.Value.(int64)
|
||||||
if ok {
|
if ok {
|
||||||
if warningPacket.Tag == 0 {
|
if warningPacket.Tag == 0 {
|
||||||
@@ -235,7 +242,10 @@ func addControlDescriptions(packet *ber.Packet) {
|
|||||||
}
|
}
|
||||||
} else if child.Tag == 1 {
|
} else if child.Tag == 1 {
|
||||||
// Error
|
// Error
|
||||||
packet := ber.DecodePacket(child.Data.Bytes())
|
packet, err := ber.DecodePacketErr(child.Data.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to decode data bytes: %s", err)
|
||||||
|
}
|
||||||
val, ok := packet.Value.(int8)
|
val, ok := packet.Value.(int8)
|
||||||
if !ok {
|
if !ok {
|
||||||
val = -1
|
val = -1
|
||||||
@@ -246,28 +256,31 @@ func addControlDescriptions(packet *ber.Packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addRequestDescriptions(packet *ber.Packet) {
|
func addRequestDescriptions(packet *ber.Packet) error {
|
||||||
packet.Description = "LDAP Request"
|
packet.Description = "LDAP Request"
|
||||||
packet.Children[0].Description = "Message ID"
|
packet.Children[0].Description = "Message ID"
|
||||||
packet.Children[1].Description = ApplicationMap[uint8(packet.Children[1].Tag)]
|
packet.Children[1].Description = ApplicationMap[uint8(packet.Children[1].Tag)]
|
||||||
if len(packet.Children) == 3 {
|
if len(packet.Children) == 3 {
|
||||||
addControlDescriptions(packet.Children[2])
|
return addControlDescriptions(packet.Children[2])
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
|
func addDefaultLDAPResponseDescriptions(packet *ber.Packet) error {
|
||||||
resultCode, _ := getLDAPResultCode(packet)
|
err := GetLDAPError(packet)
|
||||||
packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[resultCode] + ")"
|
packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[err.(*Error).ResultCode] + ")"
|
||||||
packet.Children[1].Children[1].Description = "Matched DN"
|
packet.Children[1].Children[1].Description = "Matched DN (" + err.(*Error).MatchedDN + ")"
|
||||||
packet.Children[1].Children[2].Description = "Error Message"
|
packet.Children[1].Children[2].Description = "Error Message"
|
||||||
if len(packet.Children[1].Children) > 3 {
|
if len(packet.Children[1].Children) > 3 {
|
||||||
packet.Children[1].Children[3].Description = "Referral"
|
packet.Children[1].Children[3].Description = "Referral"
|
||||||
}
|
}
|
||||||
if len(packet.Children) == 3 {
|
if len(packet.Children) == 3 {
|
||||||
addControlDescriptions(packet.Children[2])
|
return addControlDescriptions(packet.Children[2])
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DebugBinaryFile reads and prints packets from the given filename
|
// DebugBinaryFile reads and prints packets from the given filename
|
||||||
@@ -277,8 +290,13 @@ func DebugBinaryFile(fileName string) error {
|
|||||||
return NewError(ErrorDebugging, err)
|
return NewError(ErrorDebugging, err)
|
||||||
}
|
}
|
||||||
ber.PrintBytes(os.Stdout, file, "")
|
ber.PrintBytes(os.Stdout, file, "")
|
||||||
packet := ber.DecodePacket(file)
|
packet, err := ber.DecodePacketErr(file)
|
||||||
addLDAPDescriptions(packet)
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to decode packet: %s", err)
|
||||||
|
}
|
||||||
|
if err := addLDAPDescriptions(packet); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
ber.PrintPacket(packet)
|
ber.PrintPacket(packet)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
104
vendor/github.com/go-ldap/ldap/moddn.go
сгенерированный
поставляемый
Обычный файл
104
vendor/github.com/go-ldap/ldap/moddn.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,104 @@
|
|||||||
|
// Package ldap - moddn.go contains ModifyDN functionality
|
||||||
|
//
|
||||||
|
// https://tools.ietf.org/html/rfc4511
|
||||||
|
// ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
|
||||||
|
// entry LDAPDN,
|
||||||
|
// newrdn RelativeLDAPDN,
|
||||||
|
// deleteoldrdn BOOLEAN,
|
||||||
|
// newSuperior [0] LDAPDN OPTIONAL }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
package ldap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"gopkg.in/asn1-ber.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModifyDNRequest holds the request to modify a DN
|
||||||
|
type ModifyDNRequest struct {
|
||||||
|
DN string
|
||||||
|
NewRDN string
|
||||||
|
DeleteOldRDN bool
|
||||||
|
NewSuperior string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewModifyDNRequest creates a new request which can be passed to ModifyDN().
|
||||||
|
//
|
||||||
|
// To move an object in the tree, set the "newSup" to the new parent entry DN. Use an
|
||||||
|
// empty string for just changing the object's RDN.
|
||||||
|
//
|
||||||
|
// For moving the object without renaming, the "rdn" must be the first
|
||||||
|
// RDN of the given DN.
|
||||||
|
//
|
||||||
|
// A call like
|
||||||
|
// mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "")
|
||||||
|
// will setup the request to just rename uid=someone,dc=example,dc=org to
|
||||||
|
// uid=newname,dc=example,dc=org.
|
||||||
|
func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ModifyDNRequest {
|
||||||
|
return &ModifyDNRequest{
|
||||||
|
DN: dn,
|
||||||
|
NewRDN: rdn,
|
||||||
|
DeleteOldRDN: delOld,
|
||||||
|
NewSuperior: newSup,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m ModifyDNRequest) encode() *ber.Packet {
|
||||||
|
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyDNRequest, nil, "Modify DN Request")
|
||||||
|
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN"))
|
||||||
|
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.NewRDN, "New RDN"))
|
||||||
|
request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, m.DeleteOldRDN, "Delete old RDN"))
|
||||||
|
if m.NewSuperior != "" {
|
||||||
|
request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, m.NewSuperior, "New Superior"))
|
||||||
|
}
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyDN renames the given DN and optionally move to another base (when the "newSup" argument
|
||||||
|
// to NewModifyDNRequest() is not "").
|
||||||
|
func (l *Conn) ModifyDN(m *ModifyDNRequest) error {
|
||||||
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||||
|
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
||||||
|
packet.AppendChild(m.encode())
|
||||||
|
|
||||||
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
|
msgCtx, err := l.sendMessage(packet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer l.finishMessage(msgCtx)
|
||||||
|
|
||||||
|
l.Debug.Printf("%d: waiting for response", msgCtx.id)
|
||||||
|
packetResponse, ok := <-msgCtx.responses
|
||||||
|
if !ok {
|
||||||
|
return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
|
||||||
|
}
|
||||||
|
packet, err = packetResponse.ReadPacket()
|
||||||
|
l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.Debug {
|
||||||
|
if err := addLDAPDescriptions(packet); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ber.PrintPacket(packet)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.Children[1].Tag == ApplicationModifyDNResponse {
|
||||||
|
err := GetLDAPError(packet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Debug.Printf("%d: returning", msgCtx.id)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
77
vendor/github.com/go-ldap/ldap/modify.go
сгенерированный
поставляемый
77
vendor/github.com/go-ldap/ldap/modify.go
сгенерированный
поставляемый
@@ -1,7 +1,3 @@
|
|||||||
// Copyright 2014 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
//
|
|
||||||
// File contains Modify functionality
|
// File contains Modify functionality
|
||||||
//
|
//
|
||||||
// https://tools.ietf.org/html/rfc4511
|
// https://tools.ietf.org/html/rfc4511
|
||||||
@@ -62,54 +58,56 @@ func (p *PartialAttribute) encode() *ber.Packet {
|
|||||||
return seq
|
return seq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
|
||||||
|
type Change struct {
|
||||||
|
// Operation is the type of change to be made
|
||||||
|
Operation uint
|
||||||
|
// Modification is the attribute to be modified
|
||||||
|
Modification PartialAttribute
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Change) encode() *ber.Packet {
|
||||||
|
change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
|
||||||
|
change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(c.Operation), "Operation"))
|
||||||
|
change.AppendChild(c.Modification.encode())
|
||||||
|
return change
|
||||||
|
}
|
||||||
|
|
||||||
// ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
|
// ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
|
||||||
type ModifyRequest struct {
|
type ModifyRequest struct {
|
||||||
// DN is the distinguishedName of the directory entry to modify
|
// DN is the distinguishedName of the directory entry to modify
|
||||||
DN string
|
DN string
|
||||||
// AddAttributes contain the attributes to add
|
// Changes contain the attributes to modify
|
||||||
AddAttributes []PartialAttribute
|
Changes []Change
|
||||||
// DeleteAttributes contain the attributes to delete
|
// Controls hold optional controls to send with the request
|
||||||
DeleteAttributes []PartialAttribute
|
Controls []Control
|
||||||
// ReplaceAttributes contain the attributes to replace
|
|
||||||
ReplaceAttributes []PartialAttribute
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add inserts the given attribute to the list of attributes to add
|
// Add appends the given attribute to the list of changes to be made
|
||||||
func (m *ModifyRequest) Add(attrType string, attrVals []string) {
|
func (m *ModifyRequest) Add(attrType string, attrVals []string) {
|
||||||
m.AddAttributes = append(m.AddAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
|
m.appendChange(AddAttribute, attrType, attrVals)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete inserts the given attribute to the list of attributes to delete
|
// Delete appends the given attribute to the list of changes to be made
|
||||||
func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
|
func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
|
||||||
m.DeleteAttributes = append(m.DeleteAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
|
m.appendChange(DeleteAttribute, attrType, attrVals)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace inserts the given attribute to the list of attributes to replace
|
// Replace appends the given attribute to the list of changes to be made
|
||||||
func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
|
func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
|
||||||
m.ReplaceAttributes = append(m.ReplaceAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
|
m.appendChange(ReplaceAttribute, attrType, attrVals)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ModifyRequest) appendChange(operation uint, attrType string, attrVals []string) {
|
||||||
|
m.Changes = append(m.Changes, Change{operation, PartialAttribute{Type: attrType, Vals: attrVals}})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m ModifyRequest) encode() *ber.Packet {
|
func (m ModifyRequest) encode() *ber.Packet {
|
||||||
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
|
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
|
||||||
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN"))
|
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN"))
|
||||||
changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
|
changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
|
||||||
for _, attribute := range m.AddAttributes {
|
for _, change := range m.Changes {
|
||||||
change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
|
changes.AppendChild(change.encode())
|
||||||
change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(AddAttribute), "Operation"))
|
|
||||||
change.AppendChild(attribute.encode())
|
|
||||||
changes.AppendChild(change)
|
|
||||||
}
|
|
||||||
for _, attribute := range m.DeleteAttributes {
|
|
||||||
change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
|
|
||||||
change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(DeleteAttribute), "Operation"))
|
|
||||||
change.AppendChild(attribute.encode())
|
|
||||||
changes.AppendChild(change)
|
|
||||||
}
|
|
||||||
for _, attribute := range m.ReplaceAttributes {
|
|
||||||
change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
|
|
||||||
change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ReplaceAttribute), "Operation"))
|
|
||||||
change.AppendChild(attribute.encode())
|
|
||||||
changes.AppendChild(change)
|
|
||||||
}
|
}
|
||||||
request.AppendChild(changes)
|
request.AppendChild(changes)
|
||||||
return request
|
return request
|
||||||
@@ -118,9 +116,11 @@ func (m ModifyRequest) encode() *ber.Packet {
|
|||||||
// NewModifyRequest creates a modify request for the given DN
|
// NewModifyRequest creates a modify request for the given DN
|
||||||
func NewModifyRequest(
|
func NewModifyRequest(
|
||||||
dn string,
|
dn string,
|
||||||
|
controls []Control,
|
||||||
) *ModifyRequest {
|
) *ModifyRequest {
|
||||||
return &ModifyRequest{
|
return &ModifyRequest{
|
||||||
DN: dn,
|
DN: dn,
|
||||||
|
Controls: controls,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,6 +129,9 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
|
|||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
||||||
packet.AppendChild(modifyRequest.encode())
|
packet.AppendChild(modifyRequest.encode())
|
||||||
|
if len(modifyRequest.Controls) > 0 {
|
||||||
|
packet.AppendChild(encodeControls(modifyRequest.Controls))
|
||||||
|
}
|
||||||
|
|
||||||
l.Debug.PrintPacket(packet)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
@@ -157,9 +160,9 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if packet.Children[1].Tag == ApplicationModifyResponse {
|
if packet.Children[1].Tag == ApplicationModifyResponse {
|
||||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
err := GetLDAPError(packet)
|
||||||
if resultCode != 0 {
|
if err != nil {
|
||||||
return NewError(resultCode, errors.New(resultDescription))
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
|
|||||||
17
vendor/github.com/go-ldap/ldap/passwdmodify.go
сгенерированный
поставляемый
17
vendor/github.com/go-ldap/ldap/passwdmodify.go
сгенерированный
поставляемый
@@ -32,6 +32,8 @@ type PasswordModifyRequest struct {
|
|||||||
type PasswordModifyResult struct {
|
type PasswordModifyResult struct {
|
||||||
// GeneratedPassword holds a password generated by the server, if present
|
// GeneratedPassword holds a password generated by the server, if present
|
||||||
GeneratedPassword string
|
GeneratedPassword string
|
||||||
|
// Referral are the returned referral
|
||||||
|
Referral string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *PasswordModifyRequest) encode() (*ber.Packet, error) {
|
func (r *PasswordModifyRequest) encode() (*ber.Packet, error) {
|
||||||
@@ -124,12 +126,19 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
if packet.Children[1].Tag == ApplicationExtendedResponse {
|
if packet.Children[1].Tag == ApplicationExtendedResponse {
|
||||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
err := GetLDAPError(packet)
|
||||||
if resultCode != 0 {
|
if err != nil {
|
||||||
return nil, NewError(resultCode, errors.New(resultDescription))
|
if IsErrorWithCode(err, LDAPResultReferral) {
|
||||||
|
for _, child := range packet.Children[1].Children {
|
||||||
|
if child.Tag == 3 {
|
||||||
|
result.Referral = child.Children[0].Value.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, NewError(ErrorUnexpectedResponse, fmt.Errorf("Unexpected Response: %d", packet.Children[1].Tag))
|
return nil, NewError(ErrorUnexpectedResponse, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
extendedResponse := packet.Children[1]
|
extendedResponse := packet.Children[1]
|
||||||
|
|||||||
22
vendor/github.com/go-ldap/ldap/search.go
сгенерированный
поставляемый
22
vendor/github.com/go-ldap/ldap/search.go
сгенерированный
поставляемый
@@ -1,7 +1,3 @@
|
|||||||
// Copyright 2011 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
//
|
|
||||||
// File contains Search functionality
|
// File contains Search functionality
|
||||||
//
|
//
|
||||||
// https://tools.ietf.org/html/rfc4511
|
// https://tools.ietf.org/html/rfc4511
|
||||||
@@ -313,10 +309,10 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
|
|||||||
} else {
|
} else {
|
||||||
castControl, ok := control.(*ControlPaging)
|
castControl, ok := control.(*ControlPaging)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("Expected paging control to be of type *ControlPaging, got %v", control)
|
return nil, fmt.Errorf("expected paging control to be of type *ControlPaging, got %v", control)
|
||||||
}
|
}
|
||||||
if castControl.PagingSize != pagingSize {
|
if castControl.PagingSize != pagingSize {
|
||||||
return nil, fmt.Errorf("Paging size given in search request (%d) conflicts with size given in search call (%d)", castControl.PagingSize, pagingSize)
|
return nil, fmt.Errorf("paging size given in search request (%d) conflicts with size given in search call (%d)", castControl.PagingSize, pagingSize)
|
||||||
}
|
}
|
||||||
pagingControl = castControl
|
pagingControl = castControl
|
||||||
}
|
}
|
||||||
@@ -379,7 +375,7 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
|||||||
}
|
}
|
||||||
packet.AppendChild(encodedSearchRequest)
|
packet.AppendChild(encodedSearchRequest)
|
||||||
// encode search controls
|
// encode search controls
|
||||||
if searchRequest.Controls != nil {
|
if len(searchRequest.Controls) > 0 {
|
||||||
packet.AppendChild(encodeControls(searchRequest.Controls))
|
packet.AppendChild(encodeControls(searchRequest.Controls))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,13 +427,17 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
|||||||
}
|
}
|
||||||
result.Entries = append(result.Entries, entry)
|
result.Entries = append(result.Entries, entry)
|
||||||
case 5:
|
case 5:
|
||||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
err := GetLDAPError(packet)
|
||||||
if resultCode != 0 {
|
if err != nil {
|
||||||
return result, NewError(resultCode, errors.New(resultDescription))
|
return nil, err
|
||||||
}
|
}
|
||||||
if len(packet.Children) == 3 {
|
if len(packet.Children) == 3 {
|
||||||
for _, child := range packet.Children[2].Children {
|
for _, child := range packet.Children[2].Children {
|
||||||
result.Controls = append(result.Controls, DecodeControl(child))
|
decodedChild, err := DecodeControl(child)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode child control: %s", err)
|
||||||
|
}
|
||||||
|
result.Controls = append(result.Controls, decodedChild)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foundSearchResultDone = true
|
foundSearchResultDone = true
|
||||||
|
|||||||
1
vendor/github.com/go-redis/redis/.travis.yml
сгенерированный
поставляемый
1
vendor/github.com/go-redis/redis/.travis.yml
сгенерированный
поставляемый
@@ -9,6 +9,7 @@ go:
|
|||||||
- 1.8.x
|
- 1.8.x
|
||||||
- 1.9.x
|
- 1.9.x
|
||||||
- 1.10.x
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
|
|||||||
4
vendor/github.com/go-redis/redis/CHANGELOG.md
сгенерированный
поставляемый
4
vendor/github.com/go-redis/redis/CHANGELOG.md
сгенерированный
поставляемый
@@ -1,5 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Cluster and Ring pipelines process commands for each node in its own goroutine.
|
||||||
|
|
||||||
## 6.14
|
## 6.14
|
||||||
|
|
||||||
- Added Options.MinIdleConns.
|
- Added Options.MinIdleConns.
|
||||||
|
|||||||
145
vendor/github.com/go-redis/redis/cluster.go
сгенерированный
поставляемый
145
vendor/github.com/go-redis/redis/cluster.go
сгенерированный
поставляемый
@@ -82,7 +82,7 @@ func (opt *ClusterOptions) init() {
|
|||||||
opt.MaxRedirects = 8
|
opt.MaxRedirects = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
if opt.RouteByLatency || opt.RouteRandomly {
|
if (opt.RouteByLatency || opt.RouteRandomly) && opt.ClusterSlots == nil {
|
||||||
opt.ReadOnly = true
|
opt.ReadOnly = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -831,7 +831,7 @@ func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) {
|
|||||||
cmdInfo := c.cmdInfo(cmd.Name())
|
cmdInfo := c.cmdInfo(cmd.Name())
|
||||||
slot := cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo))
|
slot := cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
|
|
||||||
if cmdInfo != nil && cmdInfo.ReadOnly && c.opt.ReadOnly {
|
if c.opt.ReadOnly && cmdInfo != nil && cmdInfo.ReadOnly {
|
||||||
if c.opt.RouteByLatency {
|
if c.opt.RouteByLatency {
|
||||||
node, err := state.slotClosestNode(slot)
|
node, err := state.slotClosestNode(slot)
|
||||||
return slot, node, err
|
return slot, node, err
|
||||||
@@ -1241,7 +1241,8 @@ func (c *ClusterClient) WrapProcessPipeline(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error {
|
func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error {
|
||||||
cmdsMap, err := c.mapCmdsByNode(cmds)
|
cmdsMap := newCmdsMap()
|
||||||
|
err := c.mapCmdsByNode(cmds, cmdsMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
return err
|
return err
|
||||||
@@ -1252,28 +1253,31 @@ func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error {
|
|||||||
time.Sleep(c.retryBackoff(attempt))
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
}
|
}
|
||||||
|
|
||||||
failedCmds := make(map[*clusterNode][]Cmder)
|
failedCmds := newCmdsMap()
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
for node, cmds := range cmdsMap {
|
for node, cmds := range cmdsMap.m {
|
||||||
cn, err := node.Client.getConn()
|
wg.Add(1)
|
||||||
if err != nil {
|
go func(node *clusterNode, cmds []Cmder) {
|
||||||
if err == pool.ErrClosed {
|
defer wg.Done()
|
||||||
c.remapCmds(cmds, failedCmds)
|
|
||||||
} else {
|
cn, err := node.Client.getConn()
|
||||||
setCmdsErr(cmds, err)
|
if err != nil {
|
||||||
|
if err == pool.ErrClosed {
|
||||||
|
c.mapCmdsByNode(cmds, failedCmds)
|
||||||
|
} else {
|
||||||
|
setCmdsErr(cmds, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.pipelineProcessCmds(node, cn, cmds, failedCmds)
|
err = c.pipelineProcessCmds(node, cn, cmds, failedCmds)
|
||||||
if err == nil || internal.IsRedisError(err) {
|
node.Client.releaseConnStrict(cn, err)
|
||||||
node.Client.connPool.Put(cn)
|
}(node, cmds)
|
||||||
} else {
|
|
||||||
node.Client.connPool.Remove(cn)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(failedCmds) == 0 {
|
wg.Wait()
|
||||||
|
if len(failedCmds.m) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
cmdsMap = failedCmds
|
cmdsMap = failedCmds
|
||||||
@@ -1282,14 +1286,24 @@ func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error {
|
|||||||
return cmdsFirstErr(cmds)
|
return cmdsFirstErr(cmds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, error) {
|
type cmdsMap struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
m map[*clusterNode][]Cmder
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCmdsMap() *cmdsMap {
|
||||||
|
return &cmdsMap{
|
||||||
|
m: make(map[*clusterNode][]Cmder),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ClusterClient) mapCmdsByNode(cmds []Cmder, cmdsMap *cmdsMap) error {
|
||||||
state, err := c.state.Get()
|
state, err := c.state.Get()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdsMap := make(map[*clusterNode][]Cmder)
|
|
||||||
cmdsAreReadOnly := c.cmdsAreReadOnly(cmds)
|
cmdsAreReadOnly := c.cmdsAreReadOnly(cmds)
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
var node *clusterNode
|
var node *clusterNode
|
||||||
@@ -1301,11 +1315,13 @@ func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, e
|
|||||||
node, err = state.slotMasterNode(slot)
|
node, err = state.slotMasterNode(slot)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
cmdsMap[node] = append(cmdsMap[node], cmd)
|
cmdsMap.mu.Lock()
|
||||||
|
cmdsMap.m[node] = append(cmdsMap.m[node], cmd)
|
||||||
|
cmdsMap.mu.Unlock()
|
||||||
}
|
}
|
||||||
return cmdsMap, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) cmdsAreReadOnly(cmds []Cmder) bool {
|
func (c *ClusterClient) cmdsAreReadOnly(cmds []Cmder) bool {
|
||||||
@@ -1318,27 +1334,17 @@ func (c *ClusterClient) cmdsAreReadOnly(cmds []Cmder) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) remapCmds(cmds []Cmder, failedCmds map[*clusterNode][]Cmder) {
|
|
||||||
remappedCmds, err := c.mapCmdsByNode(cmds)
|
|
||||||
if err != nil {
|
|
||||||
setCmdsErr(cmds, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for node, cmds := range remappedCmds {
|
|
||||||
failedCmds[node] = cmds
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ClusterClient) pipelineProcessCmds(
|
func (c *ClusterClient) pipelineProcessCmds(
|
||||||
node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds *cmdsMap,
|
||||||
) error {
|
) error {
|
||||||
err := cn.WithWriter(c.opt.WriteTimeout, func(wr *proto.Writer) error {
|
err := cn.WithWriter(c.opt.WriteTimeout, func(wr *proto.Writer) error {
|
||||||
return writeCmd(wr, cmds...)
|
return writeCmd(wr, cmds...)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
failedCmds[node] = cmds
|
failedCmds.mu.Lock()
|
||||||
|
failedCmds.m[node] = cmds
|
||||||
|
failedCmds.mu.Unlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1349,7 +1355,7 @@ func (c *ClusterClient) pipelineProcessCmds(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) pipelineReadCmds(
|
func (c *ClusterClient) pipelineReadCmds(
|
||||||
rd *proto.Reader, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
rd *proto.Reader, cmds []Cmder, failedCmds *cmdsMap,
|
||||||
) error {
|
) error {
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
err := cmd.readReply(rd)
|
err := cmd.readReply(rd)
|
||||||
@@ -1371,7 +1377,7 @@ func (c *ClusterClient) pipelineReadCmds(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) checkMovedErr(
|
func (c *ClusterClient) checkMovedErr(
|
||||||
cmd Cmder, err error, failedCmds map[*clusterNode][]Cmder,
|
cmd Cmder, err error, failedCmds *cmdsMap,
|
||||||
) bool {
|
) bool {
|
||||||
moved, ask, addr := internal.IsMovedError(err)
|
moved, ask, addr := internal.IsMovedError(err)
|
||||||
|
|
||||||
@@ -1383,7 +1389,9 @@ func (c *ClusterClient) checkMovedErr(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
failedCmds[node] = append(failedCmds[node], cmd)
|
failedCmds.mu.Lock()
|
||||||
|
failedCmds.m[node] = append(failedCmds.m[node], cmd)
|
||||||
|
failedCmds.mu.Unlock()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1393,7 +1401,9 @@ func (c *ClusterClient) checkMovedErr(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
failedCmds[node] = append(failedCmds[node], NewCmd("ASKING"), cmd)
|
failedCmds.mu.Lock()
|
||||||
|
failedCmds.m[node] = append(failedCmds.m[node], NewCmd("ASKING"), cmd)
|
||||||
|
failedCmds.mu.Unlock()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1433,31 +1443,34 @@ func (c *ClusterClient) defaultProcessTxPipeline(cmds []Cmder) error {
|
|||||||
time.Sleep(c.retryBackoff(attempt))
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
}
|
}
|
||||||
|
|
||||||
failedCmds := make(map[*clusterNode][]Cmder)
|
failedCmds := newCmdsMap()
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
for node, cmds := range cmdsMap {
|
for node, cmds := range cmdsMap {
|
||||||
cn, err := node.Client.getConn()
|
wg.Add(1)
|
||||||
if err != nil {
|
go func(node *clusterNode, cmds []Cmder) {
|
||||||
if err == pool.ErrClosed {
|
defer wg.Done()
|
||||||
c.remapCmds(cmds, failedCmds)
|
|
||||||
} else {
|
|
||||||
setCmdsErr(cmds, err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = c.txPipelineProcessCmds(node, cn, cmds, failedCmds)
|
cn, err := node.Client.getConn()
|
||||||
if err == nil || internal.IsRedisError(err) {
|
if err != nil {
|
||||||
node.Client.connPool.Put(cn)
|
if err == pool.ErrClosed {
|
||||||
} else {
|
c.mapCmdsByNode(cmds, failedCmds)
|
||||||
node.Client.connPool.Remove(cn)
|
} else {
|
||||||
}
|
setCmdsErr(cmds, err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.txPipelineProcessCmds(node, cn, cmds, failedCmds)
|
||||||
|
node.Client.releaseConnStrict(cn, err)
|
||||||
|
}(node, cmds)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(failedCmds) == 0 {
|
wg.Wait()
|
||||||
|
if len(failedCmds.m) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
cmdsMap = failedCmds
|
cmdsMap = failedCmds.m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1474,14 +1487,16 @@ func (c *ClusterClient) mapCmdsBySlot(cmds []Cmder) map[int][]Cmder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) txPipelineProcessCmds(
|
func (c *ClusterClient) txPipelineProcessCmds(
|
||||||
node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds *cmdsMap,
|
||||||
) error {
|
) error {
|
||||||
err := cn.WithWriter(c.opt.WriteTimeout, func(wr *proto.Writer) error {
|
err := cn.WithWriter(c.opt.WriteTimeout, func(wr *proto.Writer) error {
|
||||||
return txPipelineWriteMulti(wr, cmds)
|
return txPipelineWriteMulti(wr, cmds)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
failedCmds[node] = cmds
|
failedCmds.mu.Lock()
|
||||||
|
failedCmds.m[node] = cmds
|
||||||
|
failedCmds.mu.Unlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1497,7 +1512,7 @@ func (c *ClusterClient) txPipelineProcessCmds(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) txPipelineReadQueued(
|
func (c *ClusterClient) txPipelineReadQueued(
|
||||||
rd *proto.Reader, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
|
rd *proto.Reader, cmds []Cmder, failedCmds *cmdsMap,
|
||||||
) error {
|
) error {
|
||||||
// Parse queued replies.
|
// Parse queued replies.
|
||||||
var statusCmd StatusCmd
|
var statusCmd StatusCmd
|
||||||
|
|||||||
13
vendor/github.com/go-redis/redis/commands.go
сгенерированный
поставляемый
13
vendor/github.com/go-redis/redis/commands.go
сгенерированный
поставляемый
@@ -8,13 +8,6 @@ import (
|
|||||||
"github.com/go-redis/redis/internal"
|
"github.com/go-redis/redis/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readTimeout(timeout time.Duration) time.Duration {
|
|
||||||
if timeout == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return timeout + 10*time.Second
|
|
||||||
}
|
|
||||||
|
|
||||||
func usePrecise(dur time.Duration) bool {
|
func usePrecise(dur time.Duration) bool {
|
||||||
return dur < time.Second || dur%time.Second != 0
|
return dur < time.Second || dur%time.Second != 0
|
||||||
}
|
}
|
||||||
@@ -1397,6 +1390,9 @@ func (c *cmdable) XRead(a *XReadArgs) *XStreamSliceCmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd := NewXStreamSliceCmd(args...)
|
cmd := NewXStreamSliceCmd(args...)
|
||||||
|
if a.Block >= 0 {
|
||||||
|
cmd.setReadTimeout(a.Block)
|
||||||
|
}
|
||||||
c.process(cmd)
|
c.process(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
@@ -1455,6 +1451,9 @@ func (c *cmdable) XReadGroup(a *XReadGroupArgs) *XStreamSliceCmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd := NewXStreamSliceCmd(args...)
|
cmd := NewXStreamSliceCmd(args...)
|
||||||
|
if a.Block >= 0 {
|
||||||
|
cmd.setReadTimeout(a.Block)
|
||||||
|
}
|
||||||
c.process(cmd)
|
c.process(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
3
vendor/github.com/go-redis/redis/internal/error.go
сгенерированный
поставляемый
3
vendor/github.com/go-redis/redis/internal/error.go
сгенерированный
поставляемый
@@ -9,6 +9,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func IsRetryableError(err error, retryTimeout bool) bool {
|
func IsRetryableError(err error, retryTimeout bool) bool {
|
||||||
|
if err == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/github.com/go-redis/redis/options.go
сгенерированный
поставляемый
2
vendor/github.com/go-redis/redis/options.go
сгенерированный
поставляемый
@@ -48,7 +48,7 @@ type Options struct {
|
|||||||
// Default is 5 seconds.
|
// Default is 5 seconds.
|
||||||
DialTimeout time.Duration
|
DialTimeout time.Duration
|
||||||
// Timeout for socket reads. If reached, commands will fail
|
// Timeout for socket reads. If reached, commands will fail
|
||||||
// with a timeout instead of blocking.
|
// with a timeout instead of blocking. Use value -1 for no timeout and 0 for default.
|
||||||
// Default is 3 seconds.
|
// Default is 3 seconds.
|
||||||
ReadTimeout time.Duration
|
ReadTimeout time.Duration
|
||||||
// Timeout for socket writes. If reached, commands will fail
|
// Timeout for socket writes. If reached, commands will fail
|
||||||
|
|||||||
10
vendor/github.com/go-redis/redis/pubsub.go
сгенерированный
поставляемый
10
vendor/github.com/go-redis/redis/pubsub.go
сгенерированный
поставляемый
@@ -1,6 +1,7 @@
|
|||||||
package redis
|
package redis
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -10,6 +11,8 @@ import (
|
|||||||
"github.com/go-redis/redis/internal/proto"
|
"github.com/go-redis/redis/internal/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errPingTimeout = errors.New("redis: ping timeout")
|
||||||
|
|
||||||
// PubSub implements Pub/Sub commands bas described in
|
// PubSub implements Pub/Sub commands bas described in
|
||||||
// http://redis.io/topics/pubsub. Message receiving is NOT safe
|
// http://redis.io/topics/pubsub. Message receiving is NOT safe
|
||||||
// for concurrent use by multiple goroutines.
|
// for concurrent use by multiple goroutines.
|
||||||
@@ -51,7 +54,6 @@ func (c *PubSub) _conn(newChannels []string) (*pool.Conn, error) {
|
|||||||
if c.closed {
|
if c.closed {
|
||||||
return nil, pool.ErrClosed
|
return nil, pool.ErrClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.cn != nil {
|
if c.cn != nil {
|
||||||
return c.cn, nil
|
return c.cn, nil
|
||||||
}
|
}
|
||||||
@@ -439,7 +441,6 @@ func (c *PubSub) initChannel() {
|
|||||||
timer.Stop()
|
timer.Stop()
|
||||||
|
|
||||||
healthy := true
|
healthy := true
|
||||||
var pingErr error
|
|
||||||
for {
|
for {
|
||||||
timer.Reset(timeout)
|
timer.Reset(timeout)
|
||||||
select {
|
select {
|
||||||
@@ -449,10 +450,13 @@ func (c *PubSub) initChannel() {
|
|||||||
<-timer.C
|
<-timer.C
|
||||||
}
|
}
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
pingErr = c.Ping()
|
pingErr := c.Ping()
|
||||||
if healthy {
|
if healthy {
|
||||||
healthy = false
|
healthy = false
|
||||||
} else {
|
} else {
|
||||||
|
if pingErr == nil {
|
||||||
|
pingErr = errPingTimeout
|
||||||
|
}
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
c._reconnect(pingErr)
|
c._reconnect(pingErr)
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
|||||||
29
vendor/github.com/go-redis/redis/redis.go
сгенерированный
поставляемый
29
vendor/github.com/go-redis/redis/redis.go
сгенерированный
поставляемый
@@ -77,14 +77,20 @@ func (c *baseClient) getConn() (*pool.Conn, error) {
|
|||||||
return cn, nil
|
return cn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseClient) releaseConn(cn *pool.Conn, err error) bool {
|
func (c *baseClient) releaseConn(cn *pool.Conn, err error) {
|
||||||
if internal.IsBadConn(err, false) {
|
if internal.IsBadConn(err, false) {
|
||||||
c.connPool.Remove(cn)
|
c.connPool.Remove(cn)
|
||||||
return false
|
} else {
|
||||||
|
c.connPool.Put(cn)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
c.connPool.Put(cn)
|
func (c *baseClient) releaseConnStrict(cn *pool.Conn, err error) {
|
||||||
return true
|
if err == nil || internal.IsRedisError(err) {
|
||||||
|
c.connPool.Put(cn)
|
||||||
|
} else {
|
||||||
|
c.connPool.Remove(cn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseClient) initConn(cn *pool.Conn) error {
|
func (c *baseClient) initConn(cn *pool.Conn) error {
|
||||||
@@ -188,7 +194,11 @@ func (c *baseClient) retryBackoff(attempt int) time.Duration {
|
|||||||
|
|
||||||
func (c *baseClient) cmdTimeout(cmd Cmder) time.Duration {
|
func (c *baseClient) cmdTimeout(cmd Cmder) time.Duration {
|
||||||
if timeout := cmd.readTimeout(); timeout != nil {
|
if timeout := cmd.readTimeout(); timeout != nil {
|
||||||
return readTimeout(*timeout)
|
t := *timeout
|
||||||
|
if t == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return t + 10*time.Second
|
||||||
}
|
}
|
||||||
return c.opt.ReadTimeout
|
return c.opt.ReadTimeout
|
||||||
}
|
}
|
||||||
@@ -244,12 +254,7 @@ func (c *baseClient) generalProcessPipeline(cmds []Cmder, p pipelineProcessor) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
canRetry, err := p(cn, cmds)
|
canRetry, err := p(cn, cmds)
|
||||||
|
c.releaseConnStrict(cn, err)
|
||||||
if err == nil || internal.IsRedisError(err) {
|
|
||||||
c.connPool.Put(cn)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
c.connPool.Remove(cn)
|
|
||||||
|
|
||||||
if !canRetry || !internal.IsRetryableError(err, true) {
|
if !canRetry || !internal.IsRetryableError(err, true) {
|
||||||
break
|
break
|
||||||
@@ -319,7 +324,7 @@ func txPipelineReadQueued(rd *proto.Reader, cmds []Cmder) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ = range cmds {
|
for range cmds {
|
||||||
err = statusCmd.readReply(rd)
|
err = statusCmd.readReply(rd)
|
||||||
if err != nil && !internal.IsRedisError(err) {
|
if err != nil && !internal.IsRedisError(err) {
|
||||||
return err
|
return err
|
||||||
|
|||||||
87
vendor/github.com/go-redis/redis/ring.go
сгенерированный
поставляемый
87
vendor/github.com/go-redis/redis/ring.go
сгенерированный
поставляемый
@@ -342,6 +342,7 @@ type Ring struct {
|
|||||||
shards *ringShards
|
shards *ringShards
|
||||||
cmdsInfoCache *cmdsInfoCache
|
cmdsInfoCache *cmdsInfoCache
|
||||||
|
|
||||||
|
process func(Cmder) error
|
||||||
processPipeline func([]Cmder) error
|
processPipeline func([]Cmder) error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,6 +355,7 @@ func NewRing(opt *RingOptions) *Ring {
|
|||||||
}
|
}
|
||||||
ring.cmdsInfoCache = newCmdsInfoCache(ring.cmdsInfo)
|
ring.cmdsInfoCache = newCmdsInfoCache(ring.cmdsInfo)
|
||||||
|
|
||||||
|
ring.process = ring.defaultProcess
|
||||||
ring.processPipeline = ring.defaultProcessPipeline
|
ring.processPipeline = ring.defaultProcessPipeline
|
||||||
ring.cmdable.setProcessor(ring.Process)
|
ring.cmdable.setProcessor(ring.Process)
|
||||||
|
|
||||||
@@ -526,19 +528,34 @@ func (c *Ring) Do(args ...interface{}) *Cmd {
|
|||||||
func (c *Ring) WrapProcess(
|
func (c *Ring) WrapProcess(
|
||||||
fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error,
|
fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error,
|
||||||
) {
|
) {
|
||||||
c.ForEachShard(func(c *Client) error {
|
c.process = fn(c.process)
|
||||||
c.WrapProcess(fn)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ring) Process(cmd Cmder) error {
|
func (c *Ring) Process(cmd Cmder) error {
|
||||||
shard, err := c.cmdShard(cmd)
|
return c.process(cmd)
|
||||||
if err != nil {
|
}
|
||||||
cmd.setErr(err)
|
|
||||||
return err
|
func (c *Ring) defaultProcess(cmd Cmder) error {
|
||||||
|
for attempt := 0; attempt <= c.opt.MaxRetries; attempt++ {
|
||||||
|
if attempt > 0 {
|
||||||
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
|
}
|
||||||
|
|
||||||
|
shard, err := c.cmdShard(cmd)
|
||||||
|
if err != nil {
|
||||||
|
cmd.setErr(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = shard.Client.Process(cmd)
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !internal.IsRetryableError(err, cmd.readTimeout() == nil) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return shard.Client.Process(cmd)
|
return cmd.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ring) Pipeline() Pipeliner {
|
func (c *Ring) Pipeline() Pipeliner {
|
||||||
@@ -575,36 +592,42 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error {
|
|||||||
time.Sleep(c.retryBackoff(attempt))
|
time.Sleep(c.retryBackoff(attempt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mu sync.Mutex
|
||||||
var failedCmdsMap map[string][]Cmder
|
var failedCmdsMap map[string][]Cmder
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
for hash, cmds := range cmdsMap {
|
for hash, cmds := range cmdsMap {
|
||||||
shard, err := c.shards.GetByHash(hash)
|
wg.Add(1)
|
||||||
if err != nil {
|
go func(hash string, cmds []Cmder) {
|
||||||
setCmdsErr(cmds, err)
|
defer wg.Done()
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cn, err := shard.Client.getConn()
|
shard, err := c.shards.GetByHash(hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
continue
|
return
|
||||||
}
|
|
||||||
|
|
||||||
canRetry, err := shard.Client.pipelineProcessCmds(cn, cmds)
|
|
||||||
if err == nil || internal.IsRedisError(err) {
|
|
||||||
shard.Client.connPool.Put(cn)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
shard.Client.connPool.Remove(cn)
|
|
||||||
|
|
||||||
if canRetry && internal.IsRetryableError(err, true) {
|
|
||||||
if failedCmdsMap == nil {
|
|
||||||
failedCmdsMap = make(map[string][]Cmder)
|
|
||||||
}
|
}
|
||||||
failedCmdsMap[hash] = cmds
|
|
||||||
}
|
cn, err := shard.Client.getConn()
|
||||||
|
if err != nil {
|
||||||
|
setCmdsErr(cmds, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
canRetry, err := shard.Client.pipelineProcessCmds(cn, cmds)
|
||||||
|
shard.Client.releaseConnStrict(cn, err)
|
||||||
|
|
||||||
|
if canRetry && internal.IsRetryableError(err, true) {
|
||||||
|
mu.Lock()
|
||||||
|
if failedCmdsMap == nil {
|
||||||
|
failedCmdsMap = make(map[string][]Cmder)
|
||||||
|
}
|
||||||
|
failedCmdsMap[hash] = cmds
|
||||||
|
mu.Unlock()
|
||||||
|
}
|
||||||
|
}(hash, cmds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
if len(failedCmdsMap) == 0 {
|
if len(failedCmdsMap) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
212
vendor/github.com/go-redis/redis/sentinel.go
сгенерированный
поставляемый
212
vendor/github.com/go-redis/redis/sentinel.go
сгенерированный
поставляемый
@@ -119,7 +119,7 @@ func NewSentinelClient(opt *Options) *SentinelClient {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SentinelClient) PubSub() *PubSub {
|
func (c *SentinelClient) pubSub() *PubSub {
|
||||||
pubsub := &PubSub{
|
pubsub := &PubSub{
|
||||||
opt: c.opt,
|
opt: c.opt,
|
||||||
|
|
||||||
@@ -132,14 +132,34 @@ func (c *SentinelClient) PubSub() *PubSub {
|
|||||||
return pubsub
|
return pubsub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subscribe subscribes the client to the specified channels.
|
||||||
|
// Channels can be omitted to create empty subscription.
|
||||||
|
func (c *SentinelClient) Subscribe(channels ...string) *PubSub {
|
||||||
|
pubsub := c.pubSub()
|
||||||
|
if len(channels) > 0 {
|
||||||
|
_ = pubsub.Subscribe(channels...)
|
||||||
|
}
|
||||||
|
return pubsub
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSubscribe subscribes the client to the given patterns.
|
||||||
|
// Patterns can be omitted to create empty subscription.
|
||||||
|
func (c *SentinelClient) PSubscribe(channels ...string) *PubSub {
|
||||||
|
pubsub := c.pubSub()
|
||||||
|
if len(channels) > 0 {
|
||||||
|
_ = pubsub.PSubscribe(channels...)
|
||||||
|
}
|
||||||
|
return pubsub
|
||||||
|
}
|
||||||
|
|
||||||
func (c *SentinelClient) GetMasterAddrByName(name string) *StringSliceCmd {
|
func (c *SentinelClient) GetMasterAddrByName(name string) *StringSliceCmd {
|
||||||
cmd := NewStringSliceCmd("SENTINEL", "get-master-addr-by-name", name)
|
cmd := NewStringSliceCmd("sentinel", "get-master-addr-by-name", name)
|
||||||
c.Process(cmd)
|
c.Process(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SentinelClient) Sentinels(name string) *SliceCmd {
|
func (c *SentinelClient) Sentinels(name string) *SliceCmd {
|
||||||
cmd := NewSliceCmd("SENTINEL", "sentinels", name)
|
cmd := NewSliceCmd("sentinel", "sentinels", name)
|
||||||
c.Process(cmd)
|
c.Process(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
@@ -158,77 +178,78 @@ type sentinelFailover struct {
|
|||||||
sentinel *SentinelClient
|
sentinel *SentinelClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) Close() error {
|
func (c *sentinelFailover) Close() error {
|
||||||
return d.resetSentinel()
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
if c.sentinel != nil {
|
||||||
|
return c.closeSentinel()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) Pool() *pool.ConnPool {
|
func (c *sentinelFailover) Pool() *pool.ConnPool {
|
||||||
d.poolOnce.Do(func() {
|
c.poolOnce.Do(func() {
|
||||||
d.opt.Dialer = d.dial
|
c.opt.Dialer = c.dial
|
||||||
d.pool = newConnPool(d.opt)
|
c.pool = newConnPool(c.opt)
|
||||||
})
|
})
|
||||||
return d.pool
|
return c.pool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) dial() (net.Conn, error) {
|
func (c *sentinelFailover) dial() (net.Conn, error) {
|
||||||
addr, err := d.MasterAddr()
|
addr, err := c.MasterAddr()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return net.DialTimeout("tcp", addr, d.opt.DialTimeout)
|
return net.DialTimeout("tcp", addr, c.opt.DialTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) MasterAddr() (string, error) {
|
func (c *sentinelFailover) MasterAddr() (string, error) {
|
||||||
d.mu.Lock()
|
addr, err := c.masterAddr()
|
||||||
defer d.mu.Unlock()
|
|
||||||
|
|
||||||
addr, err := d.masterAddr()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
d._switchMaster(addr)
|
c.switchMaster(addr)
|
||||||
|
|
||||||
return addr, nil
|
return addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) masterAddr() (string, error) {
|
func (c *sentinelFailover) masterAddr() (string, error) {
|
||||||
// Try last working sentinel.
|
addr := c.getMasterAddr()
|
||||||
if d.sentinel != nil {
|
if addr != "" {
|
||||||
addr, err := d.sentinel.GetMasterAddrByName(d.masterName).Result()
|
return addr, nil
|
||||||
if err == nil {
|
|
||||||
addr := net.JoinHostPort(addr[0], addr[1])
|
|
||||||
return addr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
internal.Logf("sentinel: GetMasterAddrByName name=%q failed: %s",
|
|
||||||
d.masterName, err)
|
|
||||||
d._resetSentinel()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, sentinelAddr := range d.sentinelAddrs {
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
for i, sentinelAddr := range c.sentinelAddrs {
|
||||||
sentinel := NewSentinelClient(&Options{
|
sentinel := NewSentinelClient(&Options{
|
||||||
Addr: sentinelAddr,
|
Addr: sentinelAddr,
|
||||||
|
|
||||||
DialTimeout: d.opt.DialTimeout,
|
MaxRetries: c.opt.MaxRetries,
|
||||||
ReadTimeout: d.opt.ReadTimeout,
|
|
||||||
WriteTimeout: d.opt.WriteTimeout,
|
|
||||||
|
|
||||||
PoolSize: d.opt.PoolSize,
|
DialTimeout: c.opt.DialTimeout,
|
||||||
PoolTimeout: d.opt.PoolTimeout,
|
ReadTimeout: c.opt.ReadTimeout,
|
||||||
IdleTimeout: d.opt.IdleTimeout,
|
WriteTimeout: c.opt.WriteTimeout,
|
||||||
|
|
||||||
|
PoolSize: c.opt.PoolSize,
|
||||||
|
PoolTimeout: c.opt.PoolTimeout,
|
||||||
|
IdleTimeout: c.opt.IdleTimeout,
|
||||||
|
IdleCheckFrequency: c.opt.IdleCheckFrequency,
|
||||||
|
|
||||||
|
TLSConfig: c.opt.TLSConfig,
|
||||||
})
|
})
|
||||||
|
|
||||||
masterAddr, err := sentinel.GetMasterAddrByName(d.masterName).Result()
|
masterAddr, err := sentinel.GetMasterAddrByName(c.masterName).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
internal.Logf("sentinel: GetMasterAddrByName master=%q failed: %s",
|
internal.Logf("sentinel: GetMasterAddrByName master=%q failed: %s",
|
||||||
d.masterName, err)
|
c.masterName, err)
|
||||||
sentinel.Close()
|
_ = sentinel.Close()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push working sentinel to the top.
|
// Push working sentinel to the top.
|
||||||
d.sentinelAddrs[0], d.sentinelAddrs[i] = d.sentinelAddrs[i], d.sentinelAddrs[0]
|
c.sentinelAddrs[0], c.sentinelAddrs[i] = c.sentinelAddrs[i], c.sentinelAddrs[0]
|
||||||
d.setSentinel(sentinel)
|
c.setSentinel(sentinel)
|
||||||
|
|
||||||
addr := net.JoinHostPort(masterAddr[0], masterAddr[1])
|
addr := net.JoinHostPort(masterAddr[0], masterAddr[1])
|
||||||
return addr, nil
|
return addr, nil
|
||||||
@@ -237,17 +258,41 @@ func (d *sentinelFailover) masterAddr() (string, error) {
|
|||||||
return "", errors.New("redis: all sentinels are unreachable")
|
return "", errors.New("redis: all sentinels are unreachable")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sentinelFailover) switchMaster(addr string) {
|
func (c *sentinelFailover) getMasterAddr() string {
|
||||||
c.mu.Lock()
|
c.mu.RLock()
|
||||||
c._switchMaster(addr)
|
sentinel := c.sentinel
|
||||||
c.mu.Unlock()
|
c.mu.RUnlock()
|
||||||
|
|
||||||
|
if sentinel == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, err := sentinel.GetMasterAddrByName(c.masterName).Result()
|
||||||
|
if err != nil {
|
||||||
|
internal.Logf("sentinel: GetMasterAddrByName name=%q failed: %s",
|
||||||
|
c.masterName, err)
|
||||||
|
c.mu.Lock()
|
||||||
|
if c.sentinel == sentinel {
|
||||||
|
c.closeSentinel()
|
||||||
|
}
|
||||||
|
c.mu.Unlock()
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return net.JoinHostPort(addr[0], addr[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *sentinelFailover) _switchMaster(addr string) {
|
func (c *sentinelFailover) switchMaster(addr string) {
|
||||||
if c._masterAddr == addr {
|
c.mu.RLock()
|
||||||
|
masterAddr := c._masterAddr
|
||||||
|
c.mu.RUnlock()
|
||||||
|
if masterAddr == addr {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
internal.Logf("sentinel: new master=%q addr=%q",
|
internal.Logf("sentinel: new master=%q addr=%q",
|
||||||
c.masterName, addr)
|
c.masterName, addr)
|
||||||
_ = c.Pool().Filter(func(cn *pool.Conn) bool {
|
_ = c.Pool().Filter(func(cn *pool.Conn) bool {
|
||||||
@@ -256,32 +301,22 @@ func (c *sentinelFailover) _switchMaster(addr string) {
|
|||||||
c._masterAddr = addr
|
c._masterAddr = addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) setSentinel(sentinel *SentinelClient) {
|
func (c *sentinelFailover) setSentinel(sentinel *SentinelClient) {
|
||||||
d.discoverSentinels(sentinel)
|
c.discoverSentinels(sentinel)
|
||||||
d.sentinel = sentinel
|
c.sentinel = sentinel
|
||||||
go d.listen(sentinel)
|
go c.listen(sentinel)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) resetSentinel() error {
|
func (c *sentinelFailover) closeSentinel() error {
|
||||||
var err error
|
err := c.sentinel.Close()
|
||||||
d.mu.Lock()
|
c.sentinel = nil
|
||||||
if d.sentinel != nil {
|
|
||||||
err = d._resetSentinel()
|
|
||||||
}
|
|
||||||
d.mu.Unlock()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) _resetSentinel() error {
|
func (c *sentinelFailover) discoverSentinels(sentinel *SentinelClient) {
|
||||||
err := d.sentinel.Close()
|
sentinels, err := sentinel.Sentinels(c.masterName).Result()
|
||||||
d.sentinel = nil
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *sentinelFailover) discoverSentinels(sentinel *SentinelClient) {
|
|
||||||
sentinels, err := sentinel.Sentinels(d.masterName).Result()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
internal.Logf("sentinel: Sentinels master=%q failed: %s", d.masterName, err)
|
internal.Logf("sentinel: Sentinels master=%q failed: %s", c.masterName, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, sentinel := range sentinels {
|
for _, sentinel := range sentinels {
|
||||||
@@ -290,49 +325,36 @@ func (d *sentinelFailover) discoverSentinels(sentinel *SentinelClient) {
|
|||||||
key := vals[i].(string)
|
key := vals[i].(string)
|
||||||
if key == "name" {
|
if key == "name" {
|
||||||
sentinelAddr := vals[i+1].(string)
|
sentinelAddr := vals[i+1].(string)
|
||||||
if !contains(d.sentinelAddrs, sentinelAddr) {
|
if !contains(c.sentinelAddrs, sentinelAddr) {
|
||||||
internal.Logf(
|
internal.Logf("sentinel: discovered new sentinel=%q for master=%q",
|
||||||
"sentinel: discovered new sentinel=%q for master=%q",
|
sentinelAddr, c.masterName)
|
||||||
sentinelAddr, d.masterName,
|
c.sentinelAddrs = append(c.sentinelAddrs, sentinelAddr)
|
||||||
)
|
|
||||||
d.sentinelAddrs = append(d.sentinelAddrs, sentinelAddr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) listen(sentinel *SentinelClient) {
|
func (c *sentinelFailover) listen(sentinel *SentinelClient) {
|
||||||
pubsub := sentinel.PubSub()
|
pubsub := sentinel.Subscribe("+switch-master")
|
||||||
defer pubsub.Close()
|
defer pubsub.Close()
|
||||||
|
|
||||||
err := pubsub.Subscribe("+switch-master")
|
ch := pubsub.Channel()
|
||||||
if err != nil {
|
|
||||||
internal.Logf("sentinel: Subscribe failed: %s", err)
|
|
||||||
d.resetSentinel()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
msg, err := pubsub.ReceiveMessage()
|
msg, ok := <-ch
|
||||||
if err != nil {
|
if !ok {
|
||||||
if err == pool.ErrClosed {
|
break
|
||||||
d.resetSentinel()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
internal.Logf("sentinel: ReceiveMessage failed: %s", err)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch msg.Channel {
|
switch msg.Channel {
|
||||||
case "+switch-master":
|
case "+switch-master":
|
||||||
parts := strings.Split(msg.Payload, " ")
|
parts := strings.Split(msg.Payload, " ")
|
||||||
if parts[0] != d.masterName {
|
if parts[0] != c.masterName {
|
||||||
internal.Logf("sentinel: ignore addr for master=%q", parts[0])
|
internal.Logf("sentinel: ignore addr for master=%q", parts[0])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
addr := net.JoinHostPort(parts[3], parts[4])
|
addr := net.JoinHostPort(parts[3], parts[4])
|
||||||
d.switchMaster(addr)
|
c.switchMaster(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
vendor/github.com/go-sql-driver/mysql/CHANGELOG.md
сгенерированный
поставляемый
11
vendor/github.com/go-sql-driver/mysql/CHANGELOG.md
сгенерированный
поставляемый
@@ -1,3 +1,14 @@
|
|||||||
|
## Version 1.4.1 (2018-11-14)
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
|
||||||
|
- Fix TIME format for binary columns (#818)
|
||||||
|
- Fix handling of empty auth plugin names (#835)
|
||||||
|
- Fix caching_sha2_password with empty password (#826)
|
||||||
|
- Fix canceled context broke mysqlConn (#862)
|
||||||
|
- Fix OldAuthSwitchRequest support (#870)
|
||||||
|
- Fix Auth Response packet for cleartext password (#887)
|
||||||
|
|
||||||
## Version 1.4 (2018-06-03)
|
## Version 1.4 (2018-06-03)
|
||||||
|
|
||||||
Changes:
|
Changes:
|
||||||
|
|||||||
36
vendor/github.com/go-sql-driver/mysql/auth.go
сгенерированный
поставляемый
36
vendor/github.com/go-sql-driver/mysql/auth.go
сгенерированный
поставляемый
@@ -234,64 +234,64 @@ func (mc *mysqlConn) sendEncryptedPassword(seed []byte, pub *rsa.PublicKey) erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return mc.writeAuthSwitchPacket(enc, false)
|
return mc.writeAuthSwitchPacket(enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, bool, error) {
|
func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, error) {
|
||||||
switch plugin {
|
switch plugin {
|
||||||
case "caching_sha2_password":
|
case "caching_sha2_password":
|
||||||
authResp := scrambleSHA256Password(authData, mc.cfg.Passwd)
|
authResp := scrambleSHA256Password(authData, mc.cfg.Passwd)
|
||||||
return authResp, (authResp == nil), nil
|
return authResp, nil
|
||||||
|
|
||||||
case "mysql_old_password":
|
case "mysql_old_password":
|
||||||
if !mc.cfg.AllowOldPasswords {
|
if !mc.cfg.AllowOldPasswords {
|
||||||
return nil, false, ErrOldPassword
|
return nil, ErrOldPassword
|
||||||
}
|
}
|
||||||
// Note: there are edge cases where this should work but doesn't;
|
// Note: there are edge cases where this should work but doesn't;
|
||||||
// this is currently "wontfix":
|
// this is currently "wontfix":
|
||||||
// https://github.com/go-sql-driver/mysql/issues/184
|
// https://github.com/go-sql-driver/mysql/issues/184
|
||||||
authResp := scrambleOldPassword(authData[:8], mc.cfg.Passwd)
|
authResp := append(scrambleOldPassword(authData[:8], mc.cfg.Passwd), 0)
|
||||||
return authResp, true, nil
|
return authResp, nil
|
||||||
|
|
||||||
case "mysql_clear_password":
|
case "mysql_clear_password":
|
||||||
if !mc.cfg.AllowCleartextPasswords {
|
if !mc.cfg.AllowCleartextPasswords {
|
||||||
return nil, false, ErrCleartextPassword
|
return nil, ErrCleartextPassword
|
||||||
}
|
}
|
||||||
// http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html
|
// http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html
|
||||||
// http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html
|
// http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html
|
||||||
return []byte(mc.cfg.Passwd), true, nil
|
return append([]byte(mc.cfg.Passwd), 0), nil
|
||||||
|
|
||||||
case "mysql_native_password":
|
case "mysql_native_password":
|
||||||
if !mc.cfg.AllowNativePasswords {
|
if !mc.cfg.AllowNativePasswords {
|
||||||
return nil, false, ErrNativePassword
|
return nil, ErrNativePassword
|
||||||
}
|
}
|
||||||
// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
|
// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
|
||||||
// Native password authentication only need and will need 20-byte challenge.
|
// Native password authentication only need and will need 20-byte challenge.
|
||||||
authResp := scramblePassword(authData[:20], mc.cfg.Passwd)
|
authResp := scramblePassword(authData[:20], mc.cfg.Passwd)
|
||||||
return authResp, false, nil
|
return authResp, nil
|
||||||
|
|
||||||
case "sha256_password":
|
case "sha256_password":
|
||||||
if len(mc.cfg.Passwd) == 0 {
|
if len(mc.cfg.Passwd) == 0 {
|
||||||
return nil, true, nil
|
return []byte{0}, nil
|
||||||
}
|
}
|
||||||
if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
|
if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
|
||||||
// write cleartext auth packet
|
// write cleartext auth packet
|
||||||
return []byte(mc.cfg.Passwd), true, nil
|
return append([]byte(mc.cfg.Passwd), 0), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pubKey := mc.cfg.pubKey
|
pubKey := mc.cfg.pubKey
|
||||||
if pubKey == nil {
|
if pubKey == nil {
|
||||||
// request public key from server
|
// request public key from server
|
||||||
return []byte{1}, false, nil
|
return []byte{1}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// encrypted password
|
// encrypted password
|
||||||
enc, err := encryptPassword(mc.cfg.Passwd, authData, pubKey)
|
enc, err := encryptPassword(mc.cfg.Passwd, authData, pubKey)
|
||||||
return enc, false, err
|
return enc, err
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errLog.Print("unknown auth plugin:", plugin)
|
errLog.Print("unknown auth plugin:", plugin)
|
||||||
return nil, false, ErrUnknownPlugin
|
return nil, ErrUnknownPlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,11 +315,11 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
|
|||||||
|
|
||||||
plugin = newPlugin
|
plugin = newPlugin
|
||||||
|
|
||||||
authResp, addNUL, err := mc.auth(authData, plugin)
|
authResp, err := mc.auth(authData, plugin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = mc.writeAuthSwitchPacket(authResp, addNUL); err != nil {
|
if err = mc.writeAuthSwitchPacket(authResp); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
|
|||||||
case cachingSha2PasswordPerformFullAuthentication:
|
case cachingSha2PasswordPerformFullAuthentication:
|
||||||
if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
|
if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
|
||||||
// write cleartext auth packet
|
// write cleartext auth packet
|
||||||
err = mc.writeAuthSwitchPacket([]byte(mc.cfg.Passwd), true)
|
err = mc.writeAuthSwitchPacket(append([]byte(mc.cfg.Passwd), 0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
15
vendor/github.com/go-sql-driver/mysql/connection_go18.go
сгенерированный
поставляемый
15
vendor/github.com/go-sql-driver/mysql/connection_go18.go
сгенерированный
поставляемый
@@ -149,22 +149,21 @@ func (mc *mysqlConn) watchCancel(ctx context.Context) error {
|
|||||||
mc.cleanup()
|
mc.cleanup()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// When ctx is already cancelled, don't watch it.
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// When ctx is not cancellable, don't watch it.
|
||||||
if ctx.Done() == nil {
|
if ctx.Done() == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// When watcher is not alive, can't watch it.
|
||||||
mc.watching = true
|
|
||||||
select {
|
|
||||||
default:
|
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
|
||||||
}
|
|
||||||
if mc.watcher == nil {
|
if mc.watcher == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mc.watching = true
|
||||||
mc.watcher <- ctx
|
mc.watcher <- ctx
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
vendor/github.com/go-sql-driver/mysql/driver.go
сгенерированный
поставляемый
9
vendor/github.com/go-sql-driver/mysql/driver.go
сгенерированный
поставляемый
@@ -112,20 +112,23 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
|
|||||||
mc.cleanup()
|
mc.cleanup()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if plugin == "" {
|
||||||
|
plugin = defaultAuthPlugin
|
||||||
|
}
|
||||||
|
|
||||||
// Send Client Authentication Packet
|
// Send Client Authentication Packet
|
||||||
authResp, addNUL, err := mc.auth(authData, plugin)
|
authResp, err := mc.auth(authData, plugin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// try the default auth plugin, if using the requested plugin failed
|
// try the default auth plugin, if using the requested plugin failed
|
||||||
errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
|
errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
|
||||||
plugin = defaultAuthPlugin
|
plugin = defaultAuthPlugin
|
||||||
authResp, addNUL, err = mc.auth(authData, plugin)
|
authResp, err = mc.auth(authData, plugin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mc.cleanup()
|
mc.cleanup()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin); err != nil {
|
if err = mc.writeHandshakeResponsePacket(authResp, plugin); err != nil {
|
||||||
mc.cleanup()
|
mc.cleanup()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
39
vendor/github.com/go-sql-driver/mysql/packets.go
сгенерированный
поставляемый
39
vendor/github.com/go-sql-driver/mysql/packets.go
сгенерированный
поставляемый
@@ -154,15 +154,15 @@ func (mc *mysqlConn) writePacket(data []byte) error {
|
|||||||
|
|
||||||
// Handshake Initialization Packet
|
// Handshake Initialization Packet
|
||||||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
|
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
|
||||||
func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
|
func (mc *mysqlConn) readHandshakePacket() (data []byte, plugin string, err error) {
|
||||||
data, err := mc.readPacket()
|
data, err = mc.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
|
// for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
|
||||||
// in connection initialization we don't risk retrying non-idempotent actions.
|
// in connection initialization we don't risk retrying non-idempotent actions.
|
||||||
if err == ErrInvalidConn {
|
if err == ErrInvalidConn {
|
||||||
return nil, "", driver.ErrBadConn
|
return nil, "", driver.ErrBadConn
|
||||||
}
|
}
|
||||||
return nil, "", err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if data[0] == iERR {
|
if data[0] == iERR {
|
||||||
@@ -198,7 +198,6 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
|
|||||||
}
|
}
|
||||||
pos += 2
|
pos += 2
|
||||||
|
|
||||||
plugin := ""
|
|
||||||
if len(data) > pos {
|
if len(data) > pos {
|
||||||
// character set [1 byte]
|
// character set [1 byte]
|
||||||
// status flags [2 bytes]
|
// status flags [2 bytes]
|
||||||
@@ -236,8 +235,6 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
|
|||||||
return b[:], plugin, nil
|
return b[:], plugin, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin = defaultAuthPlugin
|
|
||||||
|
|
||||||
// make a memory safe copy of the cipher slice
|
// make a memory safe copy of the cipher slice
|
||||||
var b [8]byte
|
var b [8]byte
|
||||||
copy(b[:], authData)
|
copy(b[:], authData)
|
||||||
@@ -246,7 +243,7 @@ func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
|
|||||||
|
|
||||||
// Client Authentication Packet
|
// Client Authentication Packet
|
||||||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
|
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
|
||||||
func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool, plugin string) error {
|
func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, plugin string) error {
|
||||||
// Adjust client flags based on server support
|
// Adjust client flags based on server support
|
||||||
clientFlags := clientProtocol41 |
|
clientFlags := clientProtocol41 |
|
||||||
clientSecureConn |
|
clientSecureConn |
|
||||||
@@ -272,7 +269,8 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||||||
|
|
||||||
// encode length of the auth plugin data
|
// encode length of the auth plugin data
|
||||||
var authRespLEIBuf [9]byte
|
var authRespLEIBuf [9]byte
|
||||||
authRespLEI := appendLengthEncodedInteger(authRespLEIBuf[:0], uint64(len(authResp)))
|
authRespLen := len(authResp)
|
||||||
|
authRespLEI := appendLengthEncodedInteger(authRespLEIBuf[:0], uint64(authRespLen))
|
||||||
if len(authRespLEI) > 1 {
|
if len(authRespLEI) > 1 {
|
||||||
// if the length can not be written in 1 byte, it must be written as a
|
// if the length can not be written in 1 byte, it must be written as a
|
||||||
// length encoded integer
|
// length encoded integer
|
||||||
@@ -280,9 +278,6 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + len(authRespLEI) + len(authResp) + 21 + 1
|
pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + len(authRespLEI) + len(authResp) + 21 + 1
|
||||||
if addNUL {
|
|
||||||
pktLen++
|
|
||||||
}
|
|
||||||
|
|
||||||
// To specify a db name
|
// To specify a db name
|
||||||
if n := len(mc.cfg.DBName); n > 0 {
|
if n := len(mc.cfg.DBName); n > 0 {
|
||||||
@@ -353,10 +348,6 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||||||
// Auth Data [length encoded integer]
|
// Auth Data [length encoded integer]
|
||||||
pos += copy(data[pos:], authRespLEI)
|
pos += copy(data[pos:], authRespLEI)
|
||||||
pos += copy(data[pos:], authResp)
|
pos += copy(data[pos:], authResp)
|
||||||
if addNUL {
|
|
||||||
data[pos] = 0x00
|
|
||||||
pos++
|
|
||||||
}
|
|
||||||
|
|
||||||
// Databasename [null terminated string]
|
// Databasename [null terminated string]
|
||||||
if len(mc.cfg.DBName) > 0 {
|
if len(mc.cfg.DBName) > 0 {
|
||||||
@@ -367,17 +358,15 @@ func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool,
|
|||||||
|
|
||||||
pos += copy(data[pos:], plugin)
|
pos += copy(data[pos:], plugin)
|
||||||
data[pos] = 0x00
|
data[pos] = 0x00
|
||||||
|
pos++
|
||||||
|
|
||||||
// Send Auth packet
|
// Send Auth packet
|
||||||
return mc.writePacket(data)
|
return mc.writePacket(data[:pos])
|
||||||
}
|
}
|
||||||
|
|
||||||
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
|
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
|
||||||
func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte, addNUL bool) error {
|
func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte) error {
|
||||||
pktLen := 4 + len(authData)
|
pktLen := 4 + len(authData)
|
||||||
if addNUL {
|
|
||||||
pktLen++
|
|
||||||
}
|
|
||||||
data := mc.buf.takeSmallBuffer(pktLen)
|
data := mc.buf.takeSmallBuffer(pktLen)
|
||||||
if data == nil {
|
if data == nil {
|
||||||
// cannot take the buffer. Something must be wrong with the connection
|
// cannot take the buffer. Something must be wrong with the connection
|
||||||
@@ -387,10 +376,6 @@ func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte, addNUL bool) error {
|
|||||||
|
|
||||||
// Add the auth data [EOF]
|
// Add the auth data [EOF]
|
||||||
copy(data[4:], authData)
|
copy(data[4:], authData)
|
||||||
if addNUL {
|
|
||||||
data[pktLen-1] = 0x00
|
|
||||||
}
|
|
||||||
|
|
||||||
return mc.writePacket(data)
|
return mc.writePacket(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +467,7 @@ func (mc *mysqlConn) readAuthResult() ([]byte, string, error) {
|
|||||||
return data[1:], "", err
|
return data[1:], "", err
|
||||||
|
|
||||||
case iEOF:
|
case iEOF:
|
||||||
if len(data) < 1 {
|
if len(data) == 1 {
|
||||||
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
|
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
|
||||||
return nil, "mysql_old_password", nil
|
return nil, "mysql_old_password", nil
|
||||||
}
|
}
|
||||||
@@ -1261,7 +1246,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
|
|||||||
rows.rs.columns[i].decimals,
|
rows.rs.columns[i].decimals,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, true)
|
dest[i], err = formatBinaryTime(data[pos:pos+int(num)], dstlen)
|
||||||
case rows.mc.parseTime:
|
case rows.mc.parseTime:
|
||||||
dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
|
dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
|
||||||
default:
|
default:
|
||||||
@@ -1281,7 +1266,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, false)
|
dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|||||||
246
vendor/github.com/go-sql-driver/mysql/utils.go
сгенерированный
поставляемый
246
vendor/github.com/go-sql-driver/mysql/utils.go
сгенерированный
поставляемый
@@ -14,6 +14,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -227,87 +228,104 @@ var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
|
|||||||
const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
|
const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
|
||||||
const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
|
const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
|
||||||
|
|
||||||
func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value, error) {
|
func appendMicrosecs(dst, src []byte, decimals int) []byte {
|
||||||
|
if decimals <= 0 {
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
if len(src) == 0 {
|
||||||
|
return append(dst, ".000000"[:decimals+1]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
microsecs := binary.LittleEndian.Uint32(src[:4])
|
||||||
|
p1 := byte(microsecs / 10000)
|
||||||
|
microsecs -= 10000 * uint32(p1)
|
||||||
|
p2 := byte(microsecs / 100)
|
||||||
|
microsecs -= 100 * uint32(p2)
|
||||||
|
p3 := byte(microsecs)
|
||||||
|
|
||||||
|
switch decimals {
|
||||||
|
default:
|
||||||
|
return append(dst, '.',
|
||||||
|
digits10[p1], digits01[p1],
|
||||||
|
digits10[p2], digits01[p2],
|
||||||
|
digits10[p3], digits01[p3],
|
||||||
|
)
|
||||||
|
case 1:
|
||||||
|
return append(dst, '.',
|
||||||
|
digits10[p1],
|
||||||
|
)
|
||||||
|
case 2:
|
||||||
|
return append(dst, '.',
|
||||||
|
digits10[p1], digits01[p1],
|
||||||
|
)
|
||||||
|
case 3:
|
||||||
|
return append(dst, '.',
|
||||||
|
digits10[p1], digits01[p1],
|
||||||
|
digits10[p2],
|
||||||
|
)
|
||||||
|
case 4:
|
||||||
|
return append(dst, '.',
|
||||||
|
digits10[p1], digits01[p1],
|
||||||
|
digits10[p2], digits01[p2],
|
||||||
|
)
|
||||||
|
case 5:
|
||||||
|
return append(dst, '.',
|
||||||
|
digits10[p1], digits01[p1],
|
||||||
|
digits10[p2], digits01[p2],
|
||||||
|
digits10[p3],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatBinaryDateTime(src []byte, length uint8) (driver.Value, error) {
|
||||||
// length expects the deterministic length of the zero value,
|
// length expects the deterministic length of the zero value,
|
||||||
// negative time and 100+ hours are automatically added if needed
|
// negative time and 100+ hours are automatically added if needed
|
||||||
if len(src) == 0 {
|
if len(src) == 0 {
|
||||||
if justTime {
|
|
||||||
return zeroDateTime[11 : 11+length], nil
|
|
||||||
}
|
|
||||||
return zeroDateTime[:length], nil
|
return zeroDateTime[:length], nil
|
||||||
}
|
}
|
||||||
var dst []byte // return value
|
var dst []byte // return value
|
||||||
var pt, p1, p2, p3 byte // current digit pair
|
var p1, p2, p3 byte // current digit pair
|
||||||
var zOffs byte // offset of value in zeroDateTime
|
|
||||||
if justTime {
|
switch length {
|
||||||
switch length {
|
case 10, 19, 21, 22, 23, 24, 25, 26:
|
||||||
case
|
default:
|
||||||
8, // time (can be up to 10 when negative and 100+ hours)
|
t := "DATE"
|
||||||
10, 11, 12, 13, 14, 15: // time with fractional seconds
|
if length > 10 {
|
||||||
default:
|
t += "TIME"
|
||||||
return nil, fmt.Errorf("illegal TIME length %d", length)
|
|
||||||
}
|
}
|
||||||
switch len(src) {
|
return nil, fmt.Errorf("illegal %s length %d", t, length)
|
||||||
case 8, 12:
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("invalid TIME packet length %d", len(src))
|
|
||||||
}
|
|
||||||
// +2 to enable negative time and 100+ hours
|
|
||||||
dst = make([]byte, 0, length+2)
|
|
||||||
if src[0] == 1 {
|
|
||||||
dst = append(dst, '-')
|
|
||||||
}
|
|
||||||
if src[1] != 0 {
|
|
||||||
hour := uint16(src[1])*24 + uint16(src[5])
|
|
||||||
pt = byte(hour / 100)
|
|
||||||
p1 = byte(hour - 100*uint16(pt))
|
|
||||||
dst = append(dst, digits01[pt])
|
|
||||||
} else {
|
|
||||||
p1 = src[5]
|
|
||||||
}
|
|
||||||
zOffs = 11
|
|
||||||
src = src[6:]
|
|
||||||
} else {
|
|
||||||
switch length {
|
|
||||||
case 10, 19, 21, 22, 23, 24, 25, 26:
|
|
||||||
default:
|
|
||||||
t := "DATE"
|
|
||||||
if length > 10 {
|
|
||||||
t += "TIME"
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("illegal %s length %d", t, length)
|
|
||||||
}
|
|
||||||
switch len(src) {
|
|
||||||
case 4, 7, 11:
|
|
||||||
default:
|
|
||||||
t := "DATE"
|
|
||||||
if length > 10 {
|
|
||||||
t += "TIME"
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
|
|
||||||
}
|
|
||||||
dst = make([]byte, 0, length)
|
|
||||||
// start with the date
|
|
||||||
year := binary.LittleEndian.Uint16(src[:2])
|
|
||||||
pt = byte(year / 100)
|
|
||||||
p1 = byte(year - 100*uint16(pt))
|
|
||||||
p2, p3 = src[2], src[3]
|
|
||||||
dst = append(dst,
|
|
||||||
digits10[pt], digits01[pt],
|
|
||||||
digits10[p1], digits01[p1], '-',
|
|
||||||
digits10[p2], digits01[p2], '-',
|
|
||||||
digits10[p3], digits01[p3],
|
|
||||||
)
|
|
||||||
if length == 10 {
|
|
||||||
return dst, nil
|
|
||||||
}
|
|
||||||
if len(src) == 4 {
|
|
||||||
return append(dst, zeroDateTime[10:length]...), nil
|
|
||||||
}
|
|
||||||
dst = append(dst, ' ')
|
|
||||||
p1 = src[4] // hour
|
|
||||||
src = src[5:]
|
|
||||||
}
|
}
|
||||||
|
switch len(src) {
|
||||||
|
case 4, 7, 11:
|
||||||
|
default:
|
||||||
|
t := "DATE"
|
||||||
|
if length > 10 {
|
||||||
|
t += "TIME"
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
|
||||||
|
}
|
||||||
|
dst = make([]byte, 0, length)
|
||||||
|
// start with the date
|
||||||
|
year := binary.LittleEndian.Uint16(src[:2])
|
||||||
|
pt := year / 100
|
||||||
|
p1 = byte(year - 100*uint16(pt))
|
||||||
|
p2, p3 = src[2], src[3]
|
||||||
|
dst = append(dst,
|
||||||
|
digits10[pt], digits01[pt],
|
||||||
|
digits10[p1], digits01[p1], '-',
|
||||||
|
digits10[p2], digits01[p2], '-',
|
||||||
|
digits10[p3], digits01[p3],
|
||||||
|
)
|
||||||
|
if length == 10 {
|
||||||
|
return dst, nil
|
||||||
|
}
|
||||||
|
if len(src) == 4 {
|
||||||
|
return append(dst, zeroDateTime[10:length]...), nil
|
||||||
|
}
|
||||||
|
dst = append(dst, ' ')
|
||||||
|
p1 = src[4] // hour
|
||||||
|
src = src[5:]
|
||||||
|
|
||||||
// p1 is 2-digit hour, src is after hour
|
// p1 is 2-digit hour, src is after hour
|
||||||
p2, p3 = src[0], src[1]
|
p2, p3 = src[0], src[1]
|
||||||
dst = append(dst,
|
dst = append(dst,
|
||||||
@@ -315,51 +333,49 @@ func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value
|
|||||||
digits10[p2], digits01[p2], ':',
|
digits10[p2], digits01[p2], ':',
|
||||||
digits10[p3], digits01[p3],
|
digits10[p3], digits01[p3],
|
||||||
)
|
)
|
||||||
if length <= byte(len(dst)) {
|
return appendMicrosecs(dst, src[2:], int(length)-20), nil
|
||||||
return dst, nil
|
}
|
||||||
}
|
|
||||||
src = src[2:]
|
func formatBinaryTime(src []byte, length uint8) (driver.Value, error) {
|
||||||
|
// length expects the deterministic length of the zero value,
|
||||||
|
// negative time and 100+ hours are automatically added if needed
|
||||||
if len(src) == 0 {
|
if len(src) == 0 {
|
||||||
return append(dst, zeroDateTime[19:zOffs+length]...), nil
|
return zeroDateTime[11 : 11+length], nil
|
||||||
}
|
}
|
||||||
microsecs := binary.LittleEndian.Uint32(src[:4])
|
var dst []byte // return value
|
||||||
p1 = byte(microsecs / 10000)
|
|
||||||
microsecs -= 10000 * uint32(p1)
|
switch length {
|
||||||
p2 = byte(microsecs / 100)
|
case
|
||||||
microsecs -= 100 * uint32(p2)
|
8, // time (can be up to 10 when negative and 100+ hours)
|
||||||
p3 = byte(microsecs)
|
10, 11, 12, 13, 14, 15: // time with fractional seconds
|
||||||
switch decimals := zOffs + length - 20; decimals {
|
|
||||||
default:
|
default:
|
||||||
return append(dst, '.',
|
return nil, fmt.Errorf("illegal TIME length %d", length)
|
||||||
digits10[p1], digits01[p1],
|
|
||||||
digits10[p2], digits01[p2],
|
|
||||||
digits10[p3], digits01[p3],
|
|
||||||
), nil
|
|
||||||
case 1:
|
|
||||||
return append(dst, '.',
|
|
||||||
digits10[p1],
|
|
||||||
), nil
|
|
||||||
case 2:
|
|
||||||
return append(dst, '.',
|
|
||||||
digits10[p1], digits01[p1],
|
|
||||||
), nil
|
|
||||||
case 3:
|
|
||||||
return append(dst, '.',
|
|
||||||
digits10[p1], digits01[p1],
|
|
||||||
digits10[p2],
|
|
||||||
), nil
|
|
||||||
case 4:
|
|
||||||
return append(dst, '.',
|
|
||||||
digits10[p1], digits01[p1],
|
|
||||||
digits10[p2], digits01[p2],
|
|
||||||
), nil
|
|
||||||
case 5:
|
|
||||||
return append(dst, '.',
|
|
||||||
digits10[p1], digits01[p1],
|
|
||||||
digits10[p2], digits01[p2],
|
|
||||||
digits10[p3],
|
|
||||||
), nil
|
|
||||||
}
|
}
|
||||||
|
switch len(src) {
|
||||||
|
case 8, 12:
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid TIME packet length %d", len(src))
|
||||||
|
}
|
||||||
|
// +2 to enable negative time and 100+ hours
|
||||||
|
dst = make([]byte, 0, length+2)
|
||||||
|
if src[0] == 1 {
|
||||||
|
dst = append(dst, '-')
|
||||||
|
}
|
||||||
|
days := binary.LittleEndian.Uint32(src[1:5])
|
||||||
|
hours := int64(days)*24 + int64(src[5])
|
||||||
|
|
||||||
|
if hours >= 100 {
|
||||||
|
dst = strconv.AppendInt(dst, hours, 10)
|
||||||
|
} else {
|
||||||
|
dst = append(dst, digits10[hours], digits01[hours])
|
||||||
|
}
|
||||||
|
|
||||||
|
min, sec := src[6], src[7]
|
||||||
|
dst = append(dst, ':',
|
||||||
|
digits10[min], digits01[min], ':',
|
||||||
|
digits10[sec], digits01[sec],
|
||||||
|
)
|
||||||
|
return appendMicrosecs(dst, src[8:], int(length)-9), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
|||||||
1
vendor/github.com/google/uuid/go.mod
сгенерированный
поставляемый
Обычный файл
1
vendor/github.com/google/uuid/go.mod
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1 @@
|
|||||||
|
module github.com/google/uuid
|
||||||
73
vendor/github.com/google/uuid/uuid.go
сгенерированный
поставляемый
73
vendor/github.com/google/uuid/uuid.go
сгенерированный
поставляемый
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2016 Google Inc. All rights reserved.
|
// Copyright 2018 Google Inc. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
@@ -35,20 +35,43 @@ const (
|
|||||||
|
|
||||||
var rander = rand.Reader // random function
|
var rander = rand.Reader // random function
|
||||||
|
|
||||||
// Parse decodes s into a UUID or returns an error. Both the UUID form of
|
// Parse decodes s into a UUID or returns an error. Both the standard UUID
|
||||||
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
|
||||||
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded.
|
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
|
||||||
|
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
|
||||||
|
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
|
||||||
func Parse(s string) (UUID, error) {
|
func Parse(s string) (UUID, error) {
|
||||||
var uuid UUID
|
var uuid UUID
|
||||||
if len(s) != 36 {
|
switch len(s) {
|
||||||
if len(s) != 36+9 {
|
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
|
case 36:
|
||||||
}
|
|
||||||
|
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
case 36 + 9:
|
||||||
if strings.ToLower(s[:9]) != "urn:uuid:" {
|
if strings.ToLower(s[:9]) != "urn:uuid:" {
|
||||||
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
|
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
|
||||||
}
|
}
|
||||||
s = s[9:]
|
s = s[9:]
|
||||||
|
|
||||||
|
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
||||||
|
case 36 + 2:
|
||||||
|
s = s[1:]
|
||||||
|
|
||||||
|
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
case 32:
|
||||||
|
var ok bool
|
||||||
|
for i := range uuid {
|
||||||
|
uuid[i], ok = xtob(s[i*2], s[i*2+1])
|
||||||
|
if !ok {
|
||||||
|
return uuid, errors.New("invalid UUID format")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uuid, nil
|
||||||
|
default:
|
||||||
|
return uuid, fmt.Errorf("invalid UUID length: %d", len(s))
|
||||||
}
|
}
|
||||||
|
// s is now at least 36 bytes long
|
||||||
|
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
||||||
return uuid, errors.New("invalid UUID format")
|
return uuid, errors.New("invalid UUID format")
|
||||||
}
|
}
|
||||||
@@ -70,15 +93,29 @@ func Parse(s string) (UUID, error) {
|
|||||||
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
|
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
|
||||||
func ParseBytes(b []byte) (UUID, error) {
|
func ParseBytes(b []byte) (UUID, error) {
|
||||||
var uuid UUID
|
var uuid UUID
|
||||||
if len(b) != 36 {
|
switch len(b) {
|
||||||
if len(b) != 36+9 {
|
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
|
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
}
|
|
||||||
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
|
if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) {
|
||||||
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
|
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
|
||||||
}
|
}
|
||||||
b = b[9:]
|
b = b[9:]
|
||||||
|
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
||||||
|
b = b[1:]
|
||||||
|
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
var ok bool
|
||||||
|
for i := 0; i < 32; i += 2 {
|
||||||
|
uuid[i/2], ok = xtob(b[i], b[i+1])
|
||||||
|
if !ok {
|
||||||
|
return uuid, errors.New("invalid UUID format")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uuid, nil
|
||||||
|
default:
|
||||||
|
return uuid, fmt.Errorf("invalid UUID length: %d", len(b))
|
||||||
}
|
}
|
||||||
|
// s is now at least 36 bytes long
|
||||||
|
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
|
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
|
||||||
return uuid, errors.New("invalid UUID format")
|
return uuid, errors.New("invalid UUID format")
|
||||||
}
|
}
|
||||||
@@ -97,6 +134,16 @@ func ParseBytes(b []byte) (UUID, error) {
|
|||||||
return uuid, nil
|
return uuid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MustParse is like Parse but panics if the string cannot be parsed.
|
||||||
|
// It simplifies safe initialization of global variables holding compiled UUIDs.
|
||||||
|
func MustParse(s string) UUID {
|
||||||
|
uuid, err := Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(`uuid: Parse(` + s + `): ` + err.Error())
|
||||||
|
}
|
||||||
|
return uuid
|
||||||
|
}
|
||||||
|
|
||||||
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
|
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
|
||||||
// does not have a length of 16. The bytes are copied from the slice.
|
// does not have a length of 16. The bytes are copied from the slice.
|
||||||
func FromBytes(b []byte) (uuid UUID, err error) {
|
func FromBytes(b []byte) (uuid UUID, err error) {
|
||||||
@@ -130,7 +177,7 @@ func (uuid UUID) URN() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func encodeHex(dst []byte, uuid UUID) {
|
func encodeHex(dst []byte, uuid UUID) {
|
||||||
hex.Encode(dst[:], uuid[:4])
|
hex.Encode(dst, uuid[:4])
|
||||||
dst[8] = '-'
|
dst[8] = '-'
|
||||||
hex.Encode(dst[9:13], uuid[4:6])
|
hex.Encode(dst[9:13], uuid[4:6])
|
||||||
dst[13] = '-'
|
dst[13] = '-'
|
||||||
|
|||||||
18
vendor/github.com/hashicorp/go-plugin/README.md
сгенерированный
поставляемый
18
vendor/github.com/hashicorp/go-plugin/README.md
сгенерированный
поставляемый
@@ -109,7 +109,7 @@ high-level steps that must be done. Examples are available in the
|
|||||||
1. Choose the interface(s) you want to expose for plugins.
|
1. Choose the interface(s) you want to expose for plugins.
|
||||||
|
|
||||||
2. For each interface, implement an implementation of that interface
|
2. For each interface, implement an implementation of that interface
|
||||||
that communicates over a `net/rpc` connection or other a
|
that communicates over a `net/rpc` connection or over a
|
||||||
[gRPC](http://www.grpc.io) connection or both. You'll have to implement
|
[gRPC](http://www.grpc.io) connection or both. You'll have to implement
|
||||||
both a client and server implementation.
|
both a client and server implementation.
|
||||||
|
|
||||||
@@ -150,19 +150,19 @@ user experience.
|
|||||||
|
|
||||||
When we started using plugins (late 2012, early 2013), plugins over RPC
|
When we started using plugins (late 2012, early 2013), plugins over RPC
|
||||||
were the only option since Go didn't support dynamic library loading. Today,
|
were the only option since Go didn't support dynamic library loading. Today,
|
||||||
Go still doesn't support dynamic library loading, but they do intend to.
|
Go supports the [plugin](https://golang.org/pkg/plugin/) standard library with
|
||||||
Since 2012, our plugin system has stabilized from millions of users using it,
|
a number of limitations. Since 2012, our plugin system has stabilized
|
||||||
and has many benefits we've come to value greatly.
|
from tens of millions of users using it, and has many benefits we've come to
|
||||||
|
value greatly.
|
||||||
|
|
||||||
For example, we intend to use this plugin system in
|
For example, we use this plugin system in
|
||||||
[Vault](https://www.vaultproject.io), and dynamic library loading will
|
[Vault](https://www.vaultproject.io) where dynamic library loading is
|
||||||
simply never be acceptable in Vault for security reasons. That is an extreme
|
not acceptable for security reasons. That is an extreme
|
||||||
example, but we believe our library system has more upsides than downsides
|
example, but we believe our library system has more upsides than downsides
|
||||||
over dynamic library loading and since we've had it built and tested for years,
|
over dynamic library loading and since we've had it built and tested for years,
|
||||||
we'll likely continue to use it.
|
we'll continue to use it.
|
||||||
|
|
||||||
Shared libraries have one major advantage over our system which is much
|
Shared libraries have one major advantage over our system which is much
|
||||||
higher performance. In real world scenarios across our various tools,
|
higher performance. In real world scenarios across our various tools,
|
||||||
we've never required any more performance out of our plugin system and it
|
we've never required any more performance out of our plugin system and it
|
||||||
has seen very high throughput, so this isn't a concern for us at the moment.
|
has seen very high throughput, so this isn't a concern for us at the moment.
|
||||||
|
|
||||||
|
|||||||
39
vendor/github.com/hashicorp/go-plugin/client.go
сгенерированный
поставляемый
39
vendor/github.com/hashicorp/go-plugin/client.go
сгенерированный
поставляемый
@@ -358,11 +358,19 @@ func (c *Client) Kill() {
|
|||||||
doneCh := c.doneLogging
|
doneCh := c.doneLogging
|
||||||
c.l.Unlock()
|
c.l.Unlock()
|
||||||
|
|
||||||
// If there is no process, we never started anything. Nothing to kill.
|
// If there is no process, there is nothing to kill.
|
||||||
if process == nil {
|
if process == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
// Make sure there is no reference to the old process after it has been
|
||||||
|
// killed.
|
||||||
|
c.l.Lock()
|
||||||
|
defer c.l.Unlock()
|
||||||
|
c.process = nil
|
||||||
|
}()
|
||||||
|
|
||||||
// We need to check for address here. It is possible that the plugin
|
// We need to check for address here. It is possible that the plugin
|
||||||
// started (process != nil) but has no address (addr == nil) if the
|
// started (process != nil) but has no address (addr == nil) if the
|
||||||
// plugin failed at startup. If we do have an address, we need to close
|
// plugin failed at startup. If we do have an address, we need to close
|
||||||
@@ -392,8 +400,12 @@ func (c *Client) Kill() {
|
|||||||
if graceful {
|
if graceful {
|
||||||
select {
|
select {
|
||||||
case <-doneCh:
|
case <-doneCh:
|
||||||
|
// FIXME: this is never reached under normal circumstances, because
|
||||||
|
// the plugin process is never signaled to exit. We can reach this
|
||||||
|
// if the child process exited abnormally before the Kill call.
|
||||||
return
|
return
|
||||||
case <-time.After(250 * time.Millisecond):
|
case <-time.After(250 * time.Millisecond):
|
||||||
|
c.logger.Warn("plugin failed to exit gracefully")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,6 +472,8 @@ func (c *Client) Start() (addr net.Addr, err error) {
|
|||||||
|
|
||||||
// Goroutine to mark exit status
|
// Goroutine to mark exit status
|
||||||
go func(pid int) {
|
go func(pid int) {
|
||||||
|
// ensure the context is cancelled when we're done
|
||||||
|
defer ctxCancel()
|
||||||
// Wait for the process to die
|
// Wait for the process to die
|
||||||
pidWait(pid)
|
pidWait(pid)
|
||||||
|
|
||||||
@@ -473,9 +487,6 @@ func (c *Client) Start() (addr net.Addr, err error) {
|
|||||||
|
|
||||||
// Close the logging channel since that doesn't work on reattach
|
// Close the logging channel since that doesn't work on reattach
|
||||||
close(c.doneLogging)
|
close(c.doneLogging)
|
||||||
|
|
||||||
// Cancel the context
|
|
||||||
ctxCancel()
|
|
||||||
}(p.Pid)
|
}(p.Pid)
|
||||||
|
|
||||||
// Set the address and process
|
// Set the address and process
|
||||||
@@ -542,6 +553,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
|
|||||||
|
|
||||||
// Set the process
|
// Set the process
|
||||||
c.process = cmd.Process
|
c.process = cmd.Process
|
||||||
|
c.logger.Debug("plugin started", "path", cmd.Path, "pid", c.process.Pid)
|
||||||
|
|
||||||
// Make sure the command is properly cleaned up if there is an error
|
// Make sure the command is properly cleaned up if there is an error
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -564,19 +576,28 @@ func (c *Client) Start() (addr net.Addr, err error) {
|
|||||||
defer stderr_w.Close()
|
defer stderr_w.Close()
|
||||||
defer stdout_w.Close()
|
defer stdout_w.Close()
|
||||||
|
|
||||||
|
// ensure the context is cancelled when we're done
|
||||||
|
defer ctxCancel()
|
||||||
|
|
||||||
// Wait for the command to end.
|
// Wait for the command to end.
|
||||||
cmd.Wait()
|
err := cmd.Wait()
|
||||||
|
|
||||||
|
debugMsgArgs := []interface{}{
|
||||||
|
"path", cmd.Path,
|
||||||
|
"pid", c.process.Pid,
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
debugMsgArgs = append(debugMsgArgs,
|
||||||
|
[]interface{}{"error", err.Error()}...)
|
||||||
|
}
|
||||||
|
|
||||||
// Log and make sure to flush the logs write away
|
// Log and make sure to flush the logs write away
|
||||||
c.logger.Debug("plugin process exited", "path", cmd.Path)
|
c.logger.Debug("plugin process exited", debugMsgArgs...)
|
||||||
os.Stderr.Sync()
|
os.Stderr.Sync()
|
||||||
|
|
||||||
// Mark that we exited
|
// Mark that we exited
|
||||||
close(exitCh)
|
close(exitCh)
|
||||||
|
|
||||||
// Cancel the context, marking that we exited
|
|
||||||
ctxCancel()
|
|
||||||
|
|
||||||
// Set that we exited, which takes a lock
|
// Set that we exited, which takes a lock
|
||||||
c.l.Lock()
|
c.l.Lock()
|
||||||
defer c.l.Unlock()
|
defer c.l.Unlock()
|
||||||
|
|||||||
13
vendor/github.com/hashicorp/go-plugin/go.mod
сгенерированный
поставляемый
Обычный файл
13
vendor/github.com/hashicorp/go-plugin/go.mod
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,13 @@
|
|||||||
|
module github.com/hashicorp/go-plugin
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/golang/protobuf v1.2.0
|
||||||
|
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb
|
||||||
|
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77
|
||||||
|
github.com/oklog/run v1.0.0
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
|
||||||
|
golang.org/x/text v0.3.0 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 // indirect
|
||||||
|
google.golang.org/grpc v1.14.0
|
||||||
|
)
|
||||||
18
vendor/github.com/hashicorp/go-plugin/go.sum
сгенерированный
поставляемый
Обычный файл
18
vendor/github.com/hashicorp/go-plugin/go.sum
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,18 @@
|
|||||||
|
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd h1:rNuUHR+CvK1IS89MMtcF0EpcVMZtjKfPRp4MEmt/aTs=
|
||||||
|
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||||
|
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=
|
||||||
|
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
|
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||||
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/grpc v1.14.0 h1:ArxJuB1NWfPY6r9Gp9gqwplT0Ge7nqv9msgu03lHLmo=
|
||||||
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
31
vendor/github.com/hashicorp/go-plugin/server.go
сгенерированный
поставляемый
31
vendor/github.com/hashicorp/go-plugin/server.go
сгенерированный
поставляемый
@@ -93,7 +93,7 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
|
|||||||
protoVersion := int(opts.ProtocolVersion)
|
protoVersion := int(opts.ProtocolVersion)
|
||||||
pluginSet := opts.Plugins
|
pluginSet := opts.Plugins
|
||||||
protoType := ProtocolNetRPC
|
protoType := ProtocolNetRPC
|
||||||
// check if the client sent a list of acceptable versions
|
// Check if the client sent a list of acceptable versions
|
||||||
var clientVersions []int
|
var clientVersions []int
|
||||||
if vs := os.Getenv("PLUGIN_PROTOCOL_VERSIONS"); vs != "" {
|
if vs := os.Getenv("PLUGIN_PROTOCOL_VERSIONS"); vs != "" {
|
||||||
for _, s := range strings.Split(vs, ",") {
|
for _, s := range strings.Split(vs, ",") {
|
||||||
@@ -106,7 +106,7 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we want to iterate in reverse order, to ensure we match the newest
|
// We want to iterate in reverse order, to ensure we match the newest
|
||||||
// compatible plugin version.
|
// compatible plugin version.
|
||||||
sort.Sort(sort.Reverse(sort.IntSlice(clientVersions)))
|
sort.Sort(sort.Reverse(sort.IntSlice(clientVersions)))
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
|
|||||||
opts.VersionedPlugins[protoVersion] = pluginSet
|
opts.VersionedPlugins[protoVersion] = pluginSet
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort the version to make sure we match the latest first
|
// Sort the version to make sure we match the latest first
|
||||||
var versions []int
|
var versions []int
|
||||||
for v := range opts.VersionedPlugins {
|
for v := range opts.VersionedPlugins {
|
||||||
versions = append(versions, v)
|
versions = append(versions, v)
|
||||||
@@ -127,23 +127,26 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
|
|||||||
|
|
||||||
sort.Sort(sort.Reverse(sort.IntSlice(versions)))
|
sort.Sort(sort.Reverse(sort.IntSlice(versions)))
|
||||||
|
|
||||||
// see if we have multiple versions of Plugins to choose from
|
// See if we have multiple versions of Plugins to choose from
|
||||||
for _, version := range versions {
|
for _, version := range versions {
|
||||||
// record each version, since we guarantee that this returns valid
|
// Record each version, since we guarantee that this returns valid
|
||||||
// values even if they are not a protocol match.
|
// values even if they are not a protocol match.
|
||||||
protoVersion = version
|
protoVersion = version
|
||||||
pluginSet = opts.VersionedPlugins[version]
|
pluginSet = opts.VersionedPlugins[version]
|
||||||
|
|
||||||
// all plugins in a set must use the same transport, so check the first
|
// If we have a configured gRPC server we should select a protocol
|
||||||
// for the protocol type
|
if opts.GRPCServer != nil {
|
||||||
for _, p := range pluginSet {
|
// All plugins in a set must use the same transport, so check the first
|
||||||
switch p.(type) {
|
// for the protocol type
|
||||||
case GRPCPlugin:
|
for _, p := range pluginSet {
|
||||||
protoType = ProtocolGRPC
|
switch p.(type) {
|
||||||
default:
|
case GRPCPlugin:
|
||||||
protoType = ProtocolNetRPC
|
protoType = ProtocolGRPC
|
||||||
|
default:
|
||||||
|
protoType = ProtocolNetRPC
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, clientVersion := range clientVersions {
|
for _, clientVersion := range clientVersions {
|
||||||
|
|||||||
13
vendor/github.com/hashicorp/memberlist/.travis.yml
сгенерированный
поставляемый
Обычный файл
13
vendor/github.com/hashicorp/memberlist/.travis.yml
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,13 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
sudo: true
|
||||||
|
|
||||||
|
go:
|
||||||
|
- "1.x"
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
|
||||||
|
install:
|
||||||
|
- make deps
|
||||||
5
vendor/github.com/hashicorp/memberlist/Makefile
сгенерированный
поставляемый
5
vendor/github.com/hashicorp/memberlist/Makefile
сгенерированный
поставляемый
@@ -1,4 +1,5 @@
|
|||||||
DEPS = $(go list -f '{{range .Imports}}{{.}} {{end}}' ./...)
|
DEPS := $(shell go list -f '{{range .Imports}}{{.}} {{end}}' ./...)
|
||||||
|
|
||||||
test: subnet
|
test: subnet
|
||||||
go test ./...
|
go test ./...
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ cov:
|
|||||||
open /tmp/coverage.html
|
open /tmp/coverage.html
|
||||||
|
|
||||||
deps:
|
deps:
|
||||||
go get -d -v ./...
|
go get -t -d -v ./...
|
||||||
echo $(DEPS) | xargs -n1 go get -d
|
echo $(DEPS) | xargs -n1 go get -d
|
||||||
|
|
||||||
.PHONY: test cov integ
|
.PHONY: test cov integ
|
||||||
|
|||||||
2
vendor/github.com/hashicorp/memberlist/README.md
сгенерированный
поставляемый
2
vendor/github.com/hashicorp/memberlist/README.md
сгенерированный
поставляемый
@@ -1,4 +1,4 @@
|
|||||||
# memberlist [](https://godoc.org/github.com/hashicorp/memberlist)
|
# memberlist [](https://godoc.org/github.com/hashicorp/memberlist) [](https://travis-ci.org/hashicorp/memberlist)
|
||||||
|
|
||||||
memberlist is a [Go](http://www.golang.org) library that manages cluster
|
memberlist is a [Go](http://www.golang.org) library that manages cluster
|
||||||
membership and member failure detection using a gossip based protocol.
|
membership and member failure detection using a gossip based protocol.
|
||||||
|
|||||||
24
vendor/github.com/hashicorp/memberlist/memberlist.go
сгенерированный
поставляемый
24
vendor/github.com/hashicorp/memberlist/memberlist.go
сгенерированный
поставляемый
@@ -665,3 +665,27 @@ func (m *Memberlist) hasShutdown() bool {
|
|||||||
func (m *Memberlist) hasLeft() bool {
|
func (m *Memberlist) hasLeft() bool {
|
||||||
return atomic.LoadInt32(&m.leave) == 1
|
return atomic.LoadInt32(&m.leave) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Memberlist) getNodeState(addr string) nodeStateType {
|
||||||
|
m.nodeLock.RLock()
|
||||||
|
defer m.nodeLock.RUnlock()
|
||||||
|
|
||||||
|
n := m.nodeMap[addr]
|
||||||
|
return n.State
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memberlist) getNodeStateChange(addr string) time.Time {
|
||||||
|
m.nodeLock.RLock()
|
||||||
|
defer m.nodeLock.RUnlock()
|
||||||
|
|
||||||
|
n := m.nodeMap[addr]
|
||||||
|
return n.StateChange
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memberlist) changeNode(addr string, f func(*nodeState)) {
|
||||||
|
m.nodeLock.Lock()
|
||||||
|
defer m.nodeLock.Unlock()
|
||||||
|
|
||||||
|
n := m.nodeMap[addr]
|
||||||
|
f(n)
|
||||||
|
}
|
||||||
|
|||||||
20
vendor/github.com/hashicorp/memberlist/queue.go
сгенерированный
поставляемый
20
vendor/github.com/hashicorp/memberlist/queue.go
сгенерированный
поставляемый
@@ -27,6 +27,26 @@ type limitedBroadcast struct {
|
|||||||
transmits int // Number of transmissions attempted.
|
transmits int // Number of transmissions attempted.
|
||||||
b Broadcast
|
b Broadcast
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for testing; emits in transmit order if reverse=false
|
||||||
|
func (q *TransmitLimitedQueue) orderedView(reverse bool) []*limitedBroadcast {
|
||||||
|
q.Lock()
|
||||||
|
defer q.Unlock()
|
||||||
|
|
||||||
|
out := make([]*limitedBroadcast, 0, len(q.bcQueue))
|
||||||
|
if reverse {
|
||||||
|
for i := 0; i < len(q.bcQueue); i++ {
|
||||||
|
out = append(out, q.bcQueue[i])
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for i := len(q.bcQueue) - 1; i >= 0; i-- {
|
||||||
|
out = append(out, q.bcQueue[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
type limitedBroadcasts []*limitedBroadcast
|
type limitedBroadcasts []*limitedBroadcast
|
||||||
|
|
||||||
// Broadcast is something that can be broadcasted via gossip to
|
// Broadcast is something that can be broadcasted via gossip to
|
||||||
|
|||||||
9
vendor/github.com/hashicorp/memberlist/state.go
сгенерированный
поставляемый
9
vendor/github.com/hashicorp/memberlist/state.go
сгенерированный
поставляемый
@@ -233,6 +233,15 @@ START:
|
|||||||
m.probeNode(&node)
|
m.probeNode(&node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// probeNodeByAddr just safely calls probeNode given only the address of the node (for tests)
|
||||||
|
func (m *Memberlist) probeNodeByAddr(addr string) {
|
||||||
|
m.nodeLock.RLock()
|
||||||
|
n := m.nodeMap[addr]
|
||||||
|
m.nodeLock.RUnlock()
|
||||||
|
|
||||||
|
m.probeNode(n)
|
||||||
|
}
|
||||||
|
|
||||||
// probeNode handles a single round of failure checking on a node.
|
// probeNode handles a single round of failure checking on a node.
|
||||||
func (m *Memberlist) probeNode(node *nodeState) {
|
func (m *Memberlist) probeNode(node *nodeState) {
|
||||||
defer metrics.MeasureSince([]string{"memberlist", "probeNode"}, time.Now())
|
defer metrics.MeasureSince([]string{"memberlist", "probeNode"}, time.Now())
|
||||||
|
|||||||
5
vendor/github.com/hashicorp/memberlist/util.go
сгенерированный
поставляемый
5
vendor/github.com/hashicorp/memberlist/util.go
сгенерированный
поставляемый
@@ -78,10 +78,9 @@ func retransmitLimit(retransmitMult, n int) int {
|
|||||||
// shuffleNodes randomly shuffles the input nodes using the Fisher-Yates shuffle
|
// shuffleNodes randomly shuffles the input nodes using the Fisher-Yates shuffle
|
||||||
func shuffleNodes(nodes []*nodeState) {
|
func shuffleNodes(nodes []*nodeState) {
|
||||||
n := len(nodes)
|
n := len(nodes)
|
||||||
for i := n - 1; i > 0; i-- {
|
rand.Shuffle(n, func(i, j int) {
|
||||||
j := rand.Intn(i + 1)
|
|
||||||
nodes[i], nodes[j] = nodes[j], nodes[i]
|
nodes[i], nodes[j] = nodes[j], nodes[i]
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// pushPushScale is used to scale the time interval at which push/pull
|
// pushPushScale is used to scale the time interval at which push/pull
|
||||||
|
|||||||
1
vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod
сгенерированный
поставляемый
Обычный файл
1
vendor/github.com/konsorten/go-windows-terminal-sequences/go.mod
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1 @@
|
|||||||
|
module github.com/konsorten/go-windows-terminal-sequences
|
||||||
2
vendor/github.com/mattermost/viper/go.mod
сгенерированный
поставляемый
2
vendor/github.com/mattermost/viper/go.mod
сгенерированный
поставляемый
@@ -1,4 +1,4 @@
|
|||||||
module github.com/spf13/viper
|
module github.com/mattermost/viper
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
github.com/fsnotify/fsnotify v1.4.7
|
||||||
|
|||||||
4
vendor/github.com/mattn/go-sqlite3/.travis.yml
сгенерированный
поставляемый
4
vendor/github.com/mattn/go-sqlite3/.travis.yml
сгенерированный
поставляемый
@@ -12,18 +12,18 @@ env:
|
|||||||
matrix:
|
matrix:
|
||||||
- GOTAGS=
|
- GOTAGS=
|
||||||
- GOTAGS=libsqlite3
|
- GOTAGS=libsqlite3
|
||||||
- GOTAGS="sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable"
|
- GOTAGS="sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable sqlite_unlock_notify"
|
||||||
- GOTAGS=sqlite_vacuum_full
|
- GOTAGS=sqlite_vacuum_full
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.9.x
|
- 1.9.x
|
||||||
- 1.10.x
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- |
|
- |
|
||||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
brew update
|
brew update
|
||||||
brew upgrade icu4c
|
|
||||||
fi
|
fi
|
||||||
- |
|
- |
|
||||||
go get github.com/smartystreets/goconvey
|
go get github.com/smartystreets/goconvey
|
||||||
|
|||||||
7
vendor/github.com/mattn/go-sqlite3/README.md
сгенерированный
поставляемый
7
vendor/github.com/mattn/go-sqlite3/README.md
сгенерированный
поставляемый
@@ -67,6 +67,7 @@ This is also known as a DSN string. (Data Source Name).
|
|||||||
|
|
||||||
Options are append after the filename of the SQLite database.
|
Options are append after the filename of the SQLite database.
|
||||||
The database filename and options are seperated by an `?` (Question Mark).
|
The database filename and options are seperated by an `?` (Question Mark).
|
||||||
|
Options should be URL-encoded (see [url.QueryEscape](https://golang.org/pkg/net/url/#QueryEscape)).
|
||||||
|
|
||||||
This also applies when using an in-memory database instead of a file.
|
This also applies when using an in-memory database instead of a file.
|
||||||
|
|
||||||
@@ -198,7 +199,7 @@ Additional information:
|
|||||||
|
|
||||||
# Google Cloud Platform
|
# Google Cloud Platform
|
||||||
|
|
||||||
Building on GCP is not possible because `Google Cloud Platform does not allow `gcc` to be executed.
|
Building on GCP is not possible because Google Cloud Platform does not allow `gcc` to be executed.
|
||||||
|
|
||||||
Please work only with compiled final binaries.
|
Please work only with compiled final binaries.
|
||||||
|
|
||||||
@@ -290,7 +291,7 @@ For example the TDM-GCC Toolchain can be found [here](ttps://sourceforge.net/pro
|
|||||||
When receiving a compile time error referencing recompile with `-FPIC` then you
|
When receiving a compile time error referencing recompile with `-FPIC` then you
|
||||||
are probably using a hardend system.
|
are probably using a hardend system.
|
||||||
|
|
||||||
You can copile the library on a hardend system with the following command.
|
You can compile the library on a hardend system with the following command.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go build -ldflags '-extldflags=-fno-PIC'
|
go build -ldflags '-extldflags=-fno-PIC'
|
||||||
@@ -473,7 +474,7 @@ For an example see [shaxbee/go-spatialite](https://github.com/shaxbee/go-spatial
|
|||||||
|
|
||||||
For more information see [#289](https://github.com/mattn/go-sqlite3/issues/289)
|
For more information see [#289](https://github.com/mattn/go-sqlite3/issues/289)
|
||||||
|
|
||||||
- Trying to execure a `.` (dot) command throws an error.
|
- Trying to execute a `.` (dot) command throws an error.
|
||||||
|
|
||||||
Error: `Error: near ".": syntax error`
|
Error: `Error: near ".": syntax error`
|
||||||
Dot command are part of SQLite3 CLI not of this library.
|
Dot command are part of SQLite3 CLI not of this library.
|
||||||
|
|||||||
6
vendor/github.com/mattn/go-sqlite3/callback.go
сгенерированный
поставляемый
6
vendor/github.com/mattn/go-sqlite3/callback.go
сгенерированный
поставляемый
@@ -77,6 +77,12 @@ func updateHookTrampoline(handle uintptr, op int, db *C.char, table *C.char, row
|
|||||||
callback(op, C.GoString(db), C.GoString(table), rowid)
|
callback(op, C.GoString(db), C.GoString(table), rowid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//export authorizerTrampoline
|
||||||
|
func authorizerTrampoline(handle uintptr, op int, arg1 *C.char, arg2 *C.char, arg3 *C.char) int {
|
||||||
|
callback := lookupHandle(handle).(func(int, string, string, string) int)
|
||||||
|
return callback(op, C.GoString(arg1), C.GoString(arg2), C.GoString(arg3))
|
||||||
|
}
|
||||||
|
|
||||||
// Use handles to avoid passing Go pointers to C.
|
// Use handles to avoid passing Go pointers to C.
|
||||||
|
|
||||||
type handleVal struct {
|
type handleVal struct {
|
||||||
|
|||||||
21393
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
сгенерированный
поставляемый
21393
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
сгенерированный
поставляемый
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
293
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
сгенерированный
поставляемый
293
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
сгенерированный
поставляемый
@@ -124,9 +124,9 @@ extern "C" {
|
|||||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||||
** [sqlite_version()] and [sqlite_source_id()].
|
** [sqlite_version()] and [sqlite_source_id()].
|
||||||
*/
|
*/
|
||||||
#define SQLITE_VERSION "3.24.0"
|
#define SQLITE_VERSION "3.25.2"
|
||||||
#define SQLITE_VERSION_NUMBER 3024000
|
#define SQLITE_VERSION_NUMBER 3025002
|
||||||
#define SQLITE_SOURCE_ID "2018-06-04 19:24:41 c7ee0833225bfd8c5ec2f9bf62b97c4e04d03bd9566366d5221ac8fb199a87ca"
|
#define SQLITE_SOURCE_ID "2018-09-25 19:08:10 fb90e7189ae6d62e77ba3a308ca5d683f90bbe633cf681865365b8e92792d1c7"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Run-Time Library Version Numbers
|
** CAPI3REF: Run-Time Library Version Numbers
|
||||||
@@ -473,6 +473,7 @@ SQLITE_API int sqlite3_exec(
|
|||||||
*/
|
*/
|
||||||
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
|
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
|
||||||
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
|
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
|
||||||
|
#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8))
|
||||||
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
|
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
|
||||||
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
|
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
|
||||||
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
|
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
|
||||||
@@ -512,6 +513,7 @@ SQLITE_API int sqlite3_exec(
|
|||||||
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
|
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
|
||||||
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
||||||
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
||||||
|
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
|
||||||
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
||||||
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
|
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
|
||||||
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
||||||
@@ -887,7 +889,8 @@ struct sqlite3_io_methods {
|
|||||||
** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
|
** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
|
||||||
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
|
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
|
||||||
** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary
|
** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary
|
||||||
** write ahead log and shared memory files used for transaction control
|
** write ahead log ([WAL file]) and shared memory
|
||||||
|
** files used for transaction control
|
||||||
** are automatically deleted when the latest connection to the database
|
** are automatically deleted when the latest connection to the database
|
||||||
** closes. Setting persistent WAL mode causes those files to persist after
|
** closes. Setting persistent WAL mode causes those files to persist after
|
||||||
** close. Persisting the files is useful when other processes that do not
|
** close. Persisting the files is useful when other processes that do not
|
||||||
@@ -1073,6 +1076,26 @@ struct sqlite3_io_methods {
|
|||||||
** a file lock using the xLock or xShmLock methods of the VFS to wait
|
** a file lock using the xLock or xShmLock methods of the VFS to wait
|
||||||
** for up to M milliseconds before failing, where M is the single
|
** for up to M milliseconds before failing, where M is the single
|
||||||
** unsigned integer parameter.
|
** unsigned integer parameter.
|
||||||
|
**
|
||||||
|
** <li>[[SQLITE_FCNTL_DATA_VERSION]]
|
||||||
|
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
|
||||||
|
** a database file. The argument is a pointer to a 32-bit unsigned integer.
|
||||||
|
** The "data version" for the pager is written into the pointer. The
|
||||||
|
** "data version" changes whenever any change occurs to the corresponding
|
||||||
|
** database file, either through SQL statements on the same database
|
||||||
|
** connection or through transactions committed by separate database
|
||||||
|
** connections possibly in other processes. The [sqlite3_total_changes()]
|
||||||
|
** interface can be used to find if any database on the connection has changed,
|
||||||
|
** but that interface responds to changes on TEMP as well as MAIN and does
|
||||||
|
** not provide a mechanism to detect changes to MAIN only. Also, the
|
||||||
|
** [sqlite3_total_changes()] interface responds to internal changes only and
|
||||||
|
** omits changes made by other database connections. The
|
||||||
|
** [PRAGMA data_version] command provide a mechanism to detect changes to
|
||||||
|
** a single attached database that occur due to other database connections,
|
||||||
|
** but omits changes implemented by the database connection on which it is
|
||||||
|
** called. This file control is the only mechanism to detect changes that
|
||||||
|
** happen either internally or externally and that are associated with
|
||||||
|
** a particular attached database.
|
||||||
** </ul>
|
** </ul>
|
||||||
*/
|
*/
|
||||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||||
@@ -1108,6 +1131,7 @@ struct sqlite3_io_methods {
|
|||||||
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
|
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
|
||||||
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
|
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
|
||||||
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
|
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
|
||||||
|
#define SQLITE_FCNTL_DATA_VERSION 35
|
||||||
|
|
||||||
/* deprecated names */
|
/* deprecated names */
|
||||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||||
@@ -2122,6 +2146,12 @@ struct sqlite3_mem_methods {
|
|||||||
** with no schema and no content. The following process works even for
|
** with no schema and no content. The following process works even for
|
||||||
** a badly corrupted database file:
|
** a badly corrupted database file:
|
||||||
** <ol>
|
** <ol>
|
||||||
|
** <li> If the database connection is newly opened, make sure it has read the
|
||||||
|
** database schema by preparing then discarding some query against the
|
||||||
|
** database, or calling sqlite3_table_column_metadata(), ignoring any
|
||||||
|
** errors. This step is only necessary if the application desires to keep
|
||||||
|
** the database in WAL mode after the reset if it was in WAL mode before
|
||||||
|
** the reset.
|
||||||
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
||||||
** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
|
** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
|
||||||
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
|
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
|
||||||
@@ -2270,12 +2300,17 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
|
|||||||
** program, the value returned reflects the number of rows modified by the
|
** program, the value returned reflects the number of rows modified by the
|
||||||
** previous INSERT, UPDATE or DELETE statement within the same trigger.
|
** previous INSERT, UPDATE or DELETE statement within the same trigger.
|
||||||
**
|
**
|
||||||
** See also the [sqlite3_total_changes()] interface, the
|
|
||||||
** [count_changes pragma], and the [changes() SQL function].
|
|
||||||
**
|
|
||||||
** If a separate thread makes changes on the same database connection
|
** If a separate thread makes changes on the same database connection
|
||||||
** while [sqlite3_changes()] is running then the value returned
|
** while [sqlite3_changes()] is running then the value returned
|
||||||
** is unpredictable and not meaningful.
|
** is unpredictable and not meaningful.
|
||||||
|
**
|
||||||
|
** See also:
|
||||||
|
** <ul>
|
||||||
|
** <li> the [sqlite3_total_changes()] interface
|
||||||
|
** <li> the [count_changes pragma]
|
||||||
|
** <li> the [changes() SQL function]
|
||||||
|
** <li> the [data_version pragma]
|
||||||
|
** </ul>
|
||||||
*/
|
*/
|
||||||
SQLITE_API int sqlite3_changes(sqlite3*);
|
SQLITE_API int sqlite3_changes(sqlite3*);
|
||||||
|
|
||||||
@@ -2293,13 +2328,26 @@ SQLITE_API int sqlite3_changes(sqlite3*);
|
|||||||
** count, but those made as part of REPLACE constraint resolution are
|
** count, but those made as part of REPLACE constraint resolution are
|
||||||
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
|
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
|
||||||
** are not counted.
|
** are not counted.
|
||||||
**
|
|
||||||
** See also the [sqlite3_changes()] interface, the
|
|
||||||
** [count_changes pragma], and the [total_changes() SQL function].
|
|
||||||
**
|
**
|
||||||
|
** This the [sqlite3_total_changes(D)] interface only reports the number
|
||||||
|
** of rows that changed due to SQL statement run against database
|
||||||
|
** connection D. Any changes by other database connections are ignored.
|
||||||
|
** To detect changes against a database file from other database
|
||||||
|
** connections use the [PRAGMA data_version] command or the
|
||||||
|
** [SQLITE_FCNTL_DATA_VERSION] [file control].
|
||||||
|
**
|
||||||
** If a separate thread makes changes on the same database connection
|
** If a separate thread makes changes on the same database connection
|
||||||
** while [sqlite3_total_changes()] is running then the value
|
** while [sqlite3_total_changes()] is running then the value
|
||||||
** returned is unpredictable and not meaningful.
|
** returned is unpredictable and not meaningful.
|
||||||
|
**
|
||||||
|
** See also:
|
||||||
|
** <ul>
|
||||||
|
** <li> the [sqlite3_changes()] interface
|
||||||
|
** <li> the [count_changes pragma]
|
||||||
|
** <li> the [changes() SQL function]
|
||||||
|
** <li> the [data_version pragma]
|
||||||
|
** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
|
||||||
|
** </ul>
|
||||||
*/
|
*/
|
||||||
SQLITE_API int sqlite3_total_changes(sqlite3*);
|
SQLITE_API int sqlite3_total_changes(sqlite3*);
|
||||||
|
|
||||||
@@ -3355,13 +3403,24 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
|
|||||||
** [database connection] D failed, then the sqlite3_errcode(D) interface
|
** [database connection] D failed, then the sqlite3_errcode(D) interface
|
||||||
** returns the numeric [result code] or [extended result code] for that
|
** returns the numeric [result code] or [extended result code] for that
|
||||||
** API call.
|
** API call.
|
||||||
** If the most recent API call was successful,
|
|
||||||
** then the return value from sqlite3_errcode() is undefined.
|
|
||||||
** ^The sqlite3_extended_errcode()
|
** ^The sqlite3_extended_errcode()
|
||||||
** interface is the same except that it always returns the
|
** interface is the same except that it always returns the
|
||||||
** [extended result code] even when extended result codes are
|
** [extended result code] even when extended result codes are
|
||||||
** disabled.
|
** disabled.
|
||||||
**
|
**
|
||||||
|
** The values returned by sqlite3_errcode() and/or
|
||||||
|
** sqlite3_extended_errcode() might change with each API call.
|
||||||
|
** Except, there are some interfaces that are guaranteed to never
|
||||||
|
** change the value of the error code. The error-code preserving
|
||||||
|
** interfaces are:
|
||||||
|
**
|
||||||
|
** <ul>
|
||||||
|
** <li> sqlite3_errcode()
|
||||||
|
** <li> sqlite3_extended_errcode()
|
||||||
|
** <li> sqlite3_errmsg()
|
||||||
|
** <li> sqlite3_errmsg16()
|
||||||
|
** </ul>
|
||||||
|
**
|
||||||
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
||||||
** text that describes the error, as either UTF-8 or UTF-16 respectively.
|
** text that describes the error, as either UTF-8 or UTF-16 respectively.
|
||||||
** ^(Memory to hold the error message string is managed internally.
|
** ^(Memory to hold the error message string is managed internally.
|
||||||
@@ -4515,11 +4574,25 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
|
|||||||
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
|
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
|
||||||
** [sqlite3_free()].
|
** [sqlite3_free()].
|
||||||
**
|
**
|
||||||
** ^(If a memory allocation error occurs during the evaluation of any
|
** As long as the input parameters are correct, these routines will only
|
||||||
** of these routines, a default value is returned. The default value
|
** fail if an out-of-memory error occurs during a format conversion.
|
||||||
** is either the integer 0, the floating point number 0.0, or a NULL
|
** Only the following subset of interfaces are subject to out-of-memory
|
||||||
** pointer. Subsequent calls to [sqlite3_errcode()] will return
|
** errors:
|
||||||
** [SQLITE_NOMEM].)^
|
**
|
||||||
|
** <ul>
|
||||||
|
** <li> sqlite3_column_blob()
|
||||||
|
** <li> sqlite3_column_text()
|
||||||
|
** <li> sqlite3_column_text16()
|
||||||
|
** <li> sqlite3_column_bytes()
|
||||||
|
** <li> sqlite3_column_bytes16()
|
||||||
|
** </ul>
|
||||||
|
**
|
||||||
|
** If an out-of-memory error occurs, then the return value from these
|
||||||
|
** routines is the same as if the column had contained an SQL NULL value.
|
||||||
|
** Valid SQL NULL returns can be distinguished from out-of-memory errors
|
||||||
|
** by invoking the [sqlite3_errcode()] immediately after the suspect
|
||||||
|
** return value is obtained and before any
|
||||||
|
** other SQLite interface is called on the same [database connection].
|
||||||
*/
|
*/
|
||||||
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
|
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
|
||||||
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
|
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
|
||||||
@@ -4596,11 +4669,13 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
|||||||
**
|
**
|
||||||
** ^These functions (collectively known as "function creation routines")
|
** ^These functions (collectively known as "function creation routines")
|
||||||
** are used to add SQL functions or aggregates or to redefine the behavior
|
** are used to add SQL functions or aggregates or to redefine the behavior
|
||||||
** of existing SQL functions or aggregates. The only differences between
|
** of existing SQL functions or aggregates. The only differences between
|
||||||
** these routines are the text encoding expected for
|
** the three "sqlite3_create_function*" routines are the text encoding
|
||||||
** the second parameter (the name of the function being created)
|
** expected for the second parameter (the name of the function being
|
||||||
** and the presence or absence of a destructor callback for
|
** created) and the presence or absence of a destructor callback for
|
||||||
** the application data pointer.
|
** the application data pointer. Function sqlite3_create_window_function()
|
||||||
|
** is similar, but allows the user to supply the extra callback functions
|
||||||
|
** needed by [aggregate window functions].
|
||||||
**
|
**
|
||||||
** ^The first parameter is the [database connection] to which the SQL
|
** ^The first parameter is the [database connection] to which the SQL
|
||||||
** function is to be added. ^If an application uses more than one database
|
** function is to be added. ^If an application uses more than one database
|
||||||
@@ -4646,7 +4721,8 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
|||||||
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
|
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
|
||||||
** function can gain access to this pointer using [sqlite3_user_data()].)^
|
** function can gain access to this pointer using [sqlite3_user_data()].)^
|
||||||
**
|
**
|
||||||
** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are
|
** ^The sixth, seventh and eighth parameters passed to the three
|
||||||
|
** "sqlite3_create_function*" functions, xFunc, xStep and xFinal, are
|
||||||
** pointers to C-language functions that implement the SQL function or
|
** pointers to C-language functions that implement the SQL function or
|
||||||
** aggregate. ^A scalar SQL function requires an implementation of the xFunc
|
** aggregate. ^A scalar SQL function requires an implementation of the xFunc
|
||||||
** callback only; NULL pointers must be passed as the xStep and xFinal
|
** callback only; NULL pointers must be passed as the xStep and xFinal
|
||||||
@@ -4655,15 +4731,24 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
|||||||
** SQL function or aggregate, pass NULL pointers for all three function
|
** SQL function or aggregate, pass NULL pointers for all three function
|
||||||
** callbacks.
|
** callbacks.
|
||||||
**
|
**
|
||||||
** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL,
|
** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue
|
||||||
** then it is destructor for the application data pointer.
|
** and xInverse) passed to sqlite3_create_window_function are pointers to
|
||||||
** The destructor is invoked when the function is deleted, either by being
|
** C-language callbacks that implement the new function. xStep and xFinal
|
||||||
** overloaded or when the database connection closes.)^
|
** must both be non-NULL. xValue and xInverse may either both be NULL, in
|
||||||
** ^The destructor is also invoked if the call to
|
** which case a regular aggregate function is created, or must both be
|
||||||
** sqlite3_create_function_v2() fails.
|
** non-NULL, in which case the new function may be used as either an aggregate
|
||||||
** ^When the destructor callback of the tenth parameter is invoked, it
|
** or aggregate window function. More details regarding the implementation
|
||||||
** is passed a single argument which is a copy of the application data
|
** of aggregate window functions are
|
||||||
** pointer which was the fifth parameter to sqlite3_create_function_v2().
|
** [user-defined window functions|available here].
|
||||||
|
**
|
||||||
|
** ^(If the final parameter to sqlite3_create_function_v2() or
|
||||||
|
** sqlite3_create_window_function() is not NULL, then it is destructor for
|
||||||
|
** the application data pointer. The destructor is invoked when the function
|
||||||
|
** is deleted, either by being overloaded or when the database connection
|
||||||
|
** closes.)^ ^The destructor is also invoked if the call to
|
||||||
|
** sqlite3_create_function_v2() fails. ^When the destructor callback is
|
||||||
|
** invoked, it is passed a single argument which is a copy of the application
|
||||||
|
** data pointer which was the fifth parameter to sqlite3_create_function_v2().
|
||||||
**
|
**
|
||||||
** ^It is permitted to register multiple implementations of the same
|
** ^It is permitted to register multiple implementations of the same
|
||||||
** functions with the same name but with either differing numbers of
|
** functions with the same name but with either differing numbers of
|
||||||
@@ -4716,6 +4801,18 @@ SQLITE_API int sqlite3_create_function_v2(
|
|||||||
void (*xFinal)(sqlite3_context*),
|
void (*xFinal)(sqlite3_context*),
|
||||||
void(*xDestroy)(void*)
|
void(*xDestroy)(void*)
|
||||||
);
|
);
|
||||||
|
SQLITE_API int sqlite3_create_window_function(
|
||||||
|
sqlite3 *db,
|
||||||
|
const char *zFunctionName,
|
||||||
|
int nArg,
|
||||||
|
int eTextRep,
|
||||||
|
void *pApp,
|
||||||
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xFinal)(sqlite3_context*),
|
||||||
|
void (*xValue)(sqlite3_context*),
|
||||||
|
void (*xInverse)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void(*xDestroy)(void*)
|
||||||
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Text Encodings
|
** CAPI3REF: Text Encodings
|
||||||
@@ -4858,6 +4955,28 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
|
|||||||
**
|
**
|
||||||
** These routines must be called from the same thread as
|
** These routines must be called from the same thread as
|
||||||
** the SQL function that supplied the [sqlite3_value*] parameters.
|
** the SQL function that supplied the [sqlite3_value*] parameters.
|
||||||
|
**
|
||||||
|
** As long as the input parameter is correct, these routines can only
|
||||||
|
** fail if an out-of-memory error occurs during a format conversion.
|
||||||
|
** Only the following subset of interfaces are subject to out-of-memory
|
||||||
|
** errors:
|
||||||
|
**
|
||||||
|
** <ul>
|
||||||
|
** <li> sqlite3_value_blob()
|
||||||
|
** <li> sqlite3_value_text()
|
||||||
|
** <li> sqlite3_value_text16()
|
||||||
|
** <li> sqlite3_value_text16le()
|
||||||
|
** <li> sqlite3_value_text16be()
|
||||||
|
** <li> sqlite3_value_bytes()
|
||||||
|
** <li> sqlite3_value_bytes16()
|
||||||
|
** </ul>
|
||||||
|
**
|
||||||
|
** If an out-of-memory error occurs, then the return value from these
|
||||||
|
** routines is the same as if the column had contained an SQL NULL value.
|
||||||
|
** Valid SQL NULL returns can be distinguished from out-of-memory errors
|
||||||
|
** by invoking the [sqlite3_errcode()] immediately after the suspect
|
||||||
|
** return value is obtained and before any
|
||||||
|
** other SQLite interface is called on the same [database connection].
|
||||||
*/
|
*/
|
||||||
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
|
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
|
||||||
SQLITE_API double sqlite3_value_double(sqlite3_value*);
|
SQLITE_API double sqlite3_value_double(sqlite3_value*);
|
||||||
@@ -6324,6 +6443,7 @@ struct sqlite3_index_info {
|
|||||||
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
|
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
|
||||||
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
|
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
|
||||||
#define SQLITE_INDEX_CONSTRAINT_IS 72
|
#define SQLITE_INDEX_CONSTRAINT_IS 72
|
||||||
|
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Register A Virtual Table Implementation
|
** CAPI3REF: Register A Virtual Table Implementation
|
||||||
@@ -7000,6 +7120,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
|
|||||||
/*
|
/*
|
||||||
** CAPI3REF: Low-Level Control Of Database Files
|
** CAPI3REF: Low-Level Control Of Database Files
|
||||||
** METHOD: sqlite3
|
** METHOD: sqlite3
|
||||||
|
** KEYWORDS: {file control}
|
||||||
**
|
**
|
||||||
** ^The [sqlite3_file_control()] interface makes a direct call to the
|
** ^The [sqlite3_file_control()] interface makes a direct call to the
|
||||||
** xFileControl method for the [sqlite3_io_methods] object associated
|
** xFileControl method for the [sqlite3_io_methods] object associated
|
||||||
@@ -7014,11 +7135,18 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
|
|||||||
** the xFileControl method. ^The return value of the xFileControl
|
** the xFileControl method. ^The return value of the xFileControl
|
||||||
** method becomes the return value of this routine.
|
** method becomes the return value of this routine.
|
||||||
**
|
**
|
||||||
|
** A few opcodes for [sqlite3_file_control()] are handled directly
|
||||||
|
** by the SQLite core and never invoke the
|
||||||
|
** sqlite3_io_methods.xFileControl method.
|
||||||
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
|
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
|
||||||
** a pointer to the underlying [sqlite3_file] object to be written into
|
** a pointer to the underlying [sqlite3_file] object to be written into
|
||||||
** the space pointed to by the 4th parameter. ^The [SQLITE_FCNTL_FILE_POINTER]
|
** the space pointed to by the 4th parameter. The
|
||||||
** case is a short-circuit path which does not actually invoke the
|
** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns
|
||||||
** underlying sqlite3_io_methods.xFileControl method.
|
** the [sqlite3_file] object associated with the journal file instead of
|
||||||
|
** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns
|
||||||
|
** a pointer to the underlying [sqlite3_vfs] object for the file.
|
||||||
|
** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter
|
||||||
|
** from the pager.
|
||||||
**
|
**
|
||||||
** ^If the second parameter (zDbName) does not match the name of any
|
** ^If the second parameter (zDbName) does not match the name of any
|
||||||
** open database file, then SQLITE_ERROR is returned. ^This error
|
** open database file, then SQLITE_ERROR is returned. ^This error
|
||||||
@@ -8837,7 +8965,6 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
|
|||||||
/*
|
/*
|
||||||
** CAPI3REF: Database Snapshot
|
** CAPI3REF: Database Snapshot
|
||||||
** KEYWORDS: {snapshot} {sqlite3_snapshot}
|
** KEYWORDS: {snapshot} {sqlite3_snapshot}
|
||||||
** EXPERIMENTAL
|
|
||||||
**
|
**
|
||||||
** An instance of the snapshot object records the state of a [WAL mode]
|
** An instance of the snapshot object records the state of a [WAL mode]
|
||||||
** database for some specific point in history.
|
** database for some specific point in history.
|
||||||
@@ -8854,11 +8981,6 @@ SQLITE_API int sqlite3_system_errno(sqlite3*);
|
|||||||
** version of the database file so that it is possible to later open a new read
|
** version of the database file so that it is possible to later open a new read
|
||||||
** transaction that sees that historical version of the database rather than
|
** transaction that sees that historical version of the database rather than
|
||||||
** the most recent version.
|
** the most recent version.
|
||||||
**
|
|
||||||
** The constructor for this object is [sqlite3_snapshot_get()]. The
|
|
||||||
** [sqlite3_snapshot_open()] method causes a fresh read transaction to refer
|
|
||||||
** to an historical snapshot (if possible). The destructor for
|
|
||||||
** sqlite3_snapshot objects is [sqlite3_snapshot_free()].
|
|
||||||
*/
|
*/
|
||||||
typedef struct sqlite3_snapshot {
|
typedef struct sqlite3_snapshot {
|
||||||
unsigned char hidden[48];
|
unsigned char hidden[48];
|
||||||
@@ -8866,7 +8988,7 @@ typedef struct sqlite3_snapshot {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Record A Database Snapshot
|
** CAPI3REF: Record A Database Snapshot
|
||||||
** EXPERIMENTAL
|
** CONSTRUCTOR: sqlite3_snapshot
|
||||||
**
|
**
|
||||||
** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a
|
** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a
|
||||||
** new [sqlite3_snapshot] object that records the current state of
|
** new [sqlite3_snapshot] object that records the current state of
|
||||||
@@ -8882,7 +9004,7 @@ typedef struct sqlite3_snapshot {
|
|||||||
** in this case.
|
** in this case.
|
||||||
**
|
**
|
||||||
** <ul>
|
** <ul>
|
||||||
** <li> The database handle must be in [autocommit mode].
|
** <li> The database handle must not be in [autocommit mode].
|
||||||
**
|
**
|
||||||
** <li> Schema S of [database connection] D must be a [WAL mode] database.
|
** <li> Schema S of [database connection] D must be a [WAL mode] database.
|
||||||
**
|
**
|
||||||
@@ -8905,7 +9027,7 @@ typedef struct sqlite3_snapshot {
|
|||||||
** to avoid a memory leak.
|
** to avoid a memory leak.
|
||||||
**
|
**
|
||||||
** The [sqlite3_snapshot_get()] interface is only available when the
|
** The [sqlite3_snapshot_get()] interface is only available when the
|
||||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
|
||||||
*/
|
*/
|
||||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
|
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
|
||||||
sqlite3 *db,
|
sqlite3 *db,
|
||||||
@@ -8915,24 +9037,35 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Start a read transaction on an historical snapshot
|
** CAPI3REF: Start a read transaction on an historical snapshot
|
||||||
** EXPERIMENTAL
|
** METHOD: sqlite3_snapshot
|
||||||
**
|
**
|
||||||
** ^The [sqlite3_snapshot_open(D,S,P)] interface starts a
|
** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read
|
||||||
** read transaction for schema S of
|
** transaction or upgrades an existing one for schema S of
|
||||||
** [database connection] D such that the read transaction
|
** [database connection] D such that the read transaction refers to
|
||||||
** refers to historical [snapshot] P, rather than the most
|
** historical [snapshot] P, rather than the most recent change to the
|
||||||
** recent change to the database.
|
** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK
|
||||||
** ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK on success
|
** on success or an appropriate [error code] if it fails.
|
||||||
** or an appropriate [error code] if it fails.
|
**
|
||||||
|
** ^In order to succeed, the database connection must not be in
|
||||||
|
** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there
|
||||||
|
** is already a read transaction open on schema S, then the database handle
|
||||||
|
** must have no active statements (SELECT statements that have been passed
|
||||||
|
** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()).
|
||||||
|
** SQLITE_ERROR is returned if either of these conditions is violated, or
|
||||||
|
** if schema S does not exist, or if the snapshot object is invalid.
|
||||||
|
**
|
||||||
|
** ^A call to sqlite3_snapshot_open() will fail to open if the specified
|
||||||
|
** snapshot has been overwritten by a [checkpoint]. In this case
|
||||||
|
** SQLITE_ERROR_SNAPSHOT is returned.
|
||||||
|
**
|
||||||
|
** If there is already a read transaction open when this function is
|
||||||
|
** invoked, then the same read transaction remains open (on the same
|
||||||
|
** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT
|
||||||
|
** is returned. If another error code - for example SQLITE_PROTOCOL or an
|
||||||
|
** SQLITE_IOERR error code - is returned, then the final state of the
|
||||||
|
** read transaction is undefined. If SQLITE_OK is returned, then the
|
||||||
|
** read transaction is now open on database snapshot P.
|
||||||
**
|
**
|
||||||
** ^In order to succeed, a call to [sqlite3_snapshot_open(D,S,P)] must be
|
|
||||||
** the first operation following the [BEGIN] that takes the schema S
|
|
||||||
** out of [autocommit mode].
|
|
||||||
** ^In other words, schema S must not currently be in
|
|
||||||
** a transaction for [sqlite3_snapshot_open(D,S,P)] to work, but the
|
|
||||||
** database connection D must be out of [autocommit mode].
|
|
||||||
** ^A [snapshot] will fail to open if it has been overwritten by a
|
|
||||||
** [checkpoint].
|
|
||||||
** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the
|
** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the
|
||||||
** database connection D does not know that the database file for
|
** database connection D does not know that the database file for
|
||||||
** schema S is in [WAL mode]. A database connection might not know
|
** schema S is in [WAL mode]. A database connection might not know
|
||||||
@@ -8943,7 +9076,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
|
|||||||
** database connection in order to make it ready to use snapshots.)
|
** database connection in order to make it ready to use snapshots.)
|
||||||
**
|
**
|
||||||
** The [sqlite3_snapshot_open()] interface is only available when the
|
** The [sqlite3_snapshot_open()] interface is only available when the
|
||||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
|
||||||
*/
|
*/
|
||||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
|
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
|
||||||
sqlite3 *db,
|
sqlite3 *db,
|
||||||
@@ -8953,20 +9086,20 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Destroy a snapshot
|
** CAPI3REF: Destroy a snapshot
|
||||||
** EXPERIMENTAL
|
** DESTRUCTOR: sqlite3_snapshot
|
||||||
**
|
**
|
||||||
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
|
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
|
||||||
** The application must eventually free every [sqlite3_snapshot] object
|
** The application must eventually free every [sqlite3_snapshot] object
|
||||||
** using this routine to avoid a memory leak.
|
** using this routine to avoid a memory leak.
|
||||||
**
|
**
|
||||||
** The [sqlite3_snapshot_free()] interface is only available when the
|
** The [sqlite3_snapshot_free()] interface is only available when the
|
||||||
** SQLITE_ENABLE_SNAPSHOT compile-time option is used.
|
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
|
||||||
*/
|
*/
|
||||||
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
|
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Compare the ages of two snapshot handles.
|
** CAPI3REF: Compare the ages of two snapshot handles.
|
||||||
** EXPERIMENTAL
|
** METHOD: sqlite3_snapshot
|
||||||
**
|
**
|
||||||
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
|
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
|
||||||
** of two valid snapshot handles.
|
** of two valid snapshot handles.
|
||||||
@@ -8985,6 +9118,9 @@ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
|
|||||||
** Otherwise, this API returns a negative value if P1 refers to an older
|
** Otherwise, this API returns a negative value if P1 refers to an older
|
||||||
** snapshot than P2, zero if the two handles refer to the same database
|
** snapshot than P2, zero if the two handles refer to the same database
|
||||||
** snapshot, and a positive value if P1 is a newer snapshot than P2.
|
** snapshot, and a positive value if P1 is a newer snapshot than P2.
|
||||||
|
**
|
||||||
|
** This interface is only available if SQLite is compiled with the
|
||||||
|
** [SQLITE_ENABLE_SNAPSHOT] option.
|
||||||
*/
|
*/
|
||||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
|
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
|
||||||
sqlite3_snapshot *p1,
|
sqlite3_snapshot *p1,
|
||||||
@@ -8993,23 +9129,26 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Recover snapshots from a wal file
|
** CAPI3REF: Recover snapshots from a wal file
|
||||||
** EXPERIMENTAL
|
** METHOD: sqlite3_snapshot
|
||||||
**
|
**
|
||||||
** If all connections disconnect from a database file but do not perform
|
** If a [WAL file] remains on disk after all database connections close
|
||||||
** a checkpoint, the existing wal file is opened along with the database
|
** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control]
|
||||||
** file the next time the database is opened. At this point it is only
|
** or because the last process to have the database opened exited without
|
||||||
** possible to successfully call sqlite3_snapshot_open() to open the most
|
** calling [sqlite3_close()]) and a new connection is subsequently opened
|
||||||
** recent snapshot of the database (the one at the head of the wal file),
|
** on that database and [WAL file], the [sqlite3_snapshot_open()] interface
|
||||||
** even though the wal file may contain other valid snapshots for which
|
** will only be able to open the last transaction added to the WAL file
|
||||||
** clients have sqlite3_snapshot handles.
|
** even though the WAL file contains other valid transactions.
|
||||||
**
|
**
|
||||||
** This function attempts to scan the wal file associated with database zDb
|
** This function attempts to scan the WAL file associated with database zDb
|
||||||
** of database handle db and make all valid snapshots available to
|
** of database handle db and make all valid snapshots available to
|
||||||
** sqlite3_snapshot_open(). It is an error if there is already a read
|
** sqlite3_snapshot_open(). It is an error if there is already a read
|
||||||
** transaction open on the database, or if the database is not a wal mode
|
** transaction open on the database, or if the database is not a WAL mode
|
||||||
** database.
|
** database.
|
||||||
**
|
**
|
||||||
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
||||||
|
**
|
||||||
|
** This interface is only available if SQLite is compiled with the
|
||||||
|
** [SQLITE_ENABLE_SNAPSHOT] option.
|
||||||
*/
|
*/
|
||||||
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
|
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
|
||||||
|
|
||||||
@@ -9120,7 +9259,7 @@ SQLITE_API int sqlite3_deserialize(
|
|||||||
** in the P argument is held in memory obtained from [sqlite3_malloc64()]
|
** in the P argument is held in memory obtained from [sqlite3_malloc64()]
|
||||||
** and that SQLite should take ownership of this memory and automatically
|
** and that SQLite should take ownership of this memory and automatically
|
||||||
** free it when it has finished using it. Without this flag, the caller
|
** free it when it has finished using it. Without this flag, the caller
|
||||||
** is resposible for freeing any dynamically allocated memory.
|
** is responsible for freeing any dynamically allocated memory.
|
||||||
**
|
**
|
||||||
** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
|
** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
|
||||||
** grow the size of the database using calls to [sqlite3_realloc64()]. This
|
** grow the size of the database using calls to [sqlite3_realloc64()]. This
|
||||||
@@ -11298,7 +11437,7 @@ struct Fts5ExtensionApi {
|
|||||||
** This way, even if the tokenizer does not provide synonyms
|
** This way, even if the tokenizer does not provide synonyms
|
||||||
** when tokenizing query text (it should not - to do would be
|
** when tokenizing query text (it should not - to do would be
|
||||||
** inefficient), it doesn't matter if the user queries for
|
** inefficient), it doesn't matter if the user queries for
|
||||||
** 'first + place' or '1st + place', as there are entires in the
|
** 'first + place' or '1st + place', as there are entries in the
|
||||||
** FTS index corresponding to both forms of the first token.
|
** FTS index corresponding to both forms of the first token.
|
||||||
** </ol>
|
** </ol>
|
||||||
**
|
**
|
||||||
@@ -11326,7 +11465,7 @@ struct Fts5ExtensionApi {
|
|||||||
** extra data to the FTS index or require FTS5 to query for multiple terms,
|
** extra data to the FTS index or require FTS5 to query for multiple terms,
|
||||||
** so it is efficient in terms of disk space and query speed. However, it
|
** so it is efficient in terms of disk space and query speed. However, it
|
||||||
** does not support prefix queries very well. If, as suggested above, the
|
** does not support prefix queries very well. If, as suggested above, the
|
||||||
** token "first" is subsituted for "1st" by the tokenizer, then the query:
|
** token "first" is substituted for "1st" by the tokenizer, then the query:
|
||||||
**
|
**
|
||||||
** <codeblock>
|
** <codeblock>
|
||||||
** ... MATCH '1s*'</codeblock>
|
** ... MATCH '1s*'</codeblock>
|
||||||
|
|||||||
116
vendor/github.com/mattn/go-sqlite3/sqlite3.go
сгенерированный
поставляемый
116
vendor/github.com/mattn/go-sqlite3/sqlite3.go
сгенерированный
поставляемый
@@ -78,8 +78,38 @@ _sqlite3_exec(sqlite3* db, const char* pcmd, long long* rowid, long long* change
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||||
|
extern int _sqlite3_step_blocking(sqlite3_stmt *stmt);
|
||||||
|
extern int _sqlite3_step_row_blocking(sqlite3_stmt* stmt, long long* rowid, long long* changes);
|
||||||
|
extern int _sqlite3_prepare_v2_blocking(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_sqlite3_step(sqlite3_stmt* stmt, long long* rowid, long long* changes)
|
_sqlite3_step_internal(sqlite3_stmt *stmt)
|
||||||
|
{
|
||||||
|
return _sqlite3_step_blocking(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_step_row_internal(sqlite3_stmt* stmt, long long* rowid, long long* changes)
|
||||||
|
{
|
||||||
|
return _sqlite3_step_row_blocking(stmt, rowid, changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_prepare_v2_internal(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail)
|
||||||
|
{
|
||||||
|
return _sqlite3_prepare_v2_blocking(db, zSql, nBytes, ppStmt, pzTail);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static int
|
||||||
|
_sqlite3_step_internal(sqlite3_stmt *stmt)
|
||||||
|
{
|
||||||
|
return sqlite3_step(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_step_row_internal(sqlite3_stmt* stmt, long long* rowid, long long* changes)
|
||||||
{
|
{
|
||||||
int rv = sqlite3_step(stmt);
|
int rv = sqlite3_step(stmt);
|
||||||
sqlite3* db = sqlite3_db_handle(stmt);
|
sqlite3* db = sqlite3_db_handle(stmt);
|
||||||
@@ -88,6 +118,13 @@ _sqlite3_step(sqlite3_stmt* stmt, long long* rowid, long long* changes)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_sqlite3_prepare_v2_internal(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail)
|
||||||
|
{
|
||||||
|
return sqlite3_prepare_v2(db, zSql, nBytes, ppStmt, pzTail);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void _sqlite3_result_text(sqlite3_context* ctx, const char* s) {
|
void _sqlite3_result_text(sqlite3_context* ctx, const char* s) {
|
||||||
sqlite3_result_text(ctx, s, -1, &free);
|
sqlite3_result_text(ctx, s, -1, &free);
|
||||||
}
|
}
|
||||||
@@ -119,6 +156,8 @@ int commitHookTrampoline(void*);
|
|||||||
void rollbackHookTrampoline(void*);
|
void rollbackHookTrampoline(void*);
|
||||||
void updateHookTrampoline(void*, int, char*, char*, sqlite3_int64);
|
void updateHookTrampoline(void*, int, char*, char*, sqlite3_int64);
|
||||||
|
|
||||||
|
int authorizerTrampoline(void*, int, char*, char*, char*, char*);
|
||||||
|
|
||||||
#ifdef SQLITE_LIMIT_WORKER_THREADS
|
#ifdef SQLITE_LIMIT_WORKER_THREADS
|
||||||
# define _SQLITE_HAS_LIMIT
|
# define _SQLITE_HAS_LIMIT
|
||||||
# define SQLITE_LIMIT_LENGTH 0
|
# define SQLITE_LIMIT_LENGTH 0
|
||||||
@@ -200,18 +239,57 @@ func Version() (libVersion string, libVersionNumber int, sourceID string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// used by authorizer and pre_update_hook
|
||||||
SQLITE_DELETE = C.SQLITE_DELETE
|
SQLITE_DELETE = C.SQLITE_DELETE
|
||||||
SQLITE_INSERT = C.SQLITE_INSERT
|
SQLITE_INSERT = C.SQLITE_INSERT
|
||||||
SQLITE_UPDATE = C.SQLITE_UPDATE
|
SQLITE_UPDATE = C.SQLITE_UPDATE
|
||||||
|
|
||||||
|
// used by authorzier - as return value
|
||||||
|
SQLITE_OK = C.SQLITE_OK
|
||||||
|
SQLITE_IGNORE = C.SQLITE_IGNORE
|
||||||
|
SQLITE_DENY = C.SQLITE_DENY
|
||||||
|
|
||||||
|
// different actions query tries to do - passed as argument to authorizer
|
||||||
|
SQLITE_CREATE_INDEX = C.SQLITE_CREATE_INDEX
|
||||||
|
SQLITE_CREATE_TABLE = C.SQLITE_CREATE_TABLE
|
||||||
|
SQLITE_CREATE_TEMP_INDEX = C.SQLITE_CREATE_TEMP_INDEX
|
||||||
|
SQLITE_CREATE_TEMP_TABLE = C.SQLITE_CREATE_TEMP_TABLE
|
||||||
|
SQLITE_CREATE_TEMP_TRIGGER = C.SQLITE_CREATE_TEMP_TRIGGER
|
||||||
|
SQLITE_CREATE_TEMP_VIEW = C.SQLITE_CREATE_TEMP_VIEW
|
||||||
|
SQLITE_CREATE_TRIGGER = C.SQLITE_CREATE_TRIGGER
|
||||||
|
SQLITE_CREATE_VIEW = C.SQLITE_CREATE_VIEW
|
||||||
|
SQLITE_CREATE_VTABLE = C.SQLITE_CREATE_VTABLE
|
||||||
|
SQLITE_DROP_INDEX = C.SQLITE_DROP_INDEX
|
||||||
|
SQLITE_DROP_TABLE = C.SQLITE_DROP_TABLE
|
||||||
|
SQLITE_DROP_TEMP_INDEX = C.SQLITE_DROP_TEMP_INDEX
|
||||||
|
SQLITE_DROP_TEMP_TABLE = C.SQLITE_DROP_TEMP_TABLE
|
||||||
|
SQLITE_DROP_TEMP_TRIGGER = C.SQLITE_DROP_TEMP_TRIGGER
|
||||||
|
SQLITE_DROP_TEMP_VIEW = C.SQLITE_DROP_TEMP_VIEW
|
||||||
|
SQLITE_DROP_TRIGGER = C.SQLITE_DROP_TRIGGER
|
||||||
|
SQLITE_DROP_VIEW = C.SQLITE_DROP_VIEW
|
||||||
|
SQLITE_DROP_VTABLE = C.SQLITE_DROP_VTABLE
|
||||||
|
SQLITE_PRAGMA = C.SQLITE_PRAGMA
|
||||||
|
SQLITE_READ = C.SQLITE_READ
|
||||||
|
SQLITE_SELECT = C.SQLITE_SELECT
|
||||||
|
SQLITE_TRANSACTION = C.SQLITE_TRANSACTION
|
||||||
|
SQLITE_ATTACH = C.SQLITE_ATTACH
|
||||||
|
SQLITE_DETACH = C.SQLITE_DETACH
|
||||||
|
SQLITE_ALTER_TABLE = C.SQLITE_ALTER_TABLE
|
||||||
|
SQLITE_REINDEX = C.SQLITE_REINDEX
|
||||||
|
SQLITE_ANALYZE = C.SQLITE_ANALYZE
|
||||||
|
SQLITE_FUNCTION = C.SQLITE_FUNCTION
|
||||||
|
SQLITE_SAVEPOINT = C.SQLITE_SAVEPOINT
|
||||||
|
SQLITE_COPY = C.SQLITE_COPY
|
||||||
|
/*SQLITE_RECURSIVE = C.SQLITE_RECURSIVE*/
|
||||||
)
|
)
|
||||||
|
|
||||||
// SQLiteDriver implement sql.Driver.
|
// SQLiteDriver implements driver.Driver.
|
||||||
type SQLiteDriver struct {
|
type SQLiteDriver struct {
|
||||||
Extensions []string
|
Extensions []string
|
||||||
ConnectHook func(*SQLiteConn) error
|
ConnectHook func(*SQLiteConn) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLiteConn implement sql.Conn.
|
// SQLiteConn implements driver.Conn.
|
||||||
type SQLiteConn struct {
|
type SQLiteConn struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
db *C.sqlite3
|
db *C.sqlite3
|
||||||
@@ -221,12 +299,12 @@ type SQLiteConn struct {
|
|||||||
aggregators []*aggInfo
|
aggregators []*aggInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLiteTx implemen sql.Tx.
|
// SQLiteTx implements driver.Tx.
|
||||||
type SQLiteTx struct {
|
type SQLiteTx struct {
|
||||||
c *SQLiteConn
|
c *SQLiteConn
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLiteStmt implement sql.Stmt.
|
// SQLiteStmt implements driver.Stmt.
|
||||||
type SQLiteStmt struct {
|
type SQLiteStmt struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
c *SQLiteConn
|
c *SQLiteConn
|
||||||
@@ -236,13 +314,13 @@ type SQLiteStmt struct {
|
|||||||
cls bool
|
cls bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLiteResult implement sql.Result.
|
// SQLiteResult implements sql.Result.
|
||||||
type SQLiteResult struct {
|
type SQLiteResult struct {
|
||||||
id int64
|
id int64
|
||||||
changes int64
|
changes int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLiteRows implement sql.Rows.
|
// SQLiteRows implements driver.Rows.
|
||||||
type SQLiteRows struct {
|
type SQLiteRows struct {
|
||||||
s *SQLiteStmt
|
s *SQLiteStmt
|
||||||
nc int
|
nc int
|
||||||
@@ -440,6 +518,20 @@ func (c *SQLiteConn) RegisterUpdateHook(callback func(int, string, string, int64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterAuthorizer sets the authorizer for connection.
|
||||||
|
//
|
||||||
|
// The parameters to the callback are the operation (one of the constants
|
||||||
|
// SQLITE_INSERT, SQLITE_DELETE, or SQLITE_UPDATE), and 1 to 3 arguments,
|
||||||
|
// depending on operation. More details see:
|
||||||
|
// https://www.sqlite.org/c3ref/c_alter_table.html
|
||||||
|
func (c *SQLiteConn) RegisterAuthorizer(callback func(int, string, string, string) int) {
|
||||||
|
if callback == nil {
|
||||||
|
C.sqlite3_set_authorizer(c.db, nil, nil)
|
||||||
|
} else {
|
||||||
|
C.sqlite3_set_authorizer(c.db, (*[0]byte)(C.authorizerTrampoline), unsafe.Pointer(newHandle(c, callback)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterFunc makes a Go function available as a SQLite function.
|
// RegisterFunc makes a Go function available as a SQLite function.
|
||||||
//
|
//
|
||||||
// The Go function can have arguments of the following types: any
|
// The Go function can have arguments of the following types: any
|
||||||
@@ -1582,7 +1674,7 @@ func (c *SQLiteConn) prepare(ctx context.Context, query string) (driver.Stmt, er
|
|||||||
defer C.free(unsafe.Pointer(pquery))
|
defer C.free(unsafe.Pointer(pquery))
|
||||||
var s *C.sqlite3_stmt
|
var s *C.sqlite3_stmt
|
||||||
var tail *C.char
|
var tail *C.char
|
||||||
rv := C.sqlite3_prepare_v2(c.db, pquery, -1, &s, &tail)
|
rv := C._sqlite3_prepare_v2_internal(c.db, pquery, -1, &s, &tail)
|
||||||
if rv != C.SQLITE_OK {
|
if rv != C.SQLITE_OK {
|
||||||
return nil, c.lastError()
|
return nil, c.lastError()
|
||||||
}
|
}
|
||||||
@@ -1816,7 +1908,7 @@ func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result
|
|||||||
}
|
}
|
||||||
|
|
||||||
var rowid, changes C.longlong
|
var rowid, changes C.longlong
|
||||||
rv := C._sqlite3_step(s.s, &rowid, &changes)
|
rv := C._sqlite3_step_row_internal(s.s, &rowid, &changes)
|
||||||
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
|
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
|
||||||
err := s.c.lastError()
|
err := s.c.lastError()
|
||||||
C.sqlite3_reset(s.s)
|
C.sqlite3_reset(s.s)
|
||||||
@@ -1883,12 +1975,12 @@ func (rc *SQLiteRows) DeclTypes() []string {
|
|||||||
|
|
||||||
// Next move cursor to next.
|
// Next move cursor to next.
|
||||||
func (rc *SQLiteRows) Next(dest []driver.Value) error {
|
func (rc *SQLiteRows) Next(dest []driver.Value) error {
|
||||||
|
rc.s.mu.Lock()
|
||||||
|
defer rc.s.mu.Unlock()
|
||||||
if rc.s.closed {
|
if rc.s.closed {
|
||||||
return io.EOF
|
return io.EOF
|
||||||
}
|
}
|
||||||
rc.s.mu.Lock()
|
rv := C._sqlite3_step_internal(rc.s.s)
|
||||||
defer rc.s.mu.Unlock()
|
|
||||||
rv := C.sqlite3_step(rc.s.s)
|
|
||||||
if rv == C.SQLITE_DONE {
|
if rv == C.SQLITE_DONE {
|
||||||
return io.EOF
|
return io.EOF
|
||||||
}
|
}
|
||||||
|
|||||||
8
vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt.go
сгенерированный
поставляемый
8
vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt.go
сгенерированный
поставляемый
@@ -83,13 +83,13 @@ func CryptEncoderSSHA256(salt string) func(pass []byte, hash interface{}) []byte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CryptEncoderSHA384 encodes a password with SHA256
|
// CryptEncoderSHA384 encodes a password with SHA384
|
||||||
func CryptEncoderSHA384(pass []byte, hash interface{}) []byte {
|
func CryptEncoderSHA384(pass []byte, hash interface{}) []byte {
|
||||||
h := sha512.Sum384(pass)
|
h := sha512.Sum384(pass)
|
||||||
return h[:]
|
return h[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// CryptEncoderSSHA384 encodes a password with SHA256
|
// CryptEncoderSSHA384 encodes a password with SHA384
|
||||||
// with the configured salt
|
// with the configured salt
|
||||||
func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte {
|
func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte {
|
||||||
return func(pass []byte, hash interface{}) []byte {
|
return func(pass []byte, hash interface{}) []byte {
|
||||||
@@ -100,13 +100,13 @@ func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CryptEncoderSHA512 encodes a password with SHA256
|
// CryptEncoderSHA512 encodes a password with SHA512
|
||||||
func CryptEncoderSHA512(pass []byte, hash interface{}) []byte {
|
func CryptEncoderSHA512(pass []byte, hash interface{}) []byte {
|
||||||
h := sha512.Sum512(pass)
|
h := sha512.Sum512(pass)
|
||||||
return h[:]
|
return h[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// CryptEncoderSSHA512 encodes a password with SHA256
|
// CryptEncoderSSHA512 encodes a password with SHA512
|
||||||
// with the configured salt
|
// with the configured salt
|
||||||
func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte {
|
func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte {
|
||||||
return func(pass []byte, hash interface{}) []byte {
|
return func(pass []byte, hash interface{}) []byte {
|
||||||
|
|||||||
85
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.c
сгенерированный
поставляемый
Обычный файл
85
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.c
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,85 @@
|
|||||||
|
// Copyright (C) 2018 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sqlite3-binding.h>
|
||||||
|
|
||||||
|
extern int unlock_notify_wait(sqlite3 *db);
|
||||||
|
|
||||||
|
int
|
||||||
|
_sqlite3_step_blocking(sqlite3_stmt *stmt)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
sqlite3* db;
|
||||||
|
|
||||||
|
db = sqlite3_db_handle(stmt);
|
||||||
|
for (;;) {
|
||||||
|
rv = sqlite3_step(stmt);
|
||||||
|
if (rv != SQLITE_LOCKED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rv = unlock_notify_wait(db);
|
||||||
|
if (rv != SQLITE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sqlite3_reset(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_sqlite3_step_row_blocking(sqlite3_stmt* stmt, long long* rowid, long long* changes)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
sqlite3* db;
|
||||||
|
|
||||||
|
db = sqlite3_db_handle(stmt);
|
||||||
|
for (;;) {
|
||||||
|
rv = sqlite3_step(stmt);
|
||||||
|
if (rv!=SQLITE_LOCKED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rv = unlock_notify_wait(db);
|
||||||
|
if (rv != SQLITE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sqlite3_reset(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
*rowid = (long long) sqlite3_last_insert_rowid(db);
|
||||||
|
*changes = (long long) sqlite3_changes(db);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_sqlite3_prepare_v2_blocking(sqlite3 *db, const char *zSql, int nBytes, sqlite3_stmt **ppStmt, const char **pzTail)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
rv = sqlite3_prepare_v2(db, zSql, nBytes, ppStmt, pzTail);
|
||||||
|
if (rv!=SQLITE_LOCKED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sqlite3_extended_errcode(db) != SQLITE_LOCKED_SHAREDCACHE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rv = unlock_notify_wait(db);
|
||||||
|
if (rv != SQLITE_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
93
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.go
сгенерированный
поставляемый
Обычный файл
93
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,93 @@
|
|||||||
|
// Copyright (C) 2018 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by an MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// +build cgo
|
||||||
|
// +build sqlite_unlock_notify
|
||||||
|
|
||||||
|
package sqlite3
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -DSQLITE_ENABLE_UNLOCK_NOTIFY
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sqlite3-binding.h>
|
||||||
|
|
||||||
|
extern void unlock_notify_callback(void *arg, int argc);
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
type unlock_notify_table struct {
|
||||||
|
sync.Mutex
|
||||||
|
seqnum uint
|
||||||
|
table map[uint]chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var unt unlock_notify_table = unlock_notify_table{table: make(map[uint]chan struct{})}
|
||||||
|
|
||||||
|
func (t *unlock_notify_table) add(c chan struct{}) uint {
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
h := t.seqnum
|
||||||
|
t.table[h] = c
|
||||||
|
t.seqnum++
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *unlock_notify_table) remove(h uint) {
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
delete(t.table, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *unlock_notify_table) get(h uint) chan struct{} {
|
||||||
|
t.Lock()
|
||||||
|
defer t.Unlock()
|
||||||
|
c, ok := t.table[h]
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("Non-existent key for unlcok-notify channel: %d", h))
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
//export unlock_notify_callback
|
||||||
|
func unlock_notify_callback(argv unsafe.Pointer, argc C.int) {
|
||||||
|
for i := 0; i < int(argc); i++ {
|
||||||
|
parg := ((*(*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.uint)(nil))]*[1]uint)(argv))[i])
|
||||||
|
arg := *parg
|
||||||
|
h := arg[0]
|
||||||
|
c := unt.get(h)
|
||||||
|
c <- struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//export unlock_notify_wait
|
||||||
|
func unlock_notify_wait(db *C.sqlite3) C.int {
|
||||||
|
// It has to be a bufferred channel to not block in sqlite_unlock_notify
|
||||||
|
// as sqlite_unlock_notify could invoke the callback before it returns.
|
||||||
|
c := make(chan struct{}, 1)
|
||||||
|
defer close(c)
|
||||||
|
|
||||||
|
h := unt.add(c)
|
||||||
|
defer unt.remove(h)
|
||||||
|
|
||||||
|
pargv := C.malloc(C.sizeof_uint)
|
||||||
|
defer C.free(pargv)
|
||||||
|
|
||||||
|
argv := (*[1]uint)(pargv)
|
||||||
|
argv[0] = h
|
||||||
|
if rv := C.sqlite3_unlock_notify(db, (*[0]byte)(C.unlock_notify_callback), unsafe.Pointer(pargv)); rv != C.SQLITE_OK {
|
||||||
|
return rv
|
||||||
|
}
|
||||||
|
|
||||||
|
<-c
|
||||||
|
|
||||||
|
return C.SQLITE_OK
|
||||||
|
}
|
||||||
3
vendor/github.com/mattn/go-sqlite3/sqlite3_other.go
сгенерированный
поставляемый
3
vendor/github.com/mattn/go-sqlite3/sqlite3_other.go
сгенерированный
поставляемый
@@ -10,5 +10,8 @@ package sqlite3
|
|||||||
/*
|
/*
|
||||||
#cgo CFLAGS: -I.
|
#cgo CFLAGS: -I.
|
||||||
#cgo linux LDFLAGS: -ldl
|
#cgo linux LDFLAGS: -ldl
|
||||||
|
#cgo linux,ppc LDFLAGS: -lpthread
|
||||||
|
#cgo linux,ppc64 LDFLAGS: -lpthread
|
||||||
|
#cgo linux,ppc64le LDFLAGS: -lpthread
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|||||||
8
vendor/github.com/mattn/go-sqlite3/sqlite3ext.h
сгенерированный
поставляемый
8
vendor/github.com/mattn/go-sqlite3/sqlite3ext.h
сгенерированный
поставляемый
@@ -311,6 +311,12 @@ struct sqlite3_api_routines {
|
|||||||
int (*str_errcode)(sqlite3_str*);
|
int (*str_errcode)(sqlite3_str*);
|
||||||
int (*str_length)(sqlite3_str*);
|
int (*str_length)(sqlite3_str*);
|
||||||
char *(*str_value)(sqlite3_str*);
|
char *(*str_value)(sqlite3_str*);
|
||||||
|
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
|
||||||
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void (*xFinal)(sqlite3_context*),
|
||||||
|
void (*xValue)(sqlite3_context*),
|
||||||
|
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
|
||||||
|
void(*xDestroy)(void*));
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -596,6 +602,8 @@ typedef int (*sqlite3_loadext_entry)(
|
|||||||
#define sqlite3_str_errcode sqlite3_api->str_errcode
|
#define sqlite3_str_errcode sqlite3_api->str_errcode
|
||||||
#define sqlite3_str_length sqlite3_api->str_length
|
#define sqlite3_str_length sqlite3_api->str_length
|
||||||
#define sqlite3_str_value sqlite3_api->str_value
|
#define sqlite3_str_value sqlite3_api->str_value
|
||||||
|
/* Version 3.25.0 and later */
|
||||||
|
#define sqlite3_create_window_function sqlite3_api->create_window_function
|
||||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||||
|
|
||||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||||
|
|||||||
7
vendor/github.com/miekg/dns/.travis.yml
сгенерированный
поставляемый
7
vendor/github.com/miekg/dns/.travis.yml
сгенерированный
поставляемый
@@ -1,21 +1,18 @@
|
|||||||
language: go
|
language: go
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.10.x
|
- 1.10.x
|
||||||
- 1.11.x
|
- 1.11.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
env:
|
|
||||||
- TESTS="-race -v -bench=. -coverprofile=coverage.txt -covermode=atomic"
|
|
||||||
- TESTS="-race -v ./..."
|
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
# don't use the miekg/dns when testing forks
|
# don't use the miekg/dns when testing forks
|
||||||
- mkdir -p $GOPATH/src/github.com/miekg
|
- mkdir -p $GOPATH/src/github.com/miekg
|
||||||
- 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)
|
||||||
|
|||||||
46
vendor/github.com/miekg/dns/Gopkg.lock
сгенерированный
поставляемый
46
vendor/github.com/miekg/dns/Gopkg.lock
сгенерированный
поставляемый
@@ -3,19 +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 = "b47b1587369238182299fe4dad77d05b8b461e06"
|
"ed25519",
|
||||||
|
"ed25519/internal/edwards25519",
|
||||||
|
]
|
||||||
|
pruneopts = ""
|
||||||
|
revision = "e3636079e1a4c1f337f212cc5cd2aca108f6c900"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
digest = "1:08e41d63f8dac84d83797368b56cf0b339e42d0224e5e56668963c28aec95685"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = ["bpf","internal/iana","internal/socket","ipv4","ipv6"]
|
packages = [
|
||||||
revision = "1e491301e022f8f977054da4c2d852decd59571f"
|
"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 = "c4abc38abaeeeeb9be92455c9c02cae32841122b8982aaa067ef25bb8e86ff9d"
|
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
|
||||||
|
|||||||
12
vendor/github.com/miekg/dns/Gopkg.toml
сгенерированный
поставляемый
12
vendor/github.com/miekg/dns/Gopkg.toml
сгенерированный
поставляемый
@@ -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"
|
||||||
|
|||||||
50
vendor/github.com/miekg/dns/README.md
сгенерированный
поставляемый
50
vendor/github.com/miekg/dns/README.md
сгенерированный
поставляемый
@@ -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,7 +55,7 @@ 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/
|
||||||
@@ -67,29 +66,28 @@ A not-so-up-to-date-list-that-may-be-actually-current:
|
|||||||
* https://github.com/xor-gate/sshfp
|
* https://github.com/xor-gate/sshfp
|
||||||
* https://github.com/rs/dnstrace
|
* https://github.com/rs/dnstrace
|
||||||
* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
|
* https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss))
|
||||||
|
* https://github.com/semihalev/sdns
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
@@ -163,9 +161,9 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
|
|||||||
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
|
* 7873 - Domain Name System (DNS) Cookies (draft-ietf-dnsop-cookies)
|
||||||
* 8080 - EdDSA for DNSSEC
|
* 8080 - EdDSA for DNSSEC
|
||||||
|
|
||||||
## 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>
|
||||||
|
|||||||
54
vendor/github.com/miekg/dns/acceptfunc.go
сгенерированный
поставляемый
Обычный файл
54
vendor/github.com/miekg/dns/acceptfunc.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,54 @@
|
|||||||
|
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 0 RRs 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.
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultMsgAcceptFunc = func(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
|
||||||
|
}
|
||||||
|
if dh.Ancount != 0 {
|
||||||
|
return MsgReject
|
||||||
|
}
|
||||||
|
if dh.Nscount != 0 {
|
||||||
|
return MsgReject
|
||||||
|
}
|
||||||
|
if dh.Arcount > 2 {
|
||||||
|
return MsgReject
|
||||||
|
}
|
||||||
|
return MsgAccept
|
||||||
|
}
|
||||||
85
vendor/github.com/miekg/dns/client.go
сгенерированный
поставляемый
85
vendor/github.com/miekg/dns/client.go
сгенерированный
поставляемый
@@ -7,11 +7,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -19,8 +16,6 @@ import (
|
|||||||
const (
|
const (
|
||||||
dnsTimeout time.Duration = 2 * time.Second
|
dnsTimeout time.Duration = 2 * time.Second
|
||||||
tcpIdleTimeout time.Duration = 8 * time.Second
|
tcpIdleTimeout time.Duration = 8 * time.Second
|
||||||
|
|
||||||
dohMimeType = "application/dns-message"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Conn represents a connection to a DNS server.
|
// A Conn represents a connection to a DNS server.
|
||||||
@@ -44,7 +39,6 @@ type Client struct {
|
|||||||
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
|
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
|
||||||
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||||
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
|
||||||
HTTPClient *http.Client // The http.Client to use for DNS-over-HTTPS
|
|
||||||
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)
|
||||||
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
|
||||||
group singleflight
|
group singleflight
|
||||||
@@ -132,11 +126,6 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
|
|||||||
// attribute appropriately
|
// attribute appropriately
|
||||||
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
|
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) {
|
||||||
if !c.SingleInflight {
|
if !c.SingleInflight {
|
||||||
if c.Net == "https" {
|
|
||||||
// TODO(tmthrgd): pipe timeouts into exchangeDOH
|
|
||||||
return c.exchangeDOH(context.TODO(), m, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.exchange(m, address)
|
return c.exchange(m, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,11 +138,6 @@ func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, er
|
|||||||
cl = cl1
|
cl = cl1
|
||||||
}
|
}
|
||||||
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
|
r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
|
||||||
if c.Net == "https" {
|
|
||||||
// TODO(tmthrgd): pipe timeouts into exchangeDOH
|
|
||||||
return c.exchangeDOH(context.TODO(), m, address)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.exchange(m, address)
|
return c.exchange(m, address)
|
||||||
})
|
})
|
||||||
if r != nil && shared {
|
if r != nil && shared {
|
||||||
@@ -199,67 +183,6 @@ func (c *Client) exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err erro
|
|||||||
return r, rtt, err
|
return r, rtt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) exchangeDOH(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
|
||||||
p, err := m.Pack()
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodPost, a, bytes.NewReader(p))
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Content-Type", dohMimeType)
|
|
||||||
req.Header.Set("Accept", dohMimeType)
|
|
||||||
|
|
||||||
hc := http.DefaultClient
|
|
||||||
if c.HTTPClient != nil {
|
|
||||||
hc = c.HTTPClient
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx != context.Background() && ctx != context.TODO() {
|
|
||||||
req = req.WithContext(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
t := time.Now()
|
|
||||||
|
|
||||||
resp, err := hc.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
defer closeHTTPBody(resp.Body)
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, 0, fmt.Errorf("dns: server returned HTTP %d error: %q", resp.StatusCode, resp.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ct := resp.Header.Get("Content-Type"); ct != dohMimeType {
|
|
||||||
return nil, 0, fmt.Errorf("dns: unexpected Content-Type %q; expected %q", ct, dohMimeType)
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err = ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rtt = time.Since(t)
|
|
||||||
|
|
||||||
r = new(Msg)
|
|
||||||
if err := r.Unpack(p); err != nil {
|
|
||||||
return r, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: TSIG? Is it even supported over DoH?
|
|
||||||
|
|
||||||
return r, rtt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func closeHTTPBody(r io.ReadCloser) error {
|
|
||||||
io.Copy(ioutil.Discard, io.LimitReader(r, 8<<20))
|
|
||||||
return r.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 signature
|
// If the received message contains a TSIG record the transaction signature
|
||||||
// is verified. This method always tries to return the message, however if an
|
// is verified. This method always tries to return the message, however if an
|
||||||
@@ -559,19 +482,15 @@ func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout
|
|||||||
// context, if present. If there is both a context deadline and a configured
|
// context, if present. If there is both a context deadline and a configured
|
||||||
// timeout on the client, the earliest of the two takes effect.
|
// timeout on the client, the earliest of the two takes effect.
|
||||||
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
|
||||||
if !c.SingleInflight && c.Net == "https" {
|
|
||||||
return c.exchangeDOH(ctx, m, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeout time.Duration
|
var timeout time.Duration
|
||||||
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): this is a race condition
|
// 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)
|
||||||
}
|
}
|
||||||
|
|||||||
198
vendor/github.com/miekg/dns/compress_generate.go
сгенерированный
поставляемый
198
vendor/github.com/miekg/dns/compress_generate.go
сгенерированный
поставляемый
@@ -1,198 +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 = `
|
|
||||||
// Code generated by "go run compress_generate.go"; DO NOT EDIT.
|
|
||||||
|
|
||||||
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, initLen int) int {\n")
|
|
||||||
fmt.Fprint(b, "currentLen := initLen\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, "currentLen -= len(x.%s) + 1\n", st.Field(i).Name())
|
|
||||||
fmt.Fprintf(b, "currentLen += compressionLenHelper(c, x.%s, currentLen)\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 {
|
|
||||||
currentLen -= len(x.%s[i]) + 1
|
|
||||||
}
|
|
||||||
`, st.Field(i).Name(), st.Field(i).Name())
|
|
||||||
fmt.Fprintf(b, `for i := range x.%s {
|
|
||||||
currentLen += compressionLenHelper(c, x.%s[i], currentLen)
|
|
||||||
}
|
|
||||||
`, 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, "}\nreturn currentLen - initLen\n}\n\n")
|
|
||||||
|
|
||||||
// compressionLenSearchType - search cdomain-tags types for compressible names.
|
|
||||||
|
|
||||||
fmt.Fprint(b, "func compressionLenSearchType(c map[string]int, r RR) (int, bool, int) {\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, sz%d := compressionLenSearch(c, x.%s)\n", j, 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"
|
|
||||||
sz := "sz1"
|
|
||||||
for i := 2; i < j; i++ {
|
|
||||||
k += fmt.Sprintf(" + k%d", i)
|
|
||||||
ok += fmt.Sprintf(" && ok%d", i)
|
|
||||||
sz += fmt.Sprintf(" + sz%d", i)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(b, "return %s, %s, %s\n", k, ok, sz)
|
|
||||||
}
|
|
||||||
fmt.Fprintln(b, "}\nreturn 0, false, 0\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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
vendor/github.com/miekg/dns/defaults.go
сгенерированный
поставляемый
2
vendor/github.com/miekg/dns/defaults.go
сгенерированный
поставляемый
@@ -166,7 +166,7 @@ func (dns *Msg) IsEdns0() *OPT {
|
|||||||
// label fits in 63 characters, but there is no length check for the entire
|
// label fits in 63 characters, but there is no length check for the entire
|
||||||
// string s. I.e. a domain name longer than 255 characters is considered valid.
|
// string s. I.e. a domain name longer than 255 characters is considered valid.
|
||||||
func IsDomainName(s string) (labels int, ok bool) {
|
func IsDomainName(s string) (labels int, ok bool) {
|
||||||
_, labels, err := packDomainName(s, nil, 0, nil, false)
|
_, labels, err := packDomainName(s, nil, 0, compressionMap{}, false)
|
||||||
return labels, err == nil
|
return labels, err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
vendor/github.com/miekg/dns/dns.go
сгенерированный
поставляемый
28
vendor/github.com/miekg/dns/dns.go
сгенерированный
поставляемый
@@ -34,10 +34,15 @@ 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.
|
||||||
|
//
|
||||||
|
// 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 an RR into wire format.
|
// pack packs an RR into wire format.
|
||||||
pack([]byte, int, map[string]int, bool) (int, error)
|
pack(msg []byte, off int, compression compressionMap, compress bool) (headerEnd int, off1 int, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RR_Header is the header all DNS resource records share.
|
// RR_Header is the header all DNS resource records share.
|
||||||
@@ -70,28 +75,29 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
rfc3597, _, err := unpackRFC3597(*r.Header(), buf, off-int(r.Header().Rdlength))
|
hdr := *r.Header()
|
||||||
|
hdr.Rdlength = uint16(off - headerEnd)
|
||||||
|
|
||||||
|
rfc3597, _, err := unpackRFC3597(hdr, buf, headerEnd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*rr = *rfc3597.(*RFC3597)
|
*rr = *rfc3597.(*RFC3597)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
4
vendor/github.com/miekg/dns/dnssec.go
сгенерированный
поставляемый
4
vendor/github.com/miekg/dns/dnssec.go
сгенерированный
поставляемый
@@ -401,7 +401,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 {
|
||||||
@@ -724,7 +724,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
|
||||||
|
|||||||
168
vendor/github.com/miekg/dns/dnssec_keyscan.go
сгенерированный
поставляемый
168
vendor/github.com/miekg/dns/dnssec_keyscan.go
сгенерированный
поставляемый
@@ -1,6 +1,7 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
@@ -194,23 +195,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:
|
||||||
@@ -219,41 +209,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':
|
||||||
@@ -261,24 +321,32 @@ func klexer(s *scan, c chan lex) {
|
|||||||
// Reset a comment
|
// Reset a comment
|
||||||
commt = false
|
commt = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
107
vendor/github.com/miekg/dns/doc.go
сгенерированный
поставляемый
107
vendor/github.com/miekg/dns/doc.go
сгенерированный
поставляемый
@@ -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")
|
||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
33
vendor/github.com/miekg/dns/edns.go
сгенерированный
поставляемый
33
vendor/github.com/miekg/dns/edns.go
сгенерированный
поставляемый
@@ -78,8 +78,8 @@ func (rr *OPT) String() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *OPT) len() int {
|
func (rr *OPT) len(off int, compression map[string]struct{}) int {
|
||||||
l := rr.Hdr.len()
|
l := rr.Hdr.len(off, compression)
|
||||||
for i := 0; i < len(rr.Option); i++ {
|
for i := 0; i < len(rr.Option); i++ {
|
||||||
l += 4 // Account for 2-byte option code and 2-byte option length.
|
l += 4 // Account for 2-byte option code and 2-byte option length.
|
||||||
lo, _ := rr.Option[i].pack()
|
lo, _ := rr.Option[i].pack()
|
||||||
@@ -102,15 +102,14 @@ func (rr *OPT) SetVersion(v uint8) {
|
|||||||
|
|
||||||
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
|
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
|
||||||
func (rr *OPT) ExtendedRcode() int {
|
func (rr *OPT) ExtendedRcode() int {
|
||||||
return int(rr.Hdr.Ttl&0xFF000000>>24) + 15
|
return int(rr.Hdr.Ttl&0xFF000000>>24) << 4
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetExtendedRcode sets the EDNS extended RCODE field.
|
// SetExtendedRcode sets the EDNS extended RCODE field.
|
||||||
func (rr *OPT) SetExtendedRcode(v uint8) {
|
//
|
||||||
if v < RcodeBadVers { // Smaller than 16.. Use the 4 bits you have!
|
// If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0.
|
||||||
return
|
func (rr *OPT) SetExtendedRcode(v uint16) {
|
||||||
}
|
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24
|
||||||
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v-15)<<24
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UDPSize returns the UDP buffer size.
|
// UDPSize returns the UDP buffer size.
|
||||||
@@ -274,22 +273,16 @@ func (e *EDNS0_SUBNET) unpack(b []byte) error {
|
|||||||
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 {
|
||||||
return errors.New("dns: bad netmask")
|
return errors.New("dns: bad netmask")
|
||||||
}
|
}
|
||||||
addr := make([]byte, net.IPv4len)
|
addr := make(net.IP, net.IPv4len)
|
||||||
for i := 0; i < net.IPv4len && 4+i < len(b); i++ {
|
copy(addr, b[4:])
|
||||||
addr[i] = b[4+i]
|
e.Address = addr.To16()
|
||||||
}
|
|
||||||
e.Address = net.IPv4(addr[0], addr[1], addr[2], addr[3])
|
|
||||||
case 2:
|
case 2:
|
||||||
if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
|
if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 {
|
||||||
return errors.New("dns: bad netmask")
|
return errors.New("dns: bad netmask")
|
||||||
}
|
}
|
||||||
addr := make([]byte, net.IPv6len)
|
addr := make(net.IP, net.IPv6len)
|
||||||
for i := 0; i < net.IPv6len && 4+i < len(b); i++ {
|
copy(addr, b[4:])
|
||||||
addr[i] = b[4+i]
|
e.Address = addr
|
||||||
}
|
|
||||||
e.Address = net.IP{addr[0], addr[1], addr[2], addr[3], addr[4],
|
|
||||||
addr[5], addr[6], addr[7], addr[8], addr[9], addr[10],
|
|
||||||
addr[11], addr[12], addr[13], addr[14], addr[15]}
|
|
||||||
default:
|
default:
|
||||||
return errors.New("dns: bad address family")
|
return errors.New("dns: bad address family")
|
||||||
}
|
}
|
||||||
|
|||||||
305
vendor/github.com/miekg/dns/generate.go
сгенерированный
поставляемый
305
vendor/github.com/miekg/dns/generate.go
сгенерированный
поставляемый
@@ -2,8 +2,8 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -18,152 +18,225 @@ import (
|
|||||||
// * rhs (rdata)
|
// * rhs (rdata)
|
||||||
// But we are lazy here, only the range is parsed *all* occurrences
|
// But we are lazy here, only the range is parsed *all* occurrences
|
||||||
// of $ after that are interpreted.
|
// of $ after that are interpreted.
|
||||||
// Any error are returned as a string value, the empty string signals
|
func (zp *ZoneParser) generate(l lex) (RR, bool) {
|
||||||
// "no error".
|
token := l.token
|
||||||
func generate(l lex, c chan lex, t chan *Token, o string) string {
|
|
||||||
step := 1
|
step := 1
|
||||||
if i := strings.IndexAny(l.token, "/"); i != -1 {
|
if i := strings.IndexByte(token, '/'); i >= 0 {
|
||||||
if i+1 == len(l.token) {
|
if i+1 == len(token) {
|
||||||
return "bad step in $GENERATE range"
|
return zp.setParseError("bad step in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
if s, err := strconv.Atoi(l.token[i+1:]); err == nil {
|
|
||||||
if s < 0 {
|
s, err := strconv.Atoi(token[i+1:])
|
||||||
return "bad step in $GENERATE range"
|
if err != nil || s <= 0 {
|
||||||
}
|
return zp.setParseError("bad step in $GENERATE range", l)
|
||||||
step = s
|
|
||||||
} else {
|
|
||||||
return "bad step in $GENERATE range"
|
|
||||||
}
|
}
|
||||||
l.token = l.token[:i]
|
|
||||||
|
step = s
|
||||||
|
token = token[:i]
|
||||||
}
|
}
|
||||||
sx := strings.SplitN(l.token, "-", 2)
|
|
||||||
|
sx := strings.SplitN(token, "-", 2)
|
||||||
if len(sx) != 2 {
|
if len(sx) != 2 {
|
||||||
return "bad start-stop in $GENERATE range"
|
return zp.setParseError("bad start-stop in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
start, err := strconv.Atoi(sx[0])
|
start, err := strconv.Atoi(sx[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "bad start in $GENERATE range"
|
return zp.setParseError("bad start in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
end, err := strconv.Atoi(sx[1])
|
end, err := strconv.Atoi(sx[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "bad stop in $GENERATE range"
|
return zp.setParseError("bad stop in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
if end < 0 || start < 0 || end < start {
|
if end < 0 || start < 0 || end < start {
|
||||||
return "bad range in $GENERATE range"
|
return zp.setParseError("bad range in $GENERATE range", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
<-c // _BLANK
|
zp.c.Next() // _BLANK
|
||||||
|
|
||||||
// Create a complete new string, which we then parse again.
|
// Create a complete new string, which we then parse again.
|
||||||
s := ""
|
var s string
|
||||||
BuildRR:
|
for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() {
|
||||||
l = <-c
|
if l.err {
|
||||||
if l.value != zNewline && l.value != zEOF {
|
return zp.setParseError("bad data in $GENERATE directive", l)
|
||||||
s += l.token
|
}
|
||||||
goto BuildRR
|
if l.value == zNewline {
|
||||||
}
|
break
|
||||||
for i := start; i <= end; i += step {
|
}
|
||||||
var (
|
|
||||||
escape bool
|
|
||||||
dom bytes.Buffer
|
|
||||||
mod string
|
|
||||||
err error
|
|
||||||
offset int
|
|
||||||
)
|
|
||||||
|
|
||||||
for j := 0; j < len(s); j++ { // No 'range' because we need to jump around
|
s += l.token
|
||||||
switch s[j] {
|
}
|
||||||
case '\\':
|
|
||||||
if escape {
|
r := &generateReader{
|
||||||
dom.WriteByte('\\')
|
s: s,
|
||||||
escape = false
|
|
||||||
continue
|
cur: start,
|
||||||
}
|
start: start,
|
||||||
escape = true
|
end: end,
|
||||||
case '$':
|
step: step,
|
||||||
mod = "%d"
|
|
||||||
offset = 0
|
file: zp.file,
|
||||||
if escape {
|
lex: &l,
|
||||||
dom.WriteByte('$')
|
}
|
||||||
escape = false
|
zp.sub = NewZoneParser(r, zp.origin, zp.file)
|
||||||
continue
|
zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed
|
||||||
}
|
zp.sub.SetDefaultTTL(defaultTtl)
|
||||||
escape = false
|
return zp.subNext()
|
||||||
if j+1 >= len(s) { // End of the string
|
}
|
||||||
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
|
||||||
continue
|
type generateReader struct {
|
||||||
} else {
|
s string
|
||||||
if s[j+1] == '$' {
|
si int
|
||||||
dom.WriteByte('$')
|
|
||||||
j++
|
cur int
|
||||||
continue
|
start int
|
||||||
}
|
end int
|
||||||
}
|
step int
|
||||||
// Search for { and }
|
|
||||||
if s[j+1] == '{' { // Modifier block
|
mod bytes.Buffer
|
||||||
sep := strings.Index(s[j+2:], "}")
|
|
||||||
if sep == -1 {
|
escape bool
|
||||||
return "bad modifier in $GENERATE"
|
|
||||||
}
|
eof bool
|
||||||
mod, offset, err = modToPrintf(s[j+2 : j+2+sep])
|
|
||||||
if err != nil {
|
file string
|
||||||
return err.Error()
|
lex *lex
|
||||||
}
|
}
|
||||||
j += 2 + sep // Jump to it
|
|
||||||
}
|
func (r *generateReader) parseError(msg string, end int) *ParseError {
|
||||||
dom.WriteString(fmt.Sprintf(mod, i+offset))
|
r.eof = true // Make errors sticky.
|
||||||
default:
|
|
||||||
if escape { // Pretty useless here
|
l := *r.lex
|
||||||
escape = false
|
l.token = r.s[r.si-1 : end]
|
||||||
continue
|
l.column += r.si // l.column starts one zBLANK before r.s
|
||||||
}
|
|
||||||
dom.WriteByte(s[j])
|
return &ParseError{r.file, msg, l}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Re-parse the RR and send it on the current channel t
|
func (r *generateReader) Read(p []byte) (int, error) {
|
||||||
rx, err := NewRR("$ORIGIN " + o + "\n" + dom.String())
|
// NewZLexer, through NewZoneParser, should use ReadByte and
|
||||||
if err != nil {
|
// not end up here.
|
||||||
return err.Error()
|
|
||||||
}
|
panic("not implemented")
|
||||||
t <- &Token{RR: rx}
|
}
|
||||||
// Its more efficient to first built the rrlist and then parse it in
|
|
||||||
// one go! But is this a problem?
|
func (r *generateReader) ReadByte() (byte, error) {
|
||||||
|
if r.eof {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
if r.mod.Len() > 0 {
|
||||||
|
return r.mod.ReadByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.si >= len(r.s) {
|
||||||
|
r.si = 0
|
||||||
|
r.cur += r.step
|
||||||
|
|
||||||
|
r.eof = r.cur > r.end || r.cur < 0
|
||||||
|
return '\n', nil
|
||||||
|
}
|
||||||
|
|
||||||
|
si := r.si
|
||||||
|
r.si++
|
||||||
|
|
||||||
|
switch r.s[si] {
|
||||||
|
case '\\':
|
||||||
|
if r.escape {
|
||||||
|
r.escape = false
|
||||||
|
return '\\', nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r.escape = true
|
||||||
|
return r.ReadByte()
|
||||||
|
case '$':
|
||||||
|
if r.escape {
|
||||||
|
r.escape = false
|
||||||
|
return '$', nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mod := "%d"
|
||||||
|
|
||||||
|
if si >= len(r.s)-1 {
|
||||||
|
// End of the string
|
||||||
|
fmt.Fprintf(&r.mod, mod, r.cur)
|
||||||
|
return r.mod.ReadByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.s[si+1] == '$' {
|
||||||
|
r.si++
|
||||||
|
return '$', nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var offset int
|
||||||
|
|
||||||
|
// Search for { and }
|
||||||
|
if r.s[si+1] == '{' {
|
||||||
|
// Modifier block
|
||||||
|
sep := strings.Index(r.s[si+2:], "}")
|
||||||
|
if sep < 0 {
|
||||||
|
return 0, r.parseError("bad modifier in $GENERATE", len(r.s))
|
||||||
|
}
|
||||||
|
|
||||||
|
var errMsg string
|
||||||
|
mod, offset, errMsg = modToPrintf(r.s[si+2 : si+2+sep])
|
||||||
|
if errMsg != "" {
|
||||||
|
return 0, r.parseError(errMsg, si+3+sep)
|
||||||
|
}
|
||||||
|
if r.start+offset < 0 || r.end+offset > 1<<31-1 {
|
||||||
|
return 0, r.parseError("bad offset in $GENERATE", si+3+sep)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.si += 2 + sep // Jump to it
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(&r.mod, mod, r.cur+offset)
|
||||||
|
return r.mod.ReadByte()
|
||||||
|
default:
|
||||||
|
if r.escape { // Pretty useless here
|
||||||
|
r.escape = false
|
||||||
|
return r.ReadByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.s[si], nil
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
|
// Convert a $GENERATE modifier 0,0,d to something Printf can deal with.
|
||||||
func modToPrintf(s string) (string, int, error) {
|
func modToPrintf(s string) (string, int, string) {
|
||||||
xs := strings.Split(s, ",")
|
|
||||||
|
|
||||||
// Modifier is { offset [ ,width [ ,base ] ] } - provide default
|
// Modifier is { offset [ ,width [ ,base ] ] } - provide default
|
||||||
// values for optional width and type, if necessary.
|
// values for optional width and type, if necessary.
|
||||||
switch len(xs) {
|
var offStr, widthStr, base string
|
||||||
|
switch xs := strings.Split(s, ","); len(xs) {
|
||||||
case 1:
|
case 1:
|
||||||
xs = append(xs, "0", "d")
|
offStr, widthStr, base = xs[0], "0", "d"
|
||||||
case 2:
|
case 2:
|
||||||
xs = append(xs, "d")
|
offStr, widthStr, base = xs[0], xs[1], "d"
|
||||||
case 3:
|
case 3:
|
||||||
|
offStr, widthStr, base = xs[0], xs[1], xs[2]
|
||||||
default:
|
default:
|
||||||
return "", 0, errors.New("bad modifier in $GENERATE")
|
return "", 0, "bad modifier in $GENERATE"
|
||||||
}
|
}
|
||||||
|
|
||||||
// xs[0] is offset, xs[1] is width, xs[2] is base
|
switch base {
|
||||||
if xs[2] != "o" && xs[2] != "d" && xs[2] != "x" && xs[2] != "X" {
|
case "o", "d", "x", "X":
|
||||||
return "", 0, errors.New("bad base in $GENERATE")
|
default:
|
||||||
|
return "", 0, "bad base in $GENERATE"
|
||||||
}
|
}
|
||||||
offset, err := strconv.Atoi(xs[0])
|
|
||||||
if err != nil || offset > 255 {
|
offset, err := strconv.Atoi(offStr)
|
||||||
return "", 0, errors.New("bad offset in $GENERATE")
|
if err != nil {
|
||||||
|
return "", 0, "bad offset in $GENERATE"
|
||||||
}
|
}
|
||||||
width, err := strconv.Atoi(xs[1])
|
|
||||||
if err != nil || width > 255 {
|
width, err := strconv.Atoi(widthStr)
|
||||||
return "", offset, errors.New("bad width in $GENERATE")
|
if err != nil || width < 0 || width > 255 {
|
||||||
|
return "", 0, "bad width in $GENERATE"
|
||||||
}
|
}
|
||||||
switch {
|
|
||||||
case width < 0:
|
if width == 0 {
|
||||||
return "", offset, errors.New("bad width in $GENERATE")
|
return "%" + base, offset, ""
|
||||||
case width == 0:
|
|
||||||
return "%" + xs[1] + xs[2], offset, nil
|
|
||||||
}
|
}
|
||||||
return "%0" + xs[1] + xs[2], offset, nil
|
|
||||||
|
return "%0" + widthStr + base, offset, ""
|
||||||
}
|
}
|
||||||
|
|||||||
3
vendor/github.com/miekg/dns/listen_go111.go
сгенерированный
поставляемый
3
vendor/github.com/miekg/dns/listen_go111.go
сгенерированный
поставляемый
@@ -1,4 +1,5 @@
|
|||||||
// +build go1.11,!windows
|
// +build go1.11
|
||||||
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
|||||||
2
vendor/github.com/miekg/dns/listen_go_not111.go
сгенерированный
поставляемый
2
vendor/github.com/miekg/dns/listen_go_not111.go
сгенерированный
поставляемый
@@ -1,4 +1,4 @@
|
|||||||
// +build !go1.11 windows
|
// +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
|
|||||||
647
vendor/github.com/miekg/dns/msg.go
сгенерированный
поставляемый
647
vendor/github.com/miekg/dns/msg.go
сгенерированный
поставляемый
@@ -9,7 +9,6 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
//go:generate go run msg_generate.go
|
//go:generate go run msg_generate.go
|
||||||
//go:generate go run compress_generate.go
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
crand "crypto/rand"
|
crand "crypto/rand"
|
||||||
@@ -18,12 +17,35 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
maxCompressionOffset = 2 << 13 // We have 14 bits for the compression pointer
|
||||||
maxDomainNameWireOctets = 255 // See RFC 1035 section 2.3.4
|
maxDomainNameWireOctets = 255 // See RFC 1035 section 2.3.4
|
||||||
|
|
||||||
|
// This is the maximum number of compression pointers that should occur in a
|
||||||
|
// semantically valid message. Each label in a domain name must be at least one
|
||||||
|
// octet and is separated by a period. The root label won't be represented by a
|
||||||
|
// compression pointer to a compression pointer, hence the -2 to exclude the
|
||||||
|
// smallest valid root label.
|
||||||
|
//
|
||||||
|
// It is possible to construct a valid message that has more compression pointers
|
||||||
|
// than this, and still doesn't loop, by pointing to a previous pointer. This is
|
||||||
|
// not something a well written implementation should ever do, so we leave them
|
||||||
|
// to trip the maximum compression pointer check.
|
||||||
|
maxCompressionPointers = (maxDomainNameWireOctets+1)/2 - 2
|
||||||
|
|
||||||
|
// This is the maximum length of a domain name in presentation format. The
|
||||||
|
// maximum wire length of a domain name is 255 octets (see above), with the
|
||||||
|
// maximum label length being 63. The wire format requires one extra byte over
|
||||||
|
// the presentation format, reducing the number of octets by 1. Each label in
|
||||||
|
// the name will be separated by a single period, with each octet in the label
|
||||||
|
// expanding to at most 4 bytes (\DDD). If all other labels are of the maximum
|
||||||
|
// length, then the final label can only be 61 octets long to not exceed the
|
||||||
|
// maximum allowed wire length.
|
||||||
|
maxDomainNamePresentationLength = 61*4 + 1 + 63*4 + 1 + 63*4 + 1 + 63*4 + 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Errors defined in this package.
|
// Errors defined in this package.
|
||||||
@@ -46,10 +68,9 @@ var (
|
|||||||
ErrRRset error = &Error{err: "bad rrset"}
|
ErrRRset error = &Error{err: "bad rrset"}
|
||||||
ErrSecret error = &Error{err: "no secrets defined"}
|
ErrSecret error = &Error{err: "no secrets defined"}
|
||||||
ErrShortRead error = &Error{err: "short read"}
|
ErrShortRead error = &Error{err: "short read"}
|
||||||
ErrSig error = &Error{err: "bad signature"} // ErrSig indicates that a signature can not be cryptographically validated.
|
ErrSig error = &Error{err: "bad signature"} // ErrSig indicates that a signature can not be cryptographically validated.
|
||||||
ErrSoa error = &Error{err: "no SOA"} // ErrSOA indicates that no SOA RR was seen when doing zone transfers.
|
ErrSoa error = &Error{err: "no SOA"} // ErrSOA indicates that no SOA RR was seen when doing zone transfers.
|
||||||
ErrTime error = &Error{err: "bad time"} // ErrTime indicates a timing error in TSIG authentication.
|
ErrTime error = &Error{err: "bad time"} // ErrTime indicates a timing error in TSIG authentication.
|
||||||
ErrTruncated error = &Error{err: "failed to unpack truncated message"} // ErrTruncated indicates that we failed to unpack a truncated message. We unpacked as much as we had so Msg can still be used, if desired.
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Id by default, returns a 16 bits random number to be used as a
|
// Id by default, returns a 16 bits random number to be used as a
|
||||||
@@ -151,7 +172,7 @@ var RcodeToString = map[int]string{
|
|||||||
RcodeFormatError: "FORMERR",
|
RcodeFormatError: "FORMERR",
|
||||||
RcodeServerFailure: "SERVFAIL",
|
RcodeServerFailure: "SERVFAIL",
|
||||||
RcodeNameError: "NXDOMAIN",
|
RcodeNameError: "NXDOMAIN",
|
||||||
RcodeNotImplemented: "NOTIMPL",
|
RcodeNotImplemented: "NOTIMP",
|
||||||
RcodeRefused: "REFUSED",
|
RcodeRefused: "REFUSED",
|
||||||
RcodeYXDomain: "YXDOMAIN", // See RFC 2136
|
RcodeYXDomain: "YXDOMAIN", // See RFC 2136
|
||||||
RcodeYXRrset: "YXRRSET",
|
RcodeYXRrset: "YXRRSET",
|
||||||
@@ -169,6 +190,39 @@ var RcodeToString = map[int]string{
|
|||||||
RcodeBadCookie: "BADCOOKIE",
|
RcodeBadCookie: "BADCOOKIE",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compressionMap is used to allow a more efficient compression map
|
||||||
|
// to be used for internal packDomainName calls without changing the
|
||||||
|
// signature or functionality of public API.
|
||||||
|
//
|
||||||
|
// In particular, map[string]uint16 uses 25% less per-entry memory
|
||||||
|
// than does map[string]int.
|
||||||
|
type compressionMap struct {
|
||||||
|
ext map[string]int // external callers
|
||||||
|
int map[string]uint16 // internal callers
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m compressionMap) valid() bool {
|
||||||
|
return m.int != nil || m.ext != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m compressionMap) insert(s string, pos int) {
|
||||||
|
if m.ext != nil {
|
||||||
|
m.ext[s] = pos
|
||||||
|
} else {
|
||||||
|
m.int[s] = uint16(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m compressionMap) find(s string) (int, bool) {
|
||||||
|
if m.ext != nil {
|
||||||
|
pos, ok := m.ext[s]
|
||||||
|
return pos, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
pos, ok := m.int[s]
|
||||||
|
return int(pos), ok
|
||||||
|
}
|
||||||
|
|
||||||
// Domain names are a sequence of counted strings
|
// Domain names are a sequence of counted strings
|
||||||
// split at the dots. They end with a zero-length string.
|
// split at the dots. They end with a zero-length string.
|
||||||
|
|
||||||
@@ -177,143 +231,168 @@ var RcodeToString = map[int]string{
|
|||||||
// map needs to hold a mapping between domain names and offsets
|
// map needs to hold a mapping between domain names and offsets
|
||||||
// pointing into msg.
|
// pointing into msg.
|
||||||
func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
|
func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
|
||||||
off1, _, err = packDomainName(s, msg, off, compression, compress)
|
off1, _, err = packDomainName(s, msg, off, compressionMap{ext: compression}, compress)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func packDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, labels int, err error) {
|
func packDomainName(s string, msg []byte, off int, compression compressionMap, compress bool) (off1 int, labels int, err error) {
|
||||||
// special case if msg == nil
|
// special case if msg == nil
|
||||||
lenmsg := 256
|
lenmsg := 256
|
||||||
if msg != nil {
|
if msg != nil {
|
||||||
lenmsg = len(msg)
|
lenmsg = len(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
ls := len(s)
|
ls := len(s)
|
||||||
if ls == 0 { // Ok, for instance when dealing with update RR without any rdata.
|
if ls == 0 { // Ok, for instance when dealing with update RR without any rdata.
|
||||||
return off, 0, nil
|
return off, 0, nil
|
||||||
}
|
}
|
||||||
// If not fully qualified, error out, but only if msg == nil #ugly
|
|
||||||
switch {
|
// If not fully qualified, error out, but only if msg != nil #ugly
|
||||||
case msg == nil:
|
if s[ls-1] != '.' {
|
||||||
if s[ls-1] != '.' {
|
if msg != nil {
|
||||||
s += "."
|
|
||||||
ls++
|
|
||||||
}
|
|
||||||
case msg != nil:
|
|
||||||
if s[ls-1] != '.' {
|
|
||||||
return lenmsg, 0, ErrFqdn
|
return lenmsg, 0, ErrFqdn
|
||||||
}
|
}
|
||||||
|
s += "."
|
||||||
|
ls++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Each dot ends a segment of the name.
|
// Each dot ends a segment of the name.
|
||||||
// We trade each dot byte for a length byte.
|
// We trade each dot byte for a length byte.
|
||||||
// Except for escaped dots (\.), which are normal dots.
|
// Except for escaped dots (\.), which are normal dots.
|
||||||
// There is also a trailing zero.
|
// There is also a trailing zero.
|
||||||
|
|
||||||
// Compression
|
// Compression
|
||||||
nameoffset := -1
|
|
||||||
pointer := -1
|
pointer := -1
|
||||||
|
|
||||||
// Emit sequence of counted strings, chopping at dots.
|
// Emit sequence of counted strings, chopping at dots.
|
||||||
begin := 0
|
var (
|
||||||
bs := []byte(s)
|
begin int
|
||||||
roBs, bsFresh, escapedDot := s, true, false
|
compBegin int
|
||||||
|
compOff int
|
||||||
|
bs []byte
|
||||||
|
wasDot bool
|
||||||
|
)
|
||||||
|
loop:
|
||||||
for i := 0; i < ls; i++ {
|
for i := 0; i < ls; i++ {
|
||||||
if bs[i] == '\\' {
|
var c byte
|
||||||
for j := i; j < ls-1; j++ {
|
if bs == nil {
|
||||||
bs[j] = bs[j+1]
|
c = s[i]
|
||||||
}
|
} else {
|
||||||
ls--
|
c = bs[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c {
|
||||||
|
case '\\':
|
||||||
if off+1 > lenmsg {
|
if off+1 > lenmsg {
|
||||||
return lenmsg, labels, ErrBuf
|
return lenmsg, labels, ErrBuf
|
||||||
}
|
}
|
||||||
// check for \DDD
|
|
||||||
if i+2 < ls && isDigit(bs[i]) && isDigit(bs[i+1]) && isDigit(bs[i+2]) {
|
|
||||||
bs[i] = dddToByte(bs[i:])
|
|
||||||
for j := i + 1; j < ls-2; j++ {
|
|
||||||
bs[j] = bs[j+2]
|
|
||||||
}
|
|
||||||
ls -= 2
|
|
||||||
}
|
|
||||||
escapedDot = bs[i] == '.'
|
|
||||||
bsFresh = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if bs[i] == '.' {
|
if bs == nil {
|
||||||
if i > 0 && bs[i-1] == '.' && !escapedDot {
|
bs = []byte(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for \DDD
|
||||||
|
if i+3 < ls && isDigit(bs[i+1]) && isDigit(bs[i+2]) && isDigit(bs[i+3]) {
|
||||||
|
bs[i] = dddToByte(bs[i+1:])
|
||||||
|
copy(bs[i+1:ls-3], bs[i+4:])
|
||||||
|
ls -= 3
|
||||||
|
compOff += 3
|
||||||
|
} else {
|
||||||
|
copy(bs[i:ls-1], bs[i+1:])
|
||||||
|
ls--
|
||||||
|
compOff++
|
||||||
|
}
|
||||||
|
|
||||||
|
wasDot = false
|
||||||
|
case '.':
|
||||||
|
if wasDot {
|
||||||
// two dots back to back is not legal
|
// two dots back to back is not legal
|
||||||
return lenmsg, labels, ErrRdata
|
return lenmsg, labels, ErrRdata
|
||||||
}
|
}
|
||||||
if i-begin >= 1<<6 { // top two bits of length must be clear
|
wasDot = true
|
||||||
|
|
||||||
|
labelLen := i - begin
|
||||||
|
if labelLen >= 1<<6 { // top two bits of length must be clear
|
||||||
return lenmsg, labels, ErrRdata
|
return lenmsg, labels, ErrRdata
|
||||||
}
|
}
|
||||||
|
|
||||||
// off can already (we're in a loop) be bigger than len(msg)
|
// off can already (we're in a loop) be bigger than len(msg)
|
||||||
// this happens when a name isn't fully qualified
|
// this happens when a name isn't fully qualified
|
||||||
if off+1 > lenmsg {
|
if off+1+labelLen > lenmsg {
|
||||||
return lenmsg, labels, ErrBuf
|
return lenmsg, labels, ErrBuf
|
||||||
}
|
}
|
||||||
if msg != nil {
|
|
||||||
msg[off] = byte(i - begin)
|
|
||||||
}
|
|
||||||
offset := off
|
|
||||||
off++
|
|
||||||
for j := begin; j < i; j++ {
|
|
||||||
if off+1 > lenmsg {
|
|
||||||
return lenmsg, labels, ErrBuf
|
|
||||||
}
|
|
||||||
if msg != nil {
|
|
||||||
msg[off] = bs[j]
|
|
||||||
}
|
|
||||||
off++
|
|
||||||
}
|
|
||||||
if compress && !bsFresh {
|
|
||||||
roBs = string(bs)
|
|
||||||
bsFresh = true
|
|
||||||
}
|
|
||||||
// Don't try to compress '.'
|
// Don't try to compress '.'
|
||||||
// We should only compress when compress it true, but we should also still pick
|
// We should only compress when compress is true, but we should also still pick
|
||||||
// up names that can be used for *future* compression(s).
|
// up names that can be used for *future* compression(s).
|
||||||
if compression != nil && roBs[begin:] != "." {
|
if compression.valid() && !isRootLabel(s, bs, begin, ls) {
|
||||||
if p, ok := compression[roBs[begin:]]; !ok {
|
if p, ok := compression.find(s[compBegin:]); ok {
|
||||||
// Only offsets smaller than this can be used.
|
|
||||||
if offset < maxCompressionOffset {
|
|
||||||
compression[roBs[begin:]] = offset
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The first hit is the longest matching dname
|
// The first hit is the longest matching dname
|
||||||
// keep the pointer offset we get back and store
|
// keep the pointer offset we get back and store
|
||||||
// the offset of the current name, because that's
|
// the offset of the current name, because that's
|
||||||
// where we need to insert the pointer later
|
// where we need to insert the pointer later
|
||||||
|
|
||||||
// If compress is true, we're allowed to compress this dname
|
// If compress is true, we're allowed to compress this dname
|
||||||
if pointer == -1 && compress {
|
if compress {
|
||||||
pointer = p // Where to point to
|
pointer = p // Where to point to
|
||||||
nameoffset = offset // Where to point from
|
break loop
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
} else if off < maxCompressionOffset {
|
||||||
|
// Only offsets smaller than maxCompressionOffset can be used.
|
||||||
|
compression.insert(s[compBegin:], off)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The following is covered by the length check above.
|
||||||
|
if msg != nil {
|
||||||
|
msg[off] = byte(labelLen)
|
||||||
|
|
||||||
|
if bs == nil {
|
||||||
|
copy(msg[off+1:], s[begin:i])
|
||||||
|
} else {
|
||||||
|
copy(msg[off+1:], bs[begin:i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
off += 1 + labelLen
|
||||||
|
|
||||||
labels++
|
labels++
|
||||||
begin = i + 1
|
begin = i + 1
|
||||||
|
compBegin = begin + compOff
|
||||||
|
default:
|
||||||
|
wasDot = false
|
||||||
}
|
}
|
||||||
escapedDot = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Root label is special
|
// Root label is special
|
||||||
if len(bs) == 1 && bs[0] == '.' {
|
if isRootLabel(s, bs, 0, ls) {
|
||||||
return off, labels, nil
|
return off, labels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we did compression and we find something add the pointer here
|
// If we did compression and we find something add the pointer here
|
||||||
if pointer != -1 {
|
if pointer != -1 {
|
||||||
// We have two bytes (14 bits) to put the pointer in
|
// We have two bytes (14 bits) to put the pointer in
|
||||||
// if msg == nil, we will never do compression
|
// if msg == nil, we will never do compression
|
||||||
binary.BigEndian.PutUint16(msg[nameoffset:], uint16(pointer^0xC000))
|
binary.BigEndian.PutUint16(msg[off:], uint16(pointer^0xC000))
|
||||||
off = nameoffset + 1
|
return off + 2, labels, nil
|
||||||
goto End
|
|
||||||
}
|
}
|
||||||
if msg != nil && off < len(msg) {
|
|
||||||
|
if msg != nil && off < lenmsg {
|
||||||
msg[off] = 0
|
msg[off] = 0
|
||||||
}
|
}
|
||||||
End:
|
|
||||||
off++
|
return off + 1, labels, nil
|
||||||
return off, labels, nil
|
}
|
||||||
|
|
||||||
|
// isRootLabel returns whether s or bs, from off to end, is the root
|
||||||
|
// label ".".
|
||||||
|
//
|
||||||
|
// If bs is nil, s will be checked, otherwise bs will be checked.
|
||||||
|
func isRootLabel(s string, bs []byte, off, end int) bool {
|
||||||
|
if bs == nil {
|
||||||
|
return s[off:end] == "."
|
||||||
|
}
|
||||||
|
|
||||||
|
return end-off == 1 && bs[off] == '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack a domain name.
|
// Unpack a domain name.
|
||||||
@@ -330,12 +409,16 @@ End:
|
|||||||
// In theory, the pointers are only allowed to jump backward.
|
// In theory, the pointers are only allowed to jump backward.
|
||||||
// We let them jump anywhere and stop jumping after a while.
|
// We let them jump anywhere and stop jumping after a while.
|
||||||
|
|
||||||
// UnpackDomainName unpacks a domain name into a string.
|
// UnpackDomainName unpacks a domain name into a string. It returns
|
||||||
|
// the name, the new offset into msg and any error that occurred.
|
||||||
|
//
|
||||||
|
// When an error is encountered, the unpacked name will be discarded
|
||||||
|
// and len(msg) will be returned as the offset.
|
||||||
func UnpackDomainName(msg []byte, off int) (string, int, error) {
|
func UnpackDomainName(msg []byte, off int) (string, int, error) {
|
||||||
s := make([]byte, 0, 64)
|
s := make([]byte, 0, maxDomainNamePresentationLength)
|
||||||
off1 := 0
|
off1 := 0
|
||||||
lenmsg := len(msg)
|
lenmsg := len(msg)
|
||||||
maxLen := maxDomainNameWireOctets
|
budget := maxDomainNameWireOctets
|
||||||
ptr := 0 // number of pointers followed
|
ptr := 0 // number of pointers followed
|
||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
@@ -354,27 +437,19 @@ Loop:
|
|||||||
if off+c > lenmsg {
|
if off+c > lenmsg {
|
||||||
return "", lenmsg, ErrBuf
|
return "", lenmsg, ErrBuf
|
||||||
}
|
}
|
||||||
|
budget -= c + 1 // +1 for the label separator
|
||||||
|
if budget <= 0 {
|
||||||
|
return "", lenmsg, ErrLongDomain
|
||||||
|
}
|
||||||
for j := off; j < off+c; j++ {
|
for j := off; j < off+c; j++ {
|
||||||
switch b := msg[j]; b {
|
switch b := msg[j]; b {
|
||||||
case '.', '(', ')', ';', ' ', '@':
|
case '.', '(', ')', ';', ' ', '@':
|
||||||
fallthrough
|
fallthrough
|
||||||
case '"', '\\':
|
case '"', '\\':
|
||||||
s = append(s, '\\', b)
|
s = append(s, '\\', b)
|
||||||
// presentation-format \X escapes add an extra byte
|
|
||||||
maxLen++
|
|
||||||
default:
|
default:
|
||||||
if b < 32 || b >= 127 { // unprintable, use \DDD
|
if b < ' ' || b > '~' { // unprintable, use \DDD
|
||||||
var buf [3]byte
|
s = append(s, escapeByte(b)...)
|
||||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
|
||||||
s = append(s, '\\')
|
|
||||||
for i := 0; i < 3-len(bufs); i++ {
|
|
||||||
s = append(s, '0')
|
|
||||||
}
|
|
||||||
for _, r := range bufs {
|
|
||||||
s = append(s, r)
|
|
||||||
}
|
|
||||||
// presentation-format \DDD escapes add 3 extra bytes
|
|
||||||
maxLen += 3
|
|
||||||
} else {
|
} else {
|
||||||
s = append(s, b)
|
s = append(s, b)
|
||||||
}
|
}
|
||||||
@@ -396,7 +471,7 @@ Loop:
|
|||||||
if ptr == 0 {
|
if ptr == 0 {
|
||||||
off1 = off
|
off1 = off
|
||||||
}
|
}
|
||||||
if ptr++; ptr > 10 {
|
if ptr++; ptr > maxCompressionPointers {
|
||||||
return "", lenmsg, &Error{err: "too many compression pointers"}
|
return "", lenmsg, &Error{err: "too many compression pointers"}
|
||||||
}
|
}
|
||||||
// pointer should guarantee that it advances and points forwards at least
|
// pointer should guarantee that it advances and points forwards at least
|
||||||
@@ -412,10 +487,7 @@ Loop:
|
|||||||
off1 = off
|
off1 = off
|
||||||
}
|
}
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
s = []byte(".")
|
return ".", off1, nil
|
||||||
} else if len(s) >= maxLen {
|
|
||||||
// error if the name is too long, but don't throw it away
|
|
||||||
return string(s), lenmsg, ErrLongDomain
|
|
||||||
}
|
}
|
||||||
return string(s), off1, nil
|
return string(s), off1, nil
|
||||||
}
|
}
|
||||||
@@ -512,7 +584,7 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
|
|||||||
off = off0
|
off = off0
|
||||||
var s string
|
var s string
|
||||||
for off < len(msg) && err == nil {
|
for off < len(msg) && err == nil {
|
||||||
s, off, err = unpackTxtString(msg, off)
|
s, off, err = unpackString(msg, off)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ss = append(ss, s)
|
ss = append(ss, s)
|
||||||
}
|
}
|
||||||
@@ -520,43 +592,16 @@ func unpackTxt(msg []byte, off0 int) (ss []string, off int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func unpackTxtString(msg []byte, offset int) (string, int, error) {
|
|
||||||
if offset+1 > len(msg) {
|
|
||||||
return "", offset, &Error{err: "overflow unpacking txt"}
|
|
||||||
}
|
|
||||||
l := int(msg[offset])
|
|
||||||
if offset+l+1 > len(msg) {
|
|
||||||
return "", offset, &Error{err: "overflow unpacking txt"}
|
|
||||||
}
|
|
||||||
s := make([]byte, 0, l)
|
|
||||||
for _, b := range msg[offset+1 : offset+1+l] {
|
|
||||||
switch b {
|
|
||||||
case '"', '\\':
|
|
||||||
s = append(s, '\\', b)
|
|
||||||
default:
|
|
||||||
if b < 32 || b > 127 { // unprintable
|
|
||||||
var buf [3]byte
|
|
||||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
|
||||||
s = append(s, '\\')
|
|
||||||
for i := 0; i < 3-len(bufs); i++ {
|
|
||||||
s = append(s, '0')
|
|
||||||
}
|
|
||||||
for _, r := range bufs {
|
|
||||||
s = append(s, r)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s = append(s, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
offset += 1 + l
|
|
||||||
return string(s), offset, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helpers for dealing with escaped bytes
|
// Helpers for dealing with escaped bytes
|
||||||
func isDigit(b byte) bool { return b >= '0' && b <= '9' }
|
func isDigit(b byte) bool { return b >= '0' && b <= '9' }
|
||||||
|
|
||||||
func dddToByte(s []byte) byte {
|
func dddToByte(s []byte) byte {
|
||||||
|
_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
|
return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
|
||||||
|
}
|
||||||
|
|
||||||
|
func dddStringToByte(s string) byte {
|
||||||
|
_ = s[2] // bounds check hint to compiler; see golang.org/issue/14808
|
||||||
return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
|
return byte((s[0]-'0')*100 + (s[1]-'0')*10 + (s[2] - '0'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,19 +619,33 @@ func intToBytes(i *big.Int, length int) []byte {
|
|||||||
// PackRR packs a resource record rr into msg[off:].
|
// PackRR packs a resource record rr into msg[off:].
|
||||||
// See PackDomainName for documentation about the compression.
|
// See PackDomainName for documentation about the compression.
|
||||||
func PackRR(rr RR, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
|
func PackRR(rr RR, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
|
||||||
|
headerEnd, off1, err := packRR(rr, msg, off, compressionMap{ext: compression}, compress)
|
||||||
|
if err == nil {
|
||||||
|
// packRR no longer sets the Rdlength field on the rr, but
|
||||||
|
// callers might be expecting it so we set it here.
|
||||||
|
rr.Header().Rdlength = uint16(off1 - headerEnd)
|
||||||
|
}
|
||||||
|
return off1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func packRR(rr RR, msg []byte, off int, compression compressionMap, compress bool) (headerEnd int, off1 int, err error) {
|
||||||
if rr == nil {
|
if rr == nil {
|
||||||
return len(msg), &Error{err: "nil rr"}
|
return len(msg), len(msg), &Error{err: "nil rr"}
|
||||||
}
|
}
|
||||||
|
|
||||||
off1, err = rr.pack(msg, off, compression, compress)
|
headerEnd, off1, err = rr.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return headerEnd, len(msg), err
|
||||||
}
|
}
|
||||||
// TODO(miek): Not sure if this is needed? If removed we can remove rawmsg.go as well.
|
|
||||||
if rawSetRdlength(msg, off, off1) {
|
rdlength := off1 - headerEnd
|
||||||
return off1, nil
|
if int(uint16(rdlength)) != rdlength { // overflow
|
||||||
|
return headerEnd, len(msg), ErrRdata
|
||||||
}
|
}
|
||||||
return off, ErrRdata
|
|
||||||
|
// The RDLENGTH field is the last field in the header and we set it here.
|
||||||
|
binary.BigEndian.PutUint16(msg[headerEnd-2:], uint16(rdlength))
|
||||||
|
return headerEnd, off1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnpackRR unpacks msg[off:] into an RR.
|
// UnpackRR unpacks msg[off:] into an RR.
|
||||||
@@ -693,32 +752,33 @@ func (dns *Msg) Pack() (msg []byte, err error) {
|
|||||||
|
|
||||||
// PackBuffer packs a Msg, using the given buffer buf. If buf is too small a new buffer is allocated.
|
// PackBuffer packs a Msg, using the given buffer buf. If buf is too small a new buffer is allocated.
|
||||||
func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
|
func (dns *Msg) PackBuffer(buf []byte) (msg []byte, err error) {
|
||||||
var compression map[string]int
|
// If this message can't be compressed, avoid filling the
|
||||||
if dns.Compress {
|
// compression map and creating garbage.
|
||||||
compression = make(map[string]int) // Compression pointer mappings.
|
if dns.Compress && dns.isCompressible() {
|
||||||
|
compression := make(map[string]uint16) // Compression pointer mappings.
|
||||||
|
return dns.packBufferWithCompressionMap(buf, compressionMap{int: compression}, true)
|
||||||
}
|
}
|
||||||
return dns.packBufferWithCompressionMap(buf, compression)
|
|
||||||
|
return dns.packBufferWithCompressionMap(buf, compressionMap{}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// packBufferWithCompressionMap packs a Msg, using the given buffer buf.
|
// packBufferWithCompressionMap packs a Msg, using the given buffer buf.
|
||||||
func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression map[string]int) (msg []byte, err error) {
|
func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression compressionMap, compress bool) (msg []byte, err error) {
|
||||||
// We use a similar function in tsig.go's stripTsig.
|
|
||||||
|
|
||||||
var dh Header
|
|
||||||
|
|
||||||
if dns.Rcode < 0 || dns.Rcode > 0xFFF {
|
if dns.Rcode < 0 || dns.Rcode > 0xFFF {
|
||||||
return nil, ErrRcode
|
return nil, ErrRcode
|
||||||
}
|
}
|
||||||
if dns.Rcode > 0xF {
|
|
||||||
// Regular RCODE field is 4 bits
|
// Set extended rcode unconditionally if we have an opt, this will allow
|
||||||
opt := dns.IsEdns0()
|
// reseting the extended rcode bits if they need to.
|
||||||
if opt == nil {
|
if opt := dns.IsEdns0(); opt != nil {
|
||||||
return nil, ErrExtendedRcode
|
opt.SetExtendedRcode(uint16(dns.Rcode))
|
||||||
}
|
} else if dns.Rcode > 0xF {
|
||||||
opt.SetExtendedRcode(uint8(dns.Rcode >> 4))
|
// If Rcode is an extended one and opt is nil, error out.
|
||||||
|
return nil, ErrExtendedRcode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert convenient Msg into wire-like Header.
|
// Convert convenient Msg into wire-like Header.
|
||||||
|
var dh Header
|
||||||
dh.Id = dns.Id
|
dh.Id = dns.Id
|
||||||
dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode&0xF)
|
dh.Bits = uint16(dns.Opcode)<<11 | uint16(dns.Rcode&0xF)
|
||||||
if dns.Response {
|
if dns.Response {
|
||||||
@@ -746,50 +806,44 @@ func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression map[string]
|
|||||||
dh.Bits |= _CD
|
dh.Bits |= _CD
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare variable sized arrays.
|
dh.Qdcount = uint16(len(dns.Question))
|
||||||
question := dns.Question
|
dh.Ancount = uint16(len(dns.Answer))
|
||||||
answer := dns.Answer
|
dh.Nscount = uint16(len(dns.Ns))
|
||||||
ns := dns.Ns
|
dh.Arcount = uint16(len(dns.Extra))
|
||||||
extra := dns.Extra
|
|
||||||
|
|
||||||
dh.Qdcount = uint16(len(question))
|
|
||||||
dh.Ancount = uint16(len(answer))
|
|
||||||
dh.Nscount = uint16(len(ns))
|
|
||||||
dh.Arcount = uint16(len(extra))
|
|
||||||
|
|
||||||
// We need the uncompressed length here, because we first pack it and then compress it.
|
// We need the uncompressed length here, because we first pack it and then compress it.
|
||||||
msg = buf
|
msg = buf
|
||||||
uncompressedLen := compressedLen(dns, false)
|
uncompressedLen := msgLenWithCompressionMap(dns, nil)
|
||||||
if packLen := uncompressedLen + 1; len(msg) < packLen {
|
if packLen := uncompressedLen + 1; len(msg) < packLen {
|
||||||
msg = make([]byte, packLen)
|
msg = make([]byte, packLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pack it in: header and then the pieces.
|
// Pack it in: header and then the pieces.
|
||||||
off := 0
|
off := 0
|
||||||
off, err = dh.pack(msg, off, compression, dns.Compress)
|
off, err = dh.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for i := 0; i < len(question); i++ {
|
for _, r := range dns.Question {
|
||||||
off, err = question[i].pack(msg, off, compression, dns.Compress)
|
off, err = r.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(answer); i++ {
|
for _, r := range dns.Answer {
|
||||||
off, err = PackRR(answer[i], msg, off, compression, dns.Compress)
|
_, off, err = packRR(r, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(ns); i++ {
|
for _, r := range dns.Ns {
|
||||||
off, err = PackRR(ns[i], msg, off, compression, dns.Compress)
|
_, off, err = packRR(r, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i := 0; i < len(extra); i++ {
|
for _, r := range dns.Extra {
|
||||||
off, err = PackRR(extra[i], msg, off, compression, dns.Compress)
|
_, off, err = packRR(r, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -797,28 +851,7 @@ func (dns *Msg) packBufferWithCompressionMap(buf []byte, compression map[string]
|
|||||||
return msg[:off], nil
|
return msg[:off], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack unpacks a binary message to a Msg structure.
|
func (dns *Msg) unpack(dh Header, msg []byte, off int) (err error) {
|
||||||
func (dns *Msg) Unpack(msg []byte) (err error) {
|
|
||||||
var (
|
|
||||||
dh Header
|
|
||||||
off int
|
|
||||||
)
|
|
||||||
if dh, off, err = unpackMsgHdr(msg, off); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
dns.Id = dh.Id
|
|
||||||
dns.Response = dh.Bits&_QR != 0
|
|
||||||
dns.Opcode = int(dh.Bits>>11) & 0xF
|
|
||||||
dns.Authoritative = dh.Bits&_AA != 0
|
|
||||||
dns.Truncated = dh.Bits&_TC != 0
|
|
||||||
dns.RecursionDesired = dh.Bits&_RD != 0
|
|
||||||
dns.RecursionAvailable = dh.Bits&_RA != 0
|
|
||||||
dns.Zero = dh.Bits&_Z != 0
|
|
||||||
dns.AuthenticatedData = dh.Bits&_AD != 0
|
|
||||||
dns.CheckingDisabled = dh.Bits&_CD != 0
|
|
||||||
dns.Rcode = int(dh.Bits & 0xF)
|
|
||||||
|
|
||||||
// If we are at the end of the message we should return *just* the
|
// If we are at the end of the message we should return *just* the
|
||||||
// header. This can still be useful to the caller. 9.9.9.9 sends these
|
// header. This can still be useful to the caller. 9.9.9.9 sends these
|
||||||
// when responding with REFUSED for instance.
|
// when responding with REFUSED for instance.
|
||||||
@@ -837,8 +870,6 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
|
|||||||
var q Question
|
var q Question
|
||||||
q, off, err = unpackQuestion(msg, off)
|
q, off, err = unpackQuestion(msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Even if Truncated is set, we only will set ErrTruncated if we
|
|
||||||
// actually got the questions
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
|
if off1 == off { // Offset does not increase anymore, dh.Qdcount is a lie!
|
||||||
@@ -862,16 +893,29 @@ func (dns *Msg) Unpack(msg []byte) (err error) {
|
|||||||
// The header counts might have been wrong so we need to update it
|
// The header counts might have been wrong so we need to update it
|
||||||
dh.Arcount = uint16(len(dns.Extra))
|
dh.Arcount = uint16(len(dns.Extra))
|
||||||
|
|
||||||
|
// Set extended Rcode
|
||||||
|
if opt := dns.IsEdns0(); opt != nil {
|
||||||
|
dns.Rcode |= opt.ExtendedRcode()
|
||||||
|
}
|
||||||
|
|
||||||
if off != len(msg) {
|
if off != len(msg) {
|
||||||
// TODO(miek) make this an error?
|
// TODO(miek) make this an error?
|
||||||
// use PackOpt to let people tell how detailed the error reporting should be?
|
// use PackOpt to let people tell how detailed the error reporting should be?
|
||||||
// println("dns: extra bytes in dns packet", off, "<", len(msg))
|
// println("dns: extra bytes in dns packet", off, "<", len(msg))
|
||||||
} else if dns.Truncated {
|
|
||||||
// Whether we ran into a an error or not, we want to return that it
|
|
||||||
// was truncated
|
|
||||||
err = ErrTruncated
|
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unpack unpacks a binary message to a Msg structure.
|
||||||
|
func (dns *Msg) Unpack(msg []byte) (err error) {
|
||||||
|
dh, off, err := unpackMsgHdr(msg, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
dns.setHdr(dh)
|
||||||
|
return dns.unpack(dh, msg, off)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a complete message to a string with dig-like output.
|
// Convert a complete message to a string with dig-like output.
|
||||||
@@ -917,151 +961,117 @@ func (dns *Msg) String() string {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isCompressible returns whether the msg may be compressible.
|
||||||
|
func (dns *Msg) isCompressible() bool {
|
||||||
|
// If we only have one question, there is nothing we can ever compress.
|
||||||
|
return len(dns.Question) > 1 || len(dns.Answer) > 0 ||
|
||||||
|
len(dns.Ns) > 0 || len(dns.Extra) > 0
|
||||||
|
}
|
||||||
|
|
||||||
// Len returns the message length when in (un)compressed wire format.
|
// Len returns the message length when in (un)compressed wire format.
|
||||||
// If dns.Compress is true compression it is taken into account. Len()
|
// If dns.Compress is true compression it is taken into account. Len()
|
||||||
// is provided to be a faster way to get the size of the resulting packet,
|
// is provided to be a faster way to get the size of the resulting packet,
|
||||||
// than packing it, measuring the size and discarding the buffer.
|
// than packing it, measuring the size and discarding the buffer.
|
||||||
func (dns *Msg) Len() int { return compressedLen(dns, dns.Compress) }
|
func (dns *Msg) Len() int {
|
||||||
|
// If this message can't be compressed, avoid filling the
|
||||||
func compressedLenWithCompressionMap(dns *Msg, compression map[string]int) int {
|
// compression map and creating garbage.
|
||||||
l := 12 // Message header is always 12 bytes
|
if dns.Compress && dns.isCompressible() {
|
||||||
for _, r := range dns.Question {
|
compression := make(map[string]struct{})
|
||||||
compressionLenHelper(compression, r.Name, l)
|
return msgLenWithCompressionMap(dns, compression)
|
||||||
l += r.len()
|
|
||||||
}
|
}
|
||||||
l += compressionLenSlice(l, compression, dns.Answer)
|
|
||||||
l += compressionLenSlice(l, compression, dns.Ns)
|
return msgLenWithCompressionMap(dns, nil)
|
||||||
l += compressionLenSlice(l, compression, dns.Extra)
|
|
||||||
return l
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compressedLen returns the message length when in compressed wire format
|
func msgLenWithCompressionMap(dns *Msg, compression map[string]struct{}) int {
|
||||||
// when compress is true, otherwise the uncompressed length is returned.
|
|
||||||
func compressedLen(dns *Msg, compress bool) int {
|
|
||||||
// We always return one more than needed.
|
|
||||||
if compress {
|
|
||||||
compression := map[string]int{}
|
|
||||||
return compressedLenWithCompressionMap(dns, compression)
|
|
||||||
}
|
|
||||||
l := 12 // Message header is always 12 bytes
|
l := 12 // Message header is always 12 bytes
|
||||||
|
|
||||||
for _, r := range dns.Question {
|
for _, r := range dns.Question {
|
||||||
l += r.len()
|
l += r.len(l, compression)
|
||||||
}
|
}
|
||||||
for _, r := range dns.Answer {
|
for _, r := range dns.Answer {
|
||||||
if r != nil {
|
if r != nil {
|
||||||
l += r.len()
|
l += r.len(l, compression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, r := range dns.Ns {
|
for _, r := range dns.Ns {
|
||||||
if r != nil {
|
if r != nil {
|
||||||
l += r.len()
|
l += r.len(l, compression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, r := range dns.Extra {
|
for _, r := range dns.Extra {
|
||||||
if r != nil {
|
if r != nil {
|
||||||
l += r.len()
|
l += r.len(l, compression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func compressionLenSlice(lenp int, c map[string]int, rs []RR) int {
|
func domainNameLen(s string, off int, compression map[string]struct{}, compress bool) int {
|
||||||
initLen := lenp
|
if s == "" || s == "." {
|
||||||
for _, r := range rs {
|
return 1
|
||||||
if r == nil {
|
}
|
||||||
|
|
||||||
|
escaped := strings.Contains(s, "\\")
|
||||||
|
|
||||||
|
if compression != nil && (compress || off < maxCompressionOffset) {
|
||||||
|
// compressionLenSearch will insert the entry into the compression
|
||||||
|
// map if it doesn't contain it.
|
||||||
|
if l, ok := compressionLenSearch(compression, s, off); ok && compress {
|
||||||
|
if escaped {
|
||||||
|
return escapedNameLen(s[:l]) + 2
|
||||||
|
}
|
||||||
|
|
||||||
|
return l + 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if escaped {
|
||||||
|
return escapedNameLen(s) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(s) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func escapedNameLen(s string) int {
|
||||||
|
nameLen := len(s)
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
if s[i] != '\\' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TmpLen is to track len of record at 14bits boudaries
|
|
||||||
tmpLen := lenp
|
|
||||||
|
|
||||||
x := r.len()
|
if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) {
|
||||||
// track this length, and the global length in len, while taking compression into account for both.
|
nameLen -= 3
|
||||||
k, ok, _ := compressionLenSearch(c, r.Header().Name)
|
i += 3
|
||||||
if ok {
|
|
||||||
// Size of x is reduced by k, but we add 1 since k includes the '.' and label descriptor take 2 bytes
|
|
||||||
// so, basically x:= x - k - 1 + 2
|
|
||||||
x += 1 - k
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpLen += compressionLenHelper(c, r.Header().Name, tmpLen)
|
|
||||||
k, ok, _ = compressionLenSearchType(c, r)
|
|
||||||
if ok {
|
|
||||||
x += 1 - k
|
|
||||||
}
|
|
||||||
lenp += x
|
|
||||||
tmpLen = lenp
|
|
||||||
tmpLen += compressionLenHelperType(c, r, tmpLen)
|
|
||||||
|
|
||||||
}
|
|
||||||
return lenp - initLen
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put the parts of the name in the compression map, return the size in bytes added in payload
|
|
||||||
func compressionLenHelper(c map[string]int, s string, currentLen int) int {
|
|
||||||
if currentLen > maxCompressionOffset {
|
|
||||||
// We won't be able to add any label that could be re-used later anyway
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if _, ok := c[s]; ok {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
initLen := currentLen
|
|
||||||
pref := ""
|
|
||||||
prev := s
|
|
||||||
lbs := Split(s)
|
|
||||||
for j := 0; j < len(lbs); j++ {
|
|
||||||
pref = s[lbs[j]:]
|
|
||||||
currentLen += len(prev) - len(pref)
|
|
||||||
prev = pref
|
|
||||||
if _, ok := c[pref]; !ok {
|
|
||||||
// If first byte label is within the first 14bits, it might be re-used later
|
|
||||||
if currentLen < maxCompressionOffset {
|
|
||||||
c[pref] = currentLen
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
added := currentLen - initLen
|
nameLen--
|
||||||
if j > 0 {
|
i++
|
||||||
// We added a new PTR
|
|
||||||
added += 2
|
|
||||||
}
|
|
||||||
return added
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return currentLen - initLen
|
|
||||||
|
return nameLen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for each part in the compression map and returns its length,
|
func compressionLenSearch(c map[string]struct{}, s string, msgOff int) (int, bool) {
|
||||||
// keep on searching so we get the longest match.
|
for off, end := 0, false; !end; off, end = NextLabel(s, off) {
|
||||||
// Will return the size of compression found, whether a match has been
|
|
||||||
// found and the size of record if added in payload
|
|
||||||
func compressionLenSearch(c map[string]int, s string) (int, bool, int) {
|
|
||||||
off := 0
|
|
||||||
end := false
|
|
||||||
if s == "" { // don't bork on bogus data
|
|
||||||
return 0, false, 0
|
|
||||||
}
|
|
||||||
fullSize := 0
|
|
||||||
for {
|
|
||||||
if _, ok := c[s[off:]]; ok {
|
if _, ok := c[s[off:]]; ok {
|
||||||
return len(s[off:]), true, fullSize + off
|
return off, true
|
||||||
}
|
}
|
||||||
if end {
|
|
||||||
break
|
if msgOff+off < maxCompressionOffset {
|
||||||
|
c[s[off:]] = struct{}{}
|
||||||
}
|
}
|
||||||
// Each label descriptor takes 2 bytes, add it
|
|
||||||
fullSize += 2
|
|
||||||
off, end = NextLabel(s, off)
|
|
||||||
}
|
}
|
||||||
return 0, false, fullSize + len(s)
|
|
||||||
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a new RR which is a deep-copy of r.
|
// Copy returns a new RR which is a deep-copy of r.
|
||||||
func Copy(r RR) RR { r1 := r.copy(); return r1 }
|
func Copy(r RR) RR { r1 := r.copy(); return r1 }
|
||||||
|
|
||||||
// Len returns the length (in octets) of the uncompressed RR in wire format.
|
// Len returns the length (in octets) of the uncompressed RR in wire format.
|
||||||
func Len(r RR) int { return r.len() }
|
func Len(r RR) int { return r.len(0, nil) }
|
||||||
|
|
||||||
// Copy returns a new *Msg which is a deep-copy of dns.
|
// Copy returns a new *Msg which is a deep-copy of dns.
|
||||||
func (dns *Msg) Copy() *Msg { return dns.CopyTo(new(Msg)) }
|
func (dns *Msg) Copy() *Msg { return dns.CopyTo(new(Msg)) }
|
||||||
@@ -1109,8 +1119,8 @@ func (dns *Msg) CopyTo(r1 *Msg) *Msg {
|
|||||||
return r1
|
return r1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Question) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
func (q *Question) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||||
off, err := PackDomainName(q.Name, msg, off, compression, compress)
|
off, _, err := packDomainName(q.Name, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
}
|
}
|
||||||
@@ -1151,7 +1161,7 @@ func unpackQuestion(msg []byte, off int) (Question, int, error) {
|
|||||||
return q, off, err
|
return q, off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dh *Header) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
func (dh *Header) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||||
off, err := packUint16(dh.Id, msg, off)
|
off, err := packUint16(dh.Id, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, err
|
||||||
@@ -1204,3 +1214,18 @@ func unpackMsgHdr(msg []byte, off int) (Header, int, error) {
|
|||||||
dh.Arcount, off, err = unpackUint16(msg, off)
|
dh.Arcount, off, err = unpackUint16(msg, off)
|
||||||
return dh, off, err
|
return dh, off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setHdr set the header in the dns using the binary data in dh.
|
||||||
|
func (dns *Msg) setHdr(dh Header) {
|
||||||
|
dns.Id = dh.Id
|
||||||
|
dns.Response = dh.Bits&_QR != 0
|
||||||
|
dns.Opcode = int(dh.Bits>>11) & 0xF
|
||||||
|
dns.Authoritative = dh.Bits&_AA != 0
|
||||||
|
dns.Truncated = dh.Bits&_TC != 0
|
||||||
|
dns.RecursionDesired = dh.Bits&_RD != 0
|
||||||
|
dns.RecursionAvailable = dh.Bits&_RA != 0
|
||||||
|
dns.Zero = dh.Bits&_Z != 0 // _Z covers the zero bit, which should be zero; not sure why we set it to the opposite.
|
||||||
|
dns.AuthenticatedData = dh.Bits&_AD != 0
|
||||||
|
dns.CheckingDisabled = dh.Bits&_CD != 0
|
||||||
|
dns.Rcode = int(dh.Bits & 0xF)
|
||||||
|
}
|
||||||
|
|||||||
21
vendor/github.com/miekg/dns/msg_generate.go
сгенерированный
поставляемый
21
vendor/github.com/miekg/dns/msg_generate.go
сгенерированный
поставляемый
@@ -80,18 +80,17 @@ func main() {
|
|||||||
o := scope.Lookup(name)
|
o := scope.Lookup(name)
|
||||||
st, _ := getTypeStruct(o.Type(), scope)
|
st, _ := getTypeStruct(o.Type(), scope)
|
||||||
|
|
||||||
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {\n", name)
|
fmt.Fprintf(b, "func (rr *%s) pack(msg []byte, off int, compression compressionMap, compress bool) (int, int, error) {\n", name)
|
||||||
fmt.Fprint(b, `off, err := rr.Hdr.pack(msg, off, compression, compress)
|
fmt.Fprint(b, `headerEnd, off, err := rr.Hdr.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return headerEnd, off, err
|
||||||
}
|
}
|
||||||
headerEnd := off
|
|
||||||
`)
|
`)
|
||||||
for i := 1; i < st.NumFields(); i++ {
|
for i := 1; i < st.NumFields(); i++ {
|
||||||
o := func(s string) {
|
o := func(s string) {
|
||||||
fmt.Fprintf(b, s, st.Field(i).Name())
|
fmt.Fprintf(b, s, st.Field(i).Name())
|
||||||
fmt.Fprint(b, `if err != nil {
|
fmt.Fprint(b, `if err != nil {
|
||||||
return off, err
|
return headerEnd, off, err
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
@@ -106,7 +105,7 @@ return off, err
|
|||||||
case `dns:"nsec"`:
|
case `dns:"nsec"`:
|
||||||
o("off, err = packDataNsec(rr.%s, msg, off)\n")
|
o("off, err = packDataNsec(rr.%s, msg, off)\n")
|
||||||
case `dns:"domain-name"`:
|
case `dns:"domain-name"`:
|
||||||
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, compress)\n")
|
o("off, err = packDataDomainNames(rr.%s, msg, off, compression, false)\n")
|
||||||
default:
|
default:
|
||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
}
|
}
|
||||||
@@ -116,9 +115,9 @@ return off, err
|
|||||||
switch {
|
switch {
|
||||||
case st.Tag(i) == `dns:"-"`: // ignored
|
case st.Tag(i) == `dns:"-"`: // ignored
|
||||||
case st.Tag(i) == `dns:"cdomain-name"`:
|
case st.Tag(i) == `dns:"cdomain-name"`:
|
||||||
o("off, err = PackDomainName(rr.%s, msg, off, compression, compress)\n")
|
o("off, _, err = packDomainName(rr.%s, msg, off, compression, compress)\n")
|
||||||
case st.Tag(i) == `dns:"domain-name"`:
|
case st.Tag(i) == `dns:"domain-name"`:
|
||||||
o("off, err = PackDomainName(rr.%s, msg, off, compression, false)\n")
|
o("off, _, err = packDomainName(rr.%s, msg, off, compression, false)\n")
|
||||||
case st.Tag(i) == `dns:"a"`:
|
case st.Tag(i) == `dns:"a"`:
|
||||||
o("off, err = packDataA(rr.%s, msg, off)\n")
|
o("off, err = packDataA(rr.%s, msg, off)\n")
|
||||||
case st.Tag(i) == `dns:"aaaa"`:
|
case st.Tag(i) == `dns:"aaaa"`:
|
||||||
@@ -145,7 +144,7 @@ return off, err
|
|||||||
if rr.%s != "-" {
|
if rr.%s != "-" {
|
||||||
off, err = packStringHex(rr.%s, msg, off)
|
off, err = packStringHex(rr.%s, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return headerEnd, off, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, field, field)
|
`, field, field)
|
||||||
@@ -176,9 +175,7 @@ if rr.%s != "-" {
|
|||||||
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
log.Fatalln(name, st.Field(i).Name(), st.Tag(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We have packed everything, only now we know the rdlength of this RR
|
fmt.Fprintln(b, "return headerEnd, off, nil }\n")
|
||||||
fmt.Fprintln(b, "rr.Header().Rdlength = uint16(off-headerEnd)")
|
|
||||||
fmt.Fprintln(b, "return off, nil }\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(b, "// unpack*() functions\n\n")
|
fmt.Fprint(b, "// unpack*() functions\n\n")
|
||||||
|
|||||||
58
vendor/github.com/miekg/dns/msg_helpers.go
сгенерированный
поставляемый
58
vendor/github.com/miekg/dns/msg_helpers.go
сгенерированный
поставляемый
@@ -6,7 +6,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// helper functions called from the generated zmsg.go
|
// helper functions called from the generated zmsg.go
|
||||||
@@ -101,32 +101,32 @@ func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte,
|
|||||||
|
|
||||||
// pack packs an RR header, returning the offset to the end of the header.
|
// pack packs an RR header, returning the offset to the end of the header.
|
||||||
// See PackDomainName for documentation about the compression.
|
// See PackDomainName for documentation about the compression.
|
||||||
func (hdr RR_Header) pack(msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error) {
|
func (hdr RR_Header) pack(msg []byte, off int, compression compressionMap, compress bool) (int, int, error) {
|
||||||
if off == len(msg) {
|
if off == len(msg) {
|
||||||
return off, nil
|
return off, off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
off, err = PackDomainName(hdr.Name, msg, off, compression, compress)
|
off, _, err := packDomainName(hdr.Name, msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return off, len(msg), err
|
||||||
}
|
}
|
||||||
off, err = packUint16(hdr.Rrtype, msg, off)
|
off, err = packUint16(hdr.Rrtype, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return off, len(msg), err
|
||||||
}
|
}
|
||||||
off, err = packUint16(hdr.Class, msg, off)
|
off, err = packUint16(hdr.Class, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return off, len(msg), err
|
||||||
}
|
}
|
||||||
off, err = packUint32(hdr.Ttl, msg, off)
|
off, err = packUint32(hdr.Ttl, msg, off)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return off, len(msg), err
|
||||||
}
|
}
|
||||||
off, err = packUint16(hdr.Rdlength, msg, off)
|
off, err = packUint16(0, msg, off) // The RDLENGTH field will be set later in packRR.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return off, len(msg), err
|
||||||
}
|
}
|
||||||
return off, nil
|
return off, off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper helper functions.
|
// helper helper functions.
|
||||||
@@ -223,8 +223,8 @@ func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
|
|||||||
return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
|
return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
|
||||||
}
|
}
|
||||||
// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
|
// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
|
||||||
i = uint64(uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
|
i = uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
|
||||||
uint64(msg[off+4])<<8 | uint64(msg[off+5]))
|
uint64(msg[off+4])<<8 | uint64(msg[off+5])
|
||||||
off += 6
|
off += 6
|
||||||
return i, off, nil
|
return i, off, nil
|
||||||
}
|
}
|
||||||
@@ -267,29 +267,21 @@ func unpackString(msg []byte, off int) (string, int, error) {
|
|||||||
if off+l+1 > len(msg) {
|
if off+l+1 > len(msg) {
|
||||||
return "", off, &Error{err: "overflow unpacking txt"}
|
return "", off, &Error{err: "overflow unpacking txt"}
|
||||||
}
|
}
|
||||||
s := make([]byte, 0, l)
|
var s strings.Builder
|
||||||
|
s.Grow(l)
|
||||||
for _, b := range msg[off+1 : off+1+l] {
|
for _, b := range msg[off+1 : off+1+l] {
|
||||||
switch b {
|
switch {
|
||||||
case '"', '\\':
|
case b == '"' || b == '\\':
|
||||||
s = append(s, '\\', b)
|
s.WriteByte('\\')
|
||||||
|
s.WriteByte(b)
|
||||||
|
case b < ' ' || b > '~': // unprintable
|
||||||
|
s.WriteString(escapeByte(b))
|
||||||
default:
|
default:
|
||||||
if b < 32 || b > 127 { // unprintable
|
s.WriteByte(b)
|
||||||
var buf [3]byte
|
|
||||||
bufs := strconv.AppendInt(buf[:0], int64(b), 10)
|
|
||||||
s = append(s, '\\')
|
|
||||||
for i := 0; i < 3-len(bufs); i++ {
|
|
||||||
s = append(s, '0')
|
|
||||||
}
|
|
||||||
for _, r := range bufs {
|
|
||||||
s = append(s, r)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s = append(s, b)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
off += 1 + l
|
off += 1 + l
|
||||||
return string(s), off, nil
|
return s.String(), off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func packString(s string, msg []byte, off int) (int, error) {
|
func packString(s string, msg []byte, off int) (int, error) {
|
||||||
@@ -629,10 +621,10 @@ func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
|
|||||||
return servers, off, nil
|
return servers, off, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func packDataDomainNames(names []string, msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
|
||||||
var err error
|
var err error
|
||||||
for j := 0; j < len(names); j++ {
|
for j := 0; j < len(names); j++ {
|
||||||
off, err = PackDomainName(names[j], msg, off, compression, false && compress)
|
off, _, err = packDomainName(names[j], msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return len(msg), err
|
||||||
}
|
}
|
||||||
|
|||||||
47
vendor/github.com/miekg/dns/nsecx.go
сгенерированный
поставляемый
47
vendor/github.com/miekg/dns/nsecx.go
сгенерированный
поставляемый
@@ -2,49 +2,44 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"hash"
|
"encoding/hex"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type saltWireFmt struct {
|
|
||||||
Salt string `dns:"size-hex"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase.
|
// HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase.
|
||||||
func HashName(label string, ha uint8, iter uint16, salt string) string {
|
func HashName(label string, ha uint8, iter uint16, salt string) string {
|
||||||
saltwire := new(saltWireFmt)
|
if ha != SHA1 {
|
||||||
saltwire.Salt = salt
|
return ""
|
||||||
wire := make([]byte, DefaultMsgSize)
|
}
|
||||||
n, err := packSaltWire(saltwire, wire)
|
|
||||||
|
wireSalt := make([]byte, hex.DecodedLen(len(salt)))
|
||||||
|
n, err := packStringHex(salt, wireSalt, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
wire = wire[:n]
|
wireSalt = wireSalt[:n]
|
||||||
|
|
||||||
name := make([]byte, 255)
|
name := make([]byte, 255)
|
||||||
off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
|
off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
name = name[:off]
|
name = name[:off]
|
||||||
var s hash.Hash
|
|
||||||
switch ha {
|
|
||||||
case SHA1:
|
|
||||||
s = sha1.New()
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
|
s := sha1.New()
|
||||||
// k = 0
|
// k = 0
|
||||||
s.Write(name)
|
s.Write(name)
|
||||||
s.Write(wire)
|
s.Write(wireSalt)
|
||||||
nsec3 := s.Sum(nil)
|
nsec3 := s.Sum(nil)
|
||||||
|
|
||||||
// k > 0
|
// k > 0
|
||||||
for k := uint16(0); k < iter; k++ {
|
for k := uint16(0); k < iter; k++ {
|
||||||
s.Reset()
|
s.Reset()
|
||||||
s.Write(nsec3)
|
s.Write(nsec3)
|
||||||
s.Write(wire)
|
s.Write(wireSalt)
|
||||||
nsec3 = s.Sum(nsec3[:0])
|
nsec3 = s.Sum(nsec3[:0])
|
||||||
}
|
}
|
||||||
|
|
||||||
return toBase32(nsec3)
|
return toBase32(nsec3)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,8 +58,10 @@ func (rr *NSEC3) Cover(name string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nextHash := rr.NextDomain
|
nextHash := rr.NextDomain
|
||||||
if ownerHash == nextHash { // empty interval
|
|
||||||
return false
|
// if empty interval found, try cover wildcard hashes so nameHash shouldn't match with ownerHash
|
||||||
|
if ownerHash == nextHash && nameHash != ownerHash { // empty interval
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
if ownerHash > nextHash { // end of zone
|
if ownerHash > nextHash { // end of zone
|
||||||
if nameHash > ownerHash { // covered since there is nothing after ownerHash
|
if nameHash > ownerHash { // covered since there is nothing after ownerHash
|
||||||
@@ -96,11 +93,3 @@ func (rr *NSEC3) Match(name string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func packSaltWire(sw *saltWireFmt, msg []byte) (int, error) {
|
|
||||||
off, err := packStringHex(sw.Salt, msg, 0)
|
|
||||||
if err != nil {
|
|
||||||
return off, err
|
|
||||||
}
|
|
||||||
return off, nil
|
|
||||||
}
|
|
||||||
|
|||||||
27
vendor/github.com/miekg/dns/privaterr.go
сгенерированный
поставляемый
27
vendor/github.com/miekg/dns/privaterr.go
сгенерированный
поставляемый
@@ -52,7 +52,12 @@ func (r *PrivateRR) Header() *RR_Header { return &r.Hdr }
|
|||||||
func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
|
func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() }
|
||||||
|
|
||||||
// Private len and copy parts to satisfy RR interface.
|
// Private len and copy parts to satisfy RR interface.
|
||||||
func (r *PrivateRR) len() int { return r.Hdr.len() + r.Data.Len() }
|
func (r *PrivateRR) len(off int, compression map[string]struct{}) int {
|
||||||
|
l := r.Hdr.len(off, compression)
|
||||||
|
l += r.Data.Len()
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
func (r *PrivateRR) copy() RR {
|
func (r *PrivateRR) copy() RR {
|
||||||
// make new RR like this:
|
// make new RR like this:
|
||||||
rr := mkPrivateRR(r.Hdr.Rrtype)
|
rr := mkPrivateRR(r.Hdr.Rrtype)
|
||||||
@@ -64,19 +69,18 @@ func (r *PrivateRR) copy() RR {
|
|||||||
}
|
}
|
||||||
return rr
|
return rr
|
||||||
}
|
}
|
||||||
func (r *PrivateRR) pack(msg []byte, off int, compression map[string]int, compress bool) (int, error) {
|
|
||||||
off, err := r.Hdr.pack(msg, off, compression, compress)
|
func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compress bool) (int, int, error) {
|
||||||
|
headerEnd, off, err := r.Hdr.pack(msg, off, compression, compress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return off, err
|
return off, off, err
|
||||||
}
|
}
|
||||||
headerEnd := off
|
|
||||||
n, err := r.Data.Pack(msg[off:])
|
n, err := r.Data.Pack(msg[off:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return len(msg), err
|
return headerEnd, len(msg), err
|
||||||
}
|
}
|
||||||
off += n
|
off += n
|
||||||
r.Header().Rdlength = uint16(off - headerEnd)
|
return headerEnd, off, nil
|
||||||
return off, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrivateHandle registers a private resource record type. It requires
|
// PrivateHandle registers a private resource record type. It requires
|
||||||
@@ -105,7 +109,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
|||||||
return rr, off, err
|
return rr, off, err
|
||||||
}
|
}
|
||||||
|
|
||||||
setPrivateRR := func(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
|
setPrivateRR := func(h RR_Header, c *zlexer, o, f string) (RR, *ParseError, string) {
|
||||||
rr := mkPrivateRR(h.Rrtype)
|
rr := mkPrivateRR(h.Rrtype)
|
||||||
rr.Hdr = h
|
rr.Hdr = h
|
||||||
|
|
||||||
@@ -115,7 +119,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
|||||||
for {
|
for {
|
||||||
// TODO(miek): we could also be returning _QUOTE, this might or might not
|
// TODO(miek): we could also be returning _QUOTE, this might or might not
|
||||||
// be an issue (basically parsing TXT becomes hard)
|
// be an issue (basically parsing TXT becomes hard)
|
||||||
switch l = <-c; l.value {
|
switch l, _ = c.Next(); l.value {
|
||||||
case zNewline, zEOF:
|
case zNewline, zEOF:
|
||||||
break Fetch
|
break Fetch
|
||||||
case zString:
|
case zString:
|
||||||
@@ -134,7 +138,7 @@ func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata)
|
|||||||
typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
|
typeToparserFunc[rtype] = parserFunc{setPrivateRR, true}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrivateHandleRemove removes defenitions required to support private RR type.
|
// PrivateHandleRemove removes definitions required to support private RR type.
|
||||||
func PrivateHandleRemove(rtype uint16) {
|
func PrivateHandleRemove(rtype uint16) {
|
||||||
rtypestr, ok := TypeToString[rtype]
|
rtypestr, ok := TypeToString[rtype]
|
||||||
if ok {
|
if ok {
|
||||||
@@ -144,5 +148,4 @@ func PrivateHandleRemove(rtype uint16) {
|
|||||||
delete(StringToType, rtypestr)
|
delete(StringToType, rtypestr)
|
||||||
delete(typeToUnpack, rtype)
|
delete(typeToUnpack, rtype)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|||||||
49
vendor/github.com/miekg/dns/rawmsg.go
сгенерированный
поставляемый
49
vendor/github.com/miekg/dns/rawmsg.go
сгенерированный
поставляемый
@@ -1,49 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import "encoding/binary"
|
|
||||||
|
|
||||||
// rawSetRdlength sets the rdlength in the header of
|
|
||||||
// the RR. The offset 'off' must be positioned at the
|
|
||||||
// start of the header of the RR, 'end' must be the
|
|
||||||
// end of the RR.
|
|
||||||
func rawSetRdlength(msg []byte, off, end int) bool {
|
|
||||||
l := len(msg)
|
|
||||||
Loop:
|
|
||||||
for {
|
|
||||||
if off+1 > l {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
c := int(msg[off])
|
|
||||||
off++
|
|
||||||
switch c & 0xC0 {
|
|
||||||
case 0x00:
|
|
||||||
if c == 0x00 {
|
|
||||||
// End of the domainname
|
|
||||||
break Loop
|
|
||||||
}
|
|
||||||
if off+c > l {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
off += c
|
|
||||||
|
|
||||||
case 0xC0:
|
|
||||||
// pointer, next byte included, ends domainname
|
|
||||||
off++
|
|
||||||
break Loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The domainname has been seen, we at the start of the fixed part in the header.
|
|
||||||
// Type is 2 bytes, class is 2 bytes, ttl 4 and then 2 bytes for the length.
|
|
||||||
off += 2 + 2 + 4
|
|
||||||
if off+2 > l {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
//off+1 is the end of the header, 'end' is the end of the rr
|
|
||||||
//so 'end' - 'off+2' is the length of the rdata
|
|
||||||
rdatalen := end - (off + 2)
|
|
||||||
if rdatalen > 0xFFFF {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
binary.BigEndian.PutUint16(msg[off:], uint16(rdatalen))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
5
vendor/github.com/miekg/dns/reverse.go
сгенерированный
поставляемый
5
vendor/github.com/miekg/dns/reverse.go
сгенерированный
поставляемый
@@ -12,6 +12,11 @@ var StringToOpcode = reverseInt(OpcodeToString)
|
|||||||
// StringToRcode is a map of rcodes to strings.
|
// StringToRcode is a map of rcodes to strings.
|
||||||
var StringToRcode = reverseInt(RcodeToString)
|
var StringToRcode = reverseInt(RcodeToString)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Preserve previous NOTIMP typo, see github.com/miekg/dns/issues/733.
|
||||||
|
StringToRcode["NOTIMPL"] = RcodeNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// Reverse a map
|
// Reverse a map
|
||||||
func reverseInt8(m map[uint8]string) map[string]uint8 {
|
func reverseInt8(m map[uint8]string) map[string]uint8 {
|
||||||
n := make(map[string]uint8, len(m))
|
n := make(map[string]uint8, len(m))
|
||||||
|
|||||||
1020
vendor/github.com/miekg/dns/scan.go
сгенерированный
поставляемый
1020
vendor/github.com/miekg/dns/scan.go
сгенерированный
поставляемый
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
730
vendor/github.com/miekg/dns/scan_rr.go
сгенерированный
поставляемый
730
vendor/github.com/miekg/dns/scan_rr.go
сгенерированный
поставляемый
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
56
vendor/github.com/miekg/dns/scanner.go
сгенерированный
поставляемый
56
vendor/github.com/miekg/dns/scanner.go
сгенерированный
поставляемый
@@ -1,56 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
// Implement a simple scanner, return a byte stream from an io reader.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"text/scanner"
|
|
||||||
)
|
|
||||||
|
|
||||||
type scan struct {
|
|
||||||
src *bufio.Reader
|
|
||||||
position scanner.Position
|
|
||||||
eof bool // Have we just seen a eof
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func scanInit(r io.Reader) (*scan, context.CancelFunc) {
|
|
||||||
s := new(scan)
|
|
||||||
s.src = bufio.NewReader(r)
|
|
||||||
s.position.Line = 1
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
s.ctx = ctx
|
|
||||||
|
|
||||||
return s, cancel
|
|
||||||
}
|
|
||||||
|
|
||||||
// tokenText returns the next byte from the input
|
|
||||||
func (s *scan) tokenText() (byte, error) {
|
|
||||||
c, err := s.src.ReadByte()
|
|
||||||
if err != nil {
|
|
||||||
return c, err
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-s.ctx.Done():
|
|
||||||
return c, context.Canceled
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// delay the newline handling until the next token is delivered,
|
|
||||||
// fixes off-by-one errors when reporting a parse error.
|
|
||||||
if s.eof == true {
|
|
||||||
s.position.Line++
|
|
||||||
s.position.Column = 0
|
|
||||||
s.eof = false
|
|
||||||
}
|
|
||||||
if c == '\n' {
|
|
||||||
s.eof = true
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
s.position.Column++
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
147
vendor/github.com/miekg/dns/serve_mux.go
сгенерированный
поставляемый
Обычный файл
147
vendor/github.com/miekg/dns/serve_mux.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,147 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServeMux is an DNS request multiplexer. It matches the zone name of
|
||||||
|
// each incoming request against a list of registered patterns add calls
|
||||||
|
// the handler for the pattern that most closely matches the zone name.
|
||||||
|
//
|
||||||
|
// ServeMux is DNSSEC aware, meaning that queries for the DS record are
|
||||||
|
// redirected to the parent zone (if that is also registered), otherwise
|
||||||
|
// the child gets the query.
|
||||||
|
//
|
||||||
|
// ServeMux is also safe for concurrent access from multiple goroutines.
|
||||||
|
//
|
||||||
|
// The zero ServeMux is empty and ready for use.
|
||||||
|
type ServeMux struct {
|
||||||
|
z map[string]Handler
|
||||||
|
m sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServeMux allocates and returns a new ServeMux.
|
||||||
|
func NewServeMux() *ServeMux {
|
||||||
|
return new(ServeMux)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultServeMux is the default ServeMux used by Serve.
|
||||||
|
var DefaultServeMux = NewServeMux()
|
||||||
|
|
||||||
|
func (mux *ServeMux) match(q string, t uint16) Handler {
|
||||||
|
mux.m.RLock()
|
||||||
|
defer mux.m.RUnlock()
|
||||||
|
if mux.z == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var handler Handler
|
||||||
|
|
||||||
|
// TODO(tmthrgd): Once https://go-review.googlesource.com/c/go/+/137575
|
||||||
|
// lands in a go release, replace the following with strings.ToLower.
|
||||||
|
var sb strings.Builder
|
||||||
|
for i := 0; i < len(q); i++ {
|
||||||
|
c := q[i]
|
||||||
|
if !(c >= 'A' && c <= 'Z') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Grow(len(q))
|
||||||
|
sb.WriteString(q[:i])
|
||||||
|
|
||||||
|
for ; i < len(q); i++ {
|
||||||
|
c := q[i]
|
||||||
|
if c >= 'A' && c <= 'Z' {
|
||||||
|
c += 'a' - 'A'
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.WriteByte(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
q = sb.String()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
for off, end := 0, false; !end; off, end = NextLabel(q, off) {
|
||||||
|
if h, ok := mux.z[q[off:]]; ok {
|
||||||
|
if t != TypeDS {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
// Continue for DS to see if we have a parent too, if so delegate to the parent
|
||||||
|
handler = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wildcard match, if we have found nothing try the root zone as a last resort.
|
||||||
|
if h, ok := mux.z["."]; ok {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle adds a handler to the ServeMux for pattern.
|
||||||
|
func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
||||||
|
if pattern == "" {
|
||||||
|
panic("dns: invalid pattern " + pattern)
|
||||||
|
}
|
||||||
|
mux.m.Lock()
|
||||||
|
if mux.z == nil {
|
||||||
|
mux.z = make(map[string]Handler)
|
||||||
|
}
|
||||||
|
mux.z[Fqdn(pattern)] = handler
|
||||||
|
mux.m.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleFunc adds a handler function to the ServeMux for pattern.
|
||||||
|
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||||
|
mux.Handle(pattern, HandlerFunc(handler))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleRemove deregisters the handler specific for pattern from the ServeMux.
|
||||||
|
func (mux *ServeMux) HandleRemove(pattern string) {
|
||||||
|
if pattern == "" {
|
||||||
|
panic("dns: invalid pattern " + pattern)
|
||||||
|
}
|
||||||
|
mux.m.Lock()
|
||||||
|
delete(mux.z, Fqdn(pattern))
|
||||||
|
mux.m.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServeDNS dispatches the request to the handler whose pattern most
|
||||||
|
// closely matches the request message.
|
||||||
|
//
|
||||||
|
// ServeDNS is DNSSEC aware, meaning that queries for the DS record
|
||||||
|
// are redirected to the parent zone (if that is also registered),
|
||||||
|
// otherwise the child gets the query.
|
||||||
|
//
|
||||||
|
// If no handler is found, or there is no question, a standard SERVFAIL
|
||||||
|
// message is returned
|
||||||
|
func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
|
||||||
|
var h Handler
|
||||||
|
if len(req.Question) >= 1 { // allow more than one question
|
||||||
|
h = mux.match(req.Question[0].Name, req.Question[0].Qtype)
|
||||||
|
}
|
||||||
|
|
||||||
|
if h != nil {
|
||||||
|
h.ServeDNS(w, req)
|
||||||
|
} else {
|
||||||
|
HandleFailed(w, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle registers the handler with the given pattern
|
||||||
|
// in the DefaultServeMux. The documentation for
|
||||||
|
// ServeMux explains how patterns are matched.
|
||||||
|
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
|
||||||
|
|
||||||
|
// HandleRemove deregisters the handle with the given pattern
|
||||||
|
// in the DefaultServeMux.
|
||||||
|
func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
|
||||||
|
|
||||||
|
// HandleFunc registers the handler function with the given pattern
|
||||||
|
// in the DefaultServeMux.
|
||||||
|
func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
|
||||||
|
DefaultServeMux.HandleFunc(pattern, handler)
|
||||||
|
}
|
||||||
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Ссылка в новой задаче
Block a user